device and profile works with changed structure

This commit is contained in:
LilleBRG 2025-04-03 17:29:51 +02:00
parent c1fbebe0da
commit c91aa4b278
12 changed files with 442 additions and 284 deletions

View File

@ -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);
}
}
}

View File

@ -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;
}
}
}

View File

@ -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);
}
}
}

View File

@ -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);
}

View File

@ -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>

View 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
}
}
}

View 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)
{
}
}
}

View File

@ -12,6 +12,6 @@
public string? ReferenceId { get; set; }
public List<TemperatureLogs>? Logs { get; set; }
public List<TemperatureLogs> Logs { get; set; }
}
}

View 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; }
}
}

View File

@ -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; }
}
}

View File

@ -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>

View File

@ -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();
});
}
};