diff --git a/Dockerfile b/Dockerfile index 736695a..1823be6 100644 --- a/Dockerfile +++ b/Dockerfile @@ -4,20 +4,30 @@ WORKDIR /app EXPOSE 8080 EXPOSE 8081 -FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/dotnet/sdk:8.0 AS build +ARG TARGETARCH +ARG BUILDPLATFORM ARG BUILD_CONFIGURATION=Release + WORKDIR /src -COPY ["Galaeth.CoreApi/Galaeth.CoreApi.csproj", "Galaeth.CoreApi/"] -RUN dotnet restore "Galaeth.CoreApi/Galaeth.CoreApi.csproj" + +COPY ["Galaeth.ApiServer/Galaeth.ApiServer.csproj", "Galaeth.ApiServer/"] +COPY ["Galaeth.Core/Galaeth.Core.csproj", "Galaeth.Core/"] +COPY ["Galaeth.Services/Galaeth.Services.csproj", "Galaeth.Services/"] +COPY ["Galaeth.DAL/Galaeth.DAL.csproj", "Galaeth.DAL/"] + +RUN dotnet restore "Galaeth.ApiServer/Galaeth.ApiServer.csproj" COPY . . -WORKDIR "/src/Galaeth.CoreApi" -RUN dotnet build "Galaeth.CoreApi.csproj" -c $BUILD_CONFIGURATION -o /app/build +WORKDIR "/src/Galaeth.ApiServer" +RUN dotnet build "Galaeth.ApiServer.csproj" -c $BUILD_CONFIGURATION -a $TARGETARCH -o /app/build FROM build AS publish +ARG TARGETARCH ARG BUILD_CONFIGURATION=Release -RUN dotnet publish "Galaeth.CoreApi.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false + +RUN dotnet publish "Galaeth.ApiServer.csproj" --no-restore -c $BUILD_CONFIGURATION -a $TARGETARCH -o /app/publish /p:UseAppHost=false FROM base AS final WORKDIR /app COPY --from=publish /app/publish . -ENTRYPOINT ["dotnet", "Galaeth.CoreApi.dll"] +ENTRYPOINT ["dotnet", "Galaeth.ApiServer.dll"] diff --git a/Galaeth.ApiServer/Controllers/AuthenticationController.cs b/Galaeth.ApiServer/Controllers/AuthenticationController.cs index 6561150..fd20411 100644 --- a/Galaeth.ApiServer/Controllers/AuthenticationController.cs +++ b/Galaeth.ApiServer/Controllers/AuthenticationController.cs @@ -5,7 +5,6 @@ using Galaeth.Services.Interfaces; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using MyCSharp.HttpUserAgentParser.AspNetCore; -using Toycloud.AspNetCore.Mvc.ModelBinding; namespace Galaeth.ApiServer.Controllers; @@ -40,7 +39,7 @@ public class AuthenticationController : ApiController /// If successful, instance of . [AllowAnonymous] [HttpPost("login")] - public async Task Authenticate([FromBodyOrDefault] AuthenticateRequest request) + public async Task Authenticate(AuthenticateRequest request) { if (request is null) { @@ -72,7 +71,7 @@ public class AuthenticationController : ApiController /// If successful, instance of . [AllowAnonymous] [HttpPost("refresh")] - public async Task RefreshSession([FromBodyOrDefault] RefreshUserAuthRequest userAuthRequest) + public async Task RefreshSession(RefreshUserAuthRequest userAuthRequest) { if (userAuthRequest is null) { @@ -101,7 +100,7 @@ public class AuthenticationController : ApiController /// /// Instance of . [HttpPost("pwd")] - public async Task ChangePassword([FromBodyOrDefault] ChangePasswordRequest request) + public async Task ChangePassword(ChangePasswordRequest request) { if (request is null) { diff --git a/Galaeth.ApiServer/Controllers/UserSelfController.cs b/Galaeth.ApiServer/Controllers/MeController.cs similarity index 88% rename from Galaeth.ApiServer/Controllers/UserSelfController.cs rename to Galaeth.ApiServer/Controllers/MeController.cs index 2cce7fd..89df699 100644 --- a/Galaeth.ApiServer/Controllers/UserSelfController.cs +++ b/Galaeth.ApiServer/Controllers/MeController.cs @@ -11,17 +11,17 @@ namespace Galaeth.ApiServer.Controllers; [ApiController] [Authorize] [Route("v1/me")] -public class UserSelfController : ApiController +public class MeController : ApiController { private readonly IIdentityProvider _identityProvider; private readonly IUserService _userService; /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// Instance of . /// Instance of . - public UserSelfController( + public MeController( IIdentityProvider identityProvider, IUserService userService) { diff --git a/Galaeth.ApiServer/Galaeth.ApiServer.csproj b/Galaeth.ApiServer/Galaeth.ApiServer.csproj index 3f16f4b..f98e33a 100644 --- a/Galaeth.ApiServer/Galaeth.ApiServer.csproj +++ b/Galaeth.ApiServer/Galaeth.ApiServer.csproj @@ -24,7 +24,9 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - + + + diff --git a/Galaeth.ApiServer/Models/ChangePasswordRequest.cs b/Galaeth.ApiServer/Models/ChangePasswordRequest.cs index ce73c05..d8d8cfe 100644 --- a/Galaeth.ApiServer/Models/ChangePasswordRequest.cs +++ b/Galaeth.ApiServer/Models/ChangePasswordRequest.cs @@ -1,3 +1,5 @@ +using System.Text.Json.Serialization; + namespace Galaeth.ApiServer.Models; /// @@ -8,10 +10,12 @@ public class ChangePasswordRequest /// /// The user's old password. /// + [JsonPropertyName("oldPassword")] public string OldPassword { get; set; } /// /// The user's new password. /// + [JsonPropertyName("newPassword")] public string NewPassword { get; set; } } diff --git a/Galaeth.ApiServer/Program.cs b/Galaeth.ApiServer/Program.cs index 8db04d5..65d23dc 100644 --- a/Galaeth.ApiServer/Program.cs +++ b/Galaeth.ApiServer/Program.cs @@ -5,10 +5,10 @@ using Galaeth.Core.Configuration; using Galaeth.Services.Configuration; using Galaeth.Services.Profiles; using Microsoft.AspNetCore.Authentication.JwtBearer; +using Microsoft.OpenApi.Models; using MyCSharp.HttpUserAgentParser.AspNetCore.DependencyInjection; using MyCSharp.HttpUserAgentParser.MemoryCache.DependencyInjection; using Serilog; -using Serilog.Events; namespace Galaeth.ApiServer; @@ -32,9 +32,6 @@ internal static class Program Log.Logger = new LoggerConfiguration() .Enrich.FromLogContext() - .MinimumLevel.Override("Default", LogEventLevel.Warning) - .MinimumLevel.Override("Microsoft", LogEventLevel.Warning) - .MinimumLevel.Override("System", LogEventLevel.Warning) .WriteTo.Console() .CreateLogger(); @@ -56,6 +53,32 @@ internal static class Program builder.Services.AddHttpContextAccessor(); builder.Services.AddControllers(); + builder.Services.AddEndpointsApiExplorer(); + builder.Services.AddSwaggerGen(setup => + { + var jwtSecurityScheme = new OpenApiSecurityScheme + { + BearerFormat = "JWT", + Name = "JWT Authentication", + In = ParameterLocation.Header, + Type = SecuritySchemeType.Http, + Scheme = JwtBearerDefaults.AuthenticationScheme, + Description = "Paste your access token below", + Reference = new OpenApiReference + { + Id = JwtBearerDefaults.AuthenticationScheme, + Type = ReferenceType.SecurityScheme, + }, + }; + + setup.AddSecurityDefinition(jwtSecurityScheme.Reference.Id, jwtSecurityScheme); + + setup.AddSecurityRequirement(new OpenApiSecurityRequirement + { + { jwtSecurityScheme, Array.Empty() }, + }); + }); + // Setup authentication. var jwtConfig = new JwtConfiguration(); builder.Configuration.Bind("JWT", jwtConfig); @@ -83,6 +106,12 @@ internal static class Program app.UseMiddleware(); app.UseMiddleware(); + if (app.Environment.IsDevelopment()) + { + app.UseSwagger(); + app.UseSwaggerUI(); + } + app.UseAuthorization(); app.MapControllers(); diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..ade316a --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,30 @@ +services: + api-server: + image: forge.alveus.dev/misc/galaeth-api:latest + build: . + container_name: "galaeth-api-server" + restart: on-failure + ports: + - 8080:8080 + environment: + ASPNETCORE_ENVIRONMENT: 'Development' + EmailDomainBlacklist__Enabled: false + Database__ConnectionString: 'Server=postgres;Port=5432;User Id=postgres;Password=postgres;Database=galaeth' + InitialUser__Username: 'admin' + InitialUser__Email: 'admin@change.me' + InitialUser__Password: 'Change!Me1234' + JWT__SecretKey: "11ca143299193d9968d31cb85cb30991820ed9dc231aac902ba38abf25b7b6f904e1d614391001e49d8b8af28c4f79b48bb7853ef20bf06a38c17cf8c3f694c0" + JWT__Issuer: 'localdev' + JWT__Audience: 'localdev' + + db: + image: postgres:17.1-bookworm + container_name: postgres + restart: on-failure + environment: + POSTGRES_USER: 'postgres' + POSTGRES_PASSWORD: 'postgres' + POSTGRES_DB: 'galaeth' + + +