From d8b98ac5ccb4ccaea044872f56a53857d6f2703b Mon Sep 17 00:00:00 2001 From: quentin Date: Mon, 15 Jul 2024 13:23:58 -0500 Subject: [PATCH] added UserAuthentication --- .../GrantNames/UserGrantNames.cs | 18 ++++ .../Interfaces/IUserAuthentication.cs | 9 ++ API/Authentication/UserAuthentication.cs | 87 +++++++++++++++++++ API/Controllers/UserController.cs | 2 +- API/Program.cs | 7 +- API/Services/UserService.cs | 4 +- 6 files changed, 123 insertions(+), 4 deletions(-) create mode 100644 API/Authentication/GrantNames/UserGrantNames.cs create mode 100644 API/Authentication/Interfaces/IUserAuthentication.cs create mode 100644 API/Authentication/UserAuthentication.cs diff --git a/API/Authentication/GrantNames/UserGrantNames.cs b/API/Authentication/GrantNames/UserGrantNames.cs new file mode 100644 index 0000000..1110a96 --- /dev/null +++ b/API/Authentication/GrantNames/UserGrantNames.cs @@ -0,0 +1,18 @@ +namespace API.Authentication.GrantNames +{ + public static class UserGrantNames + { + public const string CanGetAll = "api.user.get.all"; + public const string CanGetAny = "api.user.get.any"; + public const string CanGet = "api.user.get"; + public const string CanAdd = "api.user.add"; + public const string CanUpdateAny = "api.user.update.any"; + public const string CanUpdate = "api.user.update"; + public const string CanUpdateSelf = "api.user.update.self"; + public const string CanUpdateNames = "api.user.update.names"; + public const string CanUpdatePhoneNumber = "api.user.update.phoneNumber"; + public const string CanUpdatePermission = "api.user.update.permission"; + public const string CanDeleteAny = "api.user.delete.any"; + public const string CanDelete = "api.user.delete"; + } +} diff --git a/API/Authentication/Interfaces/IUserAuthentication.cs b/API/Authentication/Interfaces/IUserAuthentication.cs new file mode 100644 index 0000000..91a7ed5 --- /dev/null +++ b/API/Authentication/Interfaces/IUserAuthentication.cs @@ -0,0 +1,9 @@ +using API.DTO.Base; +using DAL.Models; + +namespace API.Authentication.Interfaces +{ + public interface IUserAuthentication : IGenericAuthentication + { + } +} diff --git a/API/Authentication/UserAuthentication.cs b/API/Authentication/UserAuthentication.cs new file mode 100644 index 0000000..901d759 --- /dev/null +++ b/API/Authentication/UserAuthentication.cs @@ -0,0 +1,87 @@ +using API.Authentication.GrantNames; +using API.Authentication.Interfaces; +using API.DTO.Base; +using API.Services; +using DAL.Models; + +namespace API.Authentication +{ + public class UserAuthentication : IUserAuthentication + { + private readonly GrantService _grantService; + private readonly ILogger _logger; + private readonly UserService _userService; + public UserAuthentication(ILogger logger, GrantService grantService, UserService userService) + { + _logger = logger; + _grantService = grantService; + _userService = userService; + } + + public bool canGetAll(User user) + { + return _grantService.hasGrant(user.permissionId, UserGrantNames.CanGetAll); + } + public bool canGet(User model, User user) + { + return _grantService.hasGrant(user.permissionId, UserGrantNames.CanGetAny) || + _grantService.getULongValues(user.permissionId, UserGrantNames.CanGet).Exists(x => x == model.id); + } + public bool canAdd(UserDTO item, User user) + { + return _grantService.hasGrant(user.permissionId, UserGrantNames.CanAdd); + } + + // todo this needs to be made much better + public bool canUpdate(User model, User user) + { + User origUser; + if (model.id == user.id) + { + if (!_grantService.hasGrant(user.permissionId, UserGrantNames.CanUpdateSelf) + || !_grantService.hasGrant(user.permissionId, UserGrantNames.CanUpdateAny) + || !_grantService.getULongValues(user.permissionId, UserGrantNames.CanUpdate).Exists(x => x == model.id) + ) + return false; + + // Don't let the user change their own permissionId + if (model.permissionId != user.permissionId) + return false; + origUser = user; + } + else + { + origUser = _userService.getNoAuthentication(model.id) ?? throw new InvalidOperationException("Model is null."); + } + + if (origUser.permissionId != model.permissionId) + { + if (!_grantService.hasGrant(user.permissionId, UserGrantNames.CanUpdatePermission)) + return false; + } + + if (origUser.firstName != user.firstName || origUser.lastName != user.lastName) + { + if (!_grantService.hasGrant(user.permissionId, UserGrantNames.CanUpdateNames)) + return false; + } + + if (origUser.phoneNumber != user.phoneNumber) + { + if (!_grantService.hasGrant(user.permissionId, UserGrantNames.CanUpdatePhoneNumber)) + return false; + } + + return _grantService.hasGrant(user.permissionId, UserGrantNames.CanUpdateAny) + || model.id == user.id && + _grantService.hasGrant(user.permissionId, UserGrantNames.CanUpdateSelf) + || _grantService.getULongValues(user.permissionId, UserGrantNames.CanUpdate).Exists(x => x == model.id); + } + public bool canDelete(User model, User user) + { + return (_grantService.hasGrant(user.permissionId, UserGrantNames.CanDeleteAny) || + _grantService.getULongValues(user.permissionId, UserGrantNames.CanDelete).Exists(x => x == model.id)) + && model.id != user.id; + } + } +} diff --git a/API/Controllers/UserController.cs b/API/Controllers/UserController.cs index 6953837..3e4ca5f 100644 --- a/API/Controllers/UserController.cs +++ b/API/Controllers/UserController.cs @@ -10,7 +10,7 @@ namespace API.Controllers { [ApiController] [Route("api/v1/[controller]")] - public class UserController : CRUDBase + public class UserController : CRUDBase { public UserController(ILogger logger, UserService userService, UserService service) : base(logger, userService, service) { diff --git a/API/Program.cs b/API/Program.cs index 8ab0673..b5c4924 100644 --- a/API/Program.cs +++ b/API/Program.cs @@ -45,7 +45,7 @@ namespace API { ILogger logger = options.GetRequiredService>(); SASGContext context = options.GetRequiredService(); - IYesAuthentication authentication = options.GetRequiredService(); + IUserAuthentication authentication = options.GetRequiredService(); PermissionService permissionService = options.GetRequiredService(); ulong defaultUserPermission = UInt64.Parse(builder.Configuration["defaultUserPermission"] ?? throw new InvalidOperationException("defaultUserPermission is null")); @@ -55,6 +55,11 @@ namespace API builder.Services.AddTransient(); builder.Services.AddTransient(); + builder.Services.AddTransient(); + builder.Services.AddTransient(); + builder.Services.AddTransient(); + builder.Services.AddTransient(); + builder.Services.AddTransient(); builder.Services.AddTransient(); diff --git a/API/Services/UserService.cs b/API/Services/UserService.cs index 88ad6f9..012c48d 100644 --- a/API/Services/UserService.cs +++ b/API/Services/UserService.cs @@ -7,11 +7,11 @@ using DAL.Models.Audits; namespace API.Services { - public class UserService : ServiceBase + public class UserService : ServiceBase { private readonly ulong _defaultUserPermission; private readonly PermissionService _permissionService; - public UserService(ILogger logger, SASGContext context, IYesAuthentication auth, PermissionService permissionService, ulong defaultUserPermission) : base(logger, context, auth) + public UserService(ILogger logger, SASGContext context, IUserAuthentication auth, PermissionService permissionService, ulong defaultUserPermission) : base(logger, context, auth) { _permissionService = permissionService; _defaultUserPermission = defaultUserPermission;