diff --git a/Astral.ApiServer/Controllers/OAuthController.cs b/Astral.ApiServer/Controllers/OAuthApiController.cs similarity index 88% rename from Astral.ApiServer/Controllers/OAuthController.cs rename to Astral.ApiServer/Controllers/OAuthApiController.cs index 0b9b94f..77cebbd 100644 --- a/Astral.ApiServer/Controllers/OAuthController.cs +++ b/Astral.ApiServer/Controllers/OAuthApiController.cs @@ -1,4 +1,4 @@ -// +// // Copyright (c) alveus.dev. All rights reserved. Licensed under the MIT License. // @@ -16,15 +16,15 @@ namespace Astral.ApiServer.Controllers; /// OAuth authentication controller. /// [Route("oauth")] -public class OAuthController : BaseApiController +public class OAuthApiController : BaseApiController { private readonly IAuthenticationService _authenticationService; /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// Instance of . - public OAuthController(IAuthenticationService authenticationService) + public OAuthApiController(IAuthenticationService authenticationService) { _authenticationService = authenticationService; } diff --git a/Astral.ApiServer/Controllers/V1/UserApiController.cs b/Astral.ApiServer/Controllers/V1/UserApiController.cs new file mode 100644 index 0000000..fb4ea2a --- /dev/null +++ b/Astral.ApiServer/Controllers/V1/UserApiController.cs @@ -0,0 +1,67 @@ +// +// Copyright (c) alveus.dev. All rights reserved. Licensed under the MIT License. +// + +using Astral.ApiServer.Models; +using Astral.Services.Interfaces; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; + +namespace Astral.ApiServer.Controllers.V1; + +/// +/// User api controller. +/// +[Route("api/v1/user")] +[Authorize] +public class UserApiController : BaseApiController +{ + private readonly IIdentityProvider _identityProvider; + + /// + /// Initializes a new instance of the class. + /// + /// Instance of . + public UserApiController(IIdentityProvider identityProvider) + { + _identityProvider = identityProvider; + } + + /// + /// Get the user's profile. + /// + [HttpGet("profile")] + public IActionResult GetUserProfile() + { + var userId = _identityProvider.GetUserId(); + var userName = _identityProvider.GetUserName(); + + return new JsonResult(new UserProfileResultModel() + { + Success = true, + AccountId = userId, + Username = userName, + XmppPassword = string.Empty, + DiscourseApiKey = string.Empty + }); + } + + /// + /// Does nothing for now since I believe the locker feature is deprecated. + /// + [HttpPost("locker")] + public IActionResult PostLocker() + { + return SuccessResult(); + } + + /// + /// Does nothing for now since I believe the locker feature is deprecated. + /// + [HttpGet("locker")] + public IActionResult GetLocker() + { + return SuccessResult(); + } + +} diff --git a/Astral.ApiServer/Models/TokenGrantResultModel.cs b/Astral.ApiServer/Models/TokenGrantResultModel.cs index 331462e..ce492b8 100644 --- a/Astral.ApiServer/Models/TokenGrantResultModel.cs +++ b/Astral.ApiServer/Models/TokenGrantResultModel.cs @@ -33,7 +33,7 @@ public class TokenGrantResultModel : ResultModel ExpiresIn = sessionDto.AccessTokenExpires.Ticks; RefreshToken = sessionDto.RefreshToken; Scope = sessionDto.Scope.ToString().ToLowerInvariant(); - AccountId = sessionDto.UserId.ToString(); + AccountId = sessionDto.UserId; AccountName = sessionDto.UserName; TokenType = "Bearer"; AccountRoles = sessionDto.Role.GetAccessibleRoles().Select(role => role.ToString().ToLowerInvariant()).ToList(); @@ -79,7 +79,7 @@ public class TokenGrantResultModel : ResultModel /// The user's id. /// [JsonPropertyName("account_id")] - public string AccountId { get; set; } + public Guid AccountId { get; set; } /// /// The user's name. diff --git a/Astral.ApiServer/Models/UserProfileResultModel.cs b/Astral.ApiServer/Models/UserProfileResultModel.cs new file mode 100644 index 0000000..f6937c2 --- /dev/null +++ b/Astral.ApiServer/Models/UserProfileResultModel.cs @@ -0,0 +1,38 @@ +// +// Copyright (c) alveus.dev. All rights reserved. Licensed under the MIT License. +// + +using System.Text.Json.Serialization; +using Astral.ApiServer.Models.Common; + +namespace Astral.ApiServer.Models; + +/// +/// User profile request result. +/// +public class UserProfileResultModel : ResultModel +{ + /// + /// Account id (Even used?). + /// + [JsonPropertyName("accountId")] + public Guid AccountId { get; set; } + + /// + /// Username. + /// + [JsonPropertyName("username")] + public string Username { get; set; } + + /// + /// Discourse api key (Even used?). + /// + [JsonPropertyName("discourse_api_key")] + public string DiscourseApiKey { get; set; } + + /// + /// XMPP Password (Even used?). + /// + [JsonPropertyName("xmpp_password")] + public string XmppPassword { get; set; } +} diff --git a/Astral.ApiServer/Program.cs b/Astral.ApiServer/Program.cs index 3196a10..c92f5ab 100644 --- a/Astral.ApiServer/Program.cs +++ b/Astral.ApiServer/Program.cs @@ -36,6 +36,7 @@ builder.Services.AddHttpUserAgentMemoryCachedParser(opt => builder.Services.AddHostedService(); +builder.Services.AddAstralApiServer(); builder.Services.AddAstralCore(); builder.Services.AddAstralServices(); builder.Services.AddAstralDAL(); @@ -105,4 +106,4 @@ if (app.Environment.IsDevelopment()) app.UseAuthorization(); app.MapControllers(); -await app.RunAsync(); \ No newline at end of file +await app.RunAsync(); diff --git a/Astral.ApiServer/Providers/IdentityProvider.cs b/Astral.ApiServer/Providers/IdentityProvider.cs new file mode 100644 index 0000000..9607188 --- /dev/null +++ b/Astral.ApiServer/Providers/IdentityProvider.cs @@ -0,0 +1,45 @@ +// +// Copyright (c) alveus.dev. All rights reserved. Licensed under the MIT License. +// + +using System.Security.Claims; +using Astral.Services.Constants; +using Astral.Services.Interfaces; +using Injectio.Attributes; + +namespace Astral.ApiServer.Providers; + +/// +[RegisterScoped] +public class IdentityProvider : IIdentityProvider +{ + /// + /// Initializes a new instance of the class. + /// + /// Instance of . + public IdentityProvider(IHttpContextAccessor httpContextAccessor) + { + var claims = httpContextAccessor.HttpContext?.User.Claims; + if (claims is not null) + { + Claims = claims; + } + } + + /// + /// Session claims. + /// + private IEnumerable Claims { get; set; } + + /// + public Guid GetUserId() + { + return Guid.TryParse(Claims.FirstOrDefault(c => c.Type == ClaimIds.UserId)?.Value, out var guid) ? guid : Guid.Empty; + } + + /// + public string GetUserName() + { + return Claims.FirstOrDefault(c => c.Type == ClaimIds.UserName)?.Value; + } +} diff --git a/Astral.Services/Interfaces/IIdentityProvider.cs b/Astral.Services/Interfaces/IIdentityProvider.cs index af3bb45..9f23874 100644 --- a/Astral.Services/Interfaces/IIdentityProvider.cs +++ b/Astral.Services/Interfaces/IIdentityProvider.cs @@ -5,13 +5,19 @@ namespace Astral.Services.Interfaces; /// -/// Identify who the requesting user is. +/// Identify who the requesting user is. /// public interface IIdentityProvider { /// - /// Get the user id of the requester. + /// Get the user id of the authorised agent. /// - /// String representing the user id, or null if none. - string GetRequestingUserId(); + /// Guid representing the user id, or empty guid if none. + Guid GetUserId(); + + /// + /// Get the username of the authorised agent. + /// + /// Username, or null if none. + string GetUserName(); }