device and profile works with changed structure
This commit is contained in:
parent
c1fbebe0da
commit
c91aa4b278
@ -3,6 +3,7 @@ using Api.Models;
|
||||
using Api.Models.Devices;
|
||||
using Api.Models.Users;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Api.BusinessLogic
|
||||
{
|
||||
@ -25,14 +26,28 @@ namespace Api.BusinessLogic
|
||||
/// <returns>returns the devices in a OkObjectResult and if there is some error it returns a ConflictObjectResult and a message that explain the reason</returns>
|
||||
public async Task<IActionResult> GetDevices(int userId)
|
||||
{
|
||||
var profile = await _dbAccess.ReadUser(userId);
|
||||
var userDetails = await _dbAccess.ReadUserDetails(userId);
|
||||
|
||||
if (profile == null) { return new ConflictObjectResult(new { message = "Could not find user" }); }
|
||||
if (userDetails.Devices.Count == 0) { return new OkObjectResult(new { message = "Could not find any devices connected to the user" }); }
|
||||
|
||||
var devices = await _dbAccess.ReadDevices(userId);
|
||||
|
||||
if (devices.Count == 0) { return new OkObjectResult(new { message = "Could not find any devices connected to the user" }); }
|
||||
List<GetDeviceDTO> devices = new List<GetDeviceDTO>();
|
||||
|
||||
foreach (var item in userDetails.Devices)
|
||||
{
|
||||
var latestLog = item.Logs?.OrderByDescending(log => log.Date).FirstOrDefault(); // Get the latest log
|
||||
GetDeviceDTO device = new GetDeviceDTO
|
||||
{
|
||||
Id = item.Id,
|
||||
Name = item.Name,
|
||||
TempHigh = item.TempHigh,
|
||||
TempLow = item.TempLow,
|
||||
ReferenceId = item.ReferenceId,
|
||||
LatestLog = latestLog
|
||||
};
|
||||
|
||||
devices.Add(device);
|
||||
}
|
||||
return new OkObjectResult(devices);
|
||||
}
|
||||
|
||||
@ -45,12 +60,10 @@ namespace Api.BusinessLogic
|
||||
/// <returns>returns true in a OkObjectResult and if there is some error it returns a ConflictObjectResult and a message that explain the reason</returns>
|
||||
public async Task<IActionResult> AddDevice(string referenceId, int userId)
|
||||
{
|
||||
var profile = await _dbAccess.ReadUser(userId);
|
||||
var user = await _dbAccess.ReadUserDetails(userId);
|
||||
var possibleDevice = _dbAccess.ReadDevice(referenceId);
|
||||
if (possibleDevice != null) { return new ConflictObjectResult(new { message = "Device with given referenceId already exists" }); }
|
||||
|
||||
|
||||
if (profile == null) { return new ConflictObjectResult(new { message = "Could not find user" }); }
|
||||
if (user == null) { return new ConflictObjectResult(new { message = "Could not find user" }); }
|
||||
|
||||
Device device = new Device
|
||||
{
|
||||
@ -61,8 +74,49 @@ namespace Api.BusinessLogic
|
||||
Logs = new List<TemperatureLogs>(),
|
||||
};
|
||||
|
||||
user.Devices.Add(device);
|
||||
|
||||
return await _dbAccess.CreateDevice(device, userId);
|
||||
return await _dbAccess.CreateDevice(user);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the deviceId matches a device
|
||||
/// </summary>
|
||||
/// <param name="device">The updated info</param>
|
||||
/// <param name="deviceId">The device to be edited</param>
|
||||
/// <returns>returns the updated device in a OkObjectResult and if there is some error it returns a ConflictObjectResult and a message that explain the reason</returns>
|
||||
public async Task<IActionResult> EditDevice(EditDeviceRequest request, int deviceId)
|
||||
{
|
||||
var device = await _dbAccess.ReadDevice(deviceId);
|
||||
if (device != null)
|
||||
{
|
||||
if (device.Name == "" || device.Name == null)
|
||||
return new ConflictObjectResult(new { message = "Please enter a name" });
|
||||
|
||||
device.Name = request.Name;
|
||||
device.TempLow = request.TempLow;
|
||||
device.TempHigh = request.TempHigh;
|
||||
|
||||
}
|
||||
|
||||
return await _dbAccess.EditDevice(device);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// deletes a device
|
||||
/// </summary>
|
||||
/// <param name="referenceId">the id used to delete</param>
|
||||
/// <param name="userId">Used for deleting device from devices list in user</param>
|
||||
/// <returns>returns OK</returns>
|
||||
public async Task<IActionResult> DeleteDevice(int deviceId)
|
||||
{
|
||||
var device = await _dbAccess.ReadDevice(deviceId);
|
||||
if (device != null)
|
||||
{
|
||||
return await _dbAccess.DeleteDevice(device);
|
||||
|
||||
}
|
||||
return new ConflictObjectResult(new { message = "Invalid user" });
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -83,27 +137,5 @@ namespace Api.BusinessLogic
|
||||
|
||||
return new OkObjectResult(logs);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the deviceId matches a device
|
||||
/// </summary>
|
||||
/// <param name="device">The updated info</param>
|
||||
/// <param name="deviceId">The device to be edited</param>
|
||||
/// <returns>returns the updated device in a OkObjectResult and if there is some error it returns a ConflictObjectResult and a message that explain the reason</returns>
|
||||
public async Task<IActionResult> EditDevice(EditDeviceRequest device, int deviceId)
|
||||
{
|
||||
return await _dbAccess.EditDevice(device, deviceId);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// deletes a device
|
||||
/// </summary>
|
||||
/// <param name="referenceId">the id used to delete</param>
|
||||
/// <param name="userId">Used for deleting device from devices list in user</param>
|
||||
/// <returns>returns OK</returns>
|
||||
public async Task<IActionResult> DeleteDevice(int deviceId, int userId)
|
||||
{
|
||||
return await _dbAccess.DeleteDevice(deviceId, userId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4,12 +4,14 @@ using Api.Models.Devices;
|
||||
using Api.Models.Users;
|
||||
using Microsoft.AspNetCore.Http.HttpResults;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.IdentityModel.Tokens;
|
||||
using System.IdentityModel.Tokens.Jwt;
|
||||
using System.Security.Claims;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using static System.Runtime.InteropServices.JavaScript.JSType;
|
||||
|
||||
namespace Api.BusinessLogic
|
||||
{
|
||||
@ -26,7 +28,7 @@ namespace Api.BusinessLogic
|
||||
|
||||
public async Task<IActionResult> getUser(int userId)
|
||||
{
|
||||
User user = await _dbAccess.getUser(userId);
|
||||
User user = await _dbAccess.ReadUser(userId);
|
||||
|
||||
if (user == null || user.Id == 0) { return new ConflictObjectResult(new { message = "Could not find user" }); }
|
||||
return new OkObjectResult(new { user.Id, user.UserName, user.Email });
|
||||
@ -40,29 +42,44 @@ namespace Api.BusinessLogic
|
||||
/// </summary>
|
||||
/// <param name="user">The new user</param>
|
||||
/// <returns>returns true in a OkObjectResult and if there is some error it returns a ConflictObjectResult and a message that explain the reason</returns>
|
||||
public async Task<IActionResult> RegisterUser(User user)
|
||||
public async Task<IActionResult> RegisterUser(CreateUserRequest request)
|
||||
{
|
||||
if (!new Regex(@".+@.+\..+").IsMatch(user.Email))
|
||||
if (!new Regex(@".+@.+\..+").IsMatch(request.Email))
|
||||
{
|
||||
return new ConflictObjectResult(new { message = "Invalid email address" });
|
||||
}
|
||||
|
||||
if (!PasswordSecurity(user.Password))
|
||||
if (!PasswordSecurity(request.Password))
|
||||
{
|
||||
return new ConflictObjectResult(new { message = "Password is not up to the security standard" });
|
||||
}
|
||||
|
||||
if (user.Devices == null)
|
||||
var users = await _dbAccess.ReadAllUsers();
|
||||
|
||||
foreach (var item in users)
|
||||
{
|
||||
user.Devices = new List<Device>();
|
||||
if (item.UserName == request.UserName)
|
||||
{
|
||||
return new ConflictObjectResult(new { message = "Username is already in use." });
|
||||
}
|
||||
|
||||
if (item.Email == request.Email)
|
||||
{
|
||||
return new ConflictObjectResult(new { message = "Email is being used already" });
|
||||
}
|
||||
}
|
||||
|
||||
string salt = Guid.NewGuid().ToString();
|
||||
string hashedPassword = ComputeHash(user.Password, SHA256.Create(), salt);
|
||||
|
||||
user.Salt = salt;
|
||||
user.Password = hashedPassword;
|
||||
string hashedPassword = ComputeHash(request.Password, SHA256.Create(), salt);
|
||||
|
||||
User user = new User
|
||||
{
|
||||
UserName = request.UserName,
|
||||
Email = request.Email,
|
||||
Password = hashedPassword,
|
||||
Salt = salt,
|
||||
Devices = new List<Device>()
|
||||
};
|
||||
return await _dbAccess.CreateUser(user);
|
||||
}
|
||||
|
||||
@ -75,7 +92,7 @@ namespace Api.BusinessLogic
|
||||
/// <returns>Returns a jwt token, username and userid</returns>
|
||||
public async Task<IActionResult> Login(Login login)
|
||||
{
|
||||
User user = await _dbAccess.Login(login);
|
||||
User user = await _dbAccess.ReadUserForLogin(login.EmailOrUsrn);
|
||||
|
||||
if (user == null || user.Id == 0) { return new ConflictObjectResult(new { message = "Could not find user" }); }
|
||||
|
||||
@ -84,8 +101,8 @@ namespace Api.BusinessLogic
|
||||
if (user.Password == hashedPassword)
|
||||
{
|
||||
var token = GenerateJwtToken(user);
|
||||
user.RefreshToken = Guid.NewGuid().ToString();
|
||||
_dbAccess.UpdatesRefreshToken(user.RefreshToken, user.Id);
|
||||
user = await UpdateRefreshToken(user);
|
||||
|
||||
return new OkObjectResult(new { token, user.UserName, user.Id, refreshToken = user.RefreshToken });
|
||||
}
|
||||
|
||||
@ -103,12 +120,42 @@ namespace Api.BusinessLogic
|
||||
/// <returns>returns the updated user in a OkObjectResult and if there is some error it returns a ConflictObjectResult and a message that explain the reason</returns>
|
||||
public async Task<IActionResult> EditProfile(EditUserRequest userRequest, int userId)
|
||||
{
|
||||
return await _dbAccess.UpdateUser(userRequest, userId);
|
||||
var profile = await _dbAccess.ReadUser(userId);
|
||||
var users = await _dbAccess.ReadAllUsers();
|
||||
|
||||
if (profile == null) { return new ConflictObjectResult(new { message = "User does not exist" }); }
|
||||
|
||||
foreach (var item in users)
|
||||
{
|
||||
if (item.UserName == userRequest.UserName && userId != item.Id)
|
||||
{
|
||||
return new ConflictObjectResult(new { message = "Username is already in use." });
|
||||
}
|
||||
|
||||
if (item.Email == userRequest.Email && userId != item.Id)
|
||||
{
|
||||
return new ConflictObjectResult(new { message = "Email is being used already" });
|
||||
}
|
||||
}
|
||||
|
||||
if (userRequest.Email == "" || userRequest.Email == null)
|
||||
return new ConflictObjectResult(new { message = "Please enter an email" });
|
||||
|
||||
if (userRequest.UserName == "" || userRequest.UserName == null)
|
||||
return new ConflictObjectResult(new { message = "Please enter a username" });
|
||||
|
||||
profile.Email = userRequest.Email;
|
||||
profile.UserName = userRequest.UserName;
|
||||
|
||||
|
||||
return await _dbAccess.UpdateUser(profile);
|
||||
}
|
||||
|
||||
public async Task<IActionResult> changePassword(ChangePasswordRequest passwordRequest, int userId)
|
||||
{
|
||||
var user = await _dbAccess.ReadUser(userId);
|
||||
if (user == null) { return new ConflictObjectResult(new { message = "User does not exist" }); }
|
||||
|
||||
|
||||
string hashedPassword = ComputeHash(passwordRequest.OldPassword, SHA256.Create(), user.Salt);
|
||||
|
||||
@ -124,8 +171,9 @@ namespace Api.BusinessLogic
|
||||
}
|
||||
|
||||
string hashedNewPassword = ComputeHash(passwordRequest.NewPassword, SHA256.Create(), user.Salt);
|
||||
user.Password = hashedNewPassword;
|
||||
|
||||
return await _dbAccess.updatePassword(hashedNewPassword, userId);
|
||||
return await _dbAccess.updatePassword(user);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -135,12 +183,19 @@ namespace Api.BusinessLogic
|
||||
/// <returns>returns the true in a OkObjectResult and if there is some error it returns a ConflictObjectResult and a message that explain the reason</returns>
|
||||
public async Task<IActionResult> DeleteUser(int userId)
|
||||
{
|
||||
return await _dbAccess.DeleteUser(userId);
|
||||
var user = await _dbAccess.ReadUserDetails(userId);
|
||||
if (user != null)
|
||||
{
|
||||
return await _dbAccess.DeleteUser(user);
|
||||
|
||||
}
|
||||
return new ConflictObjectResult(new { message = "Invalid user" });
|
||||
|
||||
}
|
||||
|
||||
public async Task<IActionResult> RefreshToken(string refreshToken)
|
||||
{
|
||||
User user = await _dbAccess.ReadUser(refreshToken);
|
||||
User user = await _dbAccess.ReadUserByRefreshToken(refreshToken);
|
||||
if (user == null) { return new ConflictObjectResult(new { message = "Could not match refreshtoken" }); }
|
||||
return new OkObjectResult(GenerateJwtToken(user));
|
||||
}
|
||||
@ -206,5 +261,13 @@ namespace Api.BusinessLogic
|
||||
|
||||
return new JwtSecurityTokenHandler().WriteToken(token);
|
||||
}
|
||||
|
||||
private async Task<User> UpdateRefreshToken(User user)
|
||||
{
|
||||
user.RefreshToken = Guid.NewGuid().ToString();
|
||||
user.RefreshTokenExpiresAt = DateTime.Now.AddDays(7);
|
||||
await _dbAccess.UpdateUser(user);
|
||||
return user;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -75,10 +75,10 @@ namespace Api.Controllers
|
||||
[HttpDelete("Delete/{deviceId}")]
|
||||
public async Task<IActionResult> DeleteDevice(int deviceId)
|
||||
{
|
||||
var claims = HttpContext.User.Claims;
|
||||
string userIdString = claims.FirstOrDefault(c => c.Type == ClaimTypes.NameIdentifier).Value;
|
||||
int userId = Convert.ToInt32(userIdString);
|
||||
return await _deviceLogic.DeleteDevice(deviceId, userId);
|
||||
//var claims = HttpContext.User.Claims;
|
||||
//string userIdString = claims.FirstOrDefault(c => c.Type == ClaimTypes.NameIdentifier).Value;
|
||||
//int userId = Convert.ToInt32(userIdString);
|
||||
return await _deviceLogic.DeleteDevice(deviceId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -36,7 +36,7 @@ namespace Api.Controllers
|
||||
|
||||
// Sends the user to userLogic
|
||||
[HttpPost("Create")]
|
||||
public async Task<IActionResult> CreateUser([FromBody] User user)
|
||||
public async Task<IActionResult> CreateUser([FromBody] CreateUserRequest user)
|
||||
{
|
||||
return await _userLogic.RegisterUser(user);
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ using Api.Models.Users;
|
||||
using Microsoft.AspNetCore.Http.HttpResults;
|
||||
using System.Collections.Generic;
|
||||
|
||||
|
||||
//All EF Core database calls
|
||||
namespace Api.DBAccess
|
||||
{
|
||||
public class DbAccess
|
||||
@ -18,82 +18,71 @@ namespace Api.DBAccess
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
public async Task<User> getUser(int userId)
|
||||
{
|
||||
return await _context.Users.FirstOrDefaultAsync(u => u.Id == userId);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a user using entityframework core
|
||||
/// Gets one user on id
|
||||
/// </summary>
|
||||
/// <param name="user">Need the entire user obj</param>
|
||||
/// <returns>returns true in a OkObjectResult and if there is some error it returns a ConflictObjectResult and a message that explain the reason</returns>
|
||||
public async Task<IActionResult> CreateUser(User user)
|
||||
{
|
||||
var users = await _context.Users.ToListAsync();
|
||||
|
||||
foreach (var item in users)
|
||||
{
|
||||
if (item.UserName == user.UserName)
|
||||
{
|
||||
return new ConflictObjectResult(new { message = "Username is already in use." });
|
||||
}
|
||||
|
||||
if (item.Email == user.Email)
|
||||
{
|
||||
return new ConflictObjectResult(new { message = "Email is being used already" });
|
||||
}
|
||||
}
|
||||
|
||||
_context.Users.Add(user);
|
||||
bool saved = await _context.SaveChangesAsync() == 1;
|
||||
|
||||
if (saved) { return new OkObjectResult(true); }
|
||||
|
||||
return new ConflictObjectResult(new { message = "Could not save to databse" });
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a user that matches either the email or username
|
||||
/// </summary>
|
||||
/// <param name="login">Has a username or email and a password here the password is not used</param>
|
||||
/// <returns>(user) that matches the login</returns>
|
||||
public async Task<User> Login(Login login)
|
||||
{
|
||||
User user = new User();
|
||||
if (!login.EmailOrUsrn.Contains("@"))
|
||||
{
|
||||
user = await _context.Users.FirstOrDefaultAsync(u => u.UserName == login.EmailOrUsrn);
|
||||
}
|
||||
else
|
||||
{
|
||||
user = await _context.Users.FirstOrDefaultAsync(u => u.Email == login.EmailOrUsrn);
|
||||
}
|
||||
|
||||
if (user == null || user.Id == 0) { return new User(); }
|
||||
return user;
|
||||
}
|
||||
|
||||
// Returns a user according to userID
|
||||
/// <param name="userId">used to get the specific user</param>
|
||||
/// <returns>returns a user object from the database based on the given id</returns>
|
||||
public async Task<User> ReadUser(int userId)
|
||||
{
|
||||
return await _context.Users.FirstOrDefaultAsync(u => u.Id == userId);
|
||||
}
|
||||
|
||||
public async Task<User> ReadUserDetails(int userId)
|
||||
{
|
||||
return await _context.Users
|
||||
.Include(u => u.Devices)
|
||||
.ThenInclude(u => u.Logs)
|
||||
.FirstOrDefaultAsync(u => u.Id == userId);
|
||||
}
|
||||
|
||||
// Returns a user according to refreshToken
|
||||
public async Task<User> ReadUser(string refreshToken)
|
||||
public async Task<User> ReadUserByRefreshToken(string refreshToken)
|
||||
{
|
||||
return await _context.Users.FirstOrDefaultAsync(u => u.RefreshToken == refreshToken);
|
||||
}
|
||||
|
||||
// Updates the refreshtoken saved in DB
|
||||
public async void UpdatesRefreshToken(string refreshToken, int userId)
|
||||
/// <summary>
|
||||
/// Used to check both email and login for the login.
|
||||
/// </summary>
|
||||
/// <param name="emailOrUsername">stores the input of username or email</param>
|
||||
/// <returns>returns a user object from the database based on the given email or username</returns>
|
||||
public async Task<User> ReadUserForLogin(string emailOrUsername)
|
||||
{
|
||||
var user = await _context.Users.FirstOrDefaultAsync(u => u.Id == userId);
|
||||
if (emailOrUsername.Contains("@"))
|
||||
{
|
||||
return await _context.Users.FirstOrDefaultAsync(u => u.Email == emailOrUsername);
|
||||
}
|
||||
else
|
||||
{
|
||||
return await _context.Users.FirstOrDefaultAsync(u => u.UserName == emailOrUsername);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets all users
|
||||
/// </summary>
|
||||
/// <returns>Return a list of users</returns>
|
||||
public async Task<List<User>> ReadAllUsers()
|
||||
{
|
||||
return await _context.Users.ToListAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a user
|
||||
/// </summary>
|
||||
/// <param name="user">Need the entire user obj</param>
|
||||
/// <returns>returns true in a OkObjectResult and if there is some error it returns a ConflictObjectResult and a message that explain the reason</returns>
|
||||
public async Task<IActionResult> CreateUser(User user)
|
||||
{
|
||||
_context.Users.Add(user);
|
||||
|
||||
bool saved = await _context.SaveChangesAsync() == 1;
|
||||
|
||||
if (saved) { return new OkObjectResult(true); }
|
||||
|
||||
return new ConflictObjectResult(new { message = "Could not save to database" });
|
||||
|
||||
user.RefreshToken = refreshToken;
|
||||
user.RefreshTokenExpiresAt = DateTime.Now.AddDays(7);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -102,55 +91,25 @@ namespace Api.DBAccess
|
||||
/// <param name="user">Contains the updated user info</param>
|
||||
/// <param name="userId">Has the id for the user that is to be updated</param>
|
||||
/// <returns>returns the updated user in a OkObjectResult and if there is some error it returns a ConflictObjectResult and a message that explain the reason</returns>
|
||||
public async Task<IActionResult> UpdateUser(EditUserRequest user, int userId)
|
||||
public async Task<IActionResult> UpdateUser(User user)
|
||||
{
|
||||
var profile = await _context.Users.FirstOrDefaultAsync(u => u.Id == userId);
|
||||
var users = await _context.Users.ToListAsync();
|
||||
|
||||
if (profile == null) { return new ConflictObjectResult(new { message = "User does not exist" }); }
|
||||
|
||||
foreach (var item in users)
|
||||
{
|
||||
if (item.UserName == user.UserName && userId != item.Id)
|
||||
{
|
||||
return new ConflictObjectResult(new { message = "Username is already in use." });
|
||||
}
|
||||
|
||||
if (item.Email == user.Email && userId != item.Id)
|
||||
{
|
||||
return new ConflictObjectResult(new { message = "Email is being used already" });
|
||||
}
|
||||
}
|
||||
|
||||
if(user.Email == "" || user.Email == null)
|
||||
return new ConflictObjectResult(new { message = "Please enter an email" });
|
||||
|
||||
if (user.UserName == "" || user.UserName == null)
|
||||
return new ConflictObjectResult(new { message = "Please enter a username" });
|
||||
|
||||
profile.Email = user.Email;
|
||||
profile.UserName = user.UserName;
|
||||
|
||||
|
||||
_context.Entry(user).State = EntityState.Modified;
|
||||
|
||||
bool saved = await _context.SaveChangesAsync() == 1;
|
||||
|
||||
if (saved) { return new OkObjectResult(profile); }
|
||||
if (saved) { return new OkObjectResult(user);}
|
||||
|
||||
return new ConflictObjectResult(new { message = "Could not save to database" });
|
||||
|
||||
}
|
||||
|
||||
public async Task<IActionResult> updatePassword(string newPassword, int userId)
|
||||
public async Task<IActionResult> updatePassword(User user)
|
||||
{
|
||||
var profile = await _context.Users.FirstOrDefaultAsync(u => u.Id == userId);
|
||||
|
||||
if (profile == null) { return new ConflictObjectResult(new { message = "User does not exist" }); }
|
||||
|
||||
profile.Password = newPassword;
|
||||
_context.Entry(user).State = EntityState.Modified;
|
||||
|
||||
bool saved = await _context.SaveChangesAsync() == 1;
|
||||
|
||||
if (saved) { return new OkObjectResult(profile); }
|
||||
if (saved) { return new OkObjectResult(user); }
|
||||
|
||||
return new ConflictObjectResult(new { message = "Could not save to database" });
|
||||
}
|
||||
@ -160,90 +119,50 @@ namespace Api.DBAccess
|
||||
/// </summary>
|
||||
/// <param name="userId">The Id of the user that is to be deleted</param>
|
||||
/// <returns>returns true in a OkObjectResult and if there is some error it returns a ConflictObjectResult and a message that explain the reason</returns>
|
||||
public async Task<IActionResult> DeleteUser(int userId)
|
||||
public async Task<IActionResult> DeleteUser(User user)
|
||||
{
|
||||
var user = await _context.Users.Include(u => u.Devices).FirstOrDefaultAsync(u => u.Id == userId);
|
||||
if (user != null)
|
||||
{
|
||||
if (user.Devices != null && user.Devices.Count > 0)
|
||||
{
|
||||
foreach (var item in user.Devices)
|
||||
{
|
||||
var device = await _context.Devices.Include(d => d.Logs).FirstOrDefaultAsync(d => d.Id == item.Id);
|
||||
if (device != null) { _context.Devices.Remove(device); }
|
||||
}
|
||||
}
|
||||
_context.Users.Remove(user);
|
||||
bool saved = await _context.SaveChangesAsync() >= 0;
|
||||
|
||||
if (saved) { return new OkObjectResult(saved); }
|
||||
|
||||
return new ConflictObjectResult(new { message = "Could not save to database" });
|
||||
}
|
||||
return new ConflictObjectResult(new { message = "Invalid user" });
|
||||
}
|
||||
|
||||
// Returns devices according to userID
|
||||
public async Task<List<GetDeviceDTO>> ReadDevices(int userId)
|
||||
{
|
||||
var user = await _context.Users.Include(u => u.Devices).ThenInclude(u => u.Logs).FirstOrDefaultAsync(u => u.Id == userId);
|
||||
|
||||
if (user == null || user.Devices == null) { return new List<GetDeviceDTO>(); }
|
||||
|
||||
List<GetDeviceDTO> devices = new List<GetDeviceDTO>();
|
||||
|
||||
foreach (var item in user.Devices)
|
||||
{
|
||||
var latestLog = item.Logs?.OrderByDescending(log => log.Date).FirstOrDefault(); // Get the latest log
|
||||
GetDeviceDTO device = new GetDeviceDTO
|
||||
{
|
||||
Id = item.Id,
|
||||
Name = item.Name,
|
||||
TempHigh = item.TempHigh,
|
||||
TempLow = item.TempLow,
|
||||
ReferenceId = item.ReferenceId,
|
||||
LatestLog = latestLog
|
||||
};
|
||||
|
||||
devices.Add(device);
|
||||
}
|
||||
|
||||
return devices;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a user using entityframework core
|
||||
/// </summary>
|
||||
/// <param name="device">The device that is going to be created</param>
|
||||
/// <param name="userId">The user that owns the device</param>
|
||||
/// <returns>returns the true in a OkObjectResult and if there is some error it returns a ConflictObjectResult and a message that explain the reason</returns>
|
||||
public async Task<IActionResult> CreateDevice(Device device, int userId)
|
||||
{
|
||||
var user = await _context.Users.Include(u => u.Devices).FirstOrDefaultAsync(u => u.Id == userId);
|
||||
|
||||
if (user == null || user.Devices == null) { return new ConflictObjectResult(new { message = "User did not have a device list" }); }
|
||||
|
||||
user.Devices.Add(device);
|
||||
|
||||
bool saved = await _context.SaveChangesAsync() == 1;
|
||||
_context.Users.Remove(user);
|
||||
bool saved = await _context.SaveChangesAsync() >= 0;
|
||||
|
||||
if (saved) { return new OkObjectResult(saved); }
|
||||
|
||||
return new ConflictObjectResult(new { message = "Could not save to database" });
|
||||
}
|
||||
|
||||
// Returns all devices
|
||||
public List<Device> ReadDevices()
|
||||
{
|
||||
return _context.Devices.ToList();
|
||||
}
|
||||
|
||||
// Returns a device according to deviceId
|
||||
public async Task<Device> ReadDevice(int deviceId)
|
||||
{
|
||||
return await _context.Devices.FirstOrDefaultAsync(d => d.Id == deviceId);
|
||||
}
|
||||
|
||||
// Returns a device according to refenreId
|
||||
// Returns a device according to referenceId
|
||||
public Device ReadDevice(string referenceId)
|
||||
{
|
||||
return _context.Devices.FirstOrDefault(d => d.ReferenceId == referenceId);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a user using entityframework core
|
||||
/// </summary>
|
||||
/// <param name="device">The device that is going to be created</param>
|
||||
/// <param name="userId">The user that owns the device</param>
|
||||
/// <returns>returns the true in a OkObjectResult and if there is some error it returns a ConflictObjectResult and a message that explain the reason</returns>
|
||||
public async Task<IActionResult> CreateDevice(User user)
|
||||
{
|
||||
_context.Entry(user).State = EntityState.Modified;
|
||||
|
||||
bool saved = await _context.SaveChangesAsync() == 2;
|
||||
|
||||
if (saved) { return new OkObjectResult(user.Id); }
|
||||
|
||||
return new ConflictObjectResult(new { message = "Could not save to database" });
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates a device in the database
|
||||
@ -251,62 +170,25 @@ namespace Api.DBAccess
|
||||
/// <param name="request">Contains the updated device info</param>
|
||||
/// <param name="referenceId">Has the id for the device that is to be updated</param>
|
||||
/// <returns>returns the updated device in a OkObjectResult and if there is some error it returns a ConflictObjectResult and a message that explain the reason</returns>
|
||||
public async Task<IActionResult> EditDevice(EditDeviceRequest request, int deviceId)
|
||||
public async Task<IActionResult> EditDevice(Device device)
|
||||
{
|
||||
var device = await _context.Devices.FirstOrDefaultAsync(d => d.Id == deviceId);
|
||||
if (device != null)
|
||||
{
|
||||
if (device.Name == "" || device.Name == null)
|
||||
return new ConflictObjectResult(new { message = "Please enter a name" });
|
||||
_context.Entry(device).State = EntityState.Modified;
|
||||
|
||||
bool saved = await _context.SaveChangesAsync() == 1;
|
||||
|
||||
device.Name = request.Name;
|
||||
device.TempLow = request.TempLow;
|
||||
device.TempHigh = request.TempHigh;
|
||||
if (saved) { return new OkObjectResult(device); }
|
||||
|
||||
bool saved = await _context.SaveChangesAsync() >= 0;
|
||||
|
||||
if (saved) { return new OkObjectResult(saved); }
|
||||
|
||||
return new ConflictObjectResult(new { message = "Could not save to database" });
|
||||
}
|
||||
return new ConflictObjectResult(new { message = "Invalid device. May already be deleted" });
|
||||
return new ConflictObjectResult(new { message = "Could not save to database" });
|
||||
}
|
||||
|
||||
public async Task<IActionResult> DeleteDevice(int deviceId, int userId)
|
||||
public async Task<IActionResult> DeleteDevice(Device device)
|
||||
{
|
||||
var user = await _context.Users
|
||||
.Include(u => u.Devices) // Ensure devices are loaded
|
||||
.FirstOrDefaultAsync(u => u.Id == userId);
|
||||
_context.Devices.Remove(device);
|
||||
bool saved = await _context.SaveChangesAsync() >= 0;
|
||||
|
||||
if (user == null)
|
||||
{
|
||||
return new NotFoundObjectResult(new { message = "User not found" });
|
||||
}
|
||||
if (saved) { return new OkObjectResult(saved); }
|
||||
|
||||
var device = user.Devices?.FirstOrDefault(d => d.Id == deviceId);
|
||||
|
||||
if (device != null || user.Devices != null)
|
||||
{
|
||||
user.Devices.Remove(device);
|
||||
bool userDeviceDeleted = await _context.SaveChangesAsync() > 0;
|
||||
if (userDeviceDeleted)
|
||||
{
|
||||
_context.Devices.Remove(device);
|
||||
bool saved = await _context.SaveChangesAsync() > 0;
|
||||
|
||||
if (saved) return new OkObjectResult(new { message = "Device deleted successfully" });
|
||||
}
|
||||
|
||||
return new ConflictObjectResult(new { message = "Could not save to database" });
|
||||
}
|
||||
|
||||
return new NotFoundObjectResult(new { message = "Device not found or already deleted" });
|
||||
}
|
||||
|
||||
// Returns all devices
|
||||
public List<Device> ReadDevices()
|
||||
{
|
||||
return _context.Devices.ToList();
|
||||
return new ConflictObjectResult(new { message = "Could not save to database" });
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
138
backend/Api/Migrations/20250403144251_removeNullableLists.Designer.cs
generated
Normal file
138
backend/Api/Migrations/20250403144251_removeNullableLists.Designer.cs
generated
Normal file
@ -0,0 +1,138 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using Api;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Api.Migrations
|
||||
{
|
||||
[DbContext(typeof(DBContext))]
|
||||
[Migration("20250403144251_removeNullableLists")]
|
||||
partial class removeNullableLists
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder.HasAnnotation("ProductVersion", "9.0.3");
|
||||
|
||||
modelBuilder.Entity("Api.Models.Devices.Device", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("ReferenceId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<double>("TempHigh")
|
||||
.HasColumnType("REAL");
|
||||
|
||||
b.Property<double>("TempLow")
|
||||
.HasColumnType("REAL");
|
||||
|
||||
b.Property<int?>("UserId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("Devices");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Api.Models.TemperatureLogs", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<DateTime>("Date")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int?>("DeviceId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<double>("TempHigh")
|
||||
.HasColumnType("REAL");
|
||||
|
||||
b.Property<double>("TempLow")
|
||||
.HasColumnType("REAL");
|
||||
|
||||
b.Property<double>("Temperature")
|
||||
.HasColumnType("REAL");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("DeviceId");
|
||||
|
||||
b.ToTable("TemperatureLogs");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Api.Models.Users.User", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("Email")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Password")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("RefreshToken")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("RefreshTokenExpiresAt")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Salt")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("UserName")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("Users");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Api.Models.Devices.Device", b =>
|
||||
{
|
||||
b.HasOne("Api.Models.Users.User", null)
|
||||
.WithMany("Devices")
|
||||
.HasForeignKey("UserId");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Api.Models.TemperatureLogs", b =>
|
||||
{
|
||||
b.HasOne("Api.Models.Devices.Device", null)
|
||||
.WithMany("Logs")
|
||||
.HasForeignKey("DeviceId");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Api.Models.Devices.Device", b =>
|
||||
{
|
||||
b.Navigation("Logs");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Api.Models.Users.User", b =>
|
||||
{
|
||||
b.Navigation("Devices");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
22
backend/Api/Migrations/20250403144251_removeNullableLists.cs
Normal file
22
backend/Api/Migrations/20250403144251_removeNullableLists.cs
Normal file
@ -0,0 +1,22 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Api.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class removeNullableLists : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@ -12,6 +12,6 @@
|
||||
|
||||
public string? ReferenceId { get; set; }
|
||||
|
||||
public List<TemperatureLogs>? Logs { get; set; }
|
||||
public List<TemperatureLogs> Logs { get; set; }
|
||||
}
|
||||
}
|
||||
|
11
backend/Api/Models/Users/CreateUserRequest.cs
Normal file
11
backend/Api/Models/Users/CreateUserRequest.cs
Normal file
@ -0,0 +1,11 @@
|
||||
namespace Api.Models.Users
|
||||
{
|
||||
public class CreateUserRequest
|
||||
{
|
||||
public string UserName { get; set; }
|
||||
|
||||
public string Password { get; set; }
|
||||
|
||||
public string Email { get; set; }
|
||||
}
|
||||
}
|
@ -18,6 +18,6 @@ namespace Api.Models.Users
|
||||
|
||||
public DateTime RefreshTokenExpiresAt { get; set; }
|
||||
|
||||
public List<Device>? Devices { get; set; }
|
||||
public List<Device> Devices { get; set; }
|
||||
}
|
||||
}
|
||||
|
@ -38,10 +38,10 @@
|
||||
<form id="editForm">
|
||||
<div class="form-container">
|
||||
<label for="email"><b>Email</b></label>
|
||||
<input type="text" placeholder="Enter email "id="email">
|
||||
<input type="email" placeholder="Enter email "id="email" required>
|
||||
|
||||
<label for="uname"><b>Username</b></label>
|
||||
<input type="text" placeholder="Enter username" id="uname">
|
||||
<input type="text" placeholder="Enter username" id="uname" required>
|
||||
|
||||
<button id="submitEditBtn" type="submit">Save Changes</button>
|
||||
|
||||
|
@ -3,9 +3,7 @@ import { devices } from "../mockdata/devices.mockdata.js";
|
||||
import { logout } from "../shared/utils.js";
|
||||
|
||||
getDevices().then(res => {
|
||||
if(!res.message){
|
||||
buildTable(res)
|
||||
}
|
||||
buildTable(res)
|
||||
})
|
||||
|
||||
let selectedId = null; // Store the selected referenceId
|
||||
@ -33,11 +31,6 @@ function buildTable(data) {
|
||||
table.appendChild(row);
|
||||
});
|
||||
|
||||
|
||||
document.getElementById("addDevice").onclick = () => {
|
||||
document.getElementById("addModal").style.display = "block";
|
||||
}
|
||||
|
||||
// Attach click event to all trash buttons
|
||||
document.querySelectorAll(".trashBtn").forEach((btn) => {
|
||||
btn.onclick = function () {
|
||||
@ -60,6 +53,11 @@ function buildTable(data) {
|
||||
});
|
||||
}
|
||||
|
||||
document.getElementById("addDevice").onclick = () => {
|
||||
document.getElementById("referenceId").value = "";
|
||||
document.getElementById("addModal").style.display = "block";
|
||||
}
|
||||
|
||||
|
||||
document.querySelectorAll(".cancelbtn").forEach(button => {
|
||||
button.onclick = () => {
|
||||
@ -72,15 +70,27 @@ document.querySelectorAll(".cancelbtn").forEach(button => {
|
||||
// Delete button logic
|
||||
document.getElementById("deletebtn").onclick = () => {
|
||||
if (selectedId) {
|
||||
deleteDevice(selectedId); // Call delete function with referenceId
|
||||
window.location.reload();
|
||||
deleteDevice(selectedId).then((response) => {
|
||||
if (response?.error) {
|
||||
document.getElementById("form-error").innerText = response.error;
|
||||
document.getElementById("form-error").style.display = "block";
|
||||
return;
|
||||
}
|
||||
window.location.reload();
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
document.getElementById("addbtn").onclick = () => {
|
||||
const referenceId = document.getElementById("referenceId").value;
|
||||
add(referenceId); // Call delete function with referenceId
|
||||
window.location.reload();
|
||||
add(referenceId).then((response) => {
|
||||
if (response?.error) {
|
||||
document.getElementById("form-error").innerText = response.error;
|
||||
document.getElementById("form-error").style.display = "block";
|
||||
return;
|
||||
}
|
||||
window.location.reload();
|
||||
});
|
||||
};
|
||||
|
||||
document.getElementById("editbtn").onclick = () => {
|
||||
@ -96,7 +106,7 @@ document.getElementById("editbtn").onclick = () => {
|
||||
document.getElementById("form-error").style.display = "block";
|
||||
return;
|
||||
}
|
||||
location.href = "/devices";
|
||||
window.location.reload();
|
||||
});
|
||||
}
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user