Add swagger, tidy up, fix docker, and add docker-compose.yml

This commit is contained in:
Mike 2024-11-17 11:59:08 +00:00
parent ba9f063fd6
commit 1c597e2115
7 changed files with 93 additions and 19 deletions

View file

@ -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"]

View file

@ -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
/// <returns>If successful, instance of <see cref="AccessTokensDto"/>.</returns>
[AllowAnonymous]
[HttpPost("login")]
public async Task<IActionResult> Authenticate([FromBodyOrDefault] AuthenticateRequest request)
public async Task<IActionResult> Authenticate(AuthenticateRequest request)
{
if (request is null)
{
@ -72,7 +71,7 @@ public class AuthenticationController : ApiController
/// <returns>If successful, instance of <see cref="AccessTokensDto"/>.</returns>
[AllowAnonymous]
[HttpPost("refresh")]
public async Task<IActionResult> RefreshSession([FromBodyOrDefault] RefreshUserAuthRequest userAuthRequest)
public async Task<IActionResult> RefreshSession(RefreshUserAuthRequest userAuthRequest)
{
if (userAuthRequest is null)
{
@ -101,7 +100,7 @@ public class AuthenticationController : ApiController
/// </summary>
/// <param name="request">Instance of <see cref="ChangePasswordRequest"/>.</param>
[HttpPost("pwd")]
public async Task<IActionResult> ChangePassword([FromBodyOrDefault] ChangePasswordRequest request)
public async Task<IActionResult> ChangePassword(ChangePasswordRequest request)
{
if (request is null)
{

View file

@ -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;
/// <summary>
/// Initializes a new instance of the <see cref="UserSelfController"/> class.
/// Initializes a new instance of the <see cref="MeController"/> class.
/// </summary>
/// <param name="identityProvider">Instance of <see cref="IIdentityProvider"/>.</param>
/// <param name="userService">Instance of <see cref="IUserService"/>.</param>
public UserSelfController(
public MeController(
IIdentityProvider identityProvider,
IUserService userService)
{

View file

@ -24,7 +24,9 @@
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Toycloud.AspNetCore.Mvc.ModelBinding.BodyOrDefaultBinding" Version="1.2.1" />
<PackageReference Include="Swashbuckle.AspNetCore.Swagger" Version="7.0.0" />
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerGen" Version="7.0.0" />
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerUI" Version="7.0.0" />
</ItemGroup>
<ItemGroup>

View file

@ -1,3 +1,5 @@
using System.Text.Json.Serialization;
namespace Galaeth.ApiServer.Models;
/// <summary>
@ -8,10 +10,12 @@ public class ChangePasswordRequest
/// <summary>
/// The user's old password.
/// </summary>
[JsonPropertyName("oldPassword")]
public string OldPassword { get; set; }
/// <summary>
/// The user's new password.
/// </summary>
[JsonPropertyName("newPassword")]
public string NewPassword { get; set; }
}

View file

@ -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<string>() },
});
});
// Setup authentication.
var jwtConfig = new JwtConfiguration();
builder.Configuration.Bind("JWT", jwtConfig);
@ -83,6 +106,12 @@ internal static class Program
app.UseMiddleware<ExceptionMiddleware>();
app.UseMiddleware<StatusCodeMiddleware>();
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseAuthorization();
app.MapControllers();

30
docker-compose.yml Normal file
View file

@ -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'