diff options
Diffstat (limited to 'code/api')
25 files changed, 382 insertions, 400 deletions
diff --git a/code/api/build_and_push.sh b/code/api/build_and_push.sh index 163d7f3..820533a 100755 --- a/code/api/build_and_push.sh +++ b/code/api/build_and_push.sh @@ -8,10 +8,8 @@ CURRENT_VERSION=$(cat .version) CURRENT_VERSION_INT=${CURRENT_VERSION//[!0-9]/} if [ ${1-prod} == "dev" ]; then NEW_VERSION="v$((CURRENT_DEV_VERSION_INT + 1))-dev" - OLD_VERSION=$CURRENT_DEV_VERSION else NEW_VERSION="v$((CURRENT_VERSION_INT + 1))" - OLD_VERSION=$CURRENT_VERSION fi IMAGE_NAME="greatoffice/server" HUB_NAME="dr.ivar.systems/greatoffice/server" diff --git a/code/api/src/Endpoints/EndpointBase.cs b/code/api/src/Endpoints/EndpointBase.cs index e8e2494..584f43e 100644 --- a/code/api/src/Endpoints/EndpointBase.cs +++ b/code/api/src/Endpoints/EndpointBase.cs @@ -8,18 +8,15 @@ public class EndpointBase : ControllerBase /// <summary> /// User data for the currently logged on user. /// </summary> - protected LoggedInUserModel LoggedInUser => new() - { + protected LoggedInUserModel LoggedInUser => new() { Username = User.FindFirstValue(AppClaims.NAME), Id = User.FindFirstValue(AppClaims.USER_ID).AsGuid(), }; [NonAction] - protected ActionResult KnownProblem(string title = default, string subtitle = default, Dictionary<string, string[]> errors = default) - { + protected ActionResult KnownProblem(string title = default, string subtitle = default, Dictionary<string, string[]> errors = default) { HttpContext.Response.Headers.Append(AppHeaders.IS_KNOWN_PROBLEM, "1"); - return BadRequest(new KnownProblemModel - { + return BadRequest(new KnownProblemModel { Title = title, Subtitle = subtitle, Errors = errors, @@ -28,31 +25,27 @@ public class EndpointBase : ControllerBase } [NonAction] - protected ActionResult KnownProblem(KnownProblemModel problem) - { + protected ActionResult KnownProblem(KnownProblemModel problem) { HttpContext.Response.Headers.Append(AppHeaders.IS_KNOWN_PROBLEM, "1"); problem.TraceId = HttpContext.TraceIdentifier; return BadRequest(problem); } [NonAction] - protected RequestTimeZoneInfo GetRequestTimeZone(ILogger logger = default) - { + protected RequestTimeZoneInfo GetRequestTimeZone(ILogger logger = default) { Request.Headers.TryGetValue(AppHeaders.BROWSER_TIME_ZONE, out var timeZoneHeader); var tz = TimeZoneInfo.FindSystemTimeZoneById(timeZoneHeader.ToString().HasValue() ? timeZoneHeader.ToString() : "UTC"); var offset = tz.BaseUtcOffset.Hours; // This is fine as long as the client is not connecting from Australia: Lord Howe Island, // according to https://en.wikipedia.org/wiki/Daylight_saving_time_by_country - if (tz.IsDaylightSavingTime(AppDateTime.UtcNow)) - { + if (tz.IsDaylightSavingTime(AppDateTime.UtcNow)) { offset++; } logger?.LogInformation("Request time zone (" + tz.Id + ") offset is: " + offset + " hours"); - return new RequestTimeZoneInfo() - { + return new RequestTimeZoneInfo() { TimeZoneInfo = tz, Offset = offset, LocalDateTime = TimeZoneInfo.ConvertTimeFromUtc(AppDateTime.UtcNow, tz) diff --git a/code/api/src/Endpoints/Internal/Account/GetAccountRoute.cs b/code/api/src/Endpoints/Internal/Account/GetAccountRoute.cs index 121b40f..67c4d4d 100644 --- a/code/api/src/Endpoints/Internal/Account/GetAccountRoute.cs +++ b/code/api/src/Endpoints/Internal/Account/GetAccountRoute.cs @@ -12,7 +12,7 @@ public class GetAccountRoute : RouteBaseAsync.WithoutRequest.WithActionResult<Lo public override async Task<ActionResult<LoggedInUserModel>> HandleAsync(CancellationToken cancellationToken = default) { var user = _database.Users .Select(x => new {x.Username, x.Id}) - .SingleOrDefault(c => c.Id == LoggedInUser.Id); + .FirstOrDefault(c => c.Id == LoggedInUser.Id); if (user != default) { return Ok(new LoggedInUserModel { Id = LoggedInUser.Id, @@ -23,4 +23,4 @@ public class GetAccountRoute : RouteBaseAsync.WithoutRequest.WithActionResult<Lo await HttpContext.SignOutAsync(); return Unauthorized(); } -}
\ No newline at end of file +} diff --git a/code/api/src/Endpoints/Internal/Account/UpdateAccountRoute.cs b/code/api/src/Endpoints/Internal/Account/UpdateAccountRoute.cs index 1081240..f6e18af 100644 --- a/code/api/src/Endpoints/Internal/Account/UpdateAccountRoute.cs +++ b/code/api/src/Endpoints/Internal/Account/UpdateAccountRoute.cs @@ -19,7 +19,7 @@ public class UpdateAccountRoute : RouteBaseAsync.WithRequest<UpdateAccountRoute. [HttpPost("~/_/account/update")] public override async Task<ActionResult> HandleAsync(Payload request, CancellationToken cancellationToken = default) { - var user = _database.Users.SingleOrDefault(c => c.Id == LoggedInUser.Id); + var user = _database.Users.FirstOrDefault(c => c.Id == LoggedInUser.Id); if (user == default) { await HttpContext.SignOutAsync(); return Unauthorized(); @@ -56,4 +56,4 @@ public class UpdateAccountRoute : RouteBaseAsync.WithRequest<UpdateAccountRoute. await _database.SaveChangesAsync(cancellationToken); return Ok(); } -}
\ No newline at end of file +} diff --git a/code/api/src/Endpoints/Internal/INT_EndpointBase.cs b/code/api/src/Endpoints/Internal/INT_EndpointBase.cs index 699a976..0ba6c82 100644 --- a/code/api/src/Endpoints/Internal/INT_EndpointBase.cs +++ b/code/api/src/Endpoints/Internal/INT_EndpointBase.cs @@ -6,4 +6,4 @@ namespace IOL.GreatOffice.Api.Endpoints.Internal; public class INT_EndpointBase : EndpointBase { -} +}
\ No newline at end of file diff --git a/code/api/src/Endpoints/Internal/Root/ValidateRoute.cs b/code/api/src/Endpoints/Internal/Root/ValidateRoute.cs index d8ec85a..f141fe9 100644 --- a/code/api/src/Endpoints/Internal/Root/ValidateRoute.cs +++ b/code/api/src/Endpoints/Internal/Root/ValidateRoute.cs @@ -6,8 +6,7 @@ public class ValidateRoute : RouteBaseSync.WithRequest<ValidateRoute.QueryParams private readonly string CanonicalFrontendUrl; private readonly ILogger<ValidateRoute> _logger; - public ValidateRoute(EmailValidationService emailValidation, ILogger<ValidateRoute> logger) - { + public ValidateRoute(EmailValidationService emailValidation, ILogger<ValidateRoute> logger) { _emailValidation = emailValidation; _logger = logger; CanonicalFrontendUrl = Program.AppConfiguration.CANONICAL_FRONTEND_URL; @@ -20,20 +19,18 @@ public class ValidateRoute : RouteBaseSync.WithRequest<ValidateRoute.QueryParams } [HttpGet("~/_/validate")] - public override ActionResult Handle([FromQuery] QueryParams request) - { + public override ActionResult Handle([FromQuery] QueryParams request) { var isFulfilled = _emailValidation.FulfillEmailValidationRequest(request.Id, LoggedInUser.Id); - if (!isFulfilled) - { + if (!isFulfilled) { _logger.LogError("Email validation fulfillment failed for request {requestId} and user {userId}", request.Id, LoggedInUser.Id); return StatusCode(400, $""" -<html> -<body> -<h3>The validation could not be completed</h3> -<p>We are working on fixing this, in the meantime, have patience.</p> -<a href="{CanonicalFrontendUrl}">Click here to go back to {CanonicalFrontendUrl}</a> -</body> -"""); + <html> + <body> + <h3>The validation could not be completed</h3> + <p>We are working on fixing this, in the meantime, have patience.</p> + <a href="{CanonicalFrontendUrl}">Click here to go back to {CanonicalFrontendUrl}</a> + </body> + """); } return Redirect(CanonicalFrontendUrl + "/portal?msg=emailValidated"); diff --git a/code/api/src/Endpoints/Internal/RouteBaseAsync.cs b/code/api/src/Endpoints/Internal/RouteBaseAsync.cs index a87facf..dc25499 100644 --- a/code/api/src/Endpoints/Internal/RouteBaseAsync.cs +++ b/code/api/src/Endpoints/Internal/RouteBaseAsync.cs @@ -5,69 +5,69 @@ namespace IOL.GreatOffice.Api.Endpoints.Internal; /// </summary> public static class RouteBaseAsync { - public static class WithRequest<TRequest> - { - public abstract class WithResult<TResponse> : INT_EndpointBase - { - public abstract Task<TResponse> HandleAsync( - TRequest request, - CancellationToken cancellationToken = default - ); - } + public static class WithRequest<TRequest> + { + public abstract class WithResult<TResponse> : INT_EndpointBase + { + public abstract Task<TResponse> HandleAsync( + TRequest request, + CancellationToken cancellationToken = default + ); + } - public abstract class WithoutResult : INT_EndpointBase - { - public abstract Task HandleAsync( - TRequest request, - CancellationToken cancellationToken = default - ); - } + public abstract class WithoutResult : INT_EndpointBase + { + public abstract Task HandleAsync( + TRequest request, + CancellationToken cancellationToken = default + ); + } - public abstract class WithActionResult<TResponse> : INT_EndpointBase - { - public abstract Task<ActionResult<TResponse>> HandleAsync( - TRequest request, - CancellationToken cancellationToken = default - ); - } + public abstract class WithActionResult<TResponse> : INT_EndpointBase + { + public abstract Task<ActionResult<TResponse>> HandleAsync( + TRequest request, + CancellationToken cancellationToken = default + ); + } - public abstract class WithActionResult : INT_EndpointBase - { - public abstract Task<ActionResult> HandleAsync( - TRequest request, - CancellationToken cancellationToken = default - ); - } - } + public abstract class WithActionResult : INT_EndpointBase + { + public abstract Task<ActionResult> HandleAsync( + TRequest request, + CancellationToken cancellationToken = default + ); + } + } - public static class WithoutRequest - { - public abstract class WithResult<TResponse> : INT_EndpointBase - { - public abstract Task<TResponse> HandleAsync( - CancellationToken cancellationToken = default - ); - } + public static class WithoutRequest + { + public abstract class WithResult<TResponse> : INT_EndpointBase + { + public abstract Task<TResponse> HandleAsync( + CancellationToken cancellationToken = default + ); + } - public abstract class WithoutResult : INT_EndpointBase - { - public abstract Task HandleAsync( - CancellationToken cancellationToken = default - ); - } + public abstract class WithoutResult : INT_EndpointBase + { + public abstract Task HandleAsync( + CancellationToken cancellationToken = default + ); + } - public abstract class WithActionResult<TResponse> : INT_EndpointBase - { - public abstract Task<ActionResult<TResponse>> HandleAsync( - CancellationToken cancellationToken = default - ); - } + public abstract class WithActionResult<TResponse> : INT_EndpointBase + { + public abstract Task<ActionResult<TResponse>> HandleAsync( + CancellationToken cancellationToken = default + ); + } - public abstract class WithActionResult : INT_EndpointBase - { - public abstract Task<ActionResult> HandleAsync( - CancellationToken cancellationToken = default - ); - } - } -} + public abstract class WithActionResult : INT_EndpointBase + { + public abstract Task<ActionResult> HandleAsync( + CancellationToken cancellationToken = default + ); + } + } +}
\ No newline at end of file diff --git a/code/api/src/Endpoints/Internal/RouteBaseSync.cs b/code/api/src/Endpoints/Internal/RouteBaseSync.cs index 9d9bd5a..4bbfa16 100644 --- a/code/api/src/Endpoints/Internal/RouteBaseSync.cs +++ b/code/api/src/Endpoints/Internal/RouteBaseSync.cs @@ -5,49 +5,49 @@ namespace IOL.GreatOffice.Api.Endpoints.Internal; /// </summary> public static class RouteBaseSync { - public static class WithRequest<TRequest> - { - public abstract class WithResult<TResponse> : INT_EndpointBase - { - public abstract TResponse Handle(TRequest request); - } + public static class WithRequest<TRequest> + { + public abstract class WithResult<TResponse> : INT_EndpointBase + { + public abstract TResponse Handle(TRequest request); + } - public abstract class WithoutResult : INT_EndpointBase - { - public abstract void Handle(TRequest request); - } + public abstract class WithoutResult : INT_EndpointBase + { + public abstract void Handle(TRequest request); + } - public abstract class WithActionResult<TResponse> : INT_EndpointBase - { - public abstract ActionResult<TResponse> Handle(TRequest request); - } + public abstract class WithActionResult<TResponse> : INT_EndpointBase + { + public abstract ActionResult<TResponse> Handle(TRequest request); + } - public abstract class WithActionResult : INT_EndpointBase - { - public abstract ActionResult Handle(TRequest request); - } - } + public abstract class WithActionResult : INT_EndpointBase + { + public abstract ActionResult Handle(TRequest request); + } + } - public static class WithoutRequest - { - public abstract class WithResult<TResponse> : INT_EndpointBase - { - public abstract TResponse Handle(); - } + public static class WithoutRequest + { + public abstract class WithResult<TResponse> : INT_EndpointBase + { + public abstract TResponse Handle(); + } - public abstract class WithoutResult : INT_EndpointBase - { - public abstract void Handle(); - } + public abstract class WithoutResult : INT_EndpointBase + { + public abstract void Handle(); + } - public abstract class WithActionResult<TResponse> : INT_EndpointBase - { - public abstract ActionResult<TResponse> Handle(); - } + public abstract class WithActionResult<TResponse> : INT_EndpointBase + { + public abstract ActionResult<TResponse> Handle(); + } - public abstract class WithActionResult : INT_EndpointBase - { - public abstract ActionResult Handle(); - } - } -} + public abstract class WithActionResult : INT_EndpointBase + { + public abstract ActionResult Handle(); + } + } +}
\ No newline at end of file diff --git a/code/api/src/Endpoints/V1/ApiSpecV1.cs b/code/api/src/Endpoints/V1/ApiSpecV1.cs index e4f9cc9..7a54eb0 100644 --- a/code/api/src/Endpoints/V1/ApiSpecV1.cs +++ b/code/api/src/Endpoints/V1/ApiSpecV1.cs @@ -2,17 +2,17 @@ namespace IOL.GreatOffice.Api.Endpoints.V1; public static class ApiSpecV1 { - private const int MAJOR = 1; - private const int MINOR = 0; - public const string VERSION_STRING = "1.0"; + private const int MAJOR = 1; + private const int MINOR = 0; + public const string VERSION_STRING = "1.0"; - public static ApiSpecDocument Document => new() { - Version = new ApiVersion(MAJOR, MINOR), - VersionName = VERSION_STRING, - SwaggerPath = $"/swagger/{VERSION_STRING}/swagger.json", - OpenApiInfo = new OpenApiInfo { - Title = AppConstants.API_NAME, - Version = VERSION_STRING - } - }; -} + public static ApiSpecDocument Document => new() { + Version = new ApiVersion(MAJOR, MINOR), + VersionName = VERSION_STRING, + SwaggerPath = $"/swagger/{VERSION_STRING}/swagger.json", + OpenApiInfo = new OpenApiInfo { + Title = AppConstants.API_NAME, + Version = VERSION_STRING + } + }; +}
\ No newline at end of file diff --git a/code/api/src/Endpoints/V1/ApiTokens/CreateTokenRoute.cs b/code/api/src/Endpoints/V1/ApiTokens/CreateTokenRoute.cs index c28f534..b9876c6 100644 --- a/code/api/src/Endpoints/V1/ApiTokens/CreateTokenRoute.cs +++ b/code/api/src/Endpoints/V1/ApiTokens/CreateTokenRoute.cs @@ -31,7 +31,7 @@ public class CreateTokenRoute : RouteBaseSync.WithRequest<CreateTokenRoute.Paylo [HttpPost("~/v{version:apiVersion}/api-tokens/create")] public override ActionResult Handle(Payload request) { - var user = _database.Users.SingleOrDefault(c => c.Id == LoggedInUser.Id); + var user = _database.Users.FirstOrDefault(c => c.Id == LoggedInUser.Id); if (user == default) { return NotFound(new KnownProblemModel("User does not exist")); @@ -58,4 +58,4 @@ public class CreateTokenRoute : RouteBaseSync.WithRequest<CreateTokenRoute.Paylo _database.SaveChanges(); return Ok(Convert.ToBase64String(Encoding.UTF8.GetBytes(accessToken.Id.ToString().EncryptWithAes(tokenEntropy)))); } -}
\ No newline at end of file +} diff --git a/code/api/src/Endpoints/V1/ApiTokens/DeleteTokenRoute.cs b/code/api/src/Endpoints/V1/ApiTokens/DeleteTokenRoute.cs index ee19e40..62f7c8d 100644 --- a/code/api/src/Endpoints/V1/ApiTokens/DeleteTokenRoute.cs +++ b/code/api/src/Endpoints/V1/ApiTokens/DeleteTokenRoute.cs @@ -18,7 +18,7 @@ public class DeleteTokenRoute : RouteBaseSync.WithRequest<Guid>.WithActionResult [ApiVersion(ApiSpecV1.VERSION_STRING)] [HttpDelete("~/v{version:apiVersion}/api-tokens/delete")] public override ActionResult Handle(Guid id) { - var token = _database.AccessTokens.SingleOrDefault(c => c.Id == id); + var token = _database.AccessTokens.FirstOrDefault(c => c.Id == id); if (token == default) { _logger.LogWarning("A deletion request of an already deleted (maybe) api token was received."); return NotFound(); @@ -28,4 +28,4 @@ public class DeleteTokenRoute : RouteBaseSync.WithRequest<Guid>.WithActionResult _database.SaveChanges(); return Ok(); } -}
\ No newline at end of file +} diff --git a/code/api/src/Endpoints/V1/RouteBaseAsync.cs b/code/api/src/Endpoints/V1/RouteBaseAsync.cs index 33b6f5f..cc30aa6 100644 --- a/code/api/src/Endpoints/V1/RouteBaseAsync.cs +++ b/code/api/src/Endpoints/V1/RouteBaseAsync.cs @@ -5,69 +5,69 @@ namespace IOL.GreatOffice.Api.Endpoints.V1; /// </summary> public class RouteBaseAsync { - public class WithRequest<TRequest> - { - public abstract class WithResult<TResponse> : V1_EndpointBase - { - public abstract Task<TResponse> HandleAsync( - TRequest request, - CancellationToken cancellationToken = default - ); - } + public class WithRequest<TRequest> + { + public abstract class WithResult<TResponse> : V1_EndpointBase + { + public abstract Task<TResponse> HandleAsync( + TRequest request, + CancellationToken cancellationToken = default + ); + } - public abstract class WithoutResult : V1_EndpointBase - { - public abstract Task HandleAsync( - TRequest request, - CancellationToken cancellationToken = default - ); - } + public abstract class WithoutResult : V1_EndpointBase + { + public abstract Task HandleAsync( + TRequest request, + CancellationToken cancellationToken = default + ); + } - public abstract class WithActionResult<TResponse> : V1_EndpointBase - { - public abstract Task<ActionResult<TResponse>> HandleAsync( - TRequest request, - CancellationToken cancellationToken = default - ); - } + public abstract class WithActionResult<TResponse> : V1_EndpointBase + { + public abstract Task<ActionResult<TResponse>> HandleAsync( + TRequest request, + CancellationToken cancellationToken = default + ); + } - public abstract class WithActionResult : V1_EndpointBase - { - public abstract Task<ActionResult> HandleAsync( - TRequest request, - CancellationToken cancellationToken = default - ); - } - } + public abstract class WithActionResult : V1_EndpointBase + { + public abstract Task<ActionResult> HandleAsync( + TRequest request, + CancellationToken cancellationToken = default + ); + } + } - public static class WithoutRequest - { - public abstract class WithResult<TResponse> : V1_EndpointBase - { - public abstract Task<TResponse> HandleAsync( - CancellationToken cancellationToken = default - ); - } + public static class WithoutRequest + { + public abstract class WithResult<TResponse> : V1_EndpointBase + { + public abstract Task<TResponse> HandleAsync( + CancellationToken cancellationToken = default + ); + } - public abstract class WithoutResult : V1_EndpointBase - { - public abstract Task HandleAsync( - CancellationToken cancellationToken = default - ); - } + public abstract class WithoutResult : V1_EndpointBase + { + public abstract Task HandleAsync( + CancellationToken cancellationToken = default + ); + } - public abstract class WithActionResult<TResponse> : V1_EndpointBase - { - public abstract Task<ActionResult<TResponse>> HandleAsync( - CancellationToken cancellationToken = default - ); - } + public abstract class WithActionResult<TResponse> : V1_EndpointBase + { + public abstract Task<ActionResult<TResponse>> HandleAsync( + CancellationToken cancellationToken = default + ); + } - public abstract class WithActionResult : V1_EndpointBase - { - public abstract Task<ActionResult> HandleAsync( - CancellationToken cancellationToken = default - ); - } - } -} + public abstract class WithActionResult : V1_EndpointBase + { + public abstract Task<ActionResult> HandleAsync( + CancellationToken cancellationToken = default + ); + } + } +}
\ No newline at end of file diff --git a/code/api/src/Endpoints/V1/RouteBaseSync.cs b/code/api/src/Endpoints/V1/RouteBaseSync.cs index 6a86074..3a06d14 100644 --- a/code/api/src/Endpoints/V1/RouteBaseSync.cs +++ b/code/api/src/Endpoints/V1/RouteBaseSync.cs @@ -5,49 +5,49 @@ namespace IOL.GreatOffice.Api.Endpoints.V1; /// </summary> public static class RouteBaseSync { - public static class WithRequest<TRequest> - { - public abstract class WithResult<TResponse> : V1_EndpointBase - { - public abstract TResponse Handle(TRequest request); - } + public static class WithRequest<TRequest> + { + public abstract class WithResult<TResponse> : V1_EndpointBase + { + public abstract TResponse Handle(TRequest request); + } - public abstract class WithoutResult : V1_EndpointBase - { - public abstract void Handle(TRequest request); - } + public abstract class WithoutResult : V1_EndpointBase + { + public abstract void Handle(TRequest request); + } - public abstract class WithActionResult<TResponse> : V1_EndpointBase - { - public abstract ActionResult<TResponse> Handle(TRequest request); - } + public abstract class WithActionResult<TResponse> : V1_EndpointBase + { + public abstract ActionResult<TResponse> Handle(TRequest request); + } - public abstract class WithActionResult : V1_EndpointBase - { - public abstract ActionResult Handle(TRequest request); - } - } + public abstract class WithActionResult : V1_EndpointBase + { + public abstract ActionResult Handle(TRequest request); + } + } - public static class WithoutRequest - { - public abstract class WithResult<TResponse> : V1_EndpointBase - { - public abstract TResponse Handle(); - } + public static class WithoutRequest + { + public abstract class WithResult<TResponse> : V1_EndpointBase + { + public abstract TResponse Handle(); + } - public abstract class WithoutResult : V1_EndpointBase - { - public abstract void Handle(); - } + public abstract class WithoutResult : V1_EndpointBase + { + public abstract void Handle(); + } - public abstract class WithActionResult<TResponse> : V1_EndpointBase - { - public abstract ActionResult<TResponse> Handle(); - } + public abstract class WithActionResult<TResponse> : V1_EndpointBase + { + public abstract ActionResult<TResponse> Handle(); + } - public abstract class WithActionResult : V1_EndpointBase - { - public abstract ActionResult Handle(); - } - } -} + public abstract class WithActionResult : V1_EndpointBase + { + public abstract ActionResult Handle(); + } + } +}
\ No newline at end of file diff --git a/code/api/src/Endpoints/V1/V1_EndpointBase.cs b/code/api/src/Endpoints/V1/V1_EndpointBase.cs index 08ce4ab..a5835a5 100644 --- a/code/api/src/Endpoints/V1/V1_EndpointBase.cs +++ b/code/api/src/Endpoints/V1/V1_EndpointBase.cs @@ -7,11 +7,11 @@ namespace IOL.GreatOffice.Api.Endpoints.V1; public class V1_EndpointBase : EndpointBase { private const string AuthSchemes = CookieAuthenticationDefaults.AuthenticationScheme + "," + AppConstants.BASIC_AUTH_SCHEME; - + protected bool IsApiCall() { - if (!Request.Headers.ContainsKey("Authorization")) return false; + if (!Request.Headers.TryGetValue("Authorization", out var value)) return false; try { - var authHeader = AuthenticationHeaderValue.Parse(Request.Headers["Authorization"]); + var authHeader = AuthenticationHeaderValue.Parse(value); if (authHeader.Parameter == null) return false; } catch { return false; @@ -21,7 +21,7 @@ public class V1_EndpointBase : EndpointBase } protected bool HasApiPermission(string permission_key) { - var permission_claim = User.Claims.SingleOrDefault(c => c.Type == permission_key); + var permission_claim = User.Claims.FirstOrDefault(c => c.Type == permission_key); return permission_claim is { Value: "True" }; diff --git a/code/api/src/Models/Database/BaseWithOwner.cs b/code/api/src/Models/Database/BaseWithOwner.cs index 3c29c76..40789ee 100644 --- a/code/api/src/Models/Database/BaseWithOwner.cs +++ b/code/api/src/Models/Database/BaseWithOwner.cs @@ -5,41 +5,36 @@ namespace IOL.GreatOffice.Api.Models.Database; /// </summary> public abstract class BaseWithOwner : Base { - protected BaseWithOwner() { } + protected BaseWithOwner() { } - protected BaseWithOwner(Guid createdBy) - { - CreatedBy = createdBy; - } + protected BaseWithOwner(Guid createdBy) { + CreatedBy = createdBy; + } - protected BaseWithOwner(LoggedInUserModel loggedInUser) - { - CreatedBy = loggedInUser.Id; - } + protected BaseWithOwner(LoggedInUserModel loggedInUser) { + CreatedBy = loggedInUser.Id; + } - public Guid? UserId { get; private set; } - public Guid? TenantId { get; private set; } - public Guid? ModifiedBy { get; private set; } - public Guid? CreatedBy { get; private set; } - public Guid? DeletedBy { get; private set; } - public User OwningUser { get; set; } - public Tenant OwningTenant { get; set; } + public Guid? UserId { get; private set; } + public Guid? TenantId { get; private set; } + public Guid? ModifiedBy { get; private set; } + public Guid? CreatedBy { get; private set; } + public Guid? DeletedBy { get; private set; } + public User OwningUser { get; set; } + public Tenant OwningTenant { get; set; } - public void SetDeleted(Guid userId) - { - DeletedBy = userId; - base.SetDeleted(); - } + public void SetDeleted(Guid userId) { + DeletedBy = userId; + base.SetDeleted(); + } - public void SetModified(Guid userId) - { - ModifiedBy = userId; - base.SetModified(); - } + public void SetModified(Guid userId) { + ModifiedBy = userId; + base.SetModified(); + } - public void SetOwnerIds(Guid userId = default, Guid tenantId = default) - { - if (tenantId != default) TenantId = tenantId; - if (userId != default) UserId = userId; - } -} + public void SetOwnerIds(Guid userId = default, Guid tenantId = default) { + if (tenantId != default) TenantId = tenantId; + if (userId != default) UserId = userId; + } +}
\ No newline at end of file diff --git a/code/api/src/Models/Database/MainAppDatabase.cs b/code/api/src/Models/Database/MainAppDatabase.cs index cba7269..18f534e 100644 --- a/code/api/src/Models/Database/MainAppDatabase.cs +++ b/code/api/src/Models/Database/MainAppDatabase.cs @@ -4,106 +4,106 @@ namespace IOL.GreatOffice.Api.Models.Database; public class MainAppDatabase : DbContext, IDataProtectionKeyContext { - public MainAppDatabase(DbContextOptions<MainAppDatabase> options) : base(options) { } - public DbSet<User> Users { get; set; } - public DbSet<PasswordResetRequest> PasswordResetRequests { get; set; } - public DbSet<ApiAccessToken> AccessTokens { get; set; } - public DbSet<Tenant> Tenants { get; set; } - public DbSet<DataProtectionKey> DataProtectionKeys { get; set; } - public DbSet<Project> Projects { get; set; } - public DbSet<ProjectLabel> ProjectLabels { get; set; } - public DbSet<Customer> Customers { get; set; } - public DbSet<CustomerContact> CustomersContacts { get; set; } - public DbSet<CustomerEvent> CustomerEvents { get; set; } - public DbSet<CustomerGroup> CustomerGroups { get; set; } - public DbSet<TodoLabel> TodoLabels { get; set; } - public DbSet<TodoCollectionAccessControl> TodoProjectAccessControls { get; set; } - public DbSet<TodoCollection> TodoProjects { get; set; } - public DbSet<TodoComment> TodoComments { get; set; } - public DbSet<Todo> Todos { get; set; } - public DbSet<ValidationEmail> ValidationEmails { get; set; } + public MainAppDatabase(DbContextOptions<MainAppDatabase> options) : base(options) { } + public DbSet<User> Users { get; set; } + public DbSet<PasswordResetRequest> PasswordResetRequests { get; set; } + public DbSet<ApiAccessToken> AccessTokens { get; set; } + public DbSet<Tenant> Tenants { get; set; } + public DbSet<DataProtectionKey> DataProtectionKeys { get; set; } + public DbSet<Project> Projects { get; set; } + public DbSet<ProjectLabel> ProjectLabels { get; set; } + public DbSet<Customer> Customers { get; set; } + public DbSet<CustomerContact> CustomersContacts { get; set; } + public DbSet<CustomerEvent> CustomerEvents { get; set; } + public DbSet<CustomerGroup> CustomerGroups { get; set; } + public DbSet<TodoLabel> TodoLabels { get; set; } + public DbSet<TodoCollectionAccessControl> TodoProjectAccessControls { get; set; } + public DbSet<TodoCollection> TodoProjects { get; set; } + public DbSet<TodoComment> TodoComments { get; set; } + public DbSet<Todo> Todos { get; set; } + public DbSet<ValidationEmail> ValidationEmails { get; set; } - protected override void OnModelCreating(ModelBuilder modelBuilder) { - modelBuilder.Entity<User>(e => { - e.HasMany(n => n.Tenants); - e.ToTable("users"); - }); - modelBuilder.Entity<PasswordResetRequest>(e => { - e.HasOne(c => c.User); - e.ToTable("password_reset_requests"); - }); - modelBuilder.Entity<ApiAccessToken>(e => { - e.HasOne(n => n.User); - e.ToTable("api_access_tokens"); - }); - modelBuilder.Entity<Tenant>(e => { - e.HasMany(n => n.Users); - e.ToTable("tenants"); - }); - modelBuilder.Entity<Project>(e => { - e.HasMany(n => n.Members); - e.HasMany(n => n.Customers); - e.ToTable("projects"); - }); - modelBuilder.Entity<ProjectMember>(e => { - e.HasOne(n => n.Project); - e.HasOne(n => n.User); - e.ToTable("project_members"); - }); - modelBuilder.Entity<ProjectLabel>(e => { - e.HasOne(n => n.Project); - e.ToTable("project_labels"); - }); - modelBuilder.Entity<Customer>(e => { - e.HasOne(n => n.Owner); - e.HasMany(n => n.Events); - e.HasMany(n => n.Contacts); - e.HasMany(n => n.Groups); - e.HasMany(n => n.Projects); - e.ToTable("customers"); - }); - modelBuilder.Entity<CustomerContact>(e => { - e.HasOne(n => n.Customer); - e.ToTable("customer_contacts"); - }); - modelBuilder.Entity<CustomerEvent>(e => { - e.HasOne(n => n.Customer); - e.ToTable("customer_events"); - }); - modelBuilder.Entity<CustomerGroup>(e => { - e.HasMany(n => n.Customers); - e.ToTable("customer_groups"); - }); - modelBuilder.Entity<Todo>(e => { - e.HasOne(n => n.Collection); - e.HasOne(n => n.AssignedTo); - e.HasOne(n => n.ClosedBy); - e.HasMany(n => n.Labels); - e.HasMany(n => n.Comments); - e.ToTable("todos"); - }); - modelBuilder.Entity<TodoCollection>(e => { - e.HasOne(n => n.Project); - e.HasMany(n => n.AccessControls); - e.ToTable("todo_collections"); - }); - modelBuilder.Entity<TodoComment>(e => { - e.HasOne(n => n.Todo); - e.ToTable("todo_comments"); - }); - modelBuilder.Entity<TodoLabel>(e => { - e.HasOne(n => n.Todo); - e.ToTable("todo_labels"); - }); - modelBuilder.Entity<TodoCollectionAccessControl>(e => { - e.HasOne(n => n.User); - e.HasOne(n => n.Collection); - e.ToTable("todo_collection_access_controls"); - }); - modelBuilder.Entity<ValidationEmail>(e => { - e.ToTable("validation_emails"); - }); + protected override void OnModelCreating(ModelBuilder modelBuilder) { + modelBuilder.Entity<User>(e => { + e.HasMany(n => n.Tenants); + e.ToTable("users"); + }); + modelBuilder.Entity<PasswordResetRequest>(e => { + e.HasOne(c => c.User); + e.ToTable("password_reset_requests"); + }); + modelBuilder.Entity<ApiAccessToken>(e => { + e.HasOne(n => n.User); + e.ToTable("api_access_tokens"); + }); + modelBuilder.Entity<Tenant>(e => { + e.HasMany(n => n.Users); + e.ToTable("tenants"); + }); + modelBuilder.Entity<Project>(e => { + e.HasMany(n => n.Members); + e.HasMany(n => n.Customers); + e.ToTable("projects"); + }); + modelBuilder.Entity<ProjectMember>(e => { + e.HasOne(n => n.Project); + e.HasOne(n => n.User); + e.ToTable("project_members"); + }); + modelBuilder.Entity<ProjectLabel>(e => { + e.HasOne(n => n.Project); + e.ToTable("project_labels"); + }); + modelBuilder.Entity<Customer>(e => { + e.HasOne(n => n.Owner); + e.HasMany(n => n.Events); + e.HasMany(n => n.Contacts); + e.HasMany(n => n.Groups); + e.HasMany(n => n.Projects); + e.ToTable("customers"); + }); + modelBuilder.Entity<CustomerContact>(e => { + e.HasOne(n => n.Customer); + e.ToTable("customer_contacts"); + }); + modelBuilder.Entity<CustomerEvent>(e => { + e.HasOne(n => n.Customer); + e.ToTable("customer_events"); + }); + modelBuilder.Entity<CustomerGroup>(e => { + e.HasMany(n => n.Customers); + e.ToTable("customer_groups"); + }); + modelBuilder.Entity<Todo>(e => { + e.HasOne(n => n.Collection); + e.HasOne(n => n.AssignedTo); + e.HasOne(n => n.ClosedBy); + e.HasMany(n => n.Labels); + e.HasMany(n => n.Comments); + e.ToTable("todos"); + }); + modelBuilder.Entity<TodoCollection>(e => { + e.HasOne(n => n.Project); + e.HasMany(n => n.AccessControls); + e.ToTable("todo_collections"); + }); + modelBuilder.Entity<TodoComment>(e => { + e.HasOne(n => n.Todo); + e.ToTable("todo_comments"); + }); + modelBuilder.Entity<TodoLabel>(e => { + e.HasOne(n => n.Todo); + e.ToTable("todo_labels"); + }); + modelBuilder.Entity<TodoCollectionAccessControl>(e => { + e.HasOne(n => n.User); + e.HasOne(n => n.Collection); + e.ToTable("todo_collection_access_controls"); + }); + modelBuilder.Entity<ValidationEmail>(e => { + e.ToTable("validation_emails"); + }); - base.OnModelCreating(modelBuilder); - } + base.OnModelCreating(modelBuilder); + } } diff --git a/code/api/src/Models/Misc/ApiSpecDocument.cs b/code/api/src/Models/Misc/ApiSpecDocument.cs index a515baf..8cf928d 100644 --- a/code/api/src/Models/Misc/ApiSpecDocument.cs +++ b/code/api/src/Models/Misc/ApiSpecDocument.cs @@ -1,4 +1,4 @@ -namespace IOL.GreatOffice.Api.Models.Models; +namespace IOL.GreatOffice.Api.Models.Misc; public class ApiSpecDocument { diff --git a/code/api/src/Models/Misc/AppConfiguration.cs b/code/api/src/Models/Misc/AppConfiguration.cs index a71970c..f7fc428 100644 --- a/code/api/src/Models/Misc/AppConfiguration.cs +++ b/code/api/src/Models/Misc/AppConfiguration.cs @@ -2,7 +2,7 @@ using System.Diagnostics; using System.Security.Cryptography.X509Certificates; using System.Text; -namespace IOL.GreatOffice.Api.Models.Models; +namespace IOL.GreatOffice.Api.Models.Misc; public class AppConfiguration { diff --git a/code/api/src/Models/Misc/AppPath.cs b/code/api/src/Models/Misc/AppPath.cs index 5a8c206..c020425 100644 --- a/code/api/src/Models/Misc/AppPath.cs +++ b/code/api/src/Models/Misc/AppPath.cs @@ -1,4 +1,4 @@ -namespace IOL.GreatOffice.Api.Models.Models; +namespace IOL.GreatOffice.Api.Models.Misc; public sealed record AppPath { diff --git a/code/api/src/Models/Misc/KnownProblemModel.cs b/code/api/src/Models/Misc/KnownProblemModel.cs index 5a9927f..1c948d8 100644 --- a/code/api/src/Models/Misc/KnownProblemModel.cs +++ b/code/api/src/Models/Misc/KnownProblemModel.cs @@ -1,4 +1,4 @@ -namespace IOL.GreatOffice.Api.Models.Models; +namespace IOL.GreatOffice.Api.Models.Misc; public class KnownProblemModel { diff --git a/code/api/src/Models/Misc/LoggedInUserModel.cs b/code/api/src/Models/Misc/LoggedInUserModel.cs index ce2b163..49d05d4 100644 --- a/code/api/src/Models/Misc/LoggedInUserModel.cs +++ b/code/api/src/Models/Misc/LoggedInUserModel.cs @@ -1,4 +1,4 @@ -namespace IOL.GreatOffice.Api.Models.Models; +namespace IOL.GreatOffice.Api.Models.Misc; public class LoggedInUserModel { diff --git a/code/api/src/Models/Misc/RequestTimeZoneInfo.cs b/code/api/src/Models/Misc/RequestTimeZoneInfo.cs index 4d9d8c1..9e7201c 100644 --- a/code/api/src/Models/Misc/RequestTimeZoneInfo.cs +++ b/code/api/src/Models/Misc/RequestTimeZoneInfo.cs @@ -1,4 +1,4 @@ -namespace IOL.GreatOffice.Api.Models.Models; +namespace IOL.GreatOffice.Api.Models.Misc; public class RequestTimeZoneInfo { diff --git a/code/api/src/Models/Static/AppConstants.cs b/code/api/src/Models/Static/AppConstants.cs index edd5bf0..85bf3db 100644 --- a/code/api/src/Models/Static/AppConstants.cs +++ b/code/api/src/Models/Static/AppConstants.cs @@ -2,11 +2,10 @@ namespace IOL.GreatOffice.Api.Models.Static; public static class AppConstants { - public const string API_NAME = "Greatoffice API"; - public const string BASIC_AUTH_SCHEME = "BasicAuthenticationScheme"; - public const string TOKEN_ALLOW_READ = "TOKEN_ALLOW_READ"; - public const string TOKEN_ALLOW_CREATE = "TOKEN_ALLOW_CREATE"; - public const string TOKEN_ALLOW_UPDATE = "TOKEN_ALLOW_UPDATE"; - public const string TOKEN_ALLOW_DELETE = "TOKEN_ALLOW_DELETE"; - public const string VAULT_CACHE_KEY = "VAULT_CACHE_KEY"; -} + public const string API_NAME = "Greatoffice API"; + public const string BASIC_AUTH_SCHEME = "BasicAuthenticationScheme"; + public const string TOKEN_ALLOW_READ = "TOKEN_ALLOW_READ"; + public const string TOKEN_ALLOW_CREATE = "TOKEN_ALLOW_CREATE"; + public const string TOKEN_ALLOW_UPDATE = "TOKEN_ALLOW_UPDATE"; + public const string TOKEN_ALLOW_DELETE = "TOKEN_ALLOW_DELETE"; +}
\ No newline at end of file diff --git a/code/api/src/Program.cs b/code/api/src/Program.cs index 4fa6c9f..9e4301a 100644 --- a/code/api/src/Program.cs +++ b/code/api/src/Program.cs @@ -10,7 +10,7 @@ global using System.Text.Json; global using System.Text.Json.Serialization; global using IOL.GreatOffice.Api.Models.Database; global using IOL.GreatOffice.Api.Models.Enums; -global using IOL.GreatOffice.Api.Models.Models; +global using IOL.GreatOffice.Api.Models.Misc; global using IOL.GreatOffice.Api.Models.Static; global using IOL.GreatOffice.Api.Services; global using IOL.GreatOffice.Api.Resources; diff --git a/code/api/src/Services/PasswordResetService.cs b/code/api/src/Services/PasswordResetService.cs index 7f70ad1..5dabd4d 100644 --- a/code/api/src/Services/PasswordResetService.cs +++ b/code/api/src/Services/PasswordResetService.cs @@ -22,7 +22,7 @@ public class PasswordResetService { var request = await _database.PasswordResetRequests .Include(c => c.User) - .SingleOrDefaultAsync(c => c.Id == id, cancellationToken); + .FirstOrDefaultAsync(c => c.Id == id, cancellationToken); if (request == default) { return default; @@ -104,4 +104,4 @@ If you did not request a password reset, no action is required. await _database.SaveChangesAsync(cancellationToken); _logger.LogInformation($"Deleted {deleteCount} stale password reset requests."); } -}
\ No newline at end of file +} |
