Cleanup and more fixes

This commit is contained in:
Jonathan Bourdon
2024-06-20 16:27:44 -04:00
parent d787535732
commit f57b693cd9
10 changed files with 57 additions and 1025 deletions

View File

@@ -25,6 +25,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
Directory.Packages.props = Directory.Packages.props
global.json = global.json
README.md = README.md
start-infrastructure.sh = start-infrastructure.sh
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Web", "src\Web\Web.csproj", "{4E4EE20C-F06A-4A1B-851F-C5577796941C}"

View File

@@ -15,22 +15,13 @@ namespace Hutopy.Infrastructure;
public static class DependencyInjection
{
public static IServiceCollection AddInfrastructureServices(this IServiceCollection services, IConfiguration configuration)
public static IServiceCollection AddInfrastructureServices(this IServiceCollection services,
IConfiguration configuration)
{
// Replace password in the connection string with env var in local environment.
// Prod will use the connectionString stored in the vault with password in it directly.
var connectionString = configuration.GetConnectionString("DefaultConnection") ?? "";
var dbPassword = configuration["DB_PASSWORD"] ?? "";
var dbHost = configuration["DB_HOST"] ?? "localhost";
if (dbPassword != string.Empty)
{
connectionString = connectionString.Replace("{DB_PASSWORD}", dbPassword);
connectionString = connectionString.Replace("{DB_HOST}", dbHost);
}
Guard.Against.Null(connectionString, message: "Connection string 'DefaultConnection' not found.");
var connectionString = configuration.GetConnectionString("DefaultConnection")
?? throw new InvalidOperationException("Missing ConnectionString: DefaultConnection");
services.AddScoped<ISaveChangesInterceptor, AuditableEntityInterceptor>();
services.AddScoped<ISaveChangesInterceptor, DispatchDomainEventsInterceptor>();
@@ -49,15 +40,9 @@ public static class DependencyInjection
.AddBearerToken(IdentityConstants.BearerScheme);
services.AddAuthorizationBuilder();
services.AddIdentityCore<ApplicationUser>(options =>
{
options.Password.RequireDigit = false;
options.Password.RequireLowercase = false;
options.Password.RequireUppercase = false;
options.Password.RequireNonAlphanumeric = false;
options.Password.RequiredLength = 8;
})
services
.AddIdentityCore<ApplicationUser>()
.AddRoles<IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddApiEndpoints()

View File

@@ -39,25 +39,6 @@ public static class DependencyInjection
services.AddEndpointsApiExplorer();
services.AddOpenApiDocument((configure, sp) =>
{
configure.Title = "Hutopy API";
// Add JWT
configure.AddSecurity(
"JWT",
[],
new OpenApiSecurityScheme
{
Type = OpenApiSecuritySchemeType.ApiKey,
Name = "Authorization",
In = OpenApiSecurityApiKeyLocation.Header,
Description = "Type into the textbox: Bearer {your JWT token}."
});
configure.OperationProcessors.Add(new AspNetCoreOperationSecurityScopeProcessor("JWT"));
});
return services;
}
@@ -78,7 +59,8 @@ public static class DependencyInjection
public static IServiceCollection AddAuthorizationAndAuthentication(this IServiceCollection services,
ConfigurationManager configuration)
{
var authenticationBuilder = services.AddAuthentication(options =>
var authenticationBuilder = services
.AddAuthentication(options =>
{
options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;
@@ -86,8 +68,7 @@ public static class DependencyInjection
.AddCookie("Identity.Application", options =>
{
options.LoginPath = "/api/Users/login";
})
.AddCookie();
});
var authJwt = configuration.GetSection("Authentication:Jwt");
if (authJwt.Exists())

View File

@@ -4,6 +4,8 @@ using Hutopy.Infrastructure.Data;
using Hutopy.Web;
using Azure.Identity;
using Microsoft.AspNetCore.HttpOverrides;
using NSwag;
using NSwag.Generation.Processors.Security;
var builder = WebApplication.CreateBuilder(args);
@@ -48,6 +50,25 @@ builder.Services.AddWebServices();
builder.Services.AddAuthorizationAndAuthentication(builder.Configuration);
builder.Services.AddControllers();
builder.Services.AddOpenApiDocument((configure, sp) =>
{
configure.Title = "Hutopy API";
// Add JWT
configure.AddSecurity(
"JWT",
[],
new OpenApiSecurityScheme
{
Type = OpenApiSecuritySchemeType.ApiKey,
Name = "Authorization",
In = OpenApiSecurityApiKeyLocation.Header,
Description = "Type into the textbox: Bearer {your JWT token}."
});
configure.OperationProcessors.Add(new AspNetCoreOperationSecurityScopeProcessor("JWT"));
});
var app = builder.Build();
app.UseForwardedHeaders(
@@ -75,22 +96,18 @@ app.UseHealthChecks("/health");
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseSwaggerUi(settings =>
if (app.Environment.IsDevelopment())
{
settings.Path = "/api";
settings.DocumentPath = "/api/specification.json";
});
app.UseOpenApi();
app.UseSwaggerUi(options => options.Path = "/api");
}
app.MapControllerRoute(
name: "default",
pattern: "{controller}/{action=Index}/{id?}");
app.MapFallbackToFile("index.html");
app.UseExceptionHandler(options => { });
app.Map("/", () => Results.Redirect("/api"));
//TODO: validate the behavior
// app.UseExceptionHandler();
app.MapEndpoints();
app.Run();

View File

@@ -8,9 +8,9 @@
}
},
"profiles": {
"Hutopy.Web": {
"Hutopy.Web - DEV": {
"commandName": "Project",
"launchBrowser": true,
"launchBrowser": false,
"applicationUrl": "https://localhost:5001;http://localhost:5000",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
@@ -18,7 +18,7 @@
},
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"launchBrowser": false,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}

View File

@@ -7,46 +7,26 @@
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Application\Application.csproj" />
<ProjectReference Include="..\Infrastructure\Infrastructure.csproj" />
<ProjectReference Include="..\Application\Application.csproj"/>
<ProjectReference Include="..\Infrastructure\Infrastructure.csproj"/>
</ItemGroup>
<ItemGroup>
<PackageReference Include="Azure.Extensions.AspNetCore.Configuration.Secrets" />
<PackageReference Include="Azure.Identity" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.Facebook" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.Google" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" />
<PackageReference Include="Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore" />
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" />
<PackageReference Include="Microsoft.AspNetCore.OpenApi" />
<PackageReference Include="Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore" />
<PackageReference Include="NSwag.AspNetCore" />
<PackageReference Include="Azure.Extensions.AspNetCore.Configuration.Secrets"/>
<PackageReference Include="Azure.Identity"/>
<PackageReference Include="Microsoft.AspNetCore.Authentication.Facebook"/>
<PackageReference Include="Microsoft.AspNetCore.Authentication.Google"/>
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer"/>
<PackageReference Include="Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore"/>
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore"/>
<PackageReference Include="Microsoft.AspNetCore.OpenApi"/>
<PackageReference Include="Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore"/>
<PackageReference Include="NSwag.AspNetCore"/>
<PackageReference Include="Microsoft.EntityFrameworkCore.Design">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="NSwag.MSBuild">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="FluentValidation.AspNetCore" />
<PackageReference Include="FluentValidation.AspNetCore"/>
</ItemGroup>
<!-- Auto-generated Open API specification and Angular TypeScript clients -->
<PropertyGroup>
<RunPostBuildEvent>OnBuildSuccess</RunPostBuildEvent>
</PropertyGroup>
<Target Name="NSwag" AfterTargets="PostBuildEvent" Condition=" '$(Configuration)' == 'Debug' And '$(SkipNSwag)' != 'True' ">
<Exec ConsoleToMSBuild="true" ContinueOnError="true" WorkingDirectory="$(ProjectDir)" EnvironmentVariables="ASPNETCORE_ENVIRONMENT=Development" Command="$(NSwagExe_Net80) run config.nswag /variables:Configuration=$(Configuration)">
<Output TaskParameter="ExitCode" PropertyName="NSwagExitCode" />
<Output TaskParameter="ConsoleOutput" PropertyName="NSwagOutput" />
</Exec>
<Message Text="$(NSwagOutput)" Condition="'$(NSwagExitCode)' == '0'" Importance="low" />
<Error Text="$(NSwagOutput)" Condition="'$(NSwagExitCode)' != '0'" />
</Target>
</Project>

View File

@@ -8,7 +8,7 @@
}
},
"ConnectionStrings": {
"DefaultConnection": "Server=localhost,1433;Database=Hutopy;User Id=sa;Password=P@ssword123!;MultipleActiveResultSets=true;TrustServerCertificate=True"
"DefaultConnection": "Server=localhost,1433;Initial Catalog=Hutopy;User Id=sa;Password=P@ssword123!;MultipleActiveResultSets=true;TrustServerCertificate=True"
},
"Authentication": {
"Jwt": {

View File

@@ -1,63 +0,0 @@
{
"runtime": "Net80",
"defaultVariables": null,
"documentGenerator": {
"aspNetCoreToOpenApi": {
"project": "Web.csproj",
"msBuildProjectExtensionsPath": null,
"configuration": null,
"runtime": null,
"targetFramework": null,
"noBuild": true,
"msBuildOutputPath": null,
"verbose": false,
"workingDirectory": null,
"requireParametersWithoutDefault": true,
"apiGroupNames": null,
"defaultPropertyNameHandling": "CamelCase",
"defaultReferenceTypeNullHandling": "Null",
"defaultDictionaryValueReferenceTypeNullHandling": "NotNull",
"defaultResponseReferenceTypeNullHandling": "NotNull",
"generateOriginalParameterNames": true,
"defaultEnumHandling": "Integer",
"flattenInheritanceHierarchy": false,
"generateKnownTypes": true,
"generateEnumMappingDescription": false,
"generateXmlObjects": false,
"generateAbstractProperties": false,
"generateAbstractSchemas": true,
"ignoreObsoleteProperties": false,
"allowReferencesWithProperties": false,
"useXmlDocumentation": true,
"resolveExternalXmlDocumentation": true,
"excludedTypeNames": [],
"serviceHost": null,
"serviceBasePath": null,
"serviceSchemes": [],
"infoTitle": "Hutopy API",
"infoDescription": null,
"infoVersion": "1.0.0",
"documentTemplate": null,
"documentProcessorTypes": [],
"operationProcessorTypes": [],
"typeNameGeneratorType": null,
"schemaNameGeneratorType": null,
"contractResolverType": null,
"serializerSettingsType": null,
"useDocumentProvider": true,
"documentName": "v1",
"aspNetCoreEnvironment": null,
"createWebHostBuilderMethod": null,
"startupType": null,
"allowNullableBodyParameters": true,
"useHttpAttributeNameAsOperationId": false,
"output": "wwwroot/api/specification.json",
"outputType": "OpenApi3",
"newLineBehavior": "Auto",
"assemblyPaths": [],
"assemblyConfig": null,
"referencePaths": [],
"useNuGetCache": false
}
}
}

View File

@@ -1,869 +0,0 @@
{
"x-generator": "NSwag v14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))",
"openapi": "3.0.0",
"info": {
"title": "Hutopy API",
"version": "1.0.0"
},
"paths": {
"/api/GetMyUser": {
"get": {
"tags": [
"GetMyUser"
],
"operationId": "GetCurrentUser",
"responses": {
"200": {
"description": "",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/UserDto"
}
}
}
}
},
"security": [
{
"JWT": []
}
]
}
},
"/api/GetMyUser/profile-picture": {
"get": {
"tags": [
"GetMyUser"
],
"operationId": "GetCurrentUserProfilePicture",
"responses": {
"200": {
"description": "",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Stream"
}
}
}
}
},
"security": [
{
"JWT": []
}
]
}
},
"/api/GetMyUser/profile-picture-2": {
"patch": {
"tags": [
"GetMyUser"
],
"operationId": "PatchApiGetMyUserProfilePicture2",
"responses": {
"200": {
"description": "",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Stream"
}
}
}
}
},
"security": [
{
"JWT": []
}
]
}
},
"/api/JoinUs": {
"get": {
"tags": [
"JoinUs"
],
"operationId": "GetFutureCreators",
"parameters": [
{
"name": "PageNumber",
"in": "query",
"required": true,
"schema": {
"type": "integer",
"format": "int32"
},
"x-position": 1
},
{
"name": "PageSize",
"in": "query",
"required": true,
"schema": {
"type": "integer",
"format": "int32"
},
"x-position": 2
}
],
"responses": {
"200": {
"description": "",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/PaginatedListOfFutureCreatorListDto"
}
}
}
}
}
},
"post": {
"tags": [
"JoinUs"
],
"operationId": "CreateFutureCreator",
"requestBody": {
"x-name": "command",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CreateFutureCreatorCommand"
}
}
},
"required": true,
"x-position": 1
},
"responses": {
"200": {
"description": "",
"content": {
"application/json": {
"schema": {
"type": "string",
"format": "guid"
}
}
}
}
}
}
},
"/api/Stripe/confirmTransaction": {
"post": {
"tags": [
"Stripe"
],
"operationId": "ConfirmTransaction",
"requestBody": {
"x-name": "command",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ConfirmStripeTransactionCommand"
}
}
},
"required": true,
"x-position": 1
},
"responses": {
"200": {
"description": "",
"content": {
"application/json": {
"schema": {
"type": "string"
}
}
}
}
}
}
},
"/api/Stripe/getMyLastReceipt": {
"get": {
"tags": [
"Stripe"
],
"operationId": "GetMyLastReceipt",
"parameters": [
{
"name": "Email",
"in": "query",
"required": true,
"schema": {
"type": "string",
"nullable": true
},
"x-position": 1
},
{
"name": "CreatorId",
"in": "query",
"required": true,
"schema": {
"type": "string",
"nullable": true
},
"x-position": 2
}
],
"responses": {
"200": {
"description": "",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/MyLastReceiptDto"
}
}
}
}
}
}
},
"/api/Stripe": {
"post": {
"tags": [
"Stripe"
],
"operationId": "CreateSessionCheckout",
"requestBody": {
"x-name": "command",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CreateSessionCheckoutCommand"
}
}
},
"required": true,
"x-position": 1
},
"responses": {
"200": {
"description": "",
"content": {
"application/json": {
"schema": {
"type": "string"
}
}
}
}
}
}
},
"/api/Users": {
"post": {
"tags": [
"Users"
],
"operationId": "CreateUser",
"requestBody": {
"x-name": "command",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CreateUserCommand"
}
}
},
"required": true,
"x-position": 1
},
"responses": {
"200": {
"description": "",
"content": {
"application/json": {
"schema": {
"type": "string",
"format": "guid"
}
}
}
}
}
},
"get": {
"tags": [
"Users"
],
"operationId": "GetMinimalUser",
"parameters": [
{
"name": "UserId",
"in": "query",
"schema": {
"type": "string",
"nullable": true
},
"x-position": 1
},
{
"name": "UserName",
"in": "query",
"schema": {
"type": "string",
"nullable": true
},
"x-position": 2
}
],
"responses": {
"200": {
"description": "",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/MinimalUserDto"
}
}
}
}
}
}
},
"/api/Users/login": {
"post": {
"tags": [
"Users"
],
"operationId": "Login",
"requestBody": {
"x-name": "command",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/LoginCommand"
}
}
},
"required": true,
"x-position": 1
},
"responses": {
"200": {
"description": "",
"content": {
"application/json": {
"schema": {
"type": "string"
}
}
}
}
}
}
},
"/api/Users/upload-profile-picture": {
"post": {
"tags": [
"Users"
],
"operationId": "UploadProfilePicture",
"requestBody": {
"x-name": "stream",
"content": {
"application/octet-stream": {
"schema": {
"type": "string",
"format": "binary",
"nullable": false
}
}
},
"required": true,
"x-position": 1
},
"responses": {
"200": {
"description": "",
"content": {
"application/json": {
"schema": {
"type": "string"
}
}
}
}
}
}
},
"/api/WeatherForecasts": {
"get": {
"tags": [
"WeatherForecasts"
],
"operationId": "GetWeatherForecasts",
"responses": {
"200": {
"description": "",
"content": {
"application/json": {
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/WeatherForecast"
}
}
}
}
}
},
"security": [
{
"JWT": []
}
]
}
},
"/api/facebook/sign-in": {
"get": {
"tags": [
"Facebook"
],
"operationId": "Facebook_SignIn",
"responses": {
"200": {
"description": ""
}
}
}
},
"/api/google/sign-in": {
"post": {
"tags": [
"Google"
],
"operationId": "Google_SignIn",
"requestBody": {
"x-name": "request",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/GoogleSignInRequest"
}
}
},
"required": true,
"x-position": 1
},
"responses": {
"200": {
"description": "",
"content": {
"application/octet-stream": {
"schema": {
"type": "string",
"format": "binary"
}
}
}
}
}
}
}
},
"components": {
"schemas": {
"UserDto": {
"type": "object",
"additionalProperties": false,
"properties": {
"id": {
"type": "string",
"format": "guid"
},
"firstName": {
"type": "string"
},
"lastName": {
"type": "string"
},
"userName": {
"type": "string"
},
"userTransactions": {
"type": "array",
"items": {
"$ref": "#/components/schemas/UserTransactionDto"
}
},
"userRoles": {
"type": "array",
"items": {
"type": "string"
}
},
"totalBalance": {
"type": "number",
"format": "decimal"
}
}
},
"UserTransactionDto": {
"type": "object",
"additionalProperties": false,
"properties": {
"amount": {
"type": "number",
"format": "decimal"
},
"currency": {
"type": "string"
},
"tipMessage": {
"type": "string"
},
"created": {
"type": "string",
"format": "date-time"
},
"isConfirmed": {
"type": "boolean"
}
}
},
"Stream": {
"allOf": [
{
"$ref": "#/components/schemas/MarshalByRefObject"
},
{
"type": "object",
"x-abstract": true,
"additionalProperties": false,
"properties": {
"canRead": {
"type": "boolean"
},
"canWrite": {
"type": "boolean"
},
"canSeek": {
"type": "boolean"
},
"canTimeout": {
"type": "boolean"
},
"length": {
"type": "integer",
"format": "int64"
},
"position": {
"type": "integer",
"format": "int64"
},
"readTimeout": {
"type": "integer",
"format": "int32"
},
"writeTimeout": {
"type": "integer",
"format": "int32"
}
}
}
]
},
"MarshalByRefObject": {
"type": "object",
"x-abstract": true,
"additionalProperties": false
},
"PaginatedListOfFutureCreatorListDto": {
"type": "object",
"additionalProperties": false,
"properties": {
"items": {
"type": "array",
"items": {
"$ref": "#/components/schemas/FutureCreatorListDto"
}
},
"pageNumber": {
"type": "integer",
"format": "int32"
},
"totalPages": {
"type": "integer",
"format": "int32"
},
"totalCount": {
"type": "integer",
"format": "int32"
},
"hasPreviousPage": {
"type": "boolean"
},
"hasNextPage": {
"type": "boolean"
}
}
},
"FutureCreatorListDto": {
"type": "object",
"additionalProperties": false,
"properties": {
"id": {
"type": "string",
"format": "guid"
},
"firstName": {
"type": "string"
},
"lastName": {
"type": "string"
}
}
},
"CreateFutureCreatorCommand": {
"type": "object",
"additionalProperties": false,
"properties": {
"firstName": {
"type": "string"
},
"lastName": {
"type": "string"
},
"emailAddress": {
"type": "string"
},
"phoneNumber": {
"type": "string"
},
"socialNetworkAccount": {
"type": "string"
},
"reasonToJoin": {
"type": "string"
}
}
},
"ConfirmStripeTransactionCommand": {
"type": "object",
"additionalProperties": false,
"properties": {
"id": {
"type": "string"
},
"object": {
"type": "string"
},
"created": {
"type": "integer",
"format": "int32"
},
"data": {
"$ref": "#/components/schemas/Data"
},
"request": {
"$ref": "#/components/schemas/Request"
}
}
},
"Data": {
"type": "object",
"additionalProperties": false,
"properties": {
"object": {
"$ref": "#/components/schemas/Object"
}
}
},
"Object": {
"type": "object",
"additionalProperties": false,
"properties": {
"id": {
"type": "string"
},
"amount": {
"type": "integer",
"format": "int32"
},
"billing_details": {
"$ref": "#/components/schemas/BillingDetails"
},
"calculated_statement_descriptor": {
"type": "string"
},
"currency": {
"type": "string"
},
"paid": {
"type": "boolean"
},
"payment_intent": {
"type": "string"
},
"payment_method": {
"type": "string"
},
"receipt_url": {
"type": "string"
},
"status": {
"type": "string"
},
"failure_message": {
"type": "string"
}
}
},
"BillingDetails": {
"type": "object",
"additionalProperties": false,
"properties": {
"email": {
"type": "string"
},
"name": {
"type": "string"
},
"phone": {
"type": "string"
}
}
},
"Request": {
"type": "object",
"additionalProperties": false,
"properties": {
"id": {
"type": "string"
}
}
},
"MyLastReceiptDto": {
"type": "object",
"additionalProperties": false,
"properties": {
"receiptUrl": {
"type": "string"
}
}
},
"CreateSessionCheckoutCommand": {
"type": "object",
"additionalProperties": false,
"properties": {
"creatorId": {
"type": "string"
},
"amount": {
"type": "integer",
"format": "int32"
},
"currency": {
"type": "string"
},
"tipMessage": {
"type": "string"
}
}
},
"CreateUserCommand": {
"type": "object",
"additionalProperties": false,
"properties": {
"firstName": {
"type": "string"
},
"lastName": {
"type": "string"
},
"emailAddress": {
"type": "string"
},
"userName": {
"type": "string"
},
"password": {
"type": "string"
}
}
},
"LoginCommand": {
"type": "object",
"additionalProperties": false,
"properties": {
"emailAddress": {
"type": "string"
},
"password": {
"type": "string"
}
}
},
"MinimalUserDto": {
"type": "object",
"additionalProperties": false,
"properties": {
"firstName": {
"type": "string"
},
"lastName": {
"type": "string"
},
"userName": {
"type": "string"
}
}
},
"WeatherForecast": {
"type": "object",
"additionalProperties": false,
"properties": {
"date": {
"type": "string",
"format": "date-time"
},
"temperatureC": {
"type": "integer",
"format": "int32"
},
"temperatureF": {
"type": "integer",
"format": "int32"
},
"summary": {
"type": "string",
"nullable": true
}
}
},
"GoogleSignInRequest": {
"type": "object",
"additionalProperties": false,
"properties": {
"accessToken": {
"type": "string"
}
}
}
},
"securitySchemes": {
"JWT": {
"type": "apiKey",
"description": "Type into the textbox: Bearer {your JWT token}.",
"name": "Authorization",
"in": "header"
}
}
},
"security": [
{
"JWT": []
}
]
}

View File

@@ -35,11 +35,11 @@ public class TestcontainersTestDatabase : ITestDatabase
var context = new ApplicationDbContext(options);
context.Database.Migrate();
await context.Database.MigrateAsync();
_respawner = await Respawner.CreateAsync(_connectionString, new RespawnerOptions
{
TablesToIgnore = new Respawn.Graph.Table[] { "__EFMigrationsHistory" }
TablesToIgnore = ["__EFMigrationsHistory"]
});
}