Compare commits

...

3 Commits

15 changed files with 536 additions and 677 deletions

View File

@ -1,158 +0,0 @@
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authentication;
using System.Security.Claims;
using Microsoft.AspNetCore.Mvc;
using DigitalData.UserManager.Application.Contracts;
using DigitalData.UserManager.Application.DTOs.User;
using Microsoft.AspNetCore.Authorization;
using DigitalData.UserManager.Application;
using DigitalData.UserManager.Application.DTOs.Auth;
using DigitalData.Core.Abstractions.Application;
using Microsoft.Extensions.Localization;
using DigitalData.Core.DTO;
namespace DigitalData.UserManager.API.Controllers
{
[Route("api/[controller]")]
public class AuthController : ControllerBase
{
private readonly IUserService _userService;
private readonly IGroupOfUserService _gouService;
private readonly IDirectorySearchService _dirSearchService;
private readonly IStringLocalizer<Resource> _localizer;
private readonly ILogger<AuthController> _logger;
private readonly IConfiguration _config;
public AuthController(IUserService userService, IGroupOfUserService gouService, IDirectorySearchService directorySearchService, IStringLocalizer<Resource> localizer, ILogger<AuthController> logger, IConfiguration configuration)
{
_userService = userService;
_gouService = gouService;
_dirSearchService = directorySearchService;
_localizer = localizer;
_logger = logger;
_config = configuration;
}
[AllowAnonymous]
[HttpGet("check")]
public IActionResult CheckAuthentication()
{
try
{
return Ok(User.Identity?.IsAuthenticated ?? false);
}
catch(Exception ex)
{
_logger.LogError(ex, "{Message}", ex.Message);
return StatusCode(StatusCodes.Status500InternalServerError);
}
}
[AllowAnonymous]
[HttpPost("login")]
public async Task<IActionResult> 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<string>()
?? 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)
{
return Unauthorized(uRes);
}
UserReadDto user = uRes.Data;
// Create claims
var claims = new List<Claim>
{
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")
};
// Create claimsIdentity
var claimsIdentity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);
// Create authProperties
var authProperties = new AuthenticationProperties
{
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);
}
}
[Authorize]
[HttpGet("user")]
public async Task<IActionResult> 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) =>
{
_logger.LogNotice(n);
return NotFound(Result.Fail().Message(_localizer[Key.UserNotFound]));
});
}
catch (Exception ex)
{
_logger.LogError(ex, "{Message}", ex.Message);
return StatusCode(StatusCodes.Status500InternalServerError);
}
}
[Authorize]
[HttpPost("logout")]
public async Task<IActionResult> Logout()
{
try
{
await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
return Ok();
}
catch(Exception ex)
{
_logger.LogError(ex, "{Message}", ex.Message);
return StatusCode(StatusCodes.Status500InternalServerError);
}
}
}
}

View File

@ -7,16 +7,16 @@ using DigitalData.UserManager.Domain.Entities;
using Microsoft.AspNetCore.Authorization;
using System.Security.Claims;
namespace DigitalData.UserManager.API.Controllers
{
[Authorize]
public class BaseAuthController<TCRUDService, TCreateDto, TReadDto, TUpdateDto, TBaseEntity> : CRUDControllerBaseWithErrorHandling<TCRUDService, TCreateDto, TReadDto, TUpdateDto, TBaseEntity, int>
where TCRUDService : IBaseService<TCreateDto, TReadDto, TUpdateDto, TBaseEntity>
namespace DigitalData.UserManager.API.Controllers;
[Authorize]
public class BaseAuthController<TCRUDService, TCreateDto, TReadDto, TUpdateDto, TBaseEntity> : CRUDControllerBaseWithErrorHandling<TCRUDService, TCreateDto, TReadDto, TUpdateDto, TBaseEntity, int>
where TCRUDService : IBaseService<TCreateDto, TReadDto, TBaseEntity>
where TCreateDto : BaseCreateDto
where TReadDto : class
where TUpdateDto : BaseUpdateDto
where TBaseEntity : BaseEntity
{
{
private readonly Lazy<int?> _lUserId;
public BaseAuthController(ILogger logger, TCRUDService service, IUserService userService) : base(logger, service)
@ -43,5 +43,4 @@ namespace DigitalData.UserManager.API.Controllers
: null;
};
}
}
}

View File

@ -10,13 +10,13 @@ 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 = "<Pending>")]
[Authorize]
public class DirectoryController : ControllerBase
{
[Route("api/[controller]")]
[SuppressMessage("Interoperability", "CA1416:Validate platform compatibility", Justification = "<Pending>")]
[Authorize]
public class DirectoryController : ControllerBase
{
private readonly IUserService _userService;
private readonly IDirectorySearchService _dirSearchService;
private readonly Dictionary<string, string> _customSearchFilters;
@ -231,5 +231,4 @@ namespace DigitalData.UserManager.API.Controllers
{
get => (HttpContext.User.Claims.FirstOrDefault(c => c.Type == ClaimTypes.Name)?.Value);
}
}
}

View File

@ -1,14 +1,13 @@
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)
@ -42,5 +41,4 @@ namespace DigitalData.UserManager.API.Controllers
var param = Encryptor.GenerateParameters();
return Ok(param);
}
}
}

View File

@ -5,11 +5,11 @@ 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 GroupController : BaseAuthController<IGroupService, GroupCreateDto, GroupReadDto, GroupUpdateDto, Group>
{
[Authorize]
public class GroupController : BaseAuthController<IGroupService, GroupCreateDto, GroupReadDto, GroupUpdateDto, Group>
{
public GroupController(ILogger<GroupController> logger, IGroupService service, IUserService userService) : base(logger, service, userService)
{
}
@ -39,5 +39,4 @@ namespace DigitalData.UserManager.API.Controllers
return StatusCode(StatusCodes.Status500InternalServerError);
}
}
}
}

View File

@ -5,11 +5,11 @@ 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<IGroupOfUserService, GroupOfUserCreateDto, GroupOfUserReadDto, GroupOfUserUpdateDto, GroupOfUser>
{
[Authorize]
public class GroupOfUserController : BaseAuthController<IGroupOfUserService, GroupOfUserCreateDto, GroupOfUserReadDto, GroupOfUserUpdateDto, GroupOfUser>
{
public GroupOfUserController(ILogger<GroupOfUserController> logger, IGroupOfUserService service, IUserService userService) : base(logger, service, userService)
{
}
@ -77,5 +77,4 @@ namespace DigitalData.UserManager.API.Controllers
return StatusCode(StatusCodes.Status500InternalServerError);
}
}
}
}

View File

@ -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<IModuleService, ModuleDto, Module, int>
{
[Authorize]
public class ModuleController : ReadControllerBaseWithErrorHandling<IModuleService, ModuleDto, Module, int>
{
public ModuleController(ILogger<ModuleController> logger, IModuleService service) : base(logger, service)
{
}
}
}

View File

@ -6,11 +6,11 @@ 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<IModuleOfUserService, ModuleOfUserCreateDto, ModuleOfUserReadDto, ModuleOfUserUpdateDto, ModuleOfUser, int>
{
[Authorize]
public class ModuleOfUserController : CRUDControllerBaseWithErrorHandling<IModuleOfUserService, ModuleOfUserCreateDto, ModuleOfUserReadDto, ModuleOfUserUpdateDto, ModuleOfUser, int>
{
public ModuleOfUserController(ILogger<ModuleOfUserController> logger, IModuleOfUserService service) : base(logger, service)
{
}
@ -49,5 +49,4 @@ namespace DigitalData.UserManager.API.Controllers
return StatusCode(StatusCodes.Status500InternalServerError);
}
}
}
}

View File

@ -0,0 +1,27 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Authorization;
using DigitalData.UserManager.Application.DTOs.Auth;
namespace DigitalData.UserManager.API.Controllers;
[Route("api/Auth")]
[ApiController]
[Tags("Auth")]
public class PlaceholderAuthController : ControllerBase
{
[AllowAnonymous]
[HttpGet("check")]
public IActionResult CheckAuthentication() => throw new NotImplementedException();
[AllowAnonymous]
[HttpPost("login")]
public Task<IActionResult> Login([FromBody] LogInDto login) => throw new NotImplementedException();
[Authorize]
[HttpGet("user")]
public Task<IActionResult> GetUserWithClaims() => throw new NotImplementedException();
[Authorize]
[HttpPost("logout")]
public Task<IActionResult> Logout() => throw new NotImplementedException();
}

View File

@ -1,4 +1,3 @@
using DigitalData.Core.API;
using DigitalData.Core.DTO;
using DigitalData.UserManager.Application.Contracts;
using DigitalData.UserManager.Application.DTOs.User;
@ -6,11 +5,11 @@ 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<IUserService, UserCreateDto, UserReadDto, UserUpdateDto, User>
{
[Authorize]
public class UserController : BaseAuthController<IUserService, UserCreateDto, UserReadDto, UserUpdateDto, User>
{
public UserController(ILogger<UserController> logger, IUserService service) : base(logger, service, service)
{
}
@ -96,5 +95,4 @@ namespace DigitalData.UserManager.API.Controllers
return StatusCode(StatusCodes.Status500InternalServerError);
}
}
}
}

View File

@ -5,11 +5,11 @@ 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 UserRepController : BaseAuthController<IUserRepService, UserRepCreateDto, UserRepReadDto, UserRepUpdateDto, UserRep>
{
[Authorize]
public class UserRepController : BaseAuthController<IUserRepService, UserRepCreateDto, UserRepReadDto, UserRepUpdateDto, UserRep>
{
public UserRepController(ILogger<UserRepController> logger, IUserRepService service, IUserService userService) : base(logger, service, userService)
{
}
@ -38,5 +38,4 @@ namespace DigitalData.UserManager.API.Controllers
return StatusCode(StatusCodes.Status500InternalServerError);
}
}
}
}

View File

@ -20,7 +20,8 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="DigitalData.Core.API" Version="2.0.0" />
<PackageReference Include="DigitalData.Auth.Client" Version="1.3.3" />
<PackageReference Include="DigitalData.Core.API" Version="2.1.1" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="7.0.14" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="7.0.20" />
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="7.0.4" />

View File

@ -83,7 +83,7 @@ try {
builder.Services.AddUserManager<UserManagerDbContext>();
builder.ConfigureBySection<DirectorySearchOptions>();
builder.Services.AddDirectorySearchService();
builder.Services.AddDirectorySearchService(config.GetSection("DirectorySearchOptions"));
builder.Services.AddCookieBasedLocalizer();

View File

@ -27,8 +27,8 @@
<ItemGroup>
<PackageReference Include="AutoMapper" Version="13.0.1" />
<PackageReference Include="DigitalData.Core.Abstractions" Version="3.1.0" />
<PackageReference Include="DigitalData.Core.Application" Version="3.0.1" />
<PackageReference Include="DigitalData.Core.Abstractions" Version="3.4.0" />
<PackageReference Include="DigitalData.Core.Application" Version="3.2.0" />
<PackageReference Include="DigitalData.Core.DTO" Version="2.0.1" />
<PackageReference Include="DigitalData.EmailProfilerDispatcher.Abstraction" Version="2.0.0" />
<PackageReference Include="Microsoft.Extensions.Localization.Abstractions" Version="7.0.16" />

View File

@ -26,7 +26,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="DigitalData.Core.Abstractions" Version="3.1.0" />
<PackageReference Include="DigitalData.Core.Abstractions" Version="3.4.0" />
</ItemGroup>
<ItemGroup>