diff --git a/DigitalData.UserManager.API/Controllers/AuthController.cs b/DigitalData.UserManager.API/Controllers/AuthController.cs index cfd43e6..7a350ea 100644 --- a/DigitalData.UserManager.API/Controllers/AuthController.cs +++ b/DigitalData.UserManager.API/Controllers/AuthController.cs @@ -11,148 +11,147 @@ using DigitalData.Core.Abstractions.Application; using Microsoft.Extensions.Localization; using DigitalData.Core.DTO; -namespace DigitalData.UserManager.API.Controllers +namespace DigitalData.UserManager.API.Controllers; + +[Route("api/[controller]")] +public class AuthController : ControllerBase { - [Route("api/[controller]")] - public class AuthController : ControllerBase + private readonly IUserService _userService; + private readonly IGroupOfUserService _gouService; + private readonly IDirectorySearchService _dirSearchService; + private readonly IStringLocalizer _localizer; + private readonly ILogger _logger; + private readonly IConfiguration _config; + public AuthController(IUserService userService, IGroupOfUserService gouService, IDirectorySearchService directorySearchService, IStringLocalizer localizer, ILogger logger, IConfiguration configuration) { - private readonly IUserService _userService; - private readonly IGroupOfUserService _gouService; - private readonly IDirectorySearchService _dirSearchService; - private readonly IStringLocalizer _localizer; - private readonly ILogger _logger; - private readonly IConfiguration _config; - public AuthController(IUserService userService, IGroupOfUserService gouService, IDirectorySearchService directorySearchService, IStringLocalizer localizer, ILogger logger, IConfiguration configuration) - { - _userService = userService; - _gouService = gouService; - _dirSearchService = directorySearchService; - _localizer = localizer; - _logger = logger; - _config = configuration; - } + _userService = userService; + _gouService = gouService; + _dirSearchService = directorySearchService; + _localizer = localizer; + _logger = logger; + _config = configuration; + } - [AllowAnonymous] - [HttpGet("check")] - public IActionResult CheckAuthentication() + [AllowAnonymous] + [HttpGet("check")] + public IActionResult CheckAuthentication() + { + try { - try - { - return Ok(User.Identity?.IsAuthenticated ?? false); - } - catch(Exception ex) - { - _logger.LogError(ex, "{Message}", ex.Message); - return StatusCode(StatusCodes.Status500InternalServerError); - } + return Ok(User.Identity?.IsAuthenticated ?? false); } - - [AllowAnonymous] - [HttpPost("login")] - public async Task Login([FromBody] LogInDto login) + catch(Exception ex) { - try + _logger.LogError(ex, "{Message}", ex.Message); + return StatusCode(StatusCodes.Status500InternalServerError); + } + } + + [AllowAnonymous] + [HttpPost("login")] + public async Task Login([FromBody] LogInDto login) + { + try + { + bool isValid = _dirSearchService.ValidateCredentials(login.Username, login.Password); + + if (!isValid) + return Unauthorized(Result.Fail().Message(_localizer[Key.UserNotFound])); + + var allowedGroupName = _config.GetSection("AllowedGroupName").Get() + ?? throw new InvalidOperationException("Allowed group names configuration is missing."); + + var gouMsg = await _gouService.HasGroup(login.Username, allowedGroupName, caseSensitive: false); + if (!gouMsg.IsSuccess) + return Unauthorized(Result.Fail().Message(_localizer[Key.UnauthorizedUser])); + + //find the user + var uRes = await _userService.ReadByUsernameAsync(login.Username); + if (!uRes.IsSuccess || uRes.Data is null) { - bool isValid = _dirSearchService.ValidateCredentials(login.Username, login.Password); + return Unauthorized(uRes); + } - if (!isValid) - return Unauthorized(Result.Fail().Message(_localizer[Key.UserNotFound])); + UserReadDto user = uRes.Data; - var allowedGroupName = _config.GetSection("AllowedGroupName").Get() - ?? throw new InvalidOperationException("Allowed group names configuration is missing."); + // Create claims + var claims = new List + { + new (ClaimTypes.NameIdentifier, user.Id.ToString()), + new (ClaimTypes.Name, user.Username), + new (ClaimTypes.Surname, user.Name ?? ""), + new (ClaimTypes.GivenName, user.Prename ?? ""), + new (ClaimTypes.Email, user.Email ?? ""), + new (ClaimTypes.Role, "PM_USER") + }; - var gouMsg = await _gouService.HasGroup(login.Username, allowedGroupName, caseSensitive: false); - if (!gouMsg.IsSuccess) - return Unauthorized(Result.Fail().Message(_localizer[Key.UnauthorizedUser])); - - //find the user - var uRes = await _userService.ReadByUsernameAsync(login.Username); - if (!uRes.IsSuccess || uRes.Data is null) - { - return Unauthorized(uRes); - } + // Create claimsIdentity + var claimsIdentity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme); - UserReadDto user = uRes.Data; - - // Create claims - var claims = new List + // Create authProperties + var authProperties = new AuthenticationProperties { - new (ClaimTypes.NameIdentifier, user.Id.ToString()), - new (ClaimTypes.Name, user.Username), - new (ClaimTypes.Surname, user.Name ?? ""), - new (ClaimTypes.GivenName, user.Prename ?? ""), - new (ClaimTypes.Email, user.Email ?? ""), - new (ClaimTypes.Role, "PM_USER") + IsPersistent = true, + AllowRefresh = true, + ExpiresUtc = DateTime.UtcNow.AddMinutes(60) }; - // Create claimsIdentity - var claimsIdentity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme); + // Sign in + await HttpContext.SignInAsync( + CookieAuthenticationDefaults.AuthenticationScheme, + new ClaimsPrincipal(claimsIdentity), + authProperties); - // Create authProperties - var authProperties = new AuthenticationProperties + _dirSearchService.SetSearchRootCache(user.Username, login.Password); + + return Ok(); + } + catch(Exception ex) + { + _logger.LogError(ex, "{Message}", ex.Message); + return StatusCode(StatusCodes.Status500InternalServerError); + } + } + + [Authorize] + [HttpGet("user")] + public async Task GetUserWithClaims() + { + try + { + // Extract the username from the Name claim. + string? username = User.Claims.FirstOrDefault(c => c.Type == ClaimTypes.Name)?.Value; + + if (string.IsNullOrEmpty(username)) + return Unauthorized(); + + return await _userService.ReadByUsernameAsync(username) + .ThenAsync(Ok, IActionResult (m, n) => { - IsPersistent = true, - AllowRefresh = true, - ExpiresUtc = DateTime.UtcNow.AddMinutes(60) - }; - - // Sign in - await HttpContext.SignInAsync( - CookieAuthenticationDefaults.AuthenticationScheme, - new ClaimsPrincipal(claimsIdentity), - authProperties); - - _dirSearchService.SetSearchRootCache(user.Username, login.Password); - - return Ok(); - } - catch(Exception ex) - { - _logger.LogError(ex, "{Message}", ex.Message); - return StatusCode(StatusCodes.Status500InternalServerError); - } + _logger.LogNotice(n); + return NotFound(Result.Fail().Message(_localizer[Key.UserNotFound])); + }); } - - [Authorize] - [HttpGet("user")] - public async Task GetUserWithClaims() + catch (Exception ex) { - try - { - // Extract the username from the Name claim. - string? username = User.Claims.FirstOrDefault(c => c.Type == ClaimTypes.Name)?.Value; - - if (string.IsNullOrEmpty(username)) - return Unauthorized(); - - return await _userService.ReadByUsernameAsync(username) - .ThenAsync(Ok, IActionResult (m, n) => - { - _logger.LogNotice(n); - return NotFound(Result.Fail().Message(_localizer[Key.UserNotFound])); - }); - } - catch (Exception ex) - { - _logger.LogError(ex, "{Message}", ex.Message); - return StatusCode(StatusCodes.Status500InternalServerError); - } + _logger.LogError(ex, "{Message}", ex.Message); + return StatusCode(StatusCodes.Status500InternalServerError); } + } - [Authorize] - [HttpPost("logout")] - public async Task Logout() + [Authorize] + [HttpPost("logout")] + public async Task Logout() + { + try { - try - { - await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme); - return Ok(); - } - catch(Exception ex) - { - _logger.LogError(ex, "{Message}", ex.Message); - return StatusCode(StatusCodes.Status500InternalServerError); - } + await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme); + return Ok(); + } + catch(Exception ex) + { + _logger.LogError(ex, "{Message}", ex.Message); + return StatusCode(StatusCodes.Status500InternalServerError); } } } \ No newline at end of file diff --git a/DigitalData.UserManager.API/Controllers/BaseAuthController.cs b/DigitalData.UserManager.API/Controllers/BaseAuthController.cs index 6d36161..89a38fb 100644 --- a/DigitalData.UserManager.API/Controllers/BaseAuthController.cs +++ b/DigitalData.UserManager.API/Controllers/BaseAuthController.cs @@ -7,41 +7,40 @@ using DigitalData.UserManager.Domain.Entities; using Microsoft.AspNetCore.Authorization; using System.Security.Claims; -namespace DigitalData.UserManager.API.Controllers +namespace DigitalData.UserManager.API.Controllers; + +[Authorize] +public class BaseAuthController : CRUDControllerBaseWithErrorHandling + where TCRUDService : IBaseService + where TCreateDto : BaseCreateDto + where TReadDto : class + where TUpdateDto : BaseUpdateDto + where TBaseEntity : BaseEntity { - [Authorize] - public class BaseAuthController : CRUDControllerBaseWithErrorHandling - where TCRUDService : IBaseService - where TCreateDto : BaseCreateDto - where TReadDto : class - where TUpdateDto : BaseUpdateDto - where TBaseEntity : BaseEntity + private readonly Lazy _lUserId; + + public BaseAuthController(ILogger logger, TCRUDService service, IUserService userService) : base(logger, service) { - private readonly Lazy _lUserId; - - public BaseAuthController(ILogger logger, TCRUDService service, IUserService userService) : base(logger, service) + _lUserId = new(() => { - _lUserId = new(() => - { - var idSt = User.FindFirstValue(ClaimTypes.NameIdentifier); - bool hasId = int.TryParse(idSt, out int id); - return hasId ? id : null; - }); + var idSt = User.FindFirstValue(ClaimTypes.NameIdentifier); + bool hasId = int.TryParse(idSt, out int id); + return hasId ? id : null; + }); - service.UserFactoryAsync = async () => - { - var id = _lUserId.Value; + service.UserFactoryAsync = async () => + { + var id = _lUserId.Value; - return id is int intId - ? await userService.ReadByIdAsync(intId).ThenAsync( - Success: res => res, - Fail: UserReadDto? (m, n) => - { - _logger.LogNotice(n); - return null; - }) - : null; - }; - } + return id is int intId + ? await userService.ReadByIdAsync(intId).ThenAsync( + Success: res => res, + Fail: UserReadDto? (m, n) => + { + _logger.LogNotice(n); + return null; + }) + : null; + }; } } \ No newline at end of file diff --git a/DigitalData.UserManager.API/Controllers/DirectoryController.cs b/DigitalData.UserManager.API/Controllers/DirectoryController.cs index cf62c6f..e9f41ca 100644 --- a/DigitalData.UserManager.API/Controllers/DirectoryController.cs +++ b/DigitalData.UserManager.API/Controllers/DirectoryController.cs @@ -10,226 +10,225 @@ using Microsoft.Extensions.Localization; using DigitalData.Core.DTO; using Microsoft.AspNetCore.Authorization; -namespace DigitalData.UserManager.API.Controllers +namespace DigitalData.UserManager.API.Controllers; + +[Route("api/[controller]")] +[SuppressMessage("Interoperability", "CA1416:Validate platform compatibility", Justification = "")] +[Authorize] +public class DirectoryController : ControllerBase { - [Route("api/[controller]")] - [SuppressMessage("Interoperability", "CA1416:Validate platform compatibility", Justification = "")] - [Authorize] - public class DirectoryController : ControllerBase + private readonly IUserService _userService; + private readonly IDirectorySearchService _dirSearchService; + private readonly Dictionary _customSearchFilters; + private readonly IStringLocalizer _localizer; + private readonly ILogger _logger; + + public DirectoryController(IConfiguration configuration, IStringLocalizer localizer, IUserService userService, IDirectorySearchService directorySearchService, ILogger logger) { - private readonly IUserService _userService; - private readonly IDirectorySearchService _dirSearchService; - private readonly Dictionary _customSearchFilters; - private readonly IStringLocalizer _localizer; - private readonly ILogger _logger; + _localizer = localizer; + _userService = userService; + _dirSearchService = directorySearchService; - public DirectoryController(IConfiguration configuration, IStringLocalizer localizer, IUserService userService, IDirectorySearchService directorySearchService, ILogger logger) + var customSearchFiltersSection = configuration.GetSection("DirectorySearch:CustomSearchFilters"); + _customSearchFilters = customSearchFiltersSection.Get>() ?? new(); + _logger = logger; + } + + [HttpGet("Root/{username}")] + public IActionResult GetRootOf(string username) + { + try { - _localizer = localizer; - _userService = userService; - _dirSearchService = directorySearchService; + var root = _dirSearchService.GetSearchRootCache(username); - var customSearchFiltersSection = configuration.GetSection("DirectorySearch:CustomSearchFilters"); - _customSearchFilters = customSearchFiltersSection.Get>() ?? new(); - _logger = logger; + return root is null ? NotFound() : Ok(new + { + guid = root.Guid, + nativeGuid = root.NativeGuid, + name = root.Name, + path = root.Path, + parentPath = root.Parent?.Path, + username = root.Username, + schemaClassName = root.SchemaClassName + }); } - - [HttpGet("Root/{username}")] - public IActionResult GetRootOf(string username) + catch (Exception ex) { - try - { - var root = _dirSearchService.GetSearchRootCache(username); - - return root is null ? NotFound() : Ok(new - { - guid = root.Guid, - nativeGuid = root.NativeGuid, - name = root.Name, - path = root.Path, - parentPath = root.Parent?.Path, - username = root.Username, - schemaClassName = root.SchemaClassName - }); - } - catch (Exception ex) - { - _logger.LogError(ex, "{Message}", ex.Message); - return StatusCode(StatusCodes.Status500InternalServerError); - } - } - - [HttpGet("CustomSearchFilter")] - public IActionResult GetAllCustomFilters(string? filtername) - { - try - { - if (filtername is null) - { - return Ok(_customSearchFilters); - } - else - { - _dirSearchService.CustomSearchFilters.TryGetValue(filtername, out string? filter); - return filter is null ? NotFound() : Ok(filter); - } - } - catch (Exception ex) - { - _logger.LogError(ex, "{Message}", ex.Message); - return StatusCode(StatusCodes.Status500InternalServerError); - } - } - - [HttpPost("CreateSearchRoot")] - public async Task CreateSearchRoot([FromBody] SearchRootCreateDto searchRootCreateDto) - { - try - { - var dirEntryUsername = searchRootCreateDto.DirEntryUsername ?? CurrentUser; - if (dirEntryUsername is null) - return Unauthorized(); - - bool isValid = _dirSearchService.ValidateCredentials(dirEntryUsername, searchRootCreateDto.DirEntryPassword); - - if (!isValid) - return Unauthorized(Result.Fail().Message(_localizer[Key.UserNotFound])); - - var userResult = await _userService.ReadByUsernameAsync(dirEntryUsername); - if (!userResult.IsSuccess || userResult.Data is null) - return Unauthorized(Result.Fail().Message(_localizer[Key.UserNotFoundInLocalDB])); - - _dirSearchService.SetSearchRootCache(userResult.Data.Username, searchRootCreateDto.DirEntryPassword); - return Ok(); - } - catch (Exception ex) - { - _logger.LogError(ex, "{Message}", ex.Message); - return StatusCode(StatusCodes.Status500InternalServerError); - } - } - - [HttpGet("SearchByFilter/{filter}")] - public IActionResult SearchByFilter([FromRoute] string filter, string? dirEntryUsername, params string[] propName) - { - try - { - dirEntryUsername ??= CurrentUser; - - if (dirEntryUsername is null) - return Unauthorized(); - - return _dirSearchService.FindAllByUserCache(dirEntryUsername, filter, properties: propName).Then(Ok, IActionResult (m, n) => - { - _logger.LogNotice(n); - return StatusCode(StatusCodes.Status424FailedDependency); - }); - } - catch (Exception ex) - { - _logger.LogError(ex, "{Message}", ex.Message); - return StatusCode(StatusCodes.Status500InternalServerError); - } - } - - [HttpGet("SearchByFilterName/{filterName}")] - public IActionResult SearchByFilterName([FromRoute] string filterName, string? dirEntryUsername, params string[] propName) - { - try - { - dirEntryUsername ??= CurrentUser; - - if (dirEntryUsername is null) - return Unauthorized(); - - _dirSearchService.CustomSearchFilters.TryGetValue(filterName, out string? filter); - - if (filter is null) - return NotFound($"The filter named {filterName} does not exist."); - - return _dirSearchService.FindAllByUserCache(dirEntryUsername, filter, properties: propName).Then(Ok, IActionResult (m, n) => - { - _logger.LogNotice(n); - return StatusCode(StatusCodes.Status424FailedDependency); - }); - } - catch (Exception ex) - { - _logger.LogError(ex, "{Message}", ex.Message); - return StatusCode(StatusCodes.Status500InternalServerError); - } - } - - [HttpGet("Group")] - public IActionResult GetGroups(string? dirEntryUsername, params string[] propName) - { - try - { - dirEntryUsername ??= CurrentUser; - - if (dirEntryUsername is null) - return Unauthorized(); - - _dirSearchService.CustomSearchFilters.TryGetValue("Group", out string? filter); - - if (filter is null) - throw new InvalidOperationException("The LDAP Group Search filter configuration is missing in your appsettings. Please ensure it's added under DirectorySearch:CustomSearchFilters:Group to enable group searches."); - - return _dirSearchService.FindAllByUserCache(username: dirEntryUsername, filter, properties: propName).Then(Ok, IActionResult (m, n) => - { - _logger.LogNotice(n); - return StatusCode(StatusCodes.Status424FailedDependency); - }); - } - catch (Exception ex) - { - _logger.LogError(ex, "{Message}", ex.Message); - return StatusCode(StatusCodes.Status500InternalServerError); - } - } - - [HttpGet("User")] - public IActionResult GetUsersByGroupName(string? dirEntryUsername, [FromQuery] string? groupName = null) - { - try - { - string[] propName = { "memberof", "samaccountname", "givenname", "sn", "mail" }; - dirEntryUsername ??= CurrentUser; - - if (dirEntryUsername is null) - return Unauthorized(); - - _dirSearchService.CustomSearchFilters.TryGetValue("User", out string? filter); - - if (filter is null) - throw new InvalidOperationException("The LDAP User Search filter configuration is missing in your appsettings. Please ensure it's added under DirectorySearch:CustomSearchFilters:User to enable group searches."); - - return _dirSearchService.FindAllByUserCache(username: dirEntryUsername, filter, properties: propName).Then( - Success: data => - { - if (groupName is not null) - data = data - .Where(rp => rp.PropertyNames.Cast().Contains("memberof") && - rp["memberof"].Cast().Any(ldapDir => ldapDir.Contains(groupName))) - .ToList(); - return Ok(data); - }, - Fail: IActionResult (m, n) => - { - _logger.LogNotice(n); - return StatusCode(StatusCodes.Status424FailedDependency); - }); - } - catch (Exception ex) - { - _logger.LogError(ex, "{Message}", ex.Message); - return StatusCode(StatusCodes.Status500InternalServerError); - } - } - - private string? CurrentUser - { - get => (HttpContext.User.Claims.FirstOrDefault(c => c.Type == ClaimTypes.Name)?.Value); + _logger.LogError(ex, "{Message}", ex.Message); + return StatusCode(StatusCodes.Status500InternalServerError); } } + + [HttpGet("CustomSearchFilter")] + public IActionResult GetAllCustomFilters(string? filtername) + { + try + { + if (filtername is null) + { + return Ok(_customSearchFilters); + } + else + { + _dirSearchService.CustomSearchFilters.TryGetValue(filtername, out string? filter); + return filter is null ? NotFound() : Ok(filter); + } + } + catch (Exception ex) + { + _logger.LogError(ex, "{Message}", ex.Message); + return StatusCode(StatusCodes.Status500InternalServerError); + } + } + + [HttpPost("CreateSearchRoot")] + public async Task CreateSearchRoot([FromBody] SearchRootCreateDto searchRootCreateDto) + { + try + { + var dirEntryUsername = searchRootCreateDto.DirEntryUsername ?? CurrentUser; + if (dirEntryUsername is null) + return Unauthorized(); + + bool isValid = _dirSearchService.ValidateCredentials(dirEntryUsername, searchRootCreateDto.DirEntryPassword); + + if (!isValid) + return Unauthorized(Result.Fail().Message(_localizer[Key.UserNotFound])); + + var userResult = await _userService.ReadByUsernameAsync(dirEntryUsername); + if (!userResult.IsSuccess || userResult.Data is null) + return Unauthorized(Result.Fail().Message(_localizer[Key.UserNotFoundInLocalDB])); + + _dirSearchService.SetSearchRootCache(userResult.Data.Username, searchRootCreateDto.DirEntryPassword); + return Ok(); + } + catch (Exception ex) + { + _logger.LogError(ex, "{Message}", ex.Message); + return StatusCode(StatusCodes.Status500InternalServerError); + } + } + + [HttpGet("SearchByFilter/{filter}")] + public IActionResult SearchByFilter([FromRoute] string filter, string? dirEntryUsername, params string[] propName) + { + try + { + dirEntryUsername ??= CurrentUser; + + if (dirEntryUsername is null) + return Unauthorized(); + + return _dirSearchService.FindAllByUserCache(dirEntryUsername, filter, properties: propName).Then(Ok, IActionResult (m, n) => + { + _logger.LogNotice(n); + return StatusCode(StatusCodes.Status424FailedDependency); + }); + } + catch (Exception ex) + { + _logger.LogError(ex, "{Message}", ex.Message); + return StatusCode(StatusCodes.Status500InternalServerError); + } + } + + [HttpGet("SearchByFilterName/{filterName}")] + public IActionResult SearchByFilterName([FromRoute] string filterName, string? dirEntryUsername, params string[] propName) + { + try + { + dirEntryUsername ??= CurrentUser; + + if (dirEntryUsername is null) + return Unauthorized(); + + _dirSearchService.CustomSearchFilters.TryGetValue(filterName, out string? filter); + + if (filter is null) + return NotFound($"The filter named {filterName} does not exist."); + + return _dirSearchService.FindAllByUserCache(dirEntryUsername, filter, properties: propName).Then(Ok, IActionResult (m, n) => + { + _logger.LogNotice(n); + return StatusCode(StatusCodes.Status424FailedDependency); + }); + } + catch (Exception ex) + { + _logger.LogError(ex, "{Message}", ex.Message); + return StatusCode(StatusCodes.Status500InternalServerError); + } + } + + [HttpGet("Group")] + public IActionResult GetGroups(string? dirEntryUsername, params string[] propName) + { + try + { + dirEntryUsername ??= CurrentUser; + + if (dirEntryUsername is null) + return Unauthorized(); + + _dirSearchService.CustomSearchFilters.TryGetValue("Group", out string? filter); + + if (filter is null) + throw new InvalidOperationException("The LDAP Group Search filter configuration is missing in your appsettings. Please ensure it's added under DirectorySearch:CustomSearchFilters:Group to enable group searches."); + + return _dirSearchService.FindAllByUserCache(username: dirEntryUsername, filter, properties: propName).Then(Ok, IActionResult (m, n) => + { + _logger.LogNotice(n); + return StatusCode(StatusCodes.Status424FailedDependency); + }); + } + catch (Exception ex) + { + _logger.LogError(ex, "{Message}", ex.Message); + return StatusCode(StatusCodes.Status500InternalServerError); + } + } + + [HttpGet("User")] + public IActionResult GetUsersByGroupName(string? dirEntryUsername, [FromQuery] string? groupName = null) + { + try + { + string[] propName = { "memberof", "samaccountname", "givenname", "sn", "mail" }; + dirEntryUsername ??= CurrentUser; + + if (dirEntryUsername is null) + return Unauthorized(); + + _dirSearchService.CustomSearchFilters.TryGetValue("User", out string? filter); + + if (filter is null) + throw new InvalidOperationException("The LDAP User Search filter configuration is missing in your appsettings. Please ensure it's added under DirectorySearch:CustomSearchFilters:User to enable group searches."); + + return _dirSearchService.FindAllByUserCache(username: dirEntryUsername, filter, properties: propName).Then( + Success: data => + { + if (groupName is not null) + data = data + .Where(rp => rp.PropertyNames.Cast().Contains("memberof") && + rp["memberof"].Cast().Any(ldapDir => ldapDir.Contains(groupName))) + .ToList(); + return Ok(data); + }, + Fail: IActionResult (m, n) => + { + _logger.LogNotice(n); + return StatusCode(StatusCodes.Status424FailedDependency); + }); + } + catch (Exception ex) + { + _logger.LogError(ex, "{Message}", ex.Message); + return StatusCode(StatusCodes.Status500InternalServerError); + } + } + + private string? CurrentUser + { + get => (HttpContext.User.Claims.FirstOrDefault(c => c.Type == ClaimTypes.Name)?.Value); + } } \ No newline at end of file diff --git a/DigitalData.UserManager.API/Controllers/EncryptionController.cs b/DigitalData.UserManager.API/Controllers/EncryptionController.cs index 5853269..435a98a 100644 --- a/DigitalData.UserManager.API/Controllers/EncryptionController.cs +++ b/DigitalData.UserManager.API/Controllers/EncryptionController.cs @@ -1,46 +1,44 @@ using DigitalData.UserManager.Application.Services; using DigitalData.UserManager.Application.Services.Options; using Microsoft.AspNetCore.Mvc; -using Microsoft.Extensions.Options; -namespace DigitalData.UserManager.API.Controllers +namespace DigitalData.UserManager.API.Controllers; + +[Route("api/[controller]")] +[ApiController] +public class EncryptionController : ControllerBase { - [Route("api/[controller]")] - [ApiController] - public class EncryptionController : ControllerBase + private readonly Encryptor _encryptor; + + public EncryptionController(Encryptor encryptor) { - private readonly Encryptor _encryptor; + _encryptor = encryptor; + } - public EncryptionController(Encryptor encryptor) - { - _encryptor = encryptor; - } + [HttpPost("encrypt")] + public IActionResult Encrypt([FromQuery] string plainText, [FromBody] EncryptionParameters? options = null) + { + string cipherText = options is null + ? _encryptor.Encrypt(plainText) + : Encryptor.Encrypt(plainText, options.Key, options.IV); - [HttpPost("encrypt")] - public IActionResult Encrypt([FromQuery] string plainText, [FromBody] EncryptionParameters? options = null) - { - string cipherText = options is null - ? _encryptor.Encrypt(plainText) - : Encryptor.Encrypt(plainText, options.Key, options.IV); + return Ok(cipherText); + } - return Ok(cipherText); - } + [HttpPost("decrypt")] + public IActionResult Decrypt([FromQuery] string cipherText, [FromBody] EncryptionParameters? options = null) + { + var plainText = options is null + ? _encryptor.Decrypt(cipherText) + : Encryptor.Decrypt(cipherText, options.Key, options.IV); - [HttpPost("decrypt")] - public IActionResult Decrypt([FromQuery] string cipherText, [FromBody] EncryptionParameters? options = null) - { - var plainText = options is null - ? _encryptor.Decrypt(cipherText) - : Encryptor.Decrypt(cipherText, options.Key, options.IV); + return Ok(plainText); + } - return Ok(plainText); - } - - [HttpGet] - public IActionResult Generate() - { - var param = Encryptor.GenerateParameters(); - return Ok(param); - } + [HttpGet] + public IActionResult Generate() + { + var param = Encryptor.GenerateParameters(); + return Ok(param); } } \ No newline at end of file diff --git a/DigitalData.UserManager.API/Controllers/GroupController.cs b/DigitalData.UserManager.API/Controllers/GroupController.cs index 5ac4611..8a5fcd0 100644 --- a/DigitalData.UserManager.API/Controllers/GroupController.cs +++ b/DigitalData.UserManager.API/Controllers/GroupController.cs @@ -5,39 +5,38 @@ using DigitalData.UserManager.Domain.Entities; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; -namespace DigitalData.UserManager.API.Controllers -{ - [Authorize] - public class GroupController : BaseAuthController - { - public GroupController(ILogger logger, IGroupService service, IUserService userService) : base(logger, service, userService) - { - } +namespace DigitalData.UserManager.API.Controllers; - [HttpPost("ByDir")] - public async Task CreateByDir(DirectoryGroupDto adGroup) +[Authorize] +public class GroupController : BaseAuthController +{ + public GroupController(ILogger logger, IGroupService service, IUserService userService) : base(logger, service, userService) + { + } + + [HttpPost("ByDir")] + public async Task CreateByDir(DirectoryGroupDto adGroup) + { + try { - try - { - return await _service.CreateAsync(adGroup).ThenAsync( - Success: id => - { - var createdResource = new { Id = id }; - var actionName = nameof(GetById); - var routeValues = new { id = createdResource.Id }; - return CreatedAtAction(actionName, routeValues, createdResource); - }, - Fail: IActionResult (m, n) => - { - _logger.LogNotice(n); - return BadRequest(); - }); - } - catch (Exception ex) - { - _logger.LogError(ex, "{Message}", ex.Message); - return StatusCode(StatusCodes.Status500InternalServerError); - } + return await _service.CreateAsync(adGroup).ThenAsync( + Success: id => + { + var createdResource = new { Id = id }; + var actionName = nameof(GetById); + var routeValues = new { id = createdResource.Id }; + return CreatedAtAction(actionName, routeValues, createdResource); + }, + Fail: IActionResult (m, n) => + { + _logger.LogNotice(n); + return BadRequest(); + }); + } + catch (Exception ex) + { + _logger.LogError(ex, "{Message}", ex.Message); + return StatusCode(StatusCodes.Status500InternalServerError); } } } \ No newline at end of file diff --git a/DigitalData.UserManager.API/Controllers/GroupOfUserController.cs b/DigitalData.UserManager.API/Controllers/GroupOfUserController.cs index 424cce3..f73db31 100644 --- a/DigitalData.UserManager.API/Controllers/GroupOfUserController.cs +++ b/DigitalData.UserManager.API/Controllers/GroupOfUserController.cs @@ -5,77 +5,76 @@ using DigitalData.UserManager.Domain.Entities; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; -namespace DigitalData.UserManager.API.Controllers +namespace DigitalData.UserManager.API.Controllers; + +[Authorize] +public class GroupOfUserController : BaseAuthController { - [Authorize] - public class GroupOfUserController : BaseAuthController + public GroupOfUserController(ILogger logger, IGroupOfUserService service, IUserService userService) : base(logger, service, userService) { - public GroupOfUserController(ILogger logger, IGroupOfUserService service, IUserService userService) : base(logger, service, userService) + } + + [HttpDelete] + public async Task Delete([FromQuery] int groupId, [FromQuery] int userId) + { + try { - } - - [HttpDelete] - public async Task Delete([FromQuery] int groupId, [FromQuery] int userId) - { - try + return await _service.DeleteAsyncByGroupUserId(groupId, userId).ThenAsync(Ok, IActionResult (m, n) => { - return await _service.DeleteAsyncByGroupUserId(groupId, userId).ThenAsync(Ok, IActionResult (m, n) => - { - _logger.LogNotice(n); - return StatusCode(StatusCodes.Status500InternalServerError); - }); - } - catch (Exception ex) - { - _logger.LogError(ex, "{Message}", ex.Message); + _logger.LogNotice(n); return StatusCode(StatusCodes.Status500InternalServerError); - } + }); } - - [NonAction] - public override Task GetAll() => base.GetAll(); - - [HttpGet] - public async Task GetAll([FromQuery]bool withUser = false, [FromQuery]bool withGroup = false, [FromQuery] string? username = null) + catch (Exception ex) { - try - { - if (username is not null) - return await _service.ReadByUsernameAsync(username).ThenAsync(Ok, IActionResult (m, n) => - { - _logger.LogNotice(n); - return NotFound(); - }); + _logger.LogError(ex, "{Message}", ex.Message); + return StatusCode(StatusCodes.Status500InternalServerError); + } + } - return await _service.ReadAllAsyncWith(withUser, withGroup).ThenAsync(Ok, IActionResult (m, n) => + [NonAction] + public override Task GetAll() => base.GetAll(); + + [HttpGet] + public async Task GetAll([FromQuery]bool withUser = false, [FromQuery]bool withGroup = false, [FromQuery] string? username = null) + { + try + { + if (username is not null) + return await _service.ReadByUsernameAsync(username).ThenAsync(Ok, IActionResult (m, n) => { _logger.LogNotice(n); return NotFound(); }); - } - catch(Exception ex) - { - _logger.LogError(ex, "{Message}", ex.Message); - return StatusCode(StatusCodes.Status500InternalServerError); - } - } - [HttpGet("Has")] - public async Task HasGroup([FromQuery] string username, [FromQuery] string groupname) + return await _service.ReadAllAsyncWith(withUser, withGroup).ThenAsync(Ok, IActionResult (m, n) => + { + _logger.LogNotice(n); + return NotFound(); + }); + } + catch(Exception ex) { - try + _logger.LogError(ex, "{Message}", ex.Message); + return StatusCode(StatusCodes.Status500InternalServerError); + } + } + + [HttpGet("Has")] + public async Task HasGroup([FromQuery] string username, [FromQuery] string groupname) + { + try + { + return await _service.HasGroup(username, groupname).ThenAsync(Ok, (m, n) => { - return await _service.HasGroup(username, groupname).ThenAsync(Ok, (m, n) => - { - _logger.LogNotice(n); - return StatusCode(StatusCodes.Status500InternalServerError); - }); - } - catch(Exception ex) - { - _logger.LogError(ex, "{Message}", ex.Message); + _logger.LogNotice(n); return StatusCode(StatusCodes.Status500InternalServerError); - } + }); + } + catch(Exception ex) + { + _logger.LogError(ex, "{Message}", ex.Message); + return StatusCode(StatusCodes.Status500InternalServerError); } } } \ No newline at end of file diff --git a/DigitalData.UserManager.API/Controllers/ModuleController.cs b/DigitalData.UserManager.API/Controllers/ModuleController.cs index 7b00ad1..f9cc319 100644 --- a/DigitalData.UserManager.API/Controllers/ModuleController.cs +++ b/DigitalData.UserManager.API/Controllers/ModuleController.cs @@ -4,13 +4,12 @@ using DigitalData.UserManager.Application.DTOs.Module; using DigitalData.UserManager.Domain.Entities; using Microsoft.AspNetCore.Authorization; -namespace DigitalData.UserManager.API.Controllers +namespace DigitalData.UserManager.API.Controllers; + +[Authorize] +public class ModuleController : ReadControllerBaseWithErrorHandling { - [Authorize] - public class ModuleController : ReadControllerBaseWithErrorHandling + public ModuleController(ILogger logger, IModuleService service) : base(logger, service) { - public ModuleController(ILogger logger, IModuleService service) : base(logger, service) - { - } } } \ No newline at end of file diff --git a/DigitalData.UserManager.API/Controllers/ModuleOfUserController.cs b/DigitalData.UserManager.API/Controllers/ModuleOfUserController.cs index 7a906c7..4ac96b7 100644 --- a/DigitalData.UserManager.API/Controllers/ModuleOfUserController.cs +++ b/DigitalData.UserManager.API/Controllers/ModuleOfUserController.cs @@ -6,48 +6,47 @@ using DigitalData.UserManager.Domain.Entities; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; -namespace DigitalData.UserManager.API.Controllers +namespace DigitalData.UserManager.API.Controllers; + +[Authorize] +public class ModuleOfUserController : CRUDControllerBaseWithErrorHandling { - [Authorize] - public class ModuleOfUserController : CRUDControllerBaseWithErrorHandling + public ModuleOfUserController(ILogger logger, IModuleOfUserService service) : base(logger, service) { - public ModuleOfUserController(ILogger logger, IModuleOfUserService service) : base(logger, service) - { - } + } - [NonAction] - public override Task GetAll() => base.GetAll(); + [NonAction] + public override Task GetAll() => base.GetAll(); - [HttpGet] - public async Task GetAll(string? username = null) - { + [HttpGet] + public async Task GetAll(string? username = null) + { - if (username is not null) - return await _service.ReadByUserAsync(username).ThenAsync(Ok, IActionResult (m, n) => - { - _logger.LogNotice(n); - return StatusCode(StatusCodes.Status500InternalServerError); - }); - - return await base.GetAll(); - } - - [HttpDelete] - public async Task Delete([FromQuery] int moduleId, [FromQuery]int userId) - { - try + if (username is not null) + return await _service.ReadByUserAsync(username).ThenAsync(Ok, IActionResult (m, n) => { - return await _service.DeleteAsyncByModuleUserId(moduleId, userId).ThenAsync(Ok, IActionResult (m, n) => - { - _logger.LogNotice(n); - return BadRequest(); - }); - } - catch(Exception ex) - { - _logger.LogError(ex, "{Message}", ex.Message); + _logger.LogNotice(n); return StatusCode(StatusCodes.Status500InternalServerError); - } + }); + + return await base.GetAll(); + } + + [HttpDelete] + public async Task Delete([FromQuery] int moduleId, [FromQuery]int userId) + { + try + { + return await _service.DeleteAsyncByModuleUserId(moduleId, userId).ThenAsync(Ok, IActionResult (m, n) => + { + _logger.LogNotice(n); + return BadRequest(); + }); + } + catch(Exception ex) + { + _logger.LogError(ex, "{Message}", ex.Message); + return StatusCode(StatusCodes.Status500InternalServerError); } } } \ No newline at end of file diff --git a/DigitalData.UserManager.API/Controllers/UserController.cs b/DigitalData.UserManager.API/Controllers/UserController.cs index 3a99ed7..ec25936 100644 --- a/DigitalData.UserManager.API/Controllers/UserController.cs +++ b/DigitalData.UserManager.API/Controllers/UserController.cs @@ -1,4 +1,3 @@ -using DigitalData.Core.API; using DigitalData.Core.DTO; using DigitalData.UserManager.Application.Contracts; using DigitalData.UserManager.Application.DTOs.User; @@ -6,95 +5,94 @@ using DigitalData.UserManager.Domain.Entities; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; -namespace DigitalData.UserManager.API.Controllers +namespace DigitalData.UserManager.API.Controllers; + +[Authorize] +public class UserController : BaseAuthController { - [Authorize] - public class UserController : BaseAuthController + public UserController(ILogger logger, IUserService service) : base(logger, service, service) { - public UserController(ILogger logger, IUserService service) : base(logger, service, service) - { - } + } - [HttpGet("ByModuleId/{moduleId}")] - public async Task GetByModuleId([FromRoute] int moduleId, [FromQuery]bool assigned = true) + [HttpGet("ByModuleId/{moduleId}")] + public async Task GetByModuleId([FromRoute] int moduleId, [FromQuery]bool assigned = true) + { + try { - try - { - return await (assigned ? _service.ReadByModuleIdAsync(moduleId) : _service.ReadUnassignedByModuleIdAsync(moduleId)) - .ThenAsync(Ok, IActionResult(m, n) => - { - _logger.LogNotice(n); - return StatusCode(StatusCodes.Status500InternalServerError); - }); - } - catch(Exception ex) - { - _logger.LogError(ex, "{Message}", ex.Message); - return StatusCode(StatusCodes.Status500InternalServerError); - } - } - - [HttpGet("ByGroupId/{groupId}")] - public async Task GetByGroupId([FromRoute] int groupId, [FromQuery] bool assigned = true) - { - try - { - return await (assigned ? _service.ReadByGroupIdAsync(groupId) : _service.ReadUnassignedByGroupIdAsync(groupId)) - .ThenAsync(Ok, IActionResult (m, n) => - { - _logger.LogNotice(n); - return StatusCode(StatusCodes.Status500InternalServerError); - }); - } - catch(Exception ex) - { - _logger.LogError(ex, "{Message}", ex.Message); - return StatusCode(StatusCodes.Status500InternalServerError); - } - } - - [HttpPost("ByDir")] - public async Task CreateByDir(UserPrincipalDto upDto) - { - try - { - return await _service.CreateAsync(upDto).ThenAsync( - Success: id => - { - var createdResource = new { Id = id }; - var actionName = nameof(GetById); - var routeValues = new { id = createdResource.Id }; - return CreatedAtAction(actionName, routeValues, createdResource); - }, - Fail: IActionResult (m, n) => - { - _logger.LogNotice(n); - return BadRequest(); - }); - } - catch(Exception ex) - { - _logger.LogError(ex, "{Message}", ex.Message); - return StatusCode(StatusCodes.Status500InternalServerError); - } - } - - [HttpGet("ByUsername/{username}")] - public virtual async Task GetByUsername([FromRoute] string username) - { - try - { - return await _service.ReadByUsernameAsync(username).ThenAsync(Ok, IActionResult (m, n) => + return await (assigned ? _service.ReadByModuleIdAsync(moduleId) : _service.ReadUnassignedByModuleIdAsync(moduleId)) + .ThenAsync(Ok, IActionResult(m, n) => { _logger.LogNotice(n); - return NotFound(); + return StatusCode(StatusCodes.Status500InternalServerError); }); - } - catch(Exception ex) + } + catch(Exception ex) + { + _logger.LogError(ex, "{Message}", ex.Message); + return StatusCode(StatusCodes.Status500InternalServerError); + } + } + + [HttpGet("ByGroupId/{groupId}")] + public async Task GetByGroupId([FromRoute] int groupId, [FromQuery] bool assigned = true) + { + try + { + return await (assigned ? _service.ReadByGroupIdAsync(groupId) : _service.ReadUnassignedByGroupIdAsync(groupId)) + .ThenAsync(Ok, IActionResult (m, n) => + { + _logger.LogNotice(n); + return StatusCode(StatusCodes.Status500InternalServerError); + }); + } + catch(Exception ex) + { + _logger.LogError(ex, "{Message}", ex.Message); + return StatusCode(StatusCodes.Status500InternalServerError); + } + } + + [HttpPost("ByDir")] + public async Task CreateByDir(UserPrincipalDto upDto) + { + try + { + return await _service.CreateAsync(upDto).ThenAsync( + Success: id => + { + var createdResource = new { Id = id }; + var actionName = nameof(GetById); + var routeValues = new { id = createdResource.Id }; + return CreatedAtAction(actionName, routeValues, createdResource); + }, + Fail: IActionResult (m, n) => + { + _logger.LogNotice(n); + return BadRequest(); + }); + } + catch(Exception ex) + { + _logger.LogError(ex, "{Message}", ex.Message); + return StatusCode(StatusCodes.Status500InternalServerError); + } + } + + [HttpGet("ByUsername/{username}")] + public virtual async Task GetByUsername([FromRoute] string username) + { + try + { + return await _service.ReadByUsernameAsync(username).ThenAsync(Ok, IActionResult (m, n) => { - _logger.LogError(ex, "{Message}", ex.Message); - return StatusCode(StatusCodes.Status500InternalServerError); - } + _logger.LogNotice(n); + return NotFound(); + }); + } + catch(Exception ex) + { + _logger.LogError(ex, "{Message}", ex.Message); + return StatusCode(StatusCodes.Status500InternalServerError); } } } \ No newline at end of file diff --git a/DigitalData.UserManager.API/Controllers/UserRepController.cs b/DigitalData.UserManager.API/Controllers/UserRepController.cs index d92e505..44576d1 100644 --- a/DigitalData.UserManager.API/Controllers/UserRepController.cs +++ b/DigitalData.UserManager.API/Controllers/UserRepController.cs @@ -5,38 +5,37 @@ using DigitalData.UserManager.Domain.Entities; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; -namespace DigitalData.UserManager.API.Controllers -{ - [Authorize] - public class UserRepController : BaseAuthController - { - public UserRepController(ILogger logger, IUserRepService service, IUserService userService) : base(logger, service, userService) - { - } +namespace DigitalData.UserManager.API.Controllers; - [NonAction] - public override Task GetAll() +[Authorize] +public class UserRepController : BaseAuthController +{ + public UserRepController(ILogger logger, IUserRepService service, IUserService userService) : base(logger, service, userService) + { + } + + [NonAction] + public override Task GetAll() + { + return base.GetAll(); + } + + [HttpGet] + public async Task GetAll(bool withUser = false, bool withRepGroup = false, bool withGroup = false, bool withRepUser = false, int? userId = null, int? groupId = null) + { + try { - return base.GetAll(); + return await _service.ReadAllAsync(withUser: withUser, withRepGroup: withRepGroup, withGroup: withGroup, withRepUser: withRepUser, + userId: userId, groupId: groupId).ThenAsync(Ok, IActionResult (m, n) => + { + _logger.LogNotice(n); + return NotFound(); + }); } - - [HttpGet] - public async Task GetAll(bool withUser = false, bool withRepGroup = false, bool withGroup = false, bool withRepUser = false, int? userId = null, int? groupId = null) + catch (Exception ex) { - try - { - return await _service.ReadAllAsync(withUser: withUser, withRepGroup: withRepGroup, withGroup: withGroup, withRepUser: withRepUser, - userId: userId, groupId: groupId).ThenAsync(Ok, IActionResult (m, n) => - { - _logger.LogNotice(n); - return NotFound(); - }); - } - catch (Exception ex) - { - _logger.LogError(ex, "{Message}", ex.Message); - return StatusCode(StatusCodes.Status500InternalServerError); - } + _logger.LogError(ex, "{Message}", ex.Message); + return StatusCode(StatusCodes.Status500InternalServerError); } } } \ No newline at end of file diff --git a/DigitalData.UserManager.API/DigitalData.UserManager.API.csproj b/DigitalData.UserManager.API/DigitalData.UserManager.API.csproj index 2c6ad6b..5a2c5e6 100644 --- a/DigitalData.UserManager.API/DigitalData.UserManager.API.csproj +++ b/DigitalData.UserManager.API/DigitalData.UserManager.API.csproj @@ -20,7 +20,7 @@ - + diff --git a/DigitalData.UserManager.API/Program.cs b/DigitalData.UserManager.API/Program.cs index 94b8f67..77c7433 100644 --- a/DigitalData.UserManager.API/Program.cs +++ b/DigitalData.UserManager.API/Program.cs @@ -83,7 +83,7 @@ try { builder.Services.AddUserManager(); builder.ConfigureBySection(); - builder.Services.AddDirectorySearchService(); + builder.Services.AddDirectorySearchService(config.GetSection("DirectorySearchOptions")); builder.Services.AddCookieBasedLocalizer(); diff --git a/DigitalData.UserManager.Application/DigitalData.UserManager.Application.csproj b/DigitalData.UserManager.Application/DigitalData.UserManager.Application.csproj index b92fa28..459ad2d 100644 --- a/DigitalData.UserManager.Application/DigitalData.UserManager.Application.csproj +++ b/DigitalData.UserManager.Application/DigitalData.UserManager.Application.csproj @@ -27,8 +27,8 @@ - - + + diff --git a/DigitalData.UserManager.Domain/DigitalData.UserManager.Domain.csproj b/DigitalData.UserManager.Domain/DigitalData.UserManager.Domain.csproj index fc3c6a8..5e36feb 100644 --- a/DigitalData.UserManager.Domain/DigitalData.UserManager.Domain.csproj +++ b/DigitalData.UserManager.Domain/DigitalData.UserManager.Domain.csproj @@ -26,7 +26,7 @@ - +