From bbcefcf76f52afe5166615e0b61df157430833f0 Mon Sep 17 00:00:00 2001 From: Dominic Villemure Date: Sat, 9 Mar 2024 20:25:30 -0500 Subject: [PATCH 001/229] First commit. Include junk from template to remove --- .azure/bicep/main.bicep | 362 +++++ .editorconfig | 382 +++++ .github/FUNDING.yml | 13 + .github/workflows/build.yml | 82 ++ .github/workflows/cicd.yml | 42 + .github/workflows/deploy.yml | 107 ++ .gitignore | 480 +++++++ .scripts/checks.ps1 | 29 + .scripts/cleanup.ps1 | 78 + .scripts/environments.json | 5 + .scripts/setup.ps1 | 210 +++ Directory.Build.props | 10 + Directory.Packages.props | 38 + Hutopy.sln | 91 ++ README.md | 75 + global.json | 6 + src/Application/Application.csproj | 19 + .../Behaviours/AuthorizationBehaviour.cs | 79 ++ .../Common/Behaviours/LoggingBehaviour.cs | 34 + .../Common/Behaviours/PerformanceBehaviour.cs | 53 + .../Behaviours/UnhandledExceptionBehaviour.cs | 29 + .../Common/Behaviours/ValidationBehaviour.cs | 35 + .../Exceptions/ForbiddenAccessException.cs | 6 + .../Common/Exceptions/ValidationException.cs | 22 + .../Interfaces/IApplicationDbContext.cs | 12 + .../Common/Interfaces/IIdentityService.cs | 16 + src/Application/Common/Interfaces/IUser.cs | 6 + .../Common/Mappings/MappingExtensions.cs | 12 + src/Application/Common/Models/LookupDto.cs | 19 + .../Common/Models/PaginatedList.cs | 29 + src/Application/Common/Models/Result.cs | 24 + .../Common/Security/AuthorizeAttribute.cs | 23 + src/Application/DependencyInjection.cs | 25 + src/Application/GlobalUsings.cs | 6 + .../Commands/CreateTodoItem/CreateTodoItem.cs | 40 + .../CreateTodoItemCommandValidator.cs | 11 + .../Commands/DeleteTodoItem/DeleteTodoItem.cs | 35 + .../Commands/UpdateTodoItem/UpdateTodoItem.cs | 35 + .../UpdateTodoItemCommandValidator.cs | 11 + .../UpdateTodoItemDetail.cs | 39 + .../TodoItemCompletedEventHandler.cs | 21 + .../TodoItemCreatedEventHandler.cs | 21 + .../GetTodoItemsWithPagination.cs | 34 + ...etTodoItemsWithPaginationQueryValidator.cs | 16 + .../TodoItemBriefDto.cs | 22 + .../Commands/CreateTodoList/CreateTodoList.cs | 32 + .../CreateTodoListCommandValidator.cs | 26 + .../Commands/DeleteTodoList/DeleteTodoList.cs | 28 + .../Commands/PurgeTodoLists/PurgeTodoLists.cs | 26 + .../Commands/UpdateTodoList/UpdateTodoList.cs | 33 + .../UpdateTodoListCommandValidator.cs | 27 + .../TodoLists/Queries/GetTodos/GetTodos.cs | 38 + .../TodoLists/Queries/GetTodos/TodoItemDto.cs | 27 + .../TodoLists/Queries/GetTodos/TodoListDto.cs | 27 + .../TodoLists/Queries/GetTodos/TodosVm.cs | 10 + .../GetWeatherForecastsQuery.cs | 25 + .../GetWeatherForecasts/WeatherForecast.cs | 12 + src/Domain/Common/BaseAuditableEntity.cs | 12 + src/Domain/Common/BaseEntity.cs | 30 + src/Domain/Common/BaseEvent.cs | 7 + src/Domain/Common/ValueObject.cs | 45 + src/Domain/Constants/Policies.cs | 7 + src/Domain/Constants/Roles.cs | 6 + src/Domain/Domain.csproj | 12 + src/Domain/Entities/TodoItem.cs | 31 + src/Domain/Entities/TodoList.cs | 10 + src/Domain/Enums/PriorityLevel.cs | 9 + src/Domain/Events/TodoItemCompletedEvent.cs | 11 + src/Domain/Events/TodoItemCreatedEvent.cs | 11 + src/Domain/Events/TodoItemDeletedEvent.cs | 11 + .../Exceptions/UnsupportedColourException.cs | 9 + src/Domain/GlobalUsings.cs | 6 + src/Domain/ValueObjects/Colour.cs | 69 + .../Data/ApplicationDbContext.cs | 23 + .../Data/ApplicationDbContextInitialiser.cs | 109 ++ .../Configurations/TodoItemConfiguration.cs | 15 + .../Configurations/TodoListConfiguration.cs | 18 + .../AuditableEntityInterceptor.cs | 64 + .../DispatchDomainEventsInterceptor.cs | 50 + .../00000000000000_InitialCreate.Designer.cs | 399 ++++++ .../00000000000000_InitialCreate.cs | 281 ++++ .../ApplicationDbContextModelSnapshot.cs | 396 ++++++ src/Infrastructure/DependencyInjection.cs | 58 + src/Infrastructure/GlobalUsings.cs | 1 + .../Identity/ApplicationUser.cs | 7 + .../Identity/IdentityResultExtensions.cs | 14 + .../Identity/IdentityService.cs | 80 ++ src/Infrastructure/Infrastructure.csproj | 20 + src/Web/DependencyInjection.cs | 66 + src/Web/Endpoints/TodoItems.cs | 52 + src/Web/Endpoints/TodoLists.cs | 42 + src/Web/Endpoints/Users.cs | 12 + src/Web/Endpoints/WeatherForecasts.cs | 18 + src/Web/GlobalUsings.cs | 3 + .../Infrastructure/CustomExceptionHandler.cs | 87 ++ src/Web/Infrastructure/EndpointGroupBase.cs | 6 + .../IEndpointRouteBuilderExtensions.cs | 46 + .../Infrastructure/MethodInfoExtensions.cs | 18 + .../WebApplicationExtensions.cs | 37 + src/Web/Pages/Error.cshtml | 26 + src/Web/Pages/Error.cshtml.cs | 25 + src/Web/Pages/Shared/_LoginPartial.cshtml | 36 + src/Web/Pages/_ViewImports.cshtml | 3 + src/Web/Program.cs | 64 + src/Web/Properties/launchSettings.json | 27 + src/Web/Services/CurrentUser.cs | 17 + src/Web/Web.csproj | 44 + src/Web/Web.http | 139 ++ src/Web/appsettings.Development.json | 10 + src/Web/appsettings.json | 13 + src/Web/config.nswag | 63 + src/Web/wwwroot/api/specification.json | 1250 +++++++++++++++++ src/Web/wwwroot/favicon.ico | Bin 0 -> 5430 bytes .../Application.FunctionalTests.csproj | 40 + .../BaseTestFixture.cs | 13 + .../CustomWebApplicationFactory.cs | 42 + .../GlobalUsings.cs | 4 + .../ITestDatabase.cs | 14 + .../SqlServerTestDatabase.cs | 62 + .../TestDatabaseFactory.cs | 13 + .../TestcontainersTestDatabase.cs | 61 + tests/Application.FunctionalTests/Testing.cs | 146 ++ .../TodoItems/Commands/CreateTodoItemTests.cs | 49 + .../TodoItems/Commands/DeleteTodoItemTests.cs | 41 + .../Commands/UpdateTodoItemDetailTests.cs | 57 + .../TodoItems/Commands/UpdateTodoItemTests.cs | 51 + .../TodoLists/Commands/CreateTodoListTests.cs | 54 + .../TodoLists/Commands/DeleteTodoListTests.cs | 32 + .../TodoLists/Commands/PurgeTodoListsTests.cs | 75 + .../TodoLists/Commands/UpdateTodoListTests.cs | 70 + .../TodoLists/Queries/GetTodosTests.cs | 61 + .../appsettings.json | 5 + .../Application.UnitTests.csproj | 26 + .../Common/Behaviours/RequestLoggerTests.cs | 45 + .../Exceptions/ValidationExceptionTests.cs | 63 + .../Common/Mappings/MappingTests.cs | 53 + .../Domain.UnitTests/Domain.UnitTests.csproj | 24 + .../ValueObjects/ColourTests.cs | 50 + .../GlobalUsings.cs | 1 + .../Infrastructure.IntegrationTests.csproj | 19 + 140 files changed, 8151 insertions(+) create mode 100644 .azure/bicep/main.bicep create mode 100644 .editorconfig create mode 100644 .github/FUNDING.yml create mode 100644 .github/workflows/build.yml create mode 100644 .github/workflows/cicd.yml create mode 100644 .github/workflows/deploy.yml create mode 100644 .gitignore create mode 100644 .scripts/checks.ps1 create mode 100644 .scripts/cleanup.ps1 create mode 100644 .scripts/environments.json create mode 100644 .scripts/setup.ps1 create mode 100644 Directory.Build.props create mode 100644 Directory.Packages.props create mode 100644 Hutopy.sln create mode 100644 README.md create mode 100644 global.json create mode 100644 src/Application/Application.csproj create mode 100644 src/Application/Common/Behaviours/AuthorizationBehaviour.cs create mode 100644 src/Application/Common/Behaviours/LoggingBehaviour.cs create mode 100644 src/Application/Common/Behaviours/PerformanceBehaviour.cs create mode 100644 src/Application/Common/Behaviours/UnhandledExceptionBehaviour.cs create mode 100644 src/Application/Common/Behaviours/ValidationBehaviour.cs create mode 100644 src/Application/Common/Exceptions/ForbiddenAccessException.cs create mode 100644 src/Application/Common/Exceptions/ValidationException.cs create mode 100644 src/Application/Common/Interfaces/IApplicationDbContext.cs create mode 100644 src/Application/Common/Interfaces/IIdentityService.cs create mode 100644 src/Application/Common/Interfaces/IUser.cs create mode 100644 src/Application/Common/Mappings/MappingExtensions.cs create mode 100644 src/Application/Common/Models/LookupDto.cs create mode 100644 src/Application/Common/Models/PaginatedList.cs create mode 100644 src/Application/Common/Models/Result.cs create mode 100644 src/Application/Common/Security/AuthorizeAttribute.cs create mode 100644 src/Application/DependencyInjection.cs create mode 100644 src/Application/GlobalUsings.cs create mode 100644 src/Application/TodoItems/Commands/CreateTodoItem/CreateTodoItem.cs create mode 100644 src/Application/TodoItems/Commands/CreateTodoItem/CreateTodoItemCommandValidator.cs create mode 100644 src/Application/TodoItems/Commands/DeleteTodoItem/DeleteTodoItem.cs create mode 100644 src/Application/TodoItems/Commands/UpdateTodoItem/UpdateTodoItem.cs create mode 100644 src/Application/TodoItems/Commands/UpdateTodoItem/UpdateTodoItemCommandValidator.cs create mode 100644 src/Application/TodoItems/Commands/UpdateTodoItemDetail/UpdateTodoItemDetail.cs create mode 100644 src/Application/TodoItems/EventHandlers/TodoItemCompletedEventHandler.cs create mode 100644 src/Application/TodoItems/EventHandlers/TodoItemCreatedEventHandler.cs create mode 100644 src/Application/TodoItems/Queries/GetTodoItemsWithPagination/GetTodoItemsWithPagination.cs create mode 100644 src/Application/TodoItems/Queries/GetTodoItemsWithPagination/GetTodoItemsWithPaginationQueryValidator.cs create mode 100644 src/Application/TodoItems/Queries/GetTodoItemsWithPagination/TodoItemBriefDto.cs create mode 100644 src/Application/TodoLists/Commands/CreateTodoList/CreateTodoList.cs create mode 100644 src/Application/TodoLists/Commands/CreateTodoList/CreateTodoListCommandValidator.cs create mode 100644 src/Application/TodoLists/Commands/DeleteTodoList/DeleteTodoList.cs create mode 100644 src/Application/TodoLists/Commands/PurgeTodoLists/PurgeTodoLists.cs create mode 100644 src/Application/TodoLists/Commands/UpdateTodoList/UpdateTodoList.cs create mode 100644 src/Application/TodoLists/Commands/UpdateTodoList/UpdateTodoListCommandValidator.cs create mode 100644 src/Application/TodoLists/Queries/GetTodos/GetTodos.cs create mode 100644 src/Application/TodoLists/Queries/GetTodos/TodoItemDto.cs create mode 100644 src/Application/TodoLists/Queries/GetTodos/TodoListDto.cs create mode 100644 src/Application/TodoLists/Queries/GetTodos/TodosVm.cs create mode 100644 src/Application/WeatherForecasts/Queries/GetWeatherForecasts/GetWeatherForecastsQuery.cs create mode 100644 src/Application/WeatherForecasts/Queries/GetWeatherForecasts/WeatherForecast.cs create mode 100644 src/Domain/Common/BaseAuditableEntity.cs create mode 100644 src/Domain/Common/BaseEntity.cs create mode 100644 src/Domain/Common/BaseEvent.cs create mode 100644 src/Domain/Common/ValueObject.cs create mode 100644 src/Domain/Constants/Policies.cs create mode 100644 src/Domain/Constants/Roles.cs create mode 100644 src/Domain/Domain.csproj create mode 100644 src/Domain/Entities/TodoItem.cs create mode 100644 src/Domain/Entities/TodoList.cs create mode 100644 src/Domain/Enums/PriorityLevel.cs create mode 100644 src/Domain/Events/TodoItemCompletedEvent.cs create mode 100644 src/Domain/Events/TodoItemCreatedEvent.cs create mode 100644 src/Domain/Events/TodoItemDeletedEvent.cs create mode 100644 src/Domain/Exceptions/UnsupportedColourException.cs create mode 100644 src/Domain/GlobalUsings.cs create mode 100644 src/Domain/ValueObjects/Colour.cs create mode 100644 src/Infrastructure/Data/ApplicationDbContext.cs create mode 100644 src/Infrastructure/Data/ApplicationDbContextInitialiser.cs create mode 100644 src/Infrastructure/Data/Configurations/TodoItemConfiguration.cs create mode 100644 src/Infrastructure/Data/Configurations/TodoListConfiguration.cs create mode 100644 src/Infrastructure/Data/Interceptors/AuditableEntityInterceptor.cs create mode 100644 src/Infrastructure/Data/Interceptors/DispatchDomainEventsInterceptor.cs create mode 100644 src/Infrastructure/Data/Migrations/00000000000000_InitialCreate.Designer.cs create mode 100644 src/Infrastructure/Data/Migrations/00000000000000_InitialCreate.cs create mode 100644 src/Infrastructure/Data/Migrations/ApplicationDbContextModelSnapshot.cs create mode 100644 src/Infrastructure/DependencyInjection.cs create mode 100644 src/Infrastructure/GlobalUsings.cs create mode 100644 src/Infrastructure/Identity/ApplicationUser.cs create mode 100644 src/Infrastructure/Identity/IdentityResultExtensions.cs create mode 100644 src/Infrastructure/Identity/IdentityService.cs create mode 100644 src/Infrastructure/Infrastructure.csproj create mode 100644 src/Web/DependencyInjection.cs create mode 100644 src/Web/Endpoints/TodoItems.cs create mode 100644 src/Web/Endpoints/TodoLists.cs create mode 100644 src/Web/Endpoints/Users.cs create mode 100644 src/Web/Endpoints/WeatherForecasts.cs create mode 100644 src/Web/GlobalUsings.cs create mode 100644 src/Web/Infrastructure/CustomExceptionHandler.cs create mode 100644 src/Web/Infrastructure/EndpointGroupBase.cs create mode 100644 src/Web/Infrastructure/IEndpointRouteBuilderExtensions.cs create mode 100644 src/Web/Infrastructure/MethodInfoExtensions.cs create mode 100644 src/Web/Infrastructure/WebApplicationExtensions.cs create mode 100644 src/Web/Pages/Error.cshtml create mode 100644 src/Web/Pages/Error.cshtml.cs create mode 100644 src/Web/Pages/Shared/_LoginPartial.cshtml create mode 100644 src/Web/Pages/_ViewImports.cshtml create mode 100644 src/Web/Program.cs create mode 100644 src/Web/Properties/launchSettings.json create mode 100644 src/Web/Services/CurrentUser.cs create mode 100644 src/Web/Web.csproj create mode 100644 src/Web/Web.http create mode 100644 src/Web/appsettings.Development.json create mode 100644 src/Web/appsettings.json create mode 100644 src/Web/config.nswag create mode 100644 src/Web/wwwroot/api/specification.json create mode 100644 src/Web/wwwroot/favicon.ico create mode 100644 tests/Application.FunctionalTests/Application.FunctionalTests.csproj create mode 100644 tests/Application.FunctionalTests/BaseTestFixture.cs create mode 100644 tests/Application.FunctionalTests/CustomWebApplicationFactory.cs create mode 100644 tests/Application.FunctionalTests/GlobalUsings.cs create mode 100644 tests/Application.FunctionalTests/ITestDatabase.cs create mode 100644 tests/Application.FunctionalTests/SqlServerTestDatabase.cs create mode 100644 tests/Application.FunctionalTests/TestDatabaseFactory.cs create mode 100644 tests/Application.FunctionalTests/TestcontainersTestDatabase.cs create mode 100644 tests/Application.FunctionalTests/Testing.cs create mode 100644 tests/Application.FunctionalTests/TodoItems/Commands/CreateTodoItemTests.cs create mode 100644 tests/Application.FunctionalTests/TodoItems/Commands/DeleteTodoItemTests.cs create mode 100644 tests/Application.FunctionalTests/TodoItems/Commands/UpdateTodoItemDetailTests.cs create mode 100644 tests/Application.FunctionalTests/TodoItems/Commands/UpdateTodoItemTests.cs create mode 100644 tests/Application.FunctionalTests/TodoLists/Commands/CreateTodoListTests.cs create mode 100644 tests/Application.FunctionalTests/TodoLists/Commands/DeleteTodoListTests.cs create mode 100644 tests/Application.FunctionalTests/TodoLists/Commands/PurgeTodoListsTests.cs create mode 100644 tests/Application.FunctionalTests/TodoLists/Commands/UpdateTodoListTests.cs create mode 100644 tests/Application.FunctionalTests/TodoLists/Queries/GetTodosTests.cs create mode 100644 tests/Application.FunctionalTests/appsettings.json create mode 100644 tests/Application.UnitTests/Application.UnitTests.csproj create mode 100644 tests/Application.UnitTests/Common/Behaviours/RequestLoggerTests.cs create mode 100644 tests/Application.UnitTests/Common/Exceptions/ValidationExceptionTests.cs create mode 100644 tests/Application.UnitTests/Common/Mappings/MappingTests.cs create mode 100644 tests/Domain.UnitTests/Domain.UnitTests.csproj create mode 100644 tests/Domain.UnitTests/ValueObjects/ColourTests.cs create mode 100644 tests/Infrastructure.IntegrationTests/GlobalUsings.cs create mode 100644 tests/Infrastructure.IntegrationTests/Infrastructure.IntegrationTests.csproj diff --git a/.azure/bicep/main.bicep b/.azure/bicep/main.bicep new file mode 100644 index 0000000..c5582a9 --- /dev/null +++ b/.azure/bicep/main.bicep @@ -0,0 +1,362 @@ +@description('The location into which your Azure resources should be deployed.') +param location string = resourceGroup().location + +@description('Select the type of environment you want to provision. Allowed values are Production, Staging, and Development.') +@allowed([ + 'Production' + 'Staging' + 'Development' +]) +param environmentName string + +@description('A unique suffix to add to resource names that need to be globally unique.') +@maxLength(13) +param resourceNameSuffix string = uniqueString(resourceGroup().id) + +@description('The administrator login username for the SQL server.') +param sqlAdministratorUsername string + +@secure() +@description('The administrator login password for the SQL server.') +param sqlAdministratorPassword string + +@description('The name of the project.') +param projectName string + +// Define the environment configuration map. +var environmentConfigurationMap = { + Production: { + environmentAbbreviation: 'prd' + appServicePlan: { + sku: { + name: 'S1' + capacity: 1 + } + } + sqlDatabase: { + sku: { + name: 'Standard' + tier: 'Standard' + } + } + } + Staging: { + environmentAbbreviation: 'stg' + appServicePlan: { + sku: { + name: 'B1' + } + } + sqlDatabase: { + sku: { + name: 'Standard' + tier: 'Standard' + } + } + } + Development: { + environmentAbbreviation: 'dev' + appServicePlan: { + sku: { + name: 'B1' + } + } + sqlDatabase: { + sku: { + name: 'Standard' + tier: 'Standard' + } + } + } +} + +// Define the names for resources. +var environmentAbbreviation = environmentConfigurationMap[environmentName].environmentAbbreviation +var keyVaultName = 'kv-${projectName}-${environmentAbbreviation}' +var appServiceAppName = 'as-${projectName}-${resourceNameSuffix}-${environmentAbbreviation}' +var appServicePlanName = 'plan-${projectName}-${environmentAbbreviation}' +var logAnalyticsWorkspaceName = 'log-${projectName}-${environmentAbbreviation}' +var applicationInsightsName = 'appi-${projectName}-${environmentAbbreviation}' +var sqlServerName = 'sql-${projectName}-${resourceNameSuffix}-${environmentAbbreviation}' +var sqlDatabaseName = '${projectName}-${environmentAbbreviation}' + +// Define the SKUs for each component based on the environment type. +var appServicePlanSku = environmentConfigurationMap[environmentName].appServicePlan.sku +var sqlDatabaseSku = environmentConfigurationMap[environmentName].sqlDatabase.sku + +resource logAnalyticsWorkspace 'Microsoft.OperationalInsights/workspaces@2020-10-01' = { + name: logAnalyticsWorkspaceName + location: location + properties: { + sku: { + name: 'PerGB2018' + } + } +} + +resource keyVault 'Microsoft.KeyVault/vaults@2019-09-01' = { + name: keyVaultName + location: location + properties: { + enabledForTemplateDeployment: true + tenantId: subscription().tenantId + accessPolicies: [] + sku: { + name: 'standard' + family: 'A' + } + } +} + +resource keyVault_ConnectionStringSecret 'Microsoft.KeyVault/vaults/secrets@2019-09-01' = { + parent: keyVault + name: 'ConnectionStrings--DefaultConnection' + properties: { + value: 'Server=tcp:${sqlServer.properties.fullyQualifiedDomainName},1433;Initial Catalog=${sqlDatabaseName};Persist Security Info=False;User ID=${sqlAdministratorUsername};Password=${sqlAdministratorPassword};MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;' + } + dependsOn: [ + sqlDatabase + ] +} + +resource keyVault_DiagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = { + scope: keyVault + name: 'keyVaultDiagnosticSettings' + properties: { + workspaceId: logAnalyticsWorkspace.id + logs: [ + { + category: 'AuditEvent' + enabled: true + } + ] + metrics: [ + { + category: 'AllMetrics' + enabled: true + } + ] + } +} + +resource appServicePlan 'Microsoft.Web/serverfarms@2021-01-15' = { + name: appServicePlanName + location: location + sku: appServicePlanSku +} + +resource appServicePlan_DiagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = { + scope: appServicePlan + name: 'appServicePlanDiagnosticSettings' + properties: { + workspaceId: logAnalyticsWorkspace.id + metrics: [ + { + category: 'AllMetrics' + enabled: true + } + ] + } +} + +resource appServiceApp 'Microsoft.Web/sites@2021-01-15' = { + name: appServiceAppName + location: location + identity: { + type: 'SystemAssigned' + } + properties: { + serverFarmId: appServicePlan.id + httpsOnly: true + siteConfig: { + healthCheckPath: '/health' + netFrameworkVersion: 'v7.0' + appSettings: [ + { + name: 'APPLICATIONINSIGHTS_CONNECTION_STRING' + value: applicationInsights.properties.ConnectionString + } + { + name: 'KeyVaultUri' + value: keyVault.properties.vaultUri + } + ] + } + } +} + +resource appServiceApp_DiagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = { + scope: appServiceApp + name: 'appServiceAppDiagnosticSettings' + properties: { + workspaceId: logAnalyticsWorkspace.id + logs: [ + { + category: 'AppServiceHTTPLogs' + enabled: true + } + { + category: 'AppServiceConsoleLogs' + enabled: true + } + { + category: 'AppServiceAppLogs' + enabled: true + } + { + category: 'AppServiceAuditLogs' + enabled: true + } + { + category: 'AppServiceIPSecAuditLogs' + enabled: true + } + { + category: 'AppServicePlatformLogs' + enabled: true + } + ] + metrics: [ + { + category: 'AllMetrics' + enabled: true + } + ] + } +} + +resource keyVault_AccessPolicy 'Microsoft.KeyVault/vaults/accessPolicies@2022-07-01' = { + parent: keyVault + name: 'add' + properties: { + accessPolicies: [ + { + tenantId: appServiceApp.identity.tenantId + objectId: appServiceApp.identity.principalId + permissions: { + keys: [ + 'Get' + ] + secrets: [ + 'Get' + 'List' + + ] + certificates: [ + 'Get' + 'List' + ] + } + } + ] + } +} + +resource applicationInsights 'Microsoft.Insights/components@2020-02-02' = { + name: applicationInsightsName + location: location + kind: 'web' + properties: { + Application_Type: 'web' + WorkspaceResourceId: logAnalyticsWorkspace.id + } +} + +resource sqlServer 'Microsoft.Sql/servers@2021-02-01-preview' = { + name: sqlServerName + location: location + properties: { + administratorLogin: sqlAdministratorUsername + administratorLoginPassword: sqlAdministratorPassword + } +} + +resource sqlDatabase 'Microsoft.Sql/servers/databases@2021-02-01-preview' = { + parent: sqlServer + name: sqlDatabaseName + location: location + sku: sqlDatabaseSku +} + +resource sqlServer_AuditingSettings 'Microsoft.Sql/servers/auditingSettings@2021-11-01-preview' = { + parent: sqlServer + name: 'default' + properties: { + state: 'Enabled' + isAzureMonitorTargetEnabled: true + } +} + +resource sqlServer_FirewallRule 'Microsoft.Sql/servers/firewallRules@2021-02-01-preview' = { + parent: sqlServer + name: 'AllowAllWindowsAzureIps' + properties: { + endIpAddress: '0.0.0.0' + startIpAddress: '0.0.0.0' + } +} + +resource sqlDatabase_DiagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = { + scope: sqlDatabase + name: 'sqlDatabaseDiagnosticSettings' + properties: { + workspaceId: logAnalyticsWorkspace.id + logs: [ + { + category: 'SQLInsights' + enabled: true + } + { + category: 'AutomaticTuning' + enabled: true + } + { + category: 'QueryStoreRuntimeStatistics' + enabled: true + } + { + category: 'QueryStoreWaitStatistics' + enabled: true + } + { + category: 'Errors' + enabled: true + } + { + category: 'DatabaseWaitStatistics' + enabled: true + } + { + category: 'Timeouts' + enabled: true + } + { + category: 'Blocks' + enabled: true + } + { + category: 'Deadlocks' + enabled: true + } + ] + metrics: [ + { + category: 'Basic' + enabled: true + } + { + category: 'InstanceAndAppAdvanced' + enabled: true + } + { + category: 'WorkloadManagement' + enabled: true + } + ] + } +} + +output appServiceAppName string = appServiceApp.name +output appServiceAppHostName string = appServiceApp.properties.defaultHostName +output sqlServerFullyQualifiedDomainName string = sqlServer.properties.fullyQualifiedDomainName +output sqlDatabaseName string = sqlDatabase.name diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..b6fb7e3 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,382 @@ +root = true + +# All files +[*] +indent_style = space + +# Xml files +[*.{xml,csproj,props,targets,ruleset,nuspec,resx}] +indent_size = 2 + +# Javascript files +[*.js] +indent_size = 2 + +# Json files +[*.{json,config,nswag}] +indent_size = 2 + +# C# files +[*.cs] + +#### Core EditorConfig Options #### + +# Indentation and spacing +indent_size = 4 +tab_width = 4 + +# New line preferences +end_of_line = lf +insert_final_newline = true + +#### .NET Coding Conventions #### +[*.{cs,vb}] + +# Organize usings +dotnet_separate_import_directive_groups = false +dotnet_sort_system_directives_first = true +file_header_template = unset + +# this. and Me. preferences +dotnet_style_qualification_for_event = false:silent +dotnet_style_qualification_for_field = false:silent +dotnet_style_qualification_for_method = false:silent +dotnet_style_qualification_for_property = false:silent + +# Language keywords vs BCL types preferences +dotnet_style_predefined_type_for_locals_parameters_members = true:silent +dotnet_style_predefined_type_for_member_access = true:silent + +# Parentheses preferences +dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:silent +dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:silent +dotnet_style_parentheses_in_other_operators = never_if_unnecessary:silent +dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:silent + +# Modifier preferences +dotnet_style_require_accessibility_modifiers = for_non_interface_members:silent + +# Expression-level preferences +dotnet_style_coalesce_expression = true:suggestion +dotnet_style_collection_initializer = true:suggestion +dotnet_style_explicit_tuple_names = true:suggestion +dotnet_style_null_propagation = true:suggestion +dotnet_style_object_initializer = true:suggestion +dotnet_style_operator_placement_when_wrapping = beginning_of_line +dotnet_style_prefer_auto_properties = true:suggestion +dotnet_style_prefer_compound_assignment = true:suggestion +dotnet_style_prefer_conditional_expression_over_assignment = true:suggestion +dotnet_style_prefer_conditional_expression_over_return = true:suggestion +dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion +dotnet_style_prefer_inferred_tuple_names = true:suggestion +dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion +dotnet_style_prefer_simplified_boolean_expressions = true:suggestion +dotnet_style_prefer_simplified_interpolation = true:suggestion + +# Field preferences +dotnet_style_readonly_field = true:warning + +# Parameter preferences +dotnet_code_quality_unused_parameters = all:suggestion + +# Suppression preferences +dotnet_remove_unnecessary_suppression_exclusions = none + +#### C# Coding Conventions #### +[*.cs] + +# var preferences +csharp_style_var_elsewhere = false:silent +csharp_style_var_for_built_in_types = false:silent +csharp_style_var_when_type_is_apparent = false:silent + +# Expression-bodied members +csharp_style_expression_bodied_accessors = true:silent +csharp_style_expression_bodied_constructors = false:silent +csharp_style_expression_bodied_indexers = true:silent +csharp_style_expression_bodied_lambdas = true:suggestion +csharp_style_expression_bodied_local_functions = false:silent +csharp_style_expression_bodied_methods = false:silent +csharp_style_expression_bodied_operators = false:silent +csharp_style_expression_bodied_properties = true:silent + +# Pattern matching preferences +csharp_style_pattern_matching_over_as_with_null_check = true:suggestion +csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion +csharp_style_prefer_not_pattern = true:suggestion +csharp_style_prefer_pattern_matching = true:silent +csharp_style_prefer_switch_expression = true:suggestion + +# Null-checking preferences +csharp_style_conditional_delegate_call = true:suggestion + +# Modifier preferences +csharp_prefer_static_local_function = true:warning +csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async:silent + +# Code-block preferences +csharp_prefer_braces = true:silent +csharp_prefer_simple_using_statement = true:suggestion + +# Expression-level preferences +csharp_prefer_simple_default_expression = true:suggestion +csharp_style_deconstructed_variable_declaration = true:suggestion +csharp_style_inlined_variable_declaration = true:suggestion +csharp_style_pattern_local_over_anonymous_function = true:suggestion +csharp_style_prefer_index_operator = true:suggestion +csharp_style_prefer_range_operator = true:suggestion +csharp_style_throw_expression = true:suggestion +csharp_style_unused_value_assignment_preference = discard_variable:suggestion +csharp_style_unused_value_expression_statement_preference = discard_variable:silent + +# 'using' directive preferences +csharp_using_directive_placement = outside_namespace:silent + +#### C# Formatting Rules #### + +# New line preferences +csharp_new_line_before_catch = true +csharp_new_line_before_else = true +csharp_new_line_before_finally = true +csharp_new_line_before_members_in_anonymous_types = true +csharp_new_line_before_members_in_object_initializers = true +csharp_new_line_before_open_brace = all +csharp_new_line_between_query_expression_clauses = true + +# Indentation preferences +csharp_indent_block_contents = true +csharp_indent_braces = false +csharp_indent_case_contents = true +csharp_indent_case_contents_when_block = true +csharp_indent_labels = one_less_than_current +csharp_indent_switch_labels = true + +# Space preferences +csharp_space_after_cast = false +csharp_space_after_colon_in_inheritance_clause = true +csharp_space_after_comma = true +csharp_space_after_dot = false +csharp_space_after_keywords_in_control_flow_statements = true +csharp_space_after_semicolon_in_for_statement = true +csharp_space_around_binary_operators = before_and_after +csharp_space_around_declaration_statements = false +csharp_space_before_colon_in_inheritance_clause = true +csharp_space_before_comma = false +csharp_space_before_dot = false +csharp_space_before_open_square_brackets = false +csharp_space_before_semicolon_in_for_statement = false +csharp_space_between_empty_square_brackets = false +csharp_space_between_method_call_empty_parameter_list_parentheses = false +csharp_space_between_method_call_name_and_opening_parenthesis = false +csharp_space_between_method_call_parameter_list_parentheses = false +csharp_space_between_method_declaration_empty_parameter_list_parentheses = false +csharp_space_between_method_declaration_name_and_open_parenthesis = false +csharp_space_between_method_declaration_parameter_list_parentheses = false +csharp_space_between_parentheses = false +csharp_space_between_square_brackets = false + +# Wrapping preferences +csharp_preserve_single_line_blocks = true +csharp_preserve_single_line_statements = true +csharp_style_namespace_declarations = file_scoped:silent +csharp_style_prefer_method_group_conversion = true:silent +csharp_style_prefer_top_level_statements = true:silent +csharp_style_prefer_primary_constructors = true:suggestion +csharp_style_prefer_null_check_over_type_check = true:suggestion +csharp_style_prefer_local_over_anonymous_function = true:suggestion +csharp_style_implicit_object_creation_when_type_is_apparent = true:suggestion +csharp_style_prefer_tuple_swap = true:suggestion +csharp_style_prefer_utf8_string_literals = true:suggestion + +#### Naming styles #### +[*.{cs,vb}] + +# Naming rules + +dotnet_naming_rule.types_and_namespaces_should_be_pascalcase.severity = suggestion +dotnet_naming_rule.types_and_namespaces_should_be_pascalcase.symbols = types_and_namespaces +dotnet_naming_rule.types_and_namespaces_should_be_pascalcase.style = pascalcase + +dotnet_naming_rule.interfaces_should_be_ipascalcase.severity = suggestion +dotnet_naming_rule.interfaces_should_be_ipascalcase.symbols = interfaces +dotnet_naming_rule.interfaces_should_be_ipascalcase.style = ipascalcase + +dotnet_naming_rule.type_parameters_should_be_tpascalcase.severity = suggestion +dotnet_naming_rule.type_parameters_should_be_tpascalcase.symbols = type_parameters +dotnet_naming_rule.type_parameters_should_be_tpascalcase.style = tpascalcase + +dotnet_naming_rule.methods_should_be_pascalcase.severity = suggestion +dotnet_naming_rule.methods_should_be_pascalcase.symbols = methods +dotnet_naming_rule.methods_should_be_pascalcase.style = pascalcase + +dotnet_naming_rule.properties_should_be_pascalcase.severity = suggestion +dotnet_naming_rule.properties_should_be_pascalcase.symbols = properties +dotnet_naming_rule.properties_should_be_pascalcase.style = pascalcase + +dotnet_naming_rule.events_should_be_pascalcase.severity = suggestion +dotnet_naming_rule.events_should_be_pascalcase.symbols = events +dotnet_naming_rule.events_should_be_pascalcase.style = pascalcase + +dotnet_naming_rule.local_variables_should_be_camelcase.severity = suggestion +dotnet_naming_rule.local_variables_should_be_camelcase.symbols = local_variables +dotnet_naming_rule.local_variables_should_be_camelcase.style = camelcase + +dotnet_naming_rule.local_constants_should_be_camelcase.severity = suggestion +dotnet_naming_rule.local_constants_should_be_camelcase.symbols = local_constants +dotnet_naming_rule.local_constants_should_be_camelcase.style = camelcase + +dotnet_naming_rule.parameters_should_be_camelcase.severity = suggestion +dotnet_naming_rule.parameters_should_be_camelcase.symbols = parameters +dotnet_naming_rule.parameters_should_be_camelcase.style = camelcase + +dotnet_naming_rule.public_fields_should_be_pascalcase.severity = suggestion +dotnet_naming_rule.public_fields_should_be_pascalcase.symbols = public_fields +dotnet_naming_rule.public_fields_should_be_pascalcase.style = pascalcase + +dotnet_naming_rule.private_fields_should_be__camelcase.severity = suggestion +dotnet_naming_rule.private_fields_should_be__camelcase.symbols = private_fields +dotnet_naming_rule.private_fields_should_be__camelcase.style = _camelcase + +dotnet_naming_rule.private_static_fields_should_be_s_camelcase.severity = suggestion +dotnet_naming_rule.private_static_fields_should_be_s_camelcase.symbols = private_static_fields +dotnet_naming_rule.private_static_fields_should_be_s_camelcase.style = s_camelcase + +dotnet_naming_rule.public_constant_fields_should_be_pascalcase.severity = suggestion +dotnet_naming_rule.public_constant_fields_should_be_pascalcase.symbols = public_constant_fields +dotnet_naming_rule.public_constant_fields_should_be_pascalcase.style = pascalcase + +dotnet_naming_rule.private_constant_fields_should_be_pascalcase.severity = suggestion +dotnet_naming_rule.private_constant_fields_should_be_pascalcase.symbols = private_constant_fields +dotnet_naming_rule.private_constant_fields_should_be_pascalcase.style = pascalcase + +dotnet_naming_rule.public_static_readonly_fields_should_be_pascalcase.severity = suggestion +dotnet_naming_rule.public_static_readonly_fields_should_be_pascalcase.symbols = public_static_readonly_fields +dotnet_naming_rule.public_static_readonly_fields_should_be_pascalcase.style = pascalcase + +dotnet_naming_rule.private_static_readonly_fields_should_be_pascalcase.severity = suggestion +dotnet_naming_rule.private_static_readonly_fields_should_be_pascalcase.symbols = private_static_readonly_fields +dotnet_naming_rule.private_static_readonly_fields_should_be_pascalcase.style = pascalcase + +dotnet_naming_rule.enums_should_be_pascalcase.severity = suggestion +dotnet_naming_rule.enums_should_be_pascalcase.symbols = enums +dotnet_naming_rule.enums_should_be_pascalcase.style = pascalcase + +dotnet_naming_rule.local_functions_should_be_pascalcase.severity = suggestion +dotnet_naming_rule.local_functions_should_be_pascalcase.symbols = local_functions +dotnet_naming_rule.local_functions_should_be_pascalcase.style = pascalcase + +dotnet_naming_rule.non_field_members_should_be_pascalcase.severity = suggestion +dotnet_naming_rule.non_field_members_should_be_pascalcase.symbols = non_field_members +dotnet_naming_rule.non_field_members_should_be_pascalcase.style = pascalcase + +# Symbol specifications + +dotnet_naming_symbols.interfaces.applicable_kinds = interface +dotnet_naming_symbols.interfaces.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.interfaces.required_modifiers = + +dotnet_naming_symbols.enums.applicable_kinds = enum +dotnet_naming_symbols.enums.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.enums.required_modifiers = + +dotnet_naming_symbols.events.applicable_kinds = event +dotnet_naming_symbols.events.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.events.required_modifiers = + +dotnet_naming_symbols.methods.applicable_kinds = method +dotnet_naming_symbols.methods.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.methods.required_modifiers = + +dotnet_naming_symbols.properties.applicable_kinds = property +dotnet_naming_symbols.properties.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.properties.required_modifiers = + +dotnet_naming_symbols.public_fields.applicable_kinds = field +dotnet_naming_symbols.public_fields.applicable_accessibilities = public, internal +dotnet_naming_symbols.public_fields.required_modifiers = + +dotnet_naming_symbols.private_fields.applicable_kinds = field +dotnet_naming_symbols.private_fields.applicable_accessibilities = private, protected, protected_internal, private_protected +dotnet_naming_symbols.private_fields.required_modifiers = + +dotnet_naming_symbols.private_static_fields.applicable_kinds = field +dotnet_naming_symbols.private_static_fields.applicable_accessibilities = private, protected, protected_internal, private_protected +dotnet_naming_symbols.private_static_fields.required_modifiers = static + +dotnet_naming_symbols.types_and_namespaces.applicable_kinds = namespace, class, struct, interface, enum +dotnet_naming_symbols.types_and_namespaces.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.types_and_namespaces.required_modifiers = + +dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method +dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.non_field_members.required_modifiers = + +dotnet_naming_symbols.type_parameters.applicable_kinds = namespace +dotnet_naming_symbols.type_parameters.applicable_accessibilities = * +dotnet_naming_symbols.type_parameters.required_modifiers = + +dotnet_naming_symbols.private_constant_fields.applicable_kinds = field +dotnet_naming_symbols.private_constant_fields.applicable_accessibilities = private, protected, protected_internal, private_protected +dotnet_naming_symbols.private_constant_fields.required_modifiers = const + +dotnet_naming_symbols.local_variables.applicable_kinds = local +dotnet_naming_symbols.local_variables.applicable_accessibilities = local +dotnet_naming_symbols.local_variables.required_modifiers = + +dotnet_naming_symbols.local_constants.applicable_kinds = local +dotnet_naming_symbols.local_constants.applicable_accessibilities = local +dotnet_naming_symbols.local_constants.required_modifiers = const + +dotnet_naming_symbols.parameters.applicable_kinds = parameter +dotnet_naming_symbols.parameters.applicable_accessibilities = * +dotnet_naming_symbols.parameters.required_modifiers = + +dotnet_naming_symbols.public_constant_fields.applicable_kinds = field +dotnet_naming_symbols.public_constant_fields.applicable_accessibilities = public, internal +dotnet_naming_symbols.public_constant_fields.required_modifiers = const + +dotnet_naming_symbols.public_static_readonly_fields.applicable_kinds = field +dotnet_naming_symbols.public_static_readonly_fields.applicable_accessibilities = public, internal +dotnet_naming_symbols.public_static_readonly_fields.required_modifiers = readonly, static + +dotnet_naming_symbols.private_static_readonly_fields.applicable_kinds = field +dotnet_naming_symbols.private_static_readonly_fields.applicable_accessibilities = private, protected, protected_internal, private_protected +dotnet_naming_symbols.private_static_readonly_fields.required_modifiers = readonly, static + +dotnet_naming_symbols.local_functions.applicable_kinds = local_function +dotnet_naming_symbols.local_functions.applicable_accessibilities = * +dotnet_naming_symbols.local_functions.required_modifiers = + +# Naming styles + +dotnet_naming_style.pascalcase.required_prefix = +dotnet_naming_style.pascalcase.required_suffix = +dotnet_naming_style.pascalcase.word_separator = +dotnet_naming_style.pascalcase.capitalization = pascal_case + +dotnet_naming_style.ipascalcase.required_prefix = I +dotnet_naming_style.ipascalcase.required_suffix = +dotnet_naming_style.ipascalcase.word_separator = +dotnet_naming_style.ipascalcase.capitalization = pascal_case + +dotnet_naming_style.tpascalcase.required_prefix = T +dotnet_naming_style.tpascalcase.required_suffix = +dotnet_naming_style.tpascalcase.word_separator = +dotnet_naming_style.tpascalcase.capitalization = pascal_case + +dotnet_naming_style._camelcase.required_prefix = _ +dotnet_naming_style._camelcase.required_suffix = +dotnet_naming_style._camelcase.word_separator = +dotnet_naming_style._camelcase.capitalization = camel_case + +dotnet_naming_style.camelcase.required_prefix = +dotnet_naming_style.camelcase.required_suffix = +dotnet_naming_style.camelcase.word_separator = +dotnet_naming_style.camelcase.capitalization = camel_case + +dotnet_naming_style.s_camelcase.required_prefix = s_ +dotnet_naming_style.s_camelcase.required_suffix = +dotnet_naming_style.s_camelcase.word_separator = +dotnet_naming_style.s_camelcase.capitalization = camel_case + +dotnet_style_namespace_match_folder = true:suggestion diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 0000000..27f72a1 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,13 @@ +# These are supported funding model platforms + +github: JasonTaylorDev # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] +# patreon: # Replace with a single Patreon username +# open_collective: # Replace with a single Open Collective username +# ko_fi: # Replace with a single Ko-fi username +# tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel +# community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry +# liberapay: # Replace with a single Liberapay username +# issuehunt: # Replace with a single IssueHunt username +# otechie: # Replace with a single Otechie username +# lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry +# custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..ce81956 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,82 @@ +name: Build + +on: + pull_request: + branches: [ main ] + paths-ignore: + - '.scripts/**' + - .gitignore + - CODE_OF_CONDUCT.md + - LICENSE + - README.md + + workflow_call: + inputs: + build-artifacts: + type: boolean + required: true + default: false + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + name: Checkout code + + - name: Cache NuGet packages + uses: actions/cache@v3 + with: + path: ~/.nuget/packages + key: ${{ runner.os }}-nuget-${{ hashFiles('**/packages.lock.json') }} + restore-keys: | + ${{ runner.os }}-nuget- + + + - name: Install .NET + uses: actions/setup-dotnet@v3 + + - name: Restore solution + run: dotnet restore + + - name: Build solution + run: dotnet build --no-restore --configuration Release + + - name: Test solution + run: dotnet test --no-build --configuration Release --filter "FullyQualifiedName!~AcceptanceTests" + + - name: Publish website + if: ${{ inputs.build-artifacts == true }} + run: | + dotnet publish --configuration Release --runtime win-x86 --self-contained --output ./publish + cd publish + zip -r ./publish.zip . + working-directory: ./src/Web/ + + - name: Upload website artifact (website) + if: ${{ inputs.build-artifacts == true }} + uses: actions/upload-artifact@v3 + with: + name: website + path: ./src/Web/publish/publish.zip + if-no-files-found: error + + - name: Create EF Core migrations bundle + if: ${{ inputs.build-artifacts == true }} + run: | + dotnet new tool-manifest + dotnet tool install dotnet-ef + dotnet ef migrations bundle --configuration Release -p ./src/Infrastructure/ -s ./src/Web/ -o efbundle.exe + zip -r ./efbundle.zip efbundle.exe + env: + SkipNSwag: True + + - name: Upload EF Core migrations bundle artifact (efbundle) + if: ${{ inputs.build-artifacts == true }} + uses: actions/upload-artifact@v3 + with: + name: efbundle + path: ./efbundle.zip + if-no-files-found: error diff --git a/.github/workflows/cicd.yml b/.github/workflows/cicd.yml new file mode 100644 index 0000000..ce67ab4 --- /dev/null +++ b/.github/workflows/cicd.yml @@ -0,0 +1,42 @@ +name: CICD + +on: + push: + branches: [ main ] + paths-ignore: + - .gitignore + - CODE_OF_CONDUCT.md + - LICENSE + - README.md + +permissions: + id-token: write + contents: read + +jobs: + + build: + uses: ./.github/workflows/build.yml + with: + build-artifacts: true + + deploy-development: + uses: ./.github/workflows/deploy.yml + secrets: inherit + needs: [ build ] + with: + environmentName: Development + + deploy-staging: + uses: ./.github/workflows/deploy.yml + secrets: inherit + needs: [ deploy-development ] + with: + environmentName: Staging + + deploy-production: + uses: ./.github/workflows/deploy.yml + secrets: inherit + needs: [ deploy-staging ] + with: + environmentName: Production \ No newline at end of file diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml new file mode 100644 index 0000000..d9b02a8 --- /dev/null +++ b/.github/workflows/deploy.yml @@ -0,0 +1,107 @@ +name: Deploy + +on: + workflow_call: + inputs: + environmentName: + required: true + type: string + +permissions: + id-token: write + contents: read + +jobs: + + validate: + runs-on: ubuntu-latest + environment: ${{ inputs.environmentName }} + + steps: + + - uses: actions/checkout@v3 + name: Checkout code + + - uses: azure/login@v1 + name: Login to Azure + with: + client-id: ${{ vars.AZURE_CLIENT_ID }} + tenant-id: ${{ vars.AZURE_TENANT_ID }} + subscription-id: ${{ vars.AZURE_SUBSCRIPTION_ID }} + + - if: inputs.environmentName == 'Development' + uses: azure/arm-deploy@v1 + name: Run preflight validation + with: + deploymentName: ${{ github.run_number }} + resourceGroupName: ${{ vars.AZURE_RESOURCE_GROUP_NAME }} + template: ./.azure/bicep/main.bicep + parameters: > + environmentName=${{ inputs.environmentName }} + sqlAdministratorUsername=${{ vars.AZURE_SQL_ADMINISTRATOR_USERNAME }} + sqlAdministratorPassword=${{ secrets.AZURE_SQL_ADMINISTRATOR_PASSWORD }} + projectName=${{ vars.PROJECT_NAME }} + deploymentMode: Validate + + - if: inputs.environmentName != 'Development' + uses: azure/arm-deploy@v1 + name: Run what-if + with: + failOnStdErr: false + resourceGroupName: ${{ vars.AZURE_RESOURCE_GROUP_NAME }} + template: ./.azure/bicep/main.bicep + parameters: > + environmentName=${{ inputs.environmentName }} + sqlAdministratorUsername=${{ vars.AZURE_SQL_ADMINISTRATOR_USERNAME }} + sqlAdministratorPassword=${{ secrets.AZURE_SQL_ADMINISTRATOR_PASSWORD }} + projectName=${{ vars.PROJECT_NAME }} + additionalArguments: --what-if + + deploy: + needs: [ validate ] + runs-on: ubuntu-latest + environment: ${{ inputs.environmentName }} + + steps: + + - uses: actions/checkout@v3 + name: Checkout code + + - uses: actions/download-artifact@v3 + name: Download artifacts + + - name: Install .NET + uses: actions/setup-dotnet@v3 + + - uses: azure/login@v1 + name: Login to Azure + with: + client-id: ${{ vars.AZURE_CLIENT_ID }} + tenant-id: ${{ vars.AZURE_TENANT_ID }} + subscription-id: ${{ vars.AZURE_SUBSCRIPTION_ID }} + + - uses: azure/arm-deploy@v1 + id: deploy + name: Deploy infrastructure + with: + failOnStdErr: false + deploymentName: ${{ github.run_number }} + resourceGroupName: ${{ vars.AZURE_RESOURCE_GROUP_NAME }} + template: ./.azure/bicep/main.bicep + parameters: > + environmentName=${{ inputs.environmentName }} + sqlAdministratorUsername=${{ vars.AZURE_SQL_ADMINISTRATOR_USERNAME }} + sqlAdministratorPassword=${{ secrets.AZURE_SQL_ADMINISTRATOR_PASSWORD }} + projectName=${{ vars.PROJECT_NAME }} + + - name: Initialise database + run: | + unzip -o ./efbundle/efbundle.zip + echo '{ "ConnectionStrings": { "DefaultConnection": "" } }' > appsettings.json + ./efbundle.exe --connection "Server=${{ steps.deploy.outputs.sqlServerFullyQualifiedDomainName }};Initial Catalog=${{ steps.deploy.outputs.sqlDatabaseName }};Persist Security Info=False;User ID=${{ vars.AZURE_SQL_ADMINISTRATOR_USERNAME }};Password=${{ secrets.AZURE_SQL_ADMINISTRATOR_PASSWORD }};MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;" --verbose + + - uses: azure/webapps-deploy@v2 + name: Deploy website + with: + app-name: ${{ steps.deploy.outputs.appServiceAppName }} + package: website/publish.zip diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..75f22e3 --- /dev/null +++ b/.gitignore @@ -0,0 +1,480 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from `dotnet new gitignore` + +# User-specific files +*.rsuser +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Mono auto generated files +mono_crash.* + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +[Ww][Ii][Nn]32/ +[Aa][Rr][Mm]/ +[Aa][Rr][Mm]64/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ +[Ll]ogs/ + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUnit +*.VisualState.xml +TestResult.xml +nunit-*.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET +project.lock.json +project.fragment.lock.json +artifacts/ + +# Tye +.tye/ + +# ASP.NET Scaffolding +ScaffoldingReadMe.txt + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_h.h +*.ilk +*.meta +*.obj +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*_wpftmp.csproj +*.log +*.tlog +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Coverlet is a free, cross platform Code Coverage Tool +coverage*.json +coverage*.xml +coverage*.info + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# NuGet Symbol Packages +*.snupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx +*.appxbundle +*.appxupload + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!?*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser +*- [Bb]ackup.rdl +*- [Bb]ackup ([0-9]).rdl +*- [Bb]ackup ([0-9][0-9]).rdl + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio 6 auto-generated project file (contains which files were open etc.) +*.vbp + +# Visual Studio 6 workspace and project file (working project files containing files to include in project) +*.dsw +*.dsp + +# Visual Studio 6 technical files +*.ncb +*.aps + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# CodeRush personal settings +.cr/personal + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ + +# Local History for Visual Studio +.localhistory/ + +# Visual Studio History (VSHistory) files +.vshistory/ + +# BeatPulse healthcheck temp database +healthchecksdb + +# Backup folder for Package Reference Convert tool in Visual Studio 2017 +MigrationBackup/ + +# Ionide (cross platform F# VS Code tools) working folder +.ionide/ + +# Fody - auto-generated XML schema +FodyWeavers.xsd + +# VS Code files for those working on multiple tools +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +*.code-workspace + +# Local History for Visual Studio Code +.history/ + +# Windows Installer files from build outputs +*.cab +*.msi +*.msix +*.msm +*.msp + +# JetBrains Rider +*.sln.iml + +## +## Visual studio for Mac +## + + +# globs +Makefile.in +*.userprefs +*.usertasks +config.make +config.status +aclocal.m4 +install-sh +autom4te.cache/ +*.tar.gz +tarballs/ +test-results/ + +# Mac bundle stuff +*.dmg +*.app + +# content below from: https://github.com/github/gitignore/blob/master/Global/macOS.gitignore +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +# content below from: https://github.com/github/gitignore/blob/master/Global/Windows.gitignore +# Windows thumbnail cache files +Thumbs.db +ehthumbs.db +ehthumbs_vista.db + +# Dump file +*.stackdump + +# Folder config file +[Dd]esktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msix +*.msm +*.msp + +# Windows shortcuts +*.lnk + +# Vim temporary swap files +*.swp diff --git a/.scripts/checks.ps1 b/.scripts/checks.ps1 new file mode 100644 index 0000000..5dbd5df --- /dev/null +++ b/.scripts/checks.ps1 @@ -0,0 +1,29 @@ +# Check if Azure CLI is installed +$azPath = (Get-Command az -ErrorAction SilentlyContinue).Source +if (-not $azPath) { + throw "Azure CLI (az) is not installed. Please install it and try again." +} + +# Check if Azure CLI is authenticated +az account show --output none +if ($LASTEXITCODE -ne 0) { + throw "Azure CLI (az) is not authenticated. Please authenticate with Azure CLI and try again." +} + +# Check if GitHub CLI is installed +$ghPath = (Get-Command gh -ErrorAction SilentlyContinue).Source +if (-not $ghPath) { + throw "GitHub CLI (gh) is not installed. Please install it and try again." +} + +# Check if GitHub CLI is authenticated +gh auth status | Out-Null +if ($LASTEXITCODE -ne 0) { + throw "GitHub CLI (gh) is not authenticated. Please authenticate with GitHub CLI and try again." +} + +# Check if Git repo is initialised +git status | Out-Null +if ($LASTEXITCODE -ne 0) { + throw "The Git repository has not been initialised. Please create a new GitHub repository and try again." +} \ No newline at end of file diff --git a/.scripts/cleanup.ps1 b/.scripts/cleanup.ps1 new file mode 100644 index 0000000..824909d --- /dev/null +++ b/.scripts/cleanup.ps1 @@ -0,0 +1,78 @@ +Param( + [String]$ProjectName +) + +$scriptRoot = Split-Path -Parent $MyInvocation.MyCommand.Path +$checksScript = Join-Path $scriptRoot "checks.ps1" + +try { + . $checksScript +} catch { + Write-Host $_.Exception.Message -ForegroundColor Red + Write-Host "Setup script terminated due to the checks failure." -ForegroundColor Red + exit 1 +} + +$MissingParameterValues = $false + +if (-not $ProjectName) { + $ProjectName = $(gh repo view --json name -q '.name' 2> $null) + if (-not $ProjectName) { $MissingParameterValues = $true } +} + +$ScriptParameters = @{ + "ProjectName" = $ProjectName +} + +Write-Host +Write-Host "This script performs cleanup operations to delete resource groups, Azure AD applications, and purge deleted key vaults associated with a specific project hosted on GitHub. It searches for resources based on the project name and performs the necessary deletion and purging actions. The script leverages the Azure CLI to interact with Azure resources. It aims to facilitate the cleanup process and remove unnecessary resources from your Azure environment." +Write-Host +Write-Host "Parameters:" -ForegroundColor Green +$ScriptParameters | Format-Table -AutoSize +Write-Host + +if ($MissingParameterValues) { + Write-Host "Script execution cancelled. Missing parameter values." -ForegroundColor Red + return +} + +Write-Host "Warning: This script will perform cleanup operations, including deleting resource groups, Azure AD applications, and purging deleted key vaults starting with the project name '$ProjectName'. Make sure you understand the consequences and have verified the project name before proceeding." -ForegroundColor Red +Write-Host +Write-Host "Disclaimer: Use this script at your own risk. The author and contributors are not responsible for any loss of data or unintended consequences resulting from running this script." -ForegroundColor Yellow +Write-Host + +$confirmation = Read-Host "Do you want to continue? (y/N)" + +if ($confirmation -ne "y") { + Write-Host "Script execution cancelled." -ForegroundColor Red + return +} + +Write-Host "🔍 Searching for Resource Groups..." +$resourceGroups = az group list --query "[?starts_with(name, '$ProjectName')].name" --output tsv + +foreach ($rg in $resourceGroups) { + Write-Host "🔥 Deleting: $rg" + az group delete --name $rg --yes > $null 2>&1 +} + +Write-Host "🔍 Searching for Azure AD Applications..." +$appRegistrations = az ad app list --display-name $ProjectName --query "[].{Name:displayName, AppId:appId}" --output json | ConvertFrom-Json + +foreach ($appRegistration in $appRegistrations) { + $appName = $appRegistration.Name + $appId = $appRegistration.AppId + + Write-Host "🔥 Deleting: $appName" + az ad app delete --id $appId > $null 2>&1 +} + +Write-Host "🔍 Searching for Deleted Key Vaults..." +$deletedKeyVaults = az keyvault list-deleted --query "[?starts_with(name, 'kv-$ProjectName')].name" --output tsv + +foreach ($vaultName in $deletedKeyVaults) { + Write-Host "🔥 Purging: $vaultName" + az keyvault purge --name $vaultName > $null 2>&1 +} + +Write-Host "✅ Done" diff --git a/.scripts/environments.json b/.scripts/environments.json new file mode 100644 index 0000000..917eb1b --- /dev/null +++ b/.scripts/environments.json @@ -0,0 +1,5 @@ +{ + "Dev": "Development", + "Stg": "Staging", + "Prd": "Production" +} diff --git a/.scripts/setup.ps1 b/.scripts/setup.ps1 new file mode 100644 index 0000000..5bea571 --- /dev/null +++ b/.scripts/setup.ps1 @@ -0,0 +1,210 @@ +Param( + [String]$GitHubOrganisationName, + [String]$GitHubRepositoryName, + [String]$AzureLocation, + [String]$AzureSubscriptionId, + [String]$AzureTenantId, + [ValidateLength(4, 17)] + [String]$ProjectName, + [String]$AzureSqlLogin = "SqlAdmin" +) + +$scriptRoot = Split-Path -Parent $MyInvocation.MyCommand.Path +$checksScript = Join-Path $scriptRoot "checks.ps1" +$environmentsFile = Join-Path $scriptRoot "environments.json" + +try { + . $checksScript +} catch { + Write-Host $_.Exception.Message -ForegroundColor Red + Write-Host "Setup script terminated due to the checks failure." -ForegroundColor Red + exit 1 +} + +$MissingParameterValues = $false + +if (-not $GitHubOrganisationName) { + $ownerJson = gh repo view --json owner 2>$null | ConvertFrom-Json + if ($ownerJson -and $ownerJson.owner -and $ownerJson.owner.login) { + $GitHubOrganisationName = $ownerJson.owner.login + } + else { + $MissingParameterValues = $true + } +} + +if (-not $GitHubRepositoryName) { + $GitHubRepositoryName = $(gh repo view --json name -q '.name' 2> $null) + if (-not $GitHubRepositoryName) { $MissingParameterValues = $true } +} + +if (-not $AzureLocation) { + $AzureLocation = "australiaeast" +} + +if (-not $AzureSubscriptionId) { + $AzureSubscriptionId = $(az account show --query id --output tsv 2> $null) + if (-not $AzureSubscriptionId) { $MissingParameterValues = $true } +} + +if (-not $AzureTenantId) { + $AzureTenantId = $(az account show --query tenantId --output tsv 2> $null) + if (-not $AzureTenantId) { $MissingParameterValues = $true } +} + +if (-not $ProjectName) { + if ($GitHubRepositoryName) { + $ProjectName = $GitHubRepositoryName + } + + if (-not $ProjectName) { $MissingParameterValues = $true } +} + +$repoUrl = "https://github.com/$GitHubOrganisationName/$GitHubRepositoryName" + +$environments = Get-Content -Raw -Path $environmentsFile | ConvertFrom-Json + +$ParametersTableData = @{ + "AzureLocation" = $AzureLocation + "AzureSubscriptionID" = $AzureSubscriptionId + "AzureTenantID" = $AzureTenantId + "GitHubOrganisationName" = $GitHubOrganisationName + "GitHubRepositoryName" = $GitHubRepositoryName + "ProjectName" = $ProjectName + "AzureSqlLogin" = $AzureSqlLogin +} + +Write-Host +Write-Host "This script automates the setup of environments, resources, and credentials for a project hosted on GitHub and deployed to Azure. It creates workload identities in Azure AD, sets up resource groups, and configures environment-specific variables and secrets in the GitHub repository. The script leverages the Azure CLI, GitHub CLI, and GitHub APIs to perform these tasks. It aims to streamline the process of setting up and configuring development, staging, and production environments for the project." +Write-Host +Write-Host "Parameters:" -ForegroundColor Green +$ParametersTableData | Format-Table -AutoSize + +if ($MissingParameterValues) { + Write-Host "Script execution cancelled. Missing parameter values." -ForegroundColor Red + exit 1 +} + +$EnvironmentTableData = foreach ($environment in $environments.PSObject.Properties) { + [PSCustomObject]@{ + Abbreviation = $environment.Name + Name = $environment.Value + } +} + +Write-Host "Environments:" -ForegroundColor Green +$EnvironmentTableData | Select-Object Name, Abbreviation | Format-Table -AutoSize +Write-Host + +Write-Host "Warning: Running this script will perform various operations in your GitHub repository and Azure subscription. Ensure that you have the necessary permissions and understand the consequences. " -ForegroundColor Red +Write-Host +Write-Host "Disclaimer: Use this script at your own risk. The author and contributors are not responsible for any loss of data or unintended consequences resulting from running this script." -ForegroundColor Yellow +Write-Host + +$confirmation = Read-Host "Do you want to continue? (y/N)" + +if ($confirmation -ne "y") { + Write-Host "Script execution cancelled." -ForegroundColor Red + return +} + +Write-Host + +function CreateWorkloadIdentity { + param ( + $environmentAbbr, + $environmentName + ) + + # Create Azure AD Application Registration + $applicationRegistrationDetails=$(az ad app create --display-name "$ProjectName$environmentAbbr") | ConvertFrom-Json + + # Create federated credentials + $credential = @{ + name="$ProjectName$environmentName"; + issuer="https://token.actions.githubusercontent.com"; + subject="repo:${GitHubOrganisationName}/${GitHubRepositoryName}:environment:$environmentName"; + audiences=@("api://AzureADTokenExchange") + } | ConvertTo-Json + + $credential | az ad app federated-credential create --id $applicationRegistrationDetails.id --parameters "@-" | Out-Null + + $credential = @{ + name="$ProjectName"; + issuer="https://token.actions.githubusercontent.com"; + subject="repo:${GitHubOrganisationName}/${GitHubRepositoryName}:ref:refs/heads/main"; + audiences=@("api://AzureADTokenExchange") + } | ConvertTo-Json + + $credential | az ad app federated-credential create --id $applicationRegistrationDetails.id --parameters "@-" | Out-Null + + return $applicationRegistrationDetails.appId +} + +function CreateResourceGroup { + param ( + $environmentAbbr, + $appId + ) + + $resourceGroupId = $(az group create --name "$ProjectName$environmentAbbr" --location $AzureLocation --query id --output tsv) + az ad sp create --id $appId + az role assignment create --assignee $appId --role Contributor --scope $resourceGroupId +} + +function CreateEnvironment { + param ( + $environmentName + ) + + $token = gh auth token + $header = @{"Authorization" = "token $token" } + $contentType = "application/json" + + $uri = "https://api.github.com/repos/$GitHubOrganisationName/$GitHubRepositoryName/environments/$environmentName" + Invoke-WebRequest -Method PUT -Header $header -ContentType $contentType -Uri $uri +} + +function GenerateRandomPassword { + param ( + [int]$Length = 16 + ) + + $ValidChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!#^_-+=?<>|~".ToCharArray() + $Password = -join ((Get-Random -Count $Length -InputObject $ValidChars) | Get-Random -Count $Length) + + return $Password +} + +function SetVariables() { + gh variable set AZURE_TENANT_ID --body $AzureTenantId --repo $repoUrl + gh variable set AZURE_SUBSCRIPTION_ID --body $AzureSubscriptionId --repo $repoUrl + gh variable set PROJECT_NAME --body $ProjectName --repo $repoUrl +} + +function SetEnvironmentVariablesAndSecrets { + param( + $environmentAbbr, + $environmentName, + $appId + ) + + gh variable set AZURE_CLIENT_ID --body "$appId" --env $environmentName --repo $repoUrl + gh variable set AZURE_RESOURCE_GROUP_NAME --body "$ProjectName$environmentAbbr" --env $environmentName --repo $repoUrl + gh variable set AZURE_SQL_ADMINISTRATOR_USERNAME --body "$AzureSqlLogin" --env $environmentName --repo $repoUrl + gh secret set AZURE_SQL_ADMINISTRATOR_PASSWORD --body (GenerateRandomPassword) --env $environmentName --repo $repoUrl +} + +SetVariables + +foreach ($environment in $environments.PSObject.Properties) { + $environmentAbbr = $environment.Name + $environmentName = $environment.Value + + CreateEnvironment $environmentName + $appId = CreateWorkloadIdentity $environmentAbbr $environmentName + CreateResourceGroup $environmentAbbr $appId + SetEnvironmentVariablesAndSecrets $environmentAbbr $environmentName $appId +} + +Write-Host "✅ Done" \ No newline at end of file diff --git a/Directory.Build.props b/Directory.Build.props new file mode 100644 index 0000000..63a87da --- /dev/null +++ b/Directory.Build.props @@ -0,0 +1,10 @@ + + + + net8.0 + true + $(MSBuildThisFileDirectory)artifacts + enable + enable + + \ No newline at end of file diff --git a/Directory.Packages.props b/Directory.Packages.props new file mode 100644 index 0000000..864c732 --- /dev/null +++ b/Directory.Packages.props @@ -0,0 +1,38 @@ + + + + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Hutopy.sln b/Hutopy.sln new file mode 100644 index 0000000..5714f45 --- /dev/null +++ b/Hutopy.sln @@ -0,0 +1,91 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.31903.59 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Domain", "src\Domain\Domain.csproj", "{C7E89A3E-A631-4760-8D61-BD1EAB1C4E69}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Application", "src\Application\Application.csproj", "{34C0FACD-F3D9-400C-8945-554DD6B0819A}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Infrastructure", "src\Infrastructure\Infrastructure.csproj", "{117DA02F-5274-4565-ACC6-DA9B6E568B09}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{6ED356A7-8B47-4613-AD01-C85CF28491BD}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{664D406C-2F83-48F0-BFC3-408D5CB53C65}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Application.UnitTests", "tests\Application.UnitTests\Application.UnitTests.csproj", "{DEFF4009-1FAB-4392-80B6-707E2DC5C00B}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Domain.UnitTests", "tests\Domain.UnitTests\Domain.UnitTests.csproj", "{DC37FD87-552C-4613-9F16-1537CA522898}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{E2DA20AA-28D1-455C-BF50-C49A8F831633}" + ProjectSection(SolutionItems) = preProject + .editorconfig = .editorconfig + .gitignore = .gitignore + Directory.Build.props = Directory.Build.props + Directory.Packages.props = Directory.Packages.props + global.json = global.json + README.md = README.md + EndProjectSection +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Web", "src\Web\Web.csproj", "{4E4EE20C-F06A-4A1B-851F-C5577796941C}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Application.FunctionalTests", "tests\Application.FunctionalTests\Application.FunctionalTests.csproj", "{EA6127A5-94C9-4C31-AD11-E6811B92B520}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Infrastructure.IntegrationTests", "tests\Infrastructure.IntegrationTests\Infrastructure.IntegrationTests.csproj", "{01FA6786-921D-4CE8-8C50-4FDA66C9477D}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {C7E89A3E-A631-4760-8D61-BD1EAB1C4E69}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C7E89A3E-A631-4760-8D61-BD1EAB1C4E69}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C7E89A3E-A631-4760-8D61-BD1EAB1C4E69}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C7E89A3E-A631-4760-8D61-BD1EAB1C4E69}.Release|Any CPU.Build.0 = Release|Any CPU + {34C0FACD-F3D9-400C-8945-554DD6B0819A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {34C0FACD-F3D9-400C-8945-554DD6B0819A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {34C0FACD-F3D9-400C-8945-554DD6B0819A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {34C0FACD-F3D9-400C-8945-554DD6B0819A}.Release|Any CPU.Build.0 = Release|Any CPU + {117DA02F-5274-4565-ACC6-DA9B6E568B09}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {117DA02F-5274-4565-ACC6-DA9B6E568B09}.Debug|Any CPU.Build.0 = Debug|Any CPU + {117DA02F-5274-4565-ACC6-DA9B6E568B09}.Release|Any CPU.ActiveCfg = Release|Any CPU + {117DA02F-5274-4565-ACC6-DA9B6E568B09}.Release|Any CPU.Build.0 = Release|Any CPU + {DEFF4009-1FAB-4392-80B6-707E2DC5C00B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DEFF4009-1FAB-4392-80B6-707E2DC5C00B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DEFF4009-1FAB-4392-80B6-707E2DC5C00B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DEFF4009-1FAB-4392-80B6-707E2DC5C00B}.Release|Any CPU.Build.0 = Release|Any CPU + {DC37FD87-552C-4613-9F16-1537CA522898}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DC37FD87-552C-4613-9F16-1537CA522898}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DC37FD87-552C-4613-9F16-1537CA522898}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DC37FD87-552C-4613-9F16-1537CA522898}.Release|Any CPU.Build.0 = Release|Any CPU + {4E4EE20C-F06A-4A1B-851F-C5577796941C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4E4EE20C-F06A-4A1B-851F-C5577796941C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4E4EE20C-F06A-4A1B-851F-C5577796941C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4E4EE20C-F06A-4A1B-851F-C5577796941C}.Release|Any CPU.Build.0 = Release|Any CPU + {EA6127A5-94C9-4C31-AD11-E6811B92B520}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EA6127A5-94C9-4C31-AD11-E6811B92B520}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EA6127A5-94C9-4C31-AD11-E6811B92B520}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EA6127A5-94C9-4C31-AD11-E6811B92B520}.Release|Any CPU.Build.0 = Release|Any CPU + {01FA6786-921D-4CE8-8C50-4FDA66C9477D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {01FA6786-921D-4CE8-8C50-4FDA66C9477D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {01FA6786-921D-4CE8-8C50-4FDA66C9477D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {01FA6786-921D-4CE8-8C50-4FDA66C9477D}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {C7E89A3E-A631-4760-8D61-BD1EAB1C4E69} = {6ED356A7-8B47-4613-AD01-C85CF28491BD} + {34C0FACD-F3D9-400C-8945-554DD6B0819A} = {6ED356A7-8B47-4613-AD01-C85CF28491BD} + {117DA02F-5274-4565-ACC6-DA9B6E568B09} = {6ED356A7-8B47-4613-AD01-C85CF28491BD} + {DEFF4009-1FAB-4392-80B6-707E2DC5C00B} = {664D406C-2F83-48F0-BFC3-408D5CB53C65} + {DC37FD87-552C-4613-9F16-1537CA522898} = {664D406C-2F83-48F0-BFC3-408D5CB53C65} + {4E4EE20C-F06A-4A1B-851F-C5577796941C} = {6ED356A7-8B47-4613-AD01-C85CF28491BD} + {EA6127A5-94C9-4C31-AD11-E6811B92B520} = {664D406C-2F83-48F0-BFC3-408D5CB53C65} + {01FA6786-921D-4CE8-8C50-4FDA66C9477D} = {664D406C-2F83-48F0-BFC3-408D5CB53C65} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {3CB609D9-5D54-4C11-A371-DAAC8B74E430} + EndGlobalSection +EndGlobal diff --git a/README.md b/README.md new file mode 100644 index 0000000..2c86832 --- /dev/null +++ b/README.md @@ -0,0 +1,75 @@ +# Hutopy + +## Pattern used +- Clean Architecture +- Guards ( Fail fast ) : https://github.com/ardalis/GuardClauses + +## Tools +- Install Docker : https://www.docker.com/get-started/ +- Install sql server management ( or preffered tool ) : https://learn.microsoft.com/en-us/sql/ssms/download-sql-server-management-studio-ssms?view=sql-server-ver16#download-ssms + +## Database setup in docker for local dev +``` +docker run -e "ACCEPT_EULA=Y" -e "MSSQL_SA_PASSWORD=" -p 1433:1433 -d mcr.microsoft.com/mssql/server:2022-latest +``` + +Or with a mounted volume to persist data on the computer instead ( persist data even if the container is deleted ) +``` +docker run -e 'ACCEPT_EULA=Y' -e 'MSSQL_SA_PASSWORD=' -p 1433:1433 -v C:\dev\DockerVolumes\SqlServer-Utopy-1\data:/var/opt/mssql/data -v C:\dev\DockerVolumes\SqlServer-Utopy-1\log:/var/opt/mssql/log -v C:\dev\DockerVolumes\SqlServer-Utopy-1\secrets:/var/opt/mssql/secrets -d mcr.microsoft.com/mssql/server:2022-latest +``` + +Set your password in an env var for the connection string. Windows : $Env:DB_PASSWORD = "YourPassword" + +## Build + +Run `dotnet build -tl` to build the solution. + +## Run + +To run the web application: + +```bash +cd .\src\Web\ +dotnet watch run +``` + +Navigate to https://localhost:5001. The application will automatically reload if you change any of the source files. + +## Code Styles & Formatting + +The template includes [EditorConfig](https://editorconfig.org/) support to help maintain consistent coding styles for multiple developers working on the same project across various editors and IDEs. The **.editorconfig** file defines the coding styles applicable to this solution. + +## Code Scaffolding + +Scaffold new commands and queries. + +Start in the `.\src\Application\` folder. + +Create a new command: + +``` +dotnet new ca-usecase --name CreateTodoList --feature-name TodoLists --usecase-type command --return-type int +``` + +Create a new query: + +``` +dotnet new ca-usecase -n GetTodos -fn TodoLists -ut query -rt TodosVm +``` + +If you encounter the error *"No templates or subcommands found matching: 'ca-usecase'."*, install the template and try again: + +```bash +dotnet new install Clean.Architecture.Solution.Template::8.0.4 +``` + +## Test + +The solution contains unit, integration, and functional tests. + +- Using Moq, Nunit, Respawn, FluentAssertions + +To run the tests: +```bash +dotnet test +``` \ No newline at end of file diff --git a/global.json b/global.json new file mode 100644 index 0000000..501e79a --- /dev/null +++ b/global.json @@ -0,0 +1,6 @@ +{ + "sdk": { + "version": "8.0.100", + "rollForward": "latestFeature" + } +} \ No newline at end of file diff --git a/src/Application/Application.csproj b/src/Application/Application.csproj new file mode 100644 index 0000000..8544947 --- /dev/null +++ b/src/Application/Application.csproj @@ -0,0 +1,19 @@ + + + + Hutopy.Application + Hutopy.Application + + + + + + + + + + + + + + diff --git a/src/Application/Common/Behaviours/AuthorizationBehaviour.cs b/src/Application/Common/Behaviours/AuthorizationBehaviour.cs new file mode 100644 index 0000000..2b0378f --- /dev/null +++ b/src/Application/Common/Behaviours/AuthorizationBehaviour.cs @@ -0,0 +1,79 @@ +using System.Reflection; +using Hutopy.Application.Common.Exceptions; +using Hutopy.Application.Common.Interfaces; +using Hutopy.Application.Common.Security; + +namespace Hutopy.Application.Common.Behaviours; + +public class AuthorizationBehaviour : IPipelineBehavior where TRequest : notnull +{ + private readonly IUser _user; + private readonly IIdentityService _identityService; + + public AuthorizationBehaviour( + IUser user, + IIdentityService identityService) + { + _user = user; + _identityService = identityService; + } + + public async Task Handle(TRequest request, RequestHandlerDelegate next, CancellationToken cancellationToken) + { + var authorizeAttributes = request.GetType().GetCustomAttributes(); + + if (authorizeAttributes.Any()) + { + // Must be authenticated user + if (_user.Id == null) + { + throw new UnauthorizedAccessException(); + } + + // Role-based authorization + var authorizeAttributesWithRoles = authorizeAttributes.Where(a => !string.IsNullOrWhiteSpace(a.Roles)); + + if (authorizeAttributesWithRoles.Any()) + { + var authorized = false; + + foreach (var roles in authorizeAttributesWithRoles.Select(a => a.Roles.Split(','))) + { + foreach (var role in roles) + { + var isInRole = await _identityService.IsInRoleAsync(_user.Id, role.Trim()); + if (isInRole) + { + authorized = true; + break; + } + } + } + + // Must be a member of at least one role in roles + if (!authorized) + { + throw new ForbiddenAccessException(); + } + } + + // Policy-based authorization + var authorizeAttributesWithPolicies = authorizeAttributes.Where(a => !string.IsNullOrWhiteSpace(a.Policy)); + if (authorizeAttributesWithPolicies.Any()) + { + foreach (var policy in authorizeAttributesWithPolicies.Select(a => a.Policy)) + { + var authorized = await _identityService.AuthorizeAsync(_user.Id, policy); + + if (!authorized) + { + throw new ForbiddenAccessException(); + } + } + } + } + + // User is authorized / authorization not required + return await next(); + } +} diff --git a/src/Application/Common/Behaviours/LoggingBehaviour.cs b/src/Application/Common/Behaviours/LoggingBehaviour.cs new file mode 100644 index 0000000..70812ca --- /dev/null +++ b/src/Application/Common/Behaviours/LoggingBehaviour.cs @@ -0,0 +1,34 @@ +using Hutopy.Application.Common.Interfaces; +using MediatR.Pipeline; +using Microsoft.Extensions.Logging; + +namespace Hutopy.Application.Common.Behaviours; + +public class LoggingBehaviour : IRequestPreProcessor where TRequest : notnull +{ + private readonly ILogger _logger; + private readonly IUser _user; + private readonly IIdentityService _identityService; + + public LoggingBehaviour(ILogger logger, IUser user, IIdentityService identityService) + { + _logger = logger; + _user = user; + _identityService = identityService; + } + + public async Task Process(TRequest request, CancellationToken cancellationToken) + { + var requestName = typeof(TRequest).Name; + var userId = _user.Id ?? string.Empty; + string? userName = string.Empty; + + if (!string.IsNullOrEmpty(userId)) + { + userName = await _identityService.GetUserNameAsync(userId); + } + + _logger.LogInformation("Hutopy Request: {Name} {@UserId} {@UserName} {@Request}", + requestName, userId, userName, request); + } +} diff --git a/src/Application/Common/Behaviours/PerformanceBehaviour.cs b/src/Application/Common/Behaviours/PerformanceBehaviour.cs new file mode 100644 index 0000000..64e9b55 --- /dev/null +++ b/src/Application/Common/Behaviours/PerformanceBehaviour.cs @@ -0,0 +1,53 @@ +using System.Diagnostics; +using Hutopy.Application.Common.Interfaces; +using Microsoft.Extensions.Logging; + +namespace Hutopy.Application.Common.Behaviours; + +public class PerformanceBehaviour : IPipelineBehavior where TRequest : notnull +{ + private readonly Stopwatch _timer; + private readonly ILogger _logger; + private readonly IUser _user; + private readonly IIdentityService _identityService; + + public PerformanceBehaviour( + ILogger logger, + IUser user, + IIdentityService identityService) + { + _timer = new Stopwatch(); + + _logger = logger; + _user = user; + _identityService = identityService; + } + + public async Task Handle(TRequest request, RequestHandlerDelegate next, CancellationToken cancellationToken) + { + _timer.Start(); + + var response = await next(); + + _timer.Stop(); + + var elapsedMilliseconds = _timer.ElapsedMilliseconds; + + if (elapsedMilliseconds > 500) + { + var requestName = typeof(TRequest).Name; + var userId = _user.Id ?? string.Empty; + var userName = string.Empty; + + if (!string.IsNullOrEmpty(userId)) + { + userName = await _identityService.GetUserNameAsync(userId); + } + + _logger.LogWarning("Hutopy Long Running Request: {Name} ({ElapsedMilliseconds} milliseconds) {@UserId} {@UserName} {@Request}", + requestName, elapsedMilliseconds, userId, userName, request); + } + + return response; + } +} diff --git a/src/Application/Common/Behaviours/UnhandledExceptionBehaviour.cs b/src/Application/Common/Behaviours/UnhandledExceptionBehaviour.cs new file mode 100644 index 0000000..a79558a --- /dev/null +++ b/src/Application/Common/Behaviours/UnhandledExceptionBehaviour.cs @@ -0,0 +1,29 @@ +using Microsoft.Extensions.Logging; + +namespace Hutopy.Application.Common.Behaviours; + +public class UnhandledExceptionBehaviour : IPipelineBehavior where TRequest : notnull +{ + private readonly ILogger _logger; + + public UnhandledExceptionBehaviour(ILogger logger) + { + _logger = logger; + } + + public async Task Handle(TRequest request, RequestHandlerDelegate next, CancellationToken cancellationToken) + { + try + { + return await next(); + } + catch (Exception ex) + { + var requestName = typeof(TRequest).Name; + + _logger.LogError(ex, "Hutopy Request: Unhandled Exception for Request {Name} {@Request}", requestName, request); + + throw; + } + } +} diff --git a/src/Application/Common/Behaviours/ValidationBehaviour.cs b/src/Application/Common/Behaviours/ValidationBehaviour.cs new file mode 100644 index 0000000..262fce7 --- /dev/null +++ b/src/Application/Common/Behaviours/ValidationBehaviour.cs @@ -0,0 +1,35 @@ +using ValidationException = Hutopy.Application.Common.Exceptions.ValidationException; + +namespace Hutopy.Application.Common.Behaviours; + +public class ValidationBehaviour : IPipelineBehavior + where TRequest : notnull +{ + private readonly IEnumerable> _validators; + + public ValidationBehaviour(IEnumerable> validators) + { + _validators = validators; + } + + public async Task Handle(TRequest request, RequestHandlerDelegate next, CancellationToken cancellationToken) + { + if (_validators.Any()) + { + var context = new ValidationContext(request); + + var validationResults = await Task.WhenAll( + _validators.Select(v => + v.ValidateAsync(context, cancellationToken))); + + var failures = validationResults + .Where(r => r.Errors.Any()) + .SelectMany(r => r.Errors) + .ToList(); + + if (failures.Any()) + throw new ValidationException(failures); + } + return await next(); + } +} diff --git a/src/Application/Common/Exceptions/ForbiddenAccessException.cs b/src/Application/Common/Exceptions/ForbiddenAccessException.cs new file mode 100644 index 0000000..41f91eb --- /dev/null +++ b/src/Application/Common/Exceptions/ForbiddenAccessException.cs @@ -0,0 +1,6 @@ +namespace Hutopy.Application.Common.Exceptions; + +public class ForbiddenAccessException : Exception +{ + public ForbiddenAccessException() : base() { } +} diff --git a/src/Application/Common/Exceptions/ValidationException.cs b/src/Application/Common/Exceptions/ValidationException.cs new file mode 100644 index 0000000..1570fbc --- /dev/null +++ b/src/Application/Common/Exceptions/ValidationException.cs @@ -0,0 +1,22 @@ +using FluentValidation.Results; + +namespace Hutopy.Application.Common.Exceptions; + +public class ValidationException : Exception +{ + public ValidationException() + : base("One or more validation failures have occurred.") + { + Errors = new Dictionary(); + } + + public ValidationException(IEnumerable failures) + : this() + { + Errors = failures + .GroupBy(e => e.PropertyName, e => e.ErrorMessage) + .ToDictionary(failureGroup => failureGroup.Key, failureGroup => failureGroup.ToArray()); + } + + public IDictionary Errors { get; } +} diff --git a/src/Application/Common/Interfaces/IApplicationDbContext.cs b/src/Application/Common/Interfaces/IApplicationDbContext.cs new file mode 100644 index 0000000..5b7e5d9 --- /dev/null +++ b/src/Application/Common/Interfaces/IApplicationDbContext.cs @@ -0,0 +1,12 @@ +using Hutopy.Domain.Entities; + +namespace Hutopy.Application.Common.Interfaces; + +public interface IApplicationDbContext +{ + DbSet TodoLists { get; } + + DbSet TodoItems { get; } + + Task SaveChangesAsync(CancellationToken cancellationToken); +} diff --git a/src/Application/Common/Interfaces/IIdentityService.cs b/src/Application/Common/Interfaces/IIdentityService.cs new file mode 100644 index 0000000..5dbcb4c --- /dev/null +++ b/src/Application/Common/Interfaces/IIdentityService.cs @@ -0,0 +1,16 @@ +using Hutopy.Application.Common.Models; + +namespace Hutopy.Application.Common.Interfaces; + +public interface IIdentityService +{ + Task GetUserNameAsync(string userId); + + Task IsInRoleAsync(string userId, string role); + + Task AuthorizeAsync(string userId, string policyName); + + Task<(Result Result, string UserId)> CreateUserAsync(string userName, string password); + + Task DeleteUserAsync(string userId); +} diff --git a/src/Application/Common/Interfaces/IUser.cs b/src/Application/Common/Interfaces/IUser.cs new file mode 100644 index 0000000..f6112a1 --- /dev/null +++ b/src/Application/Common/Interfaces/IUser.cs @@ -0,0 +1,6 @@ +namespace Hutopy.Application.Common.Interfaces; + +public interface IUser +{ + string? Id { get; } +} diff --git a/src/Application/Common/Mappings/MappingExtensions.cs b/src/Application/Common/Mappings/MappingExtensions.cs new file mode 100644 index 0000000..bdbb707 --- /dev/null +++ b/src/Application/Common/Mappings/MappingExtensions.cs @@ -0,0 +1,12 @@ +using Hutopy.Application.Common.Models; + +namespace Hutopy.Application.Common.Mappings; + +public static class MappingExtensions +{ + public static Task> PaginatedListAsync(this IQueryable queryable, int pageNumber, int pageSize) where TDestination : class + => PaginatedList.CreateAsync(queryable.AsNoTracking(), pageNumber, pageSize); + + public static Task> ProjectToListAsync(this IQueryable queryable, IConfigurationProvider configuration) where TDestination : class + => queryable.ProjectTo(configuration).AsNoTracking().ToListAsync(); +} diff --git a/src/Application/Common/Models/LookupDto.cs b/src/Application/Common/Models/LookupDto.cs new file mode 100644 index 0000000..bde00c2 --- /dev/null +++ b/src/Application/Common/Models/LookupDto.cs @@ -0,0 +1,19 @@ +using Hutopy.Domain.Entities; + +namespace Hutopy.Application.Common.Models; + +public class LookupDto +{ + public int Id { get; init; } + + public string? Title { get; init; } + + private class Mapping : Profile + { + public Mapping() + { + CreateMap(); + CreateMap(); + } + } +} diff --git a/src/Application/Common/Models/PaginatedList.cs b/src/Application/Common/Models/PaginatedList.cs new file mode 100644 index 0000000..53636fa --- /dev/null +++ b/src/Application/Common/Models/PaginatedList.cs @@ -0,0 +1,29 @@ +namespace Hutopy.Application.Common.Models; + +public class PaginatedList +{ + public IReadOnlyCollection Items { get; } + public int PageNumber { get; } + public int TotalPages { get; } + public int TotalCount { get; } + + public PaginatedList(IReadOnlyCollection items, int count, int pageNumber, int pageSize) + { + PageNumber = pageNumber; + TotalPages = (int)Math.Ceiling(count / (double)pageSize); + TotalCount = count; + Items = items; + } + + public bool HasPreviousPage => PageNumber > 1; + + public bool HasNextPage => PageNumber < TotalPages; + + public static async Task> CreateAsync(IQueryable source, int pageNumber, int pageSize) + { + var count = await source.CountAsync(); + var items = await source.Skip((pageNumber - 1) * pageSize).Take(pageSize).ToListAsync(); + + return new PaginatedList(items, count, pageNumber, pageSize); + } +} diff --git a/src/Application/Common/Models/Result.cs b/src/Application/Common/Models/Result.cs new file mode 100644 index 0000000..f052240 --- /dev/null +++ b/src/Application/Common/Models/Result.cs @@ -0,0 +1,24 @@ +namespace Hutopy.Application.Common.Models; + +public class Result +{ + internal Result(bool succeeded, IEnumerable errors) + { + Succeeded = succeeded; + Errors = errors.ToArray(); + } + + public bool Succeeded { get; init; } + + public string[] Errors { get; init; } + + public static Result Success() + { + return new Result(true, Array.Empty()); + } + + public static Result Failure(IEnumerable errors) + { + return new Result(false, errors); + } +} diff --git a/src/Application/Common/Security/AuthorizeAttribute.cs b/src/Application/Common/Security/AuthorizeAttribute.cs new file mode 100644 index 0000000..6a8a965 --- /dev/null +++ b/src/Application/Common/Security/AuthorizeAttribute.cs @@ -0,0 +1,23 @@ +namespace Hutopy.Application.Common.Security; + +/// +/// Specifies the class this attribute is applied to requires authorization. +/// +[AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)] +public class AuthorizeAttribute : Attribute +{ + /// + /// Initializes a new instance of the class. + /// + public AuthorizeAttribute() { } + + /// + /// Gets or sets a comma delimited list of roles that are allowed to access the resource. + /// + public string Roles { get; set; } = string.Empty; + + /// + /// Gets or sets the policy name that determines access to the resource. + /// + public string Policy { get; set; } = string.Empty; +} diff --git a/src/Application/DependencyInjection.cs b/src/Application/DependencyInjection.cs new file mode 100644 index 0000000..ebbe093 --- /dev/null +++ b/src/Application/DependencyInjection.cs @@ -0,0 +1,25 @@ +using System.Reflection; +using Hutopy.Application.Common.Behaviours; + +namespace Microsoft.Extensions.DependencyInjection; + +public static class DependencyInjection +{ + public static IServiceCollection AddApplicationServices(this IServiceCollection services) + { + services.AddAutoMapper(Assembly.GetExecutingAssembly()); + + services.AddValidatorsFromAssembly(Assembly.GetExecutingAssembly()); + + services.AddMediatR(cfg => + { + cfg.RegisterServicesFromAssembly(Assembly.GetExecutingAssembly()); + //cfg.AddBehavior(typeof(IPipelineBehavior<,>), typeof(UnhandledExceptionBehaviour<,>)); + //cfg.AddBehavior(typeof(IPipelineBehavior<,>), typeof(AuthorizationBehaviour<,>)); + //cfg.AddBehavior(typeof(IPipelineBehavior<,>), typeof(ValidationBehaviour<,>)); + //cfg.AddBehavior(typeof(IPipelineBehavior<,>), typeof(PerformanceBehaviour<,>)); + }); + + return services; + } +} diff --git a/src/Application/GlobalUsings.cs b/src/Application/GlobalUsings.cs new file mode 100644 index 0000000..fa904ba --- /dev/null +++ b/src/Application/GlobalUsings.cs @@ -0,0 +1,6 @@ +global using Ardalis.GuardClauses; +global using AutoMapper; +global using AutoMapper.QueryableExtensions; +global using Microsoft.EntityFrameworkCore; +global using FluentValidation; +global using MediatR; \ No newline at end of file diff --git a/src/Application/TodoItems/Commands/CreateTodoItem/CreateTodoItem.cs b/src/Application/TodoItems/Commands/CreateTodoItem/CreateTodoItem.cs new file mode 100644 index 0000000..a560109 --- /dev/null +++ b/src/Application/TodoItems/Commands/CreateTodoItem/CreateTodoItem.cs @@ -0,0 +1,40 @@ +using Hutopy.Application.Common.Interfaces; +using Hutopy.Domain.Entities; +using Hutopy.Domain.Events; + +namespace Hutopy.Application.TodoItems.Commands.CreateTodoItem; + +public record CreateTodoItemCommand : IRequest +{ + public int ListId { get; init; } + + public string? Title { get; init; } +} + +public class CreateTodoItemCommandHandler : IRequestHandler +{ + private readonly IApplicationDbContext _context; + + public CreateTodoItemCommandHandler(IApplicationDbContext context) + { + _context = context; + } + + public async Task Handle(CreateTodoItemCommand request, CancellationToken cancellationToken) + { + var entity = new TodoItem + { + ListId = request.ListId, + Title = request.Title, + Done = false + }; + + entity.AddDomainEvent(new TodoItemCreatedEvent(entity)); + + _context.TodoItems.Add(entity); + + await _context.SaveChangesAsync(cancellationToken); + + return entity.Id; + } +} diff --git a/src/Application/TodoItems/Commands/CreateTodoItem/CreateTodoItemCommandValidator.cs b/src/Application/TodoItems/Commands/CreateTodoItem/CreateTodoItemCommandValidator.cs new file mode 100644 index 0000000..e6d876a --- /dev/null +++ b/src/Application/TodoItems/Commands/CreateTodoItem/CreateTodoItemCommandValidator.cs @@ -0,0 +1,11 @@ +namespace Hutopy.Application.TodoItems.Commands.CreateTodoItem; + +public class CreateTodoItemCommandValidator : AbstractValidator +{ + public CreateTodoItemCommandValidator() + { + RuleFor(v => v.Title) + .MaximumLength(200) + .NotEmpty(); + } +} diff --git a/src/Application/TodoItems/Commands/DeleteTodoItem/DeleteTodoItem.cs b/src/Application/TodoItems/Commands/DeleteTodoItem/DeleteTodoItem.cs new file mode 100644 index 0000000..d08cb44 --- /dev/null +++ b/src/Application/TodoItems/Commands/DeleteTodoItem/DeleteTodoItem.cs @@ -0,0 +1,35 @@ +using Hutopy.Application.Common.Interfaces; +using Hutopy.Domain.Events; +using Hutopy.Application.Common.Security; +using Hutopy.Domain.Constants; + +namespace Hutopy.Application.TodoItems.Commands.DeleteTodoItem; + +[Authorize(Roles = Roles.Administrator)] +[Authorize(Policy = Policies.CanDelete)] +public record DeleteTodoItemCommand(int Id) : IRequest; + +public class DeleteTodoItemCommandHandler : IRequestHandler +{ + private readonly IApplicationDbContext _context; + + public DeleteTodoItemCommandHandler(IApplicationDbContext context) + { + _context = context; + } + + public async Task Handle(DeleteTodoItemCommand request, CancellationToken cancellationToken) + { + var entity = await _context.TodoItems + .FindAsync(new object[] { request.Id }, cancellationToken); + + Guard.Against.NotFound(request.Id, entity); + + _context.TodoItems.Remove(entity); + + entity.AddDomainEvent(new TodoItemDeletedEvent(entity)); + + await _context.SaveChangesAsync(cancellationToken); + } + +} diff --git a/src/Application/TodoItems/Commands/UpdateTodoItem/UpdateTodoItem.cs b/src/Application/TodoItems/Commands/UpdateTodoItem/UpdateTodoItem.cs new file mode 100644 index 0000000..9699859 --- /dev/null +++ b/src/Application/TodoItems/Commands/UpdateTodoItem/UpdateTodoItem.cs @@ -0,0 +1,35 @@ +using Hutopy.Application.Common.Interfaces; + +namespace Hutopy.Application.TodoItems.Commands.UpdateTodoItem; + +public record UpdateTodoItemCommand : IRequest +{ + public int Id { get; init; } + + public string? Title { get; init; } + + public bool Done { get; init; } +} + +public class UpdateTodoItemCommandHandler : IRequestHandler +{ + private readonly IApplicationDbContext _context; + + public UpdateTodoItemCommandHandler(IApplicationDbContext context) + { + _context = context; + } + + public async Task Handle(UpdateTodoItemCommand request, CancellationToken cancellationToken) + { + var entity = await _context.TodoItems + .FindAsync(new object[] { request.Id }, cancellationToken); + + Guard.Against.NotFound(request.Id, entity); + + entity.Title = request.Title; + entity.Done = request.Done; + + await _context.SaveChangesAsync(cancellationToken); + } +} diff --git a/src/Application/TodoItems/Commands/UpdateTodoItem/UpdateTodoItemCommandValidator.cs b/src/Application/TodoItems/Commands/UpdateTodoItem/UpdateTodoItemCommandValidator.cs new file mode 100644 index 0000000..38383c6 --- /dev/null +++ b/src/Application/TodoItems/Commands/UpdateTodoItem/UpdateTodoItemCommandValidator.cs @@ -0,0 +1,11 @@ +namespace Hutopy.Application.TodoItems.Commands.UpdateTodoItem; + +public class UpdateTodoItemCommandValidator : AbstractValidator +{ + public UpdateTodoItemCommandValidator() + { + RuleFor(v => v.Title) + .MaximumLength(200) + .NotEmpty(); + } +} diff --git a/src/Application/TodoItems/Commands/UpdateTodoItemDetail/UpdateTodoItemDetail.cs b/src/Application/TodoItems/Commands/UpdateTodoItemDetail/UpdateTodoItemDetail.cs new file mode 100644 index 0000000..f02b254 --- /dev/null +++ b/src/Application/TodoItems/Commands/UpdateTodoItemDetail/UpdateTodoItemDetail.cs @@ -0,0 +1,39 @@ +using Hutopy.Application.Common.Interfaces; +using Hutopy.Domain.Enums; + +namespace Hutopy.Application.TodoItems.Commands.UpdateTodoItemDetail; + +public record UpdateTodoItemDetailCommand : IRequest +{ + public int Id { get; init; } + + public int ListId { get; init; } + + public PriorityLevel Priority { get; init; } + + public string? Note { get; init; } +} + +public class UpdateTodoItemDetailCommandHandler : IRequestHandler +{ + private readonly IApplicationDbContext _context; + + public UpdateTodoItemDetailCommandHandler(IApplicationDbContext context) + { + _context = context; + } + + public async Task Handle(UpdateTodoItemDetailCommand request, CancellationToken cancellationToken) + { + var entity = await _context.TodoItems + .FindAsync(new object[] { request.Id }, cancellationToken); + + Guard.Against.NotFound(request.Id, entity); + + entity.ListId = request.ListId; + entity.Priority = request.Priority; + entity.Note = request.Note; + + await _context.SaveChangesAsync(cancellationToken); + } +} diff --git a/src/Application/TodoItems/EventHandlers/TodoItemCompletedEventHandler.cs b/src/Application/TodoItems/EventHandlers/TodoItemCompletedEventHandler.cs new file mode 100644 index 0000000..2a1a001 --- /dev/null +++ b/src/Application/TodoItems/EventHandlers/TodoItemCompletedEventHandler.cs @@ -0,0 +1,21 @@ +using Hutopy.Domain.Events; +using Microsoft.Extensions.Logging; + +namespace Hutopy.Application.TodoItems.EventHandlers; + +public class TodoItemCompletedEventHandler : INotificationHandler +{ + private readonly ILogger _logger; + + public TodoItemCompletedEventHandler(ILogger logger) + { + _logger = logger; + } + + public Task Handle(TodoItemCompletedEvent notification, CancellationToken cancellationToken) + { + _logger.LogInformation("Hutopy Domain Event: {DomainEvent}", notification.GetType().Name); + + return Task.CompletedTask; + } +} diff --git a/src/Application/TodoItems/EventHandlers/TodoItemCreatedEventHandler.cs b/src/Application/TodoItems/EventHandlers/TodoItemCreatedEventHandler.cs new file mode 100644 index 0000000..7e20348 --- /dev/null +++ b/src/Application/TodoItems/EventHandlers/TodoItemCreatedEventHandler.cs @@ -0,0 +1,21 @@ +using Hutopy.Domain.Events; +using Microsoft.Extensions.Logging; + +namespace Hutopy.Application.TodoItems.EventHandlers; + +public class TodoItemCreatedEventHandler : INotificationHandler +{ + private readonly ILogger _logger; + + public TodoItemCreatedEventHandler(ILogger logger) + { + _logger = logger; + } + + public Task Handle(TodoItemCreatedEvent notification, CancellationToken cancellationToken) + { + _logger.LogInformation("Hutopy Domain Event: {DomainEvent}", notification.GetType().Name); + + return Task.CompletedTask; + } +} diff --git a/src/Application/TodoItems/Queries/GetTodoItemsWithPagination/GetTodoItemsWithPagination.cs b/src/Application/TodoItems/Queries/GetTodoItemsWithPagination/GetTodoItemsWithPagination.cs new file mode 100644 index 0000000..a34f162 --- /dev/null +++ b/src/Application/TodoItems/Queries/GetTodoItemsWithPagination/GetTodoItemsWithPagination.cs @@ -0,0 +1,34 @@ +using Hutopy.Application.Common.Interfaces; +using Hutopy.Application.Common.Mappings; +using Hutopy.Application.Common.Models; + +namespace Hutopy.Application.TodoItems.Queries.GetTodoItemsWithPagination; + +public record GetTodoItemsWithPaginationQuery : IRequest> +{ + public int ListId { get; init; } + public int PageNumber { get; init; } = 1; + public int PageSize { get; init; } = 10; +} + +public class GetTodoItemsWithPaginationQueryHandler : IRequestHandler> +{ + private readonly IApplicationDbContext _context; + private readonly IMapper _mapper; + + public GetTodoItemsWithPaginationQueryHandler(IApplicationDbContext context, IMapper mapper) + { + _context = context; + _mapper = mapper; + } + + public async Task> Handle(GetTodoItemsWithPaginationQuery request, CancellationToken cancellationToken) + { + Console.WriteLine(request); + return await _context.TodoItems + .Where(x => x.ListId == request.ListId) + .OrderBy(x => x.Title) + .ProjectTo(_mapper.ConfigurationProvider) + .PaginatedListAsync(request.PageNumber, request.PageSize); + } +} diff --git a/src/Application/TodoItems/Queries/GetTodoItemsWithPagination/GetTodoItemsWithPaginationQueryValidator.cs b/src/Application/TodoItems/Queries/GetTodoItemsWithPagination/GetTodoItemsWithPaginationQueryValidator.cs new file mode 100644 index 0000000..99bfd24 --- /dev/null +++ b/src/Application/TodoItems/Queries/GetTodoItemsWithPagination/GetTodoItemsWithPaginationQueryValidator.cs @@ -0,0 +1,16 @@ +namespace Hutopy.Application.TodoItems.Queries.GetTodoItemsWithPagination; + +public class GetTodoItemsWithPaginationQueryValidator : AbstractValidator +{ + public GetTodoItemsWithPaginationQueryValidator() + { + RuleFor(x => x.ListId) + .NotEmpty().WithMessage("ListId is required."); + + RuleFor(x => x.PageNumber) + .GreaterThanOrEqualTo(1).WithMessage("PageNumber at least greater than or equal to 1."); + + RuleFor(x => x.PageSize) + .GreaterThanOrEqualTo(1).WithMessage("PageSize at least greater than or equal to 1."); + } +} diff --git a/src/Application/TodoItems/Queries/GetTodoItemsWithPagination/TodoItemBriefDto.cs b/src/Application/TodoItems/Queries/GetTodoItemsWithPagination/TodoItemBriefDto.cs new file mode 100644 index 0000000..b7c40a3 --- /dev/null +++ b/src/Application/TodoItems/Queries/GetTodoItemsWithPagination/TodoItemBriefDto.cs @@ -0,0 +1,22 @@ +using Hutopy.Domain.Entities; + +namespace Hutopy.Application.TodoItems.Queries.GetTodoItemsWithPagination; + +public class TodoItemBriefDto +{ + public int Id { get; init; } + + public int ListId { get; init; } + + public string? Title { get; init; } + + public bool Done { get; init; } + + private class Mapping : Profile + { + public Mapping() + { + CreateMap(); + } + } +} diff --git a/src/Application/TodoLists/Commands/CreateTodoList/CreateTodoList.cs b/src/Application/TodoLists/Commands/CreateTodoList/CreateTodoList.cs new file mode 100644 index 0000000..c557f94 --- /dev/null +++ b/src/Application/TodoLists/Commands/CreateTodoList/CreateTodoList.cs @@ -0,0 +1,32 @@ +using Hutopy.Application.Common.Interfaces; +using Hutopy.Domain.Entities; + +namespace Hutopy.Application.TodoLists.Commands.CreateTodoList; + +public record CreateTodoListCommand : IRequest +{ + public string? Title { get; init; } +} + +public class CreateTodoListCommandHandler : IRequestHandler +{ + private readonly IApplicationDbContext _context; + + public CreateTodoListCommandHandler(IApplicationDbContext context) + { + _context = context; + } + + public async Task Handle(CreateTodoListCommand request, CancellationToken cancellationToken) + { + var entity = new TodoList(); + + entity.Title = request.Title; + + _context.TodoLists.Add(entity); + + await _context.SaveChangesAsync(cancellationToken); + + return entity.Id; + } +} diff --git a/src/Application/TodoLists/Commands/CreateTodoList/CreateTodoListCommandValidator.cs b/src/Application/TodoLists/Commands/CreateTodoList/CreateTodoListCommandValidator.cs new file mode 100644 index 0000000..4c627b4 --- /dev/null +++ b/src/Application/TodoLists/Commands/CreateTodoList/CreateTodoListCommandValidator.cs @@ -0,0 +1,26 @@ +using Hutopy.Application.Common.Interfaces; + +namespace Hutopy.Application.TodoLists.Commands.CreateTodoList; + +public class CreateTodoListCommandValidator : AbstractValidator +{ + private readonly IApplicationDbContext _context; + + public CreateTodoListCommandValidator(IApplicationDbContext context) + { + _context = context; + + RuleFor(v => v.Title) + .NotEmpty() + .MaximumLength(200) + .MustAsync(BeUniqueTitle) + .WithMessage("'{PropertyName}' must be unique.") + .WithErrorCode("Unique"); + } + + public async Task BeUniqueTitle(string title, CancellationToken cancellationToken) + { + return await _context.TodoLists + .AllAsync(l => l.Title != title, cancellationToken); + } +} diff --git a/src/Application/TodoLists/Commands/DeleteTodoList/DeleteTodoList.cs b/src/Application/TodoLists/Commands/DeleteTodoList/DeleteTodoList.cs new file mode 100644 index 0000000..a5c3634 --- /dev/null +++ b/src/Application/TodoLists/Commands/DeleteTodoList/DeleteTodoList.cs @@ -0,0 +1,28 @@ +using Hutopy.Application.Common.Interfaces; + +namespace Hutopy.Application.TodoLists.Commands.DeleteTodoList; + +public record DeleteTodoListCommand(int Id) : IRequest; + +public class DeleteTodoListCommandHandler : IRequestHandler +{ + private readonly IApplicationDbContext _context; + + public DeleteTodoListCommandHandler(IApplicationDbContext context) + { + _context = context; + } + + public async Task Handle(DeleteTodoListCommand request, CancellationToken cancellationToken) + { + var entity = await _context.TodoLists + .Where(l => l.Id == request.Id) + .SingleOrDefaultAsync(cancellationToken); + + Guard.Against.NotFound(request.Id, entity); + + _context.TodoLists.Remove(entity); + + await _context.SaveChangesAsync(cancellationToken); + } +} diff --git a/src/Application/TodoLists/Commands/PurgeTodoLists/PurgeTodoLists.cs b/src/Application/TodoLists/Commands/PurgeTodoLists/PurgeTodoLists.cs new file mode 100644 index 0000000..9778b6a --- /dev/null +++ b/src/Application/TodoLists/Commands/PurgeTodoLists/PurgeTodoLists.cs @@ -0,0 +1,26 @@ +using Hutopy.Application.Common.Interfaces; +using Hutopy.Application.Common.Security; +using Hutopy.Domain.Constants; + +namespace Hutopy.Application.TodoLists.Commands.PurgeTodoLists; + +[Authorize(Roles = Roles.Administrator)] +[Authorize(Policy = Policies.CanPurge)] +public record PurgeTodoListsCommand : IRequest; + +public class PurgeTodoListsCommandHandler : IRequestHandler +{ + private readonly IApplicationDbContext _context; + + public PurgeTodoListsCommandHandler(IApplicationDbContext context) + { + _context = context; + } + + public async Task Handle(PurgeTodoListsCommand request, CancellationToken cancellationToken) + { + _context.TodoLists.RemoveRange(_context.TodoLists); + + await _context.SaveChangesAsync(cancellationToken); + } +} diff --git a/src/Application/TodoLists/Commands/UpdateTodoList/UpdateTodoList.cs b/src/Application/TodoLists/Commands/UpdateTodoList/UpdateTodoList.cs new file mode 100644 index 0000000..98b44e9 --- /dev/null +++ b/src/Application/TodoLists/Commands/UpdateTodoList/UpdateTodoList.cs @@ -0,0 +1,33 @@ +using Hutopy.Application.Common.Interfaces; + +namespace Hutopy.Application.TodoLists.Commands.UpdateTodoList; + +public record UpdateTodoListCommand : IRequest +{ + public int Id { get; init; } + + public string? Title { get; init; } +} + +public class UpdateTodoListCommandHandler : IRequestHandler +{ + private readonly IApplicationDbContext _context; + + public UpdateTodoListCommandHandler(IApplicationDbContext context) + { + _context = context; + } + + public async Task Handle(UpdateTodoListCommand request, CancellationToken cancellationToken) + { + var entity = await _context.TodoLists + .FindAsync(new object[] { request.Id }, cancellationToken); + + Guard.Against.NotFound(request.Id, entity); + + entity.Title = request.Title; + + await _context.SaveChangesAsync(cancellationToken); + + } +} diff --git a/src/Application/TodoLists/Commands/UpdateTodoList/UpdateTodoListCommandValidator.cs b/src/Application/TodoLists/Commands/UpdateTodoList/UpdateTodoListCommandValidator.cs new file mode 100644 index 0000000..2e7ef97 --- /dev/null +++ b/src/Application/TodoLists/Commands/UpdateTodoList/UpdateTodoListCommandValidator.cs @@ -0,0 +1,27 @@ +using Hutopy.Application.Common.Interfaces; + +namespace Hutopy.Application.TodoLists.Commands.UpdateTodoList; + +public class UpdateTodoListCommandValidator : AbstractValidator +{ + private readonly IApplicationDbContext _context; + + public UpdateTodoListCommandValidator(IApplicationDbContext context) + { + _context = context; + + RuleFor(v => v.Title) + .NotEmpty() + .MaximumLength(200) + .MustAsync(BeUniqueTitle) + .WithMessage("'{PropertyName}' must be unique.") + .WithErrorCode("Unique"); + } + + public async Task BeUniqueTitle(UpdateTodoListCommand model, string title, CancellationToken cancellationToken) + { + return await _context.TodoLists + .Where(l => l.Id != model.Id) + .AllAsync(l => l.Title != title, cancellationToken); + } +} diff --git a/src/Application/TodoLists/Queries/GetTodos/GetTodos.cs b/src/Application/TodoLists/Queries/GetTodos/GetTodos.cs new file mode 100644 index 0000000..cb44450 --- /dev/null +++ b/src/Application/TodoLists/Queries/GetTodos/GetTodos.cs @@ -0,0 +1,38 @@ +using Hutopy.Application.Common.Interfaces; +using Hutopy.Application.Common.Models; +using Hutopy.Application.Common.Security; +using Hutopy.Domain.Enums; + +namespace Hutopy.Application.TodoLists.Queries.GetTodos; + +[Authorize] +public record GetTodosQuery : IRequest; + +public class GetTodosQueryHandler : IRequestHandler +{ + private readonly IApplicationDbContext _context; + private readonly IMapper _mapper; + + public GetTodosQueryHandler(IApplicationDbContext context, IMapper mapper) + { + _context = context; + _mapper = mapper; + } + + public async Task Handle(GetTodosQuery request, CancellationToken cancellationToken) + { + return new TodosVm + { + PriorityLevels = Enum.GetValues(typeof(PriorityLevel)) + .Cast() + .Select(p => new LookupDto { Id = (int)p, Title = p.ToString() }) + .ToList(), + + Lists = await _context.TodoLists + .AsNoTracking() + .ProjectTo(_mapper.ConfigurationProvider) + .OrderBy(t => t.Title) + .ToListAsync(cancellationToken) + }; + } +} diff --git a/src/Application/TodoLists/Queries/GetTodos/TodoItemDto.cs b/src/Application/TodoLists/Queries/GetTodos/TodoItemDto.cs new file mode 100644 index 0000000..18d86a3 --- /dev/null +++ b/src/Application/TodoLists/Queries/GetTodos/TodoItemDto.cs @@ -0,0 +1,27 @@ +using Hutopy.Domain.Entities; + +namespace Hutopy.Application.TodoLists.Queries.GetTodos; + +public class TodoItemDto +{ + public int Id { get; init; } + + public int ListId { get; init; } + + public string? Title { get; init; } + + public bool Done { get; init; } + + public int Priority { get; init; } + + public string? Note { get; init; } + + private class Mapping : Profile + { + public Mapping() + { + CreateMap().ForMember(d => d.Priority, + opt => opt.MapFrom(s => (int)s.Priority)); + } + } +} diff --git a/src/Application/TodoLists/Queries/GetTodos/TodoListDto.cs b/src/Application/TodoLists/Queries/GetTodos/TodoListDto.cs new file mode 100644 index 0000000..6236f9a --- /dev/null +++ b/src/Application/TodoLists/Queries/GetTodos/TodoListDto.cs @@ -0,0 +1,27 @@ +using Hutopy.Domain.Entities; + +namespace Hutopy.Application.TodoLists.Queries.GetTodos; + +public class TodoListDto +{ + public TodoListDto() + { + Items = Array.Empty(); + } + + public int Id { get; init; } + + public string? Title { get; init; } + + public string? Colour { get; init; } + + public IReadOnlyCollection Items { get; init; } + + private class Mapping : Profile + { + public Mapping() + { + CreateMap(); + } + } +} diff --git a/src/Application/TodoLists/Queries/GetTodos/TodosVm.cs b/src/Application/TodoLists/Queries/GetTodos/TodosVm.cs new file mode 100644 index 0000000..6bff5af --- /dev/null +++ b/src/Application/TodoLists/Queries/GetTodos/TodosVm.cs @@ -0,0 +1,10 @@ +using Hutopy.Application.Common.Models; + +namespace Hutopy.Application.TodoLists.Queries.GetTodos; + +public class TodosVm +{ + public IReadOnlyCollection PriorityLevels { get; init; } = Array.Empty(); + + public IReadOnlyCollection Lists { get; init; } = Array.Empty(); +} diff --git a/src/Application/WeatherForecasts/Queries/GetWeatherForecasts/GetWeatherForecastsQuery.cs b/src/Application/WeatherForecasts/Queries/GetWeatherForecasts/GetWeatherForecastsQuery.cs new file mode 100644 index 0000000..cf75269 --- /dev/null +++ b/src/Application/WeatherForecasts/Queries/GetWeatherForecasts/GetWeatherForecastsQuery.cs @@ -0,0 +1,25 @@ +namespace Hutopy.Application.WeatherForecasts.Queries.GetWeatherForecasts; + +public record GetWeatherForecastsQuery : IRequest>; + +public class GetWeatherForecastsQueryHandler : IRequestHandler> +{ + private static readonly string[] Summaries = new[] + { + "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" + }; + +#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously + public async Task> Handle(GetWeatherForecastsQuery request, CancellationToken cancellationToken) +#pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously + { + var rng = new Random(); + + return Enumerable.Range(1, 5).Select(index => new WeatherForecast + { + Date = DateTime.Now.AddDays(index), + TemperatureC = rng.Next(-20, 55), + Summary = Summaries[rng.Next(Summaries.Length)] + }); + } +} diff --git a/src/Application/WeatherForecasts/Queries/GetWeatherForecasts/WeatherForecast.cs b/src/Application/WeatherForecasts/Queries/GetWeatherForecasts/WeatherForecast.cs new file mode 100644 index 0000000..e01216a --- /dev/null +++ b/src/Application/WeatherForecasts/Queries/GetWeatherForecasts/WeatherForecast.cs @@ -0,0 +1,12 @@ +namespace Hutopy.Application.WeatherForecasts.Queries.GetWeatherForecasts; + +public class WeatherForecast +{ + public DateTime Date { get; init; } + + public int TemperatureC { get; init; } + + public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); + + public string? Summary { get; init; } +} diff --git a/src/Domain/Common/BaseAuditableEntity.cs b/src/Domain/Common/BaseAuditableEntity.cs new file mode 100644 index 0000000..f1da955 --- /dev/null +++ b/src/Domain/Common/BaseAuditableEntity.cs @@ -0,0 +1,12 @@ +namespace Hutopy.Domain.Common; + +public abstract class BaseAuditableEntity : BaseEntity +{ + public DateTimeOffset Created { get; set; } + + public string? CreatedBy { get; set; } + + public DateTimeOffset LastModified { get; set; } + + public string? LastModifiedBy { get; set; } +} diff --git a/src/Domain/Common/BaseEntity.cs b/src/Domain/Common/BaseEntity.cs new file mode 100644 index 0000000..2ecc1fe --- /dev/null +++ b/src/Domain/Common/BaseEntity.cs @@ -0,0 +1,30 @@ +using System.ComponentModel.DataAnnotations.Schema; + +namespace Hutopy.Domain.Common; + +public abstract class BaseEntity +{ + // This can easily be modified to be BaseEntity and public T Id to support different key types. + // Using non-generic integer types for simplicity + public int Id { get; set; } + + private readonly List _domainEvents = new(); + + [NotMapped] + public IReadOnlyCollection DomainEvents => _domainEvents.AsReadOnly(); + + public void AddDomainEvent(BaseEvent domainEvent) + { + _domainEvents.Add(domainEvent); + } + + public void RemoveDomainEvent(BaseEvent domainEvent) + { + _domainEvents.Remove(domainEvent); + } + + public void ClearDomainEvents() + { + _domainEvents.Clear(); + } +} diff --git a/src/Domain/Common/BaseEvent.cs b/src/Domain/Common/BaseEvent.cs new file mode 100644 index 0000000..5df80ee --- /dev/null +++ b/src/Domain/Common/BaseEvent.cs @@ -0,0 +1,7 @@ +using MediatR; + +namespace Hutopy.Domain.Common; + +public abstract class BaseEvent : INotification +{ +} diff --git a/src/Domain/Common/ValueObject.cs b/src/Domain/Common/ValueObject.cs new file mode 100644 index 0000000..e419f3e --- /dev/null +++ b/src/Domain/Common/ValueObject.cs @@ -0,0 +1,45 @@ +namespace Hutopy.Domain.Common; + +// Learn more: https://docs.microsoft.com/en-us/dotnet/standard/microservices-architecture/microservice-ddd-cqrs-patterns/implement-value-objects +public abstract class ValueObject +{ + protected static bool EqualOperator(ValueObject left, ValueObject right) + { + if (left is null ^ right is null) + { + return false; + } + + return left?.Equals(right!) != false; + } + + protected static bool NotEqualOperator(ValueObject left, ValueObject right) + { + return !(EqualOperator(left, right)); + } + + protected abstract IEnumerable GetEqualityComponents(); + + public override bool Equals(object? obj) + { + if (obj == null || obj.GetType() != GetType()) + { + return false; + } + + var other = (ValueObject)obj; + return GetEqualityComponents().SequenceEqual(other.GetEqualityComponents()); + } + + public override int GetHashCode() + { + var hash = new HashCode(); + + foreach (var component in GetEqualityComponents()) + { + hash.Add(component); + } + + return hash.ToHashCode(); + } +} diff --git a/src/Domain/Constants/Policies.cs b/src/Domain/Constants/Policies.cs new file mode 100644 index 0000000..401d6dd --- /dev/null +++ b/src/Domain/Constants/Policies.cs @@ -0,0 +1,7 @@ +namespace Hutopy.Domain.Constants; + +public abstract class Policies +{ + public const string CanPurge = nameof(CanPurge); + public const string CanDelete = nameof(CanDelete); +} \ No newline at end of file diff --git a/src/Domain/Constants/Roles.cs b/src/Domain/Constants/Roles.cs new file mode 100644 index 0000000..38d9bf3 --- /dev/null +++ b/src/Domain/Constants/Roles.cs @@ -0,0 +1,6 @@ +namespace Hutopy.Domain.Constants; + +public abstract class Roles +{ + public const string Administrator = nameof(Administrator); +} \ No newline at end of file diff --git a/src/Domain/Domain.csproj b/src/Domain/Domain.csproj new file mode 100644 index 0000000..efab6e8 --- /dev/null +++ b/src/Domain/Domain.csproj @@ -0,0 +1,12 @@ + + + + Hutopy.Domain + Hutopy.Domain + + + + + + + diff --git a/src/Domain/Entities/TodoItem.cs b/src/Domain/Entities/TodoItem.cs new file mode 100644 index 0000000..e10f25b --- /dev/null +++ b/src/Domain/Entities/TodoItem.cs @@ -0,0 +1,31 @@ +namespace Hutopy.Domain.Entities; + +public class TodoItem : BaseAuditableEntity +{ + public int ListId { get; set; } + + public string? Title { get; set; } + + public string? Note { get; set; } + + public PriorityLevel Priority { get; set; } + + public DateTime? Reminder { get; set; } + + private bool _done; + public bool Done + { + get => _done; + set + { + if (value && !_done) + { + AddDomainEvent(new TodoItemCompletedEvent(this)); + } + + _done = value; + } + } + + public TodoList List { get; set; } = null!; +} diff --git a/src/Domain/Entities/TodoList.cs b/src/Domain/Entities/TodoList.cs new file mode 100644 index 0000000..365525e --- /dev/null +++ b/src/Domain/Entities/TodoList.cs @@ -0,0 +1,10 @@ +namespace Hutopy.Domain.Entities; + +public class TodoList : BaseAuditableEntity +{ + public string? Title { get; set; } + + public Colour Colour { get; set; } = Colour.White; + + public IList Items { get; private set; } = new List(); +} diff --git a/src/Domain/Enums/PriorityLevel.cs b/src/Domain/Enums/PriorityLevel.cs new file mode 100644 index 0000000..0a7ca16 --- /dev/null +++ b/src/Domain/Enums/PriorityLevel.cs @@ -0,0 +1,9 @@ +namespace Hutopy.Domain.Enums; + +public enum PriorityLevel +{ + None = 0, + Low = 1, + Medium = 2, + High = 3 +} diff --git a/src/Domain/Events/TodoItemCompletedEvent.cs b/src/Domain/Events/TodoItemCompletedEvent.cs new file mode 100644 index 0000000..b44c3ea --- /dev/null +++ b/src/Domain/Events/TodoItemCompletedEvent.cs @@ -0,0 +1,11 @@ +namespace Hutopy.Domain.Events; + +public class TodoItemCompletedEvent : BaseEvent +{ + public TodoItemCompletedEvent(TodoItem item) + { + Item = item; + } + + public TodoItem Item { get; } +} diff --git a/src/Domain/Events/TodoItemCreatedEvent.cs b/src/Domain/Events/TodoItemCreatedEvent.cs new file mode 100644 index 0000000..35db47f --- /dev/null +++ b/src/Domain/Events/TodoItemCreatedEvent.cs @@ -0,0 +1,11 @@ +namespace Hutopy.Domain.Events; + +public class TodoItemCreatedEvent : BaseEvent +{ + public TodoItemCreatedEvent(TodoItem item) + { + Item = item; + } + + public TodoItem Item { get; } +} diff --git a/src/Domain/Events/TodoItemDeletedEvent.cs b/src/Domain/Events/TodoItemDeletedEvent.cs new file mode 100644 index 0000000..d65711d --- /dev/null +++ b/src/Domain/Events/TodoItemDeletedEvent.cs @@ -0,0 +1,11 @@ +namespace Hutopy.Domain.Events; + +public class TodoItemDeletedEvent : BaseEvent +{ + public TodoItemDeletedEvent(TodoItem item) + { + Item = item; + } + + public TodoItem Item { get; } +} diff --git a/src/Domain/Exceptions/UnsupportedColourException.cs b/src/Domain/Exceptions/UnsupportedColourException.cs new file mode 100644 index 0000000..3946c28 --- /dev/null +++ b/src/Domain/Exceptions/UnsupportedColourException.cs @@ -0,0 +1,9 @@ +namespace Hutopy.Domain.Exceptions; + +public class UnsupportedColourException : Exception +{ + public UnsupportedColourException(string code) + : base($"Colour \"{code}\" is unsupported.") + { + } +} diff --git a/src/Domain/GlobalUsings.cs b/src/Domain/GlobalUsings.cs new file mode 100644 index 0000000..a15ae6d --- /dev/null +++ b/src/Domain/GlobalUsings.cs @@ -0,0 +1,6 @@ +global using Hutopy.Domain.Common; +global using Hutopy.Domain.Entities; +global using Hutopy.Domain.Enums; +global using Hutopy.Domain.Events; +global using Hutopy.Domain.Exceptions; +global using Hutopy.Domain.ValueObjects; \ No newline at end of file diff --git a/src/Domain/ValueObjects/Colour.cs b/src/Domain/ValueObjects/Colour.cs new file mode 100644 index 0000000..cf3d5ab --- /dev/null +++ b/src/Domain/ValueObjects/Colour.cs @@ -0,0 +1,69 @@ +namespace Hutopy.Domain.ValueObjects; + +public class Colour(string code) : ValueObject +{ + public static Colour From(string code) + { + var colour = new Colour(code); + + if (!SupportedColours.Contains(colour)) + { + throw new UnsupportedColourException(code); + } + + return colour; + } + + public static Colour White => new("#FFFFFF"); + + public static Colour Red => new("#FF5733"); + + public static Colour Orange => new("#FFC300"); + + public static Colour Yellow => new("#FFFF66"); + + public static Colour Green => new("#CCFF99"); + + public static Colour Blue => new("#6666FF"); + + public static Colour Purple => new("#9966CC"); + + public static Colour Grey => new("#999999"); + + public string Code { get; private set; } = string.IsNullOrWhiteSpace(code)?"#000000":code; + + public static implicit operator string(Colour colour) + { + return colour.ToString(); + } + + public static explicit operator Colour(string code) + { + return From(code); + } + + public override string ToString() + { + return Code; + } + + protected static IEnumerable SupportedColours + { + get + { + yield return White; + yield return Red; + yield return Orange; + yield return Yellow; + yield return Green; + yield return Blue; + yield return Purple; + yield return Grey; + } + } + + protected override IEnumerable GetEqualityComponents() + { + yield return Code; + } +} diff --git a/src/Infrastructure/Data/ApplicationDbContext.cs b/src/Infrastructure/Data/ApplicationDbContext.cs new file mode 100644 index 0000000..721bf1b --- /dev/null +++ b/src/Infrastructure/Data/ApplicationDbContext.cs @@ -0,0 +1,23 @@ +using System.Reflection; +using Hutopy.Application.Common.Interfaces; +using Hutopy.Domain.Entities; +using Hutopy.Infrastructure.Identity; +using Microsoft.AspNetCore.Identity.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore; + +namespace Hutopy.Infrastructure.Data; + +public class ApplicationDbContext : IdentityDbContext, IApplicationDbContext +{ + public ApplicationDbContext(DbContextOptions options) : base(options) { } + + public DbSet TodoLists => Set(); + + public DbSet TodoItems => Set(); + + protected override void OnModelCreating(ModelBuilder builder) + { + base.OnModelCreating(builder); + builder.ApplyConfigurationsFromAssembly(Assembly.GetExecutingAssembly()); + } +} diff --git a/src/Infrastructure/Data/ApplicationDbContextInitialiser.cs b/src/Infrastructure/Data/ApplicationDbContextInitialiser.cs new file mode 100644 index 0000000..eb7b336 --- /dev/null +++ b/src/Infrastructure/Data/ApplicationDbContextInitialiser.cs @@ -0,0 +1,109 @@ +using System.Runtime.InteropServices; +using Hutopy.Domain.Constants; +using Hutopy.Domain.Entities; +using Hutopy.Infrastructure.Identity; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Identity; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; + +namespace Hutopy.Infrastructure.Data; + +public static class InitialiserExtensions +{ + public static async Task InitialiseDatabaseAsync(this WebApplication app) + { + using var scope = app.Services.CreateScope(); + + var initialiser = scope.ServiceProvider.GetRequiredService(); + + await initialiser.InitialiseAsync(); + + await initialiser.SeedAsync(); + } +} + +public class ApplicationDbContextInitialiser +{ + private readonly ILogger _logger; + private readonly ApplicationDbContext _context; + private readonly UserManager _userManager; + private readonly RoleManager _roleManager; + + public ApplicationDbContextInitialiser(ILogger logger, ApplicationDbContext context, UserManager userManager, RoleManager roleManager) + { + _logger = logger; + _context = context; + _userManager = userManager; + _roleManager = roleManager; + } + + public async Task InitialiseAsync() + { + try + { + await _context.Database.MigrateAsync(); + } + catch (Exception ex) + { + _logger.LogError(ex, "An error occurred while initialising the database."); + throw; + } + } + + public async Task SeedAsync() + { + try + { + await TrySeedAsync(); + } + catch (Exception ex) + { + _logger.LogError(ex, "An error occurred while seeding the database."); + throw; + } + } + + public async Task TrySeedAsync() + { + // Default roles + var administratorRole = new IdentityRole(Roles.Administrator); + + if (_roleManager.Roles.All(r => r.Name != administratorRole.Name)) + { + await _roleManager.CreateAsync(administratorRole); + } + + // Default users + var administrator = new ApplicationUser { UserName = "administrator@localhost", Email = "administrator@localhost" }; + + if (_userManager.Users.All(u => u.UserName != administrator.UserName)) + { + await _userManager.CreateAsync(administrator, "Administrator1!"); + if (!string.IsNullOrWhiteSpace(administratorRole.Name)) + { + await _userManager.AddToRolesAsync(administrator, new [] { administratorRole.Name }); + } + } + + // Default data + // Seed, if necessary + if (!_context.TodoLists.Any()) + { + _context.TodoLists.Add(new TodoList + { + Title = "Todo List", + Items = + { + new TodoItem { Title = "Make a todo list 📃" }, + new TodoItem { Title = "Check off the first item ✅" }, + new TodoItem { Title = "Realise you've already done two things on the list! 🤯"}, + new TodoItem { Title = "Reward yourself with a nice, long nap 🏆" }, + } + }); + + await _context.SaveChangesAsync(); + } + } +} diff --git a/src/Infrastructure/Data/Configurations/TodoItemConfiguration.cs b/src/Infrastructure/Data/Configurations/TodoItemConfiguration.cs new file mode 100644 index 0000000..c6f9a2f --- /dev/null +++ b/src/Infrastructure/Data/Configurations/TodoItemConfiguration.cs @@ -0,0 +1,15 @@ +using Hutopy.Domain.Entities; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; + +namespace Hutopy.Infrastructure.Data.Configurations; + +public class TodoItemConfiguration : IEntityTypeConfiguration +{ + public void Configure(EntityTypeBuilder builder) + { + builder.Property(t => t.Title) + .HasMaxLength(200) + .IsRequired(); + } +} diff --git a/src/Infrastructure/Data/Configurations/TodoListConfiguration.cs b/src/Infrastructure/Data/Configurations/TodoListConfiguration.cs new file mode 100644 index 0000000..3350621 --- /dev/null +++ b/src/Infrastructure/Data/Configurations/TodoListConfiguration.cs @@ -0,0 +1,18 @@ +using Hutopy.Domain.Entities; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; + +namespace Hutopy.Infrastructure.Data.Configurations; + +public class TodoListConfiguration : IEntityTypeConfiguration +{ + public void Configure(EntityTypeBuilder builder) + { + builder.Property(t => t.Title) + .HasMaxLength(200) + .IsRequired(); + + builder + .OwnsOne(b => b.Colour); + } +} diff --git a/src/Infrastructure/Data/Interceptors/AuditableEntityInterceptor.cs b/src/Infrastructure/Data/Interceptors/AuditableEntityInterceptor.cs new file mode 100644 index 0000000..9d4b202 --- /dev/null +++ b/src/Infrastructure/Data/Interceptors/AuditableEntityInterceptor.cs @@ -0,0 +1,64 @@ +using Hutopy.Application.Common.Interfaces; +using Hutopy.Domain.Common; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.ChangeTracking; +using Microsoft.EntityFrameworkCore.Diagnostics; + +namespace Hutopy.Infrastructure.Data.Interceptors; + +public class AuditableEntityInterceptor : SaveChangesInterceptor +{ + private readonly IUser _user; + private readonly TimeProvider _dateTime; + + public AuditableEntityInterceptor( + IUser user, + TimeProvider dateTime) + { + _user = user; + _dateTime = dateTime; + } + + public override InterceptionResult SavingChanges(DbContextEventData eventData, InterceptionResult result) + { + UpdateEntities(eventData.Context); + + return base.SavingChanges(eventData, result); + } + + public override ValueTask> SavingChangesAsync(DbContextEventData eventData, InterceptionResult result, CancellationToken cancellationToken = default) + { + UpdateEntities(eventData.Context); + + return base.SavingChangesAsync(eventData, result, cancellationToken); + } + + public void UpdateEntities(DbContext? context) + { + if (context == null) return; + + foreach (var entry in context.ChangeTracker.Entries()) + { + if (entry.State is EntityState.Added or EntityState.Modified || entry.HasChangedOwnedEntities()) + { + var utcNow = _dateTime.GetUtcNow(); + if (entry.State == EntityState.Added) + { + entry.Entity.CreatedBy = _user.Id; + entry.Entity.Created = utcNow; + } + entry.Entity.LastModifiedBy = _user.Id; + entry.Entity.LastModified = utcNow; + } + } + } +} + +public static class Extensions +{ + public static bool HasChangedOwnedEntities(this EntityEntry entry) => + entry.References.Any(r => + r.TargetEntry != null && + r.TargetEntry.Metadata.IsOwned() && + (r.TargetEntry.State == EntityState.Added || r.TargetEntry.State == EntityState.Modified)); +} diff --git a/src/Infrastructure/Data/Interceptors/DispatchDomainEventsInterceptor.cs b/src/Infrastructure/Data/Interceptors/DispatchDomainEventsInterceptor.cs new file mode 100644 index 0000000..3664dd3 --- /dev/null +++ b/src/Infrastructure/Data/Interceptors/DispatchDomainEventsInterceptor.cs @@ -0,0 +1,50 @@ +using Hutopy.Domain.Common; +using MediatR; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Diagnostics; + +namespace Hutopy.Infrastructure.Data.Interceptors; + +public class DispatchDomainEventsInterceptor : SaveChangesInterceptor +{ + private readonly IMediator _mediator; + + public DispatchDomainEventsInterceptor(IMediator mediator) + { + _mediator = mediator; + } + + public override InterceptionResult SavingChanges(DbContextEventData eventData, InterceptionResult result) + { + DispatchDomainEvents(eventData.Context).GetAwaiter().GetResult(); + + return base.SavingChanges(eventData, result); + + } + + public override async ValueTask> SavingChangesAsync(DbContextEventData eventData, InterceptionResult result, CancellationToken cancellationToken = default) + { + await DispatchDomainEvents(eventData.Context); + + return await base.SavingChangesAsync(eventData, result, cancellationToken); + } + + public async Task DispatchDomainEvents(DbContext? context) + { + if (context == null) return; + + var entities = context.ChangeTracker + .Entries() + .Where(e => e.Entity.DomainEvents.Any()) + .Select(e => e.Entity); + + var domainEvents = entities + .SelectMany(e => e.DomainEvents) + .ToList(); + + entities.ToList().ForEach(e => e.ClearDomainEvents()); + + foreach (var domainEvent in domainEvents) + await _mediator.Publish(domainEvent); + } +} diff --git a/src/Infrastructure/Data/Migrations/00000000000000_InitialCreate.Designer.cs b/src/Infrastructure/Data/Migrations/00000000000000_InitialCreate.Designer.cs new file mode 100644 index 0000000..6b2f5af --- /dev/null +++ b/src/Infrastructure/Data/Migrations/00000000000000_InitialCreate.Designer.cs @@ -0,0 +1,399 @@ +// +using System; +using Hutopy.Infrastructure.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Hutopy.Infrastructure.Data.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + [Migration("00000000000000_InitialCreate")] + partial class InitialCreate + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.0-preview.6.23329.4") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("Hutopy.Domain.Entities.TodoItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Created") + .HasColumnType("datetimeoffset"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("Done") + .HasColumnType("bit"); + + b.Property("LastModified") + .HasColumnType("datetimeoffset"); + + b.Property("LastModifiedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("ListId") + .HasColumnType("int"); + + b.Property("Note") + .HasColumnType("nvarchar(max)"); + + b.Property("Priority") + .HasColumnType("int"); + + b.Property("Reminder") + .HasColumnType("datetime2"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.HasKey("Id"); + + b.HasIndex("ListId"); + + b.ToTable("TodoItems"); + }); + + modelBuilder.Entity("Hutopy.Domain.Entities.TodoList", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Created") + .HasColumnType("datetimeoffset"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("LastModified") + .HasColumnType("datetimeoffset"); + + b.Property("LastModifiedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.HasKey("Id"); + + b.ToTable("TodoLists"); + }); + + modelBuilder.Entity("Hutopy.Infrastructure.Identity.ApplicationUser", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("AccessFailedCount") + .HasColumnType("int"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("nvarchar(max)"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("EmailConfirmed") + .HasColumnType("bit"); + + b.Property("LockoutEnabled") + .HasColumnType("bit"); + + b.Property("LockoutEnd") + .HasColumnType("datetimeoffset"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("PasswordHash") + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumber") + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("bit"); + + b.Property("SecurityStamp") + .HasColumnType("nvarchar(max)"); + + b.Property("TwoFactorEnabled") + .HasColumnType("bit"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex") + .HasFilter("[NormalizedUserName] IS NOT NULL"); + + b.ToTable("AspNetUsers", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("nvarchar(max)"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex") + .HasFilter("[NormalizedName] IS NOT NULL"); + + b.ToTable("AspNetRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("nvarchar(max)"); + + b.Property("ClaimValue") + .HasColumnType("nvarchar(max)"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("nvarchar(max)"); + + b.Property("ClaimValue") + .HasColumnType("nvarchar(max)"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("ProviderKey") + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("ProviderDisplayName") + .HasColumnType("nvarchar(max)"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("nvarchar(450)"); + + b.Property("RoleId") + .HasColumnType("nvarchar(450)"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("nvarchar(450)"); + + b.Property("LoginProvider") + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("Name") + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("Value") + .HasColumnType("nvarchar(max)"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens", (string)null); + }); + + modelBuilder.Entity("Hutopy.Domain.Entities.TodoItem", b => + { + b.HasOne("Hutopy.Domain.Entities.TodoList", "List") + .WithMany("Items") + .HasForeignKey("ListId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("List"); + }); + + modelBuilder.Entity("Hutopy.Domain.Entities.TodoList", b => + { + b.OwnsOne("Hutopy.Domain.ValueObjects.Colour", "Colour", b1 => + { + b1.Property("TodoListId") + .HasColumnType("int"); + + b1.Property("Code") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.HasKey("TodoListId"); + + b1.ToTable("TodoLists"); + + b1.WithOwner() + .HasForeignKey("TodoListId"); + }); + + b.Navigation("Colour") + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Hutopy.Domain.Entities.TodoList", b => + { + b.Navigation("Items"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Infrastructure/Data/Migrations/00000000000000_InitialCreate.cs b/src/Infrastructure/Data/Migrations/00000000000000_InitialCreate.cs new file mode 100644 index 0000000..3335275 --- /dev/null +++ b/src/Infrastructure/Data/Migrations/00000000000000_InitialCreate.cs @@ -0,0 +1,281 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Hutopy.Infrastructure.Data.Migrations +{ + /// + public partial class InitialCreate : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "AspNetRoles", + columns: table => new + { + Id = table.Column(type: "nvarchar(450)", nullable: false), + Name = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), + NormalizedName = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), + ConcurrencyStamp = table.Column(type: "nvarchar(max)", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AspNetRoles", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AspNetUsers", + columns: table => new + { + Id = table.Column(type: "nvarchar(450)", nullable: false), + UserName = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), + NormalizedUserName = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), + Email = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), + NormalizedEmail = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), + EmailConfirmed = table.Column(type: "bit", nullable: false), + PasswordHash = table.Column(type: "nvarchar(max)", nullable: true), + SecurityStamp = table.Column(type: "nvarchar(max)", nullable: true), + ConcurrencyStamp = table.Column(type: "nvarchar(max)", nullable: true), + PhoneNumber = table.Column(type: "nvarchar(max)", nullable: true), + PhoneNumberConfirmed = table.Column(type: "bit", nullable: false), + TwoFactorEnabled = table.Column(type: "bit", nullable: false), + LockoutEnd = table.Column(type: "datetimeoffset", nullable: true), + LockoutEnabled = table.Column(type: "bit", nullable: false), + AccessFailedCount = table.Column(type: "int", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AspNetUsers", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "TodoLists", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + Title = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: false), + Colour_Code = table.Column(type: "nvarchar(max)", nullable: false), + Created = table.Column(type: "datetimeoffset", nullable: false), + CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), + LastModified = table.Column(type: "datetimeoffset", nullable: false), + LastModifiedBy = table.Column(type: "nvarchar(max)", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_TodoLists", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AspNetRoleClaims", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + RoleId = table.Column(type: "nvarchar(450)", nullable: false), + ClaimType = table.Column(type: "nvarchar(max)", nullable: true), + ClaimValue = table.Column(type: "nvarchar(max)", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AspNetRoleClaims", x => x.Id); + table.ForeignKey( + name: "FK_AspNetRoleClaims_AspNetRoles_RoleId", + column: x => x.RoleId, + principalTable: "AspNetRoles", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AspNetUserClaims", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + UserId = table.Column(type: "nvarchar(450)", nullable: false), + ClaimType = table.Column(type: "nvarchar(max)", nullable: true), + ClaimValue = table.Column(type: "nvarchar(max)", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AspNetUserClaims", x => x.Id); + table.ForeignKey( + name: "FK_AspNetUserClaims_AspNetUsers_UserId", + column: x => x.UserId, + principalTable: "AspNetUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AspNetUserLogins", + columns: table => new + { + LoginProvider = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: false), + ProviderKey = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: false), + ProviderDisplayName = table.Column(type: "nvarchar(max)", nullable: true), + UserId = table.Column(type: "nvarchar(450)", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AspNetUserLogins", x => new { x.LoginProvider, x.ProviderKey }); + table.ForeignKey( + name: "FK_AspNetUserLogins_AspNetUsers_UserId", + column: x => x.UserId, + principalTable: "AspNetUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AspNetUserRoles", + columns: table => new + { + UserId = table.Column(type: "nvarchar(450)", nullable: false), + RoleId = table.Column(type: "nvarchar(450)", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AspNetUserRoles", x => new { x.UserId, x.RoleId }); + table.ForeignKey( + name: "FK_AspNetUserRoles_AspNetRoles_RoleId", + column: x => x.RoleId, + principalTable: "AspNetRoles", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_AspNetUserRoles_AspNetUsers_UserId", + column: x => x.UserId, + principalTable: "AspNetUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AspNetUserTokens", + columns: table => new + { + UserId = table.Column(type: "nvarchar(450)", nullable: false), + LoginProvider = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: false), + Name = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: false), + Value = table.Column(type: "nvarchar(max)", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AspNetUserTokens", x => new { x.UserId, x.LoginProvider, x.Name }); + table.ForeignKey( + name: "FK_AspNetUserTokens_AspNetUsers_UserId", + column: x => x.UserId, + principalTable: "AspNetUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "TodoItems", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + ListId = table.Column(type: "int", nullable: false), + Title = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: false), + Note = table.Column(type: "nvarchar(max)", nullable: true), + Priority = table.Column(type: "int", nullable: false), + Reminder = table.Column(type: "datetime2", nullable: true), + Done = table.Column(type: "bit", nullable: false), + Created = table.Column(type: "datetimeoffset", nullable: false), + CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), + LastModified = table.Column(type: "datetimeoffset", nullable: false), + LastModifiedBy = table.Column(type: "nvarchar(max)", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_TodoItems", x => x.Id); + table.ForeignKey( + name: "FK_TodoItems_TodoLists_ListId", + column: x => x.ListId, + principalTable: "TodoLists", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "IX_AspNetRoleClaims_RoleId", + table: "AspNetRoleClaims", + column: "RoleId"); + + migrationBuilder.CreateIndex( + name: "RoleNameIndex", + table: "AspNetRoles", + column: "NormalizedName", + unique: true, + filter: "[NormalizedName] IS NOT NULL"); + + migrationBuilder.CreateIndex( + name: "IX_AspNetUserClaims_UserId", + table: "AspNetUserClaims", + column: "UserId"); + + migrationBuilder.CreateIndex( + name: "IX_AspNetUserLogins_UserId", + table: "AspNetUserLogins", + column: "UserId"); + + migrationBuilder.CreateIndex( + name: "IX_AspNetUserRoles_RoleId", + table: "AspNetUserRoles", + column: "RoleId"); + + migrationBuilder.CreateIndex( + name: "EmailIndex", + table: "AspNetUsers", + column: "NormalizedEmail"); + + migrationBuilder.CreateIndex( + name: "UserNameIndex", + table: "AspNetUsers", + column: "NormalizedUserName", + unique: true, + filter: "[NormalizedUserName] IS NOT NULL"); + + migrationBuilder.CreateIndex( + name: "IX_TodoItems_ListId", + table: "TodoItems", + column: "ListId"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "AspNetRoleClaims"); + + migrationBuilder.DropTable( + name: "AspNetUserClaims"); + + migrationBuilder.DropTable( + name: "AspNetUserLogins"); + + migrationBuilder.DropTable( + name: "AspNetUserRoles"); + + migrationBuilder.DropTable( + name: "AspNetUserTokens"); + + migrationBuilder.DropTable( + name: "TodoItems"); + + migrationBuilder.DropTable( + name: "AspNetRoles"); + + migrationBuilder.DropTable( + name: "AspNetUsers"); + + migrationBuilder.DropTable( + name: "TodoLists"); + } + } +} diff --git a/src/Infrastructure/Data/Migrations/ApplicationDbContextModelSnapshot.cs b/src/Infrastructure/Data/Migrations/ApplicationDbContextModelSnapshot.cs new file mode 100644 index 0000000..7a9ffa0 --- /dev/null +++ b/src/Infrastructure/Data/Migrations/ApplicationDbContextModelSnapshot.cs @@ -0,0 +1,396 @@ +// +using System; +using Hutopy.Infrastructure.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Hutopy.Infrastructure.Data.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + partial class ApplicationDbContextModelSnapshot : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.0-preview.6.23329.4") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("Hutopy.Domain.Entities.TodoItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Created") + .HasColumnType("datetimeoffset"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("Done") + .HasColumnType("bit"); + + b.Property("LastModified") + .HasColumnType("datetimeoffset"); + + b.Property("LastModifiedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("ListId") + .HasColumnType("int"); + + b.Property("Note") + .HasColumnType("nvarchar(max)"); + + b.Property("Priority") + .HasColumnType("int"); + + b.Property("Reminder") + .HasColumnType("datetime2"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.HasKey("Id"); + + b.HasIndex("ListId"); + + b.ToTable("TodoItems"); + }); + + modelBuilder.Entity("Hutopy.Domain.Entities.TodoList", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Created") + .HasColumnType("datetimeoffset"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("LastModified") + .HasColumnType("datetimeoffset"); + + b.Property("LastModifiedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.HasKey("Id"); + + b.ToTable("TodoLists"); + }); + + modelBuilder.Entity("Hutopy.Infrastructure.Identity.ApplicationUser", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("AccessFailedCount") + .HasColumnType("int"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("nvarchar(max)"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("EmailConfirmed") + .HasColumnType("bit"); + + b.Property("LockoutEnabled") + .HasColumnType("bit"); + + b.Property("LockoutEnd") + .HasColumnType("datetimeoffset"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("PasswordHash") + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumber") + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("bit"); + + b.Property("SecurityStamp") + .HasColumnType("nvarchar(max)"); + + b.Property("TwoFactorEnabled") + .HasColumnType("bit"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex") + .HasFilter("[NormalizedUserName] IS NOT NULL"); + + b.ToTable("AspNetUsers", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("nvarchar(max)"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex") + .HasFilter("[NormalizedName] IS NOT NULL"); + + b.ToTable("AspNetRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("nvarchar(max)"); + + b.Property("ClaimValue") + .HasColumnType("nvarchar(max)"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("nvarchar(max)"); + + b.Property("ClaimValue") + .HasColumnType("nvarchar(max)"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("ProviderKey") + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("ProviderDisplayName") + .HasColumnType("nvarchar(max)"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("nvarchar(450)"); + + b.Property("RoleId") + .HasColumnType("nvarchar(450)"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("nvarchar(450)"); + + b.Property("LoginProvider") + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("Name") + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("Value") + .HasColumnType("nvarchar(max)"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens", (string)null); + }); + + modelBuilder.Entity("Hutopy.Domain.Entities.TodoItem", b => + { + b.HasOne("Hutopy.Domain.Entities.TodoList", "List") + .WithMany("Items") + .HasForeignKey("ListId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("List"); + }); + + modelBuilder.Entity("Hutopy.Domain.Entities.TodoList", b => + { + b.OwnsOne("Hutopy.Domain.ValueObjects.Colour", "Colour", b1 => + { + b1.Property("TodoListId") + .HasColumnType("int"); + + b1.Property("Code") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.HasKey("TodoListId"); + + b1.ToTable("TodoLists"); + + b1.WithOwner() + .HasForeignKey("TodoListId"); + }); + + b.Navigation("Colour") + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Hutopy.Domain.Entities.TodoList", b => + { + b.Navigation("Items"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Infrastructure/DependencyInjection.cs b/src/Infrastructure/DependencyInjection.cs new file mode 100644 index 0000000..3a2b7a8 --- /dev/null +++ b/src/Infrastructure/DependencyInjection.cs @@ -0,0 +1,58 @@ +using Hutopy.Application.Common.Interfaces; +using Hutopy.Domain.Constants; +using Hutopy.Infrastructure.Data; +using Hutopy.Infrastructure.Data.Interceptors; +using Hutopy.Infrastructure.Identity; +using Microsoft.AspNetCore.Identity; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Diagnostics; +using Microsoft.Extensions.Configuration; + +namespace Microsoft.Extensions.DependencyInjection; + +public static class DependencyInjection +{ + public static IServiceCollection AddInfrastructureServices(this IServiceCollection services, IConfiguration configuration) + { + // Replace password in the connection string with env var. + var connectionString = configuration.GetConnectionString("DefaultConnection") ?? ""; + var dbPassword = Environment.GetEnvironmentVariable("DB_PASSWORD"); + + connectionString = connectionString.Replace("{DB_PASSWORD}", dbPassword); + + Guard.Against.Null(connectionString, message: "Connection string 'DefaultConnection' not found."); + + services.AddScoped(); + services.AddScoped(); + + services.AddDbContext((sp, options) => + { + options.AddInterceptors(sp.GetServices()); + + options.UseSqlServer(connectionString); + }); + + services.AddScoped(provider => provider.GetRequiredService()); + + services.AddScoped(); + + services.AddAuthentication() + .AddBearerToken(IdentityConstants.BearerScheme); + + services.AddAuthorizationBuilder(); + + services + .AddIdentityCore() + .AddRoles() + .AddEntityFrameworkStores() + .AddApiEndpoints(); + + services.AddSingleton(TimeProvider.System); + services.AddTransient(); + + services.AddAuthorization(options => + options.AddPolicy(Policies.CanPurge, policy => policy.RequireRole(Roles.Administrator))); + + return services; + } +} diff --git a/src/Infrastructure/GlobalUsings.cs b/src/Infrastructure/GlobalUsings.cs new file mode 100644 index 0000000..4668da2 --- /dev/null +++ b/src/Infrastructure/GlobalUsings.cs @@ -0,0 +1 @@ +global using Ardalis.GuardClauses; \ No newline at end of file diff --git a/src/Infrastructure/Identity/ApplicationUser.cs b/src/Infrastructure/Identity/ApplicationUser.cs new file mode 100644 index 0000000..badd6ee --- /dev/null +++ b/src/Infrastructure/Identity/ApplicationUser.cs @@ -0,0 +1,7 @@ +using Microsoft.AspNetCore.Identity; + +namespace Hutopy.Infrastructure.Identity; + +public class ApplicationUser : IdentityUser +{ +} diff --git a/src/Infrastructure/Identity/IdentityResultExtensions.cs b/src/Infrastructure/Identity/IdentityResultExtensions.cs new file mode 100644 index 0000000..630c372 --- /dev/null +++ b/src/Infrastructure/Identity/IdentityResultExtensions.cs @@ -0,0 +1,14 @@ +using Hutopy.Application.Common.Models; +using Microsoft.AspNetCore.Identity; + +namespace Hutopy.Infrastructure.Identity; + +public static class IdentityResultExtensions +{ + public static Result ToApplicationResult(this IdentityResult result) + { + return result.Succeeded + ? Result.Success() + : Result.Failure(result.Errors.Select(e => e.Description)); + } +} diff --git a/src/Infrastructure/Identity/IdentityService.cs b/src/Infrastructure/Identity/IdentityService.cs new file mode 100644 index 0000000..015100b --- /dev/null +++ b/src/Infrastructure/Identity/IdentityService.cs @@ -0,0 +1,80 @@ +using Hutopy.Application.Common.Interfaces; +using Hutopy.Application.Common.Models; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Identity; + +namespace Hutopy.Infrastructure.Identity; + +public class IdentityService : IIdentityService +{ + private readonly UserManager _userManager; + private readonly IUserClaimsPrincipalFactory _userClaimsPrincipalFactory; + private readonly IAuthorizationService _authorizationService; + + public IdentityService( + UserManager userManager, + IUserClaimsPrincipalFactory userClaimsPrincipalFactory, + IAuthorizationService authorizationService) + { + _userManager = userManager; + _userClaimsPrincipalFactory = userClaimsPrincipalFactory; + _authorizationService = authorizationService; + } + + public async Task GetUserNameAsync(string userId) + { + var user = await _userManager.FindByIdAsync(userId); + + return user?.UserName; + } + + public async Task<(Result Result, string UserId)> CreateUserAsync(string userName, string password) + { + var user = new ApplicationUser + { + UserName = userName, + Email = userName, + }; + + var result = await _userManager.CreateAsync(user, password); + + return (result.ToApplicationResult(), user.Id); + } + + public async Task IsInRoleAsync(string userId, string role) + { + var user = await _userManager.FindByIdAsync(userId); + + return user != null && await _userManager.IsInRoleAsync(user, role); + } + + public async Task AuthorizeAsync(string userId, string policyName) + { + var user = await _userManager.FindByIdAsync(userId); + + if (user == null) + { + return false; + } + + var principal = await _userClaimsPrincipalFactory.CreateAsync(user); + + var result = await _authorizationService.AuthorizeAsync(principal, policyName); + + return result.Succeeded; + } + + public async Task DeleteUserAsync(string userId) + { + var user = await _userManager.FindByIdAsync(userId); + + return user != null ? await DeleteUserAsync(user) : Result.Success(); + } + + public async Task DeleteUserAsync(ApplicationUser user) + { + var result = await _userManager.DeleteAsync(user); + + return result.ToApplicationResult(); + } +} diff --git a/src/Infrastructure/Infrastructure.csproj b/src/Infrastructure/Infrastructure.csproj new file mode 100644 index 0000000..f68f7c8 --- /dev/null +++ b/src/Infrastructure/Infrastructure.csproj @@ -0,0 +1,20 @@ + + + + Hutopy.Infrastructure + Hutopy.Infrastructure + + + + + + + + + + + + + + + diff --git a/src/Web/DependencyInjection.cs b/src/Web/DependencyInjection.cs new file mode 100644 index 0000000..a7dbc86 --- /dev/null +++ b/src/Web/DependencyInjection.cs @@ -0,0 +1,66 @@ +using Azure.Identity; +using Hutopy.Application.Common.Interfaces; +using Hutopy.Infrastructure.Data; +using Hutopy.Web.Services; +using Microsoft.AspNetCore.Mvc; + +using NSwag; +using NSwag.Generation.Processors.Security; + +namespace Microsoft.Extensions.DependencyInjection; + +public static class DependencyInjection +{ + public static IServiceCollection AddWebServices(this IServiceCollection services) + { + services.AddDatabaseDeveloperPageExceptionFilter(); + + services.AddScoped(); + + services.AddHttpContextAccessor(); + + services.AddHealthChecks() + .AddDbContextCheck(); + + services.AddExceptionHandler(); + + services.AddRazorPages(); + + // Customise default API behaviour + services.Configure(options => + options.SuppressModelStateInvalidFilter = true); + + services.AddEndpointsApiExplorer(); + + services.AddOpenApiDocument((configure, sp) => + { + configure.Title = "Hutopy API"; + + // Add JWT + configure.AddSecurity("JWT", Enumerable.Empty(), 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; + } + + public static IServiceCollection AddKeyVaultIfConfigured(this IServiceCollection services, ConfigurationManager configuration) + { + var keyVaultUri = configuration["KeyVaultUri"]; + if (!string.IsNullOrWhiteSpace(keyVaultUri)) + { + configuration.AddAzureKeyVault( + new Uri(keyVaultUri), + new DefaultAzureCredential()); + } + + return services; + } +} diff --git a/src/Web/Endpoints/TodoItems.cs b/src/Web/Endpoints/TodoItems.cs new file mode 100644 index 0000000..7cb1fa4 --- /dev/null +++ b/src/Web/Endpoints/TodoItems.cs @@ -0,0 +1,52 @@ +using Hutopy.Application.Common.Models; +using Hutopy.Application.TodoItems.Commands.CreateTodoItem; +using Hutopy.Application.TodoItems.Commands.DeleteTodoItem; +using Hutopy.Application.TodoItems.Commands.UpdateTodoItem; +using Hutopy.Application.TodoItems.Commands.UpdateTodoItemDetail; +using Hutopy.Application.TodoItems.Queries.GetTodoItemsWithPagination; + +namespace Hutopy.Web.Endpoints; + +public class TodoItems : EndpointGroupBase +{ + public override void Map(WebApplication app) + { + app.MapGroup(this) + .RequireAuthorization() + .MapGet(GetTodoItemsWithPagination) + .MapPost(CreateTodoItem) + .MapPut(UpdateTodoItem, "{id}") + .MapPut(UpdateTodoItemDetail, "UpdateDetail/{id}") + .MapDelete(DeleteTodoItem, "{id}"); + } + + public Task> GetTodoItemsWithPagination(ISender sender, [AsParameters] GetTodoItemsWithPaginationQuery query) + { + return sender.Send(query); + } + + public Task CreateTodoItem(ISender sender, CreateTodoItemCommand command) + { + return sender.Send(command); + } + + public async Task UpdateTodoItem(ISender sender, int id, UpdateTodoItemCommand command) + { + if (id != command.Id) return Results.BadRequest(); + await sender.Send(command); + return Results.NoContent(); + } + + public async Task UpdateTodoItemDetail(ISender sender, int id, UpdateTodoItemDetailCommand command) + { + if (id != command.Id) return Results.BadRequest(); + await sender.Send(command); + return Results.NoContent(); + } + + public async Task DeleteTodoItem(ISender sender, int id) + { + await sender.Send(new DeleteTodoItemCommand(id)); + return Results.NoContent(); + } +} diff --git a/src/Web/Endpoints/TodoLists.cs b/src/Web/Endpoints/TodoLists.cs new file mode 100644 index 0000000..fafd341 --- /dev/null +++ b/src/Web/Endpoints/TodoLists.cs @@ -0,0 +1,42 @@ +using Hutopy.Application.TodoLists.Commands.CreateTodoList; +using Hutopy.Application.TodoLists.Commands.DeleteTodoList; +using Hutopy.Application.TodoLists.Commands.UpdateTodoList; +using Hutopy.Application.TodoLists.Queries.GetTodos; + +namespace Hutopy.Web.Endpoints; + +public class TodoLists : EndpointGroupBase +{ + public override void Map(WebApplication app) + { + app.MapGroup(this) + .RequireAuthorization() + .MapGet(GetTodoLists) + .MapPost(CreateTodoList) + .MapPut(UpdateTodoList, "{id}") + .MapDelete(DeleteTodoList, "{id}"); + } + + public Task GetTodoLists(ISender sender) + { + return sender.Send(new GetTodosQuery()); + } + + public Task CreateTodoList(ISender sender, CreateTodoListCommand command) + { + return sender.Send(command); + } + + public async Task UpdateTodoList(ISender sender, int id, UpdateTodoListCommand command) + { + if (id != command.Id) return Results.BadRequest(); + await sender.Send(command); + return Results.NoContent(); + } + + public async Task DeleteTodoList(ISender sender, int id) + { + await sender.Send(new DeleteTodoListCommand(id)); + return Results.NoContent(); + } +} diff --git a/src/Web/Endpoints/Users.cs b/src/Web/Endpoints/Users.cs new file mode 100644 index 0000000..c27114b --- /dev/null +++ b/src/Web/Endpoints/Users.cs @@ -0,0 +1,12 @@ +using Hutopy.Infrastructure.Identity; + +namespace Hutopy.Web.Endpoints; + +public class Users : EndpointGroupBase +{ + public override void Map(WebApplication app) + { + app.MapGroup(this) + .MapIdentityApi(); + } +} diff --git a/src/Web/Endpoints/WeatherForecasts.cs b/src/Web/Endpoints/WeatherForecasts.cs new file mode 100644 index 0000000..8eef1fd --- /dev/null +++ b/src/Web/Endpoints/WeatherForecasts.cs @@ -0,0 +1,18 @@ +using Hutopy.Application.WeatherForecasts.Queries.GetWeatherForecasts; + +namespace Hutopy.Web.Endpoints; + +public class WeatherForecasts : EndpointGroupBase +{ + public override void Map(WebApplication app) + { + app.MapGroup(this) + .RequireAuthorization() + .MapGet(GetWeatherForecasts); + } + + public async Task> GetWeatherForecasts(ISender sender) + { + return await sender.Send(new GetWeatherForecastsQuery()); + } +} diff --git a/src/Web/GlobalUsings.cs b/src/Web/GlobalUsings.cs new file mode 100644 index 0000000..a69805b --- /dev/null +++ b/src/Web/GlobalUsings.cs @@ -0,0 +1,3 @@ +global using Ardalis.GuardClauses; +global using Hutopy.Web.Infrastructure; +global using MediatR; diff --git a/src/Web/Infrastructure/CustomExceptionHandler.cs b/src/Web/Infrastructure/CustomExceptionHandler.cs new file mode 100644 index 0000000..e49063b --- /dev/null +++ b/src/Web/Infrastructure/CustomExceptionHandler.cs @@ -0,0 +1,87 @@ +using Hutopy.Application.Common.Exceptions; +using Microsoft.AspNetCore.Diagnostics; +using Microsoft.AspNetCore.Mvc; + +namespace Hutopy.Web.Infrastructure; + +public class CustomExceptionHandler : IExceptionHandler +{ + private readonly Dictionary> _exceptionHandlers; + + public CustomExceptionHandler() + { + // Register known exception types and handlers. + _exceptionHandlers = new() + { + { typeof(ValidationException), HandleValidationException }, + { typeof(NotFoundException), HandleNotFoundException }, + { typeof(UnauthorizedAccessException), HandleUnauthorizedAccessException }, + { typeof(ForbiddenAccessException), HandleForbiddenAccessException }, + }; + } + + public async ValueTask TryHandleAsync(HttpContext httpContext, Exception exception, CancellationToken cancellationToken) + { + var exceptionType = exception.GetType(); + + if (_exceptionHandlers.ContainsKey(exceptionType)) + { + await _exceptionHandlers[exceptionType].Invoke(httpContext, exception); + return true; + } + + return false; + } + + private async Task HandleValidationException(HttpContext httpContext, Exception ex) + { + var exception = (ValidationException)ex; + + httpContext.Response.StatusCode = StatusCodes.Status400BadRequest; + + await httpContext.Response.WriteAsJsonAsync(new ValidationProblemDetails(exception.Errors) + { + Status = StatusCodes.Status400BadRequest, + Type = "https://tools.ietf.org/html/rfc7231#section-6.5.1" + }); + } + + private async Task HandleNotFoundException(HttpContext httpContext, Exception ex) + { + var exception = (NotFoundException)ex; + + httpContext.Response.StatusCode = StatusCodes.Status404NotFound; + + await httpContext.Response.WriteAsJsonAsync(new ProblemDetails() + { + Status = StatusCodes.Status404NotFound, + Type = "https://tools.ietf.org/html/rfc7231#section-6.5.4", + Title = "The specified resource was not found.", + Detail = exception.Message + }); + } + + private async Task HandleUnauthorizedAccessException(HttpContext httpContext, Exception ex) + { + httpContext.Response.StatusCode = StatusCodes.Status401Unauthorized; + + await httpContext.Response.WriteAsJsonAsync(new ProblemDetails + { + Status = StatusCodes.Status401Unauthorized, + Title = "Unauthorized", + Type = "https://tools.ietf.org/html/rfc7235#section-3.1" + }); + } + + private async Task HandleForbiddenAccessException(HttpContext httpContext, Exception ex) + { + httpContext.Response.StatusCode = StatusCodes.Status403Forbidden; + + await httpContext.Response.WriteAsJsonAsync(new ProblemDetails + { + Status = StatusCodes.Status403Forbidden, + Title = "Forbidden", + Type = "https://tools.ietf.org/html/rfc7231#section-6.5.3" + }); + } +} diff --git a/src/Web/Infrastructure/EndpointGroupBase.cs b/src/Web/Infrastructure/EndpointGroupBase.cs new file mode 100644 index 0000000..00b4ca7 --- /dev/null +++ b/src/Web/Infrastructure/EndpointGroupBase.cs @@ -0,0 +1,6 @@ +namespace Hutopy.Web.Infrastructure; + +public abstract class EndpointGroupBase +{ + public abstract void Map(WebApplication app); +} diff --git a/src/Web/Infrastructure/IEndpointRouteBuilderExtensions.cs b/src/Web/Infrastructure/IEndpointRouteBuilderExtensions.cs new file mode 100644 index 0000000..08badbc --- /dev/null +++ b/src/Web/Infrastructure/IEndpointRouteBuilderExtensions.cs @@ -0,0 +1,46 @@ +using System.Diagnostics.CodeAnalysis; + +namespace Hutopy.Web.Infrastructure; + +public static class IEndpointRouteBuilderExtensions +{ + public static IEndpointRouteBuilder MapGet(this IEndpointRouteBuilder builder, Delegate handler, [StringSyntax("Route")] string pattern = "") + { + Guard.Against.AnonymousMethod(handler); + + builder.MapGet(pattern, handler) + .WithName(handler.Method.Name); + + return builder; + } + + public static IEndpointRouteBuilder MapPost(this IEndpointRouteBuilder builder, Delegate handler, [StringSyntax("Route")] string pattern = "") + { + Guard.Against.AnonymousMethod(handler); + + builder.MapPost(pattern, handler) + .WithName(handler.Method.Name); + + return builder; + } + + public static IEndpointRouteBuilder MapPut(this IEndpointRouteBuilder builder, Delegate handler, [StringSyntax("Route")] string pattern) + { + Guard.Against.AnonymousMethod(handler); + + builder.MapPut(pattern, handler) + .WithName(handler.Method.Name); + + return builder; + } + + public static IEndpointRouteBuilder MapDelete(this IEndpointRouteBuilder builder, Delegate handler, [StringSyntax("Route")] string pattern) + { + Guard.Against.AnonymousMethod(handler); + + builder.MapDelete(pattern, handler) + .WithName(handler.Method.Name); + + return builder; + } +} diff --git a/src/Web/Infrastructure/MethodInfoExtensions.cs b/src/Web/Infrastructure/MethodInfoExtensions.cs new file mode 100644 index 0000000..d526cb4 --- /dev/null +++ b/src/Web/Infrastructure/MethodInfoExtensions.cs @@ -0,0 +1,18 @@ +using System.Reflection; + +namespace Hutopy.Web.Infrastructure; + +public static class MethodInfoExtensions +{ + public static bool IsAnonymous(this MethodInfo method) + { + var invalidChars = new[] { '<', '>' }; + return method.Name.Any(invalidChars.Contains); + } + + public static void AnonymousMethod(this IGuardClause guardClause, Delegate input) + { + if (input.Method.IsAnonymous()) + throw new ArgumentException("The endpoint name must be specified when using anonymous handlers."); + } +} \ No newline at end of file diff --git a/src/Web/Infrastructure/WebApplicationExtensions.cs b/src/Web/Infrastructure/WebApplicationExtensions.cs new file mode 100644 index 0000000..7d977fc --- /dev/null +++ b/src/Web/Infrastructure/WebApplicationExtensions.cs @@ -0,0 +1,37 @@ +using System.Reflection; + +namespace Hutopy.Web.Infrastructure; + +public static class WebApplicationExtensions +{ + public static RouteGroupBuilder MapGroup(this WebApplication app, EndpointGroupBase group) + { + var groupName = group.GetType().Name; + + return app + .MapGroup($"/api/{groupName}") + .WithGroupName(groupName) + .WithTags(groupName) + .WithOpenApi(); + } + + public static WebApplication MapEndpoints(this WebApplication app) + { + var endpointGroupType = typeof(EndpointGroupBase); + + var assembly = Assembly.GetExecutingAssembly(); + + var endpointGroupTypes = assembly.GetExportedTypes() + .Where(t => t.IsSubclassOf(endpointGroupType)); + + foreach (var type in endpointGroupTypes) + { + if (Activator.CreateInstance(type) is EndpointGroupBase instance) + { + instance.Map(app); + } + } + + return app; + } +} diff --git a/src/Web/Pages/Error.cshtml b/src/Web/Pages/Error.cshtml new file mode 100644 index 0000000..6f92b95 --- /dev/null +++ b/src/Web/Pages/Error.cshtml @@ -0,0 +1,26 @@ +@page +@model ErrorModel +@{ + ViewData["Title"] = "Error"; +} + +

Error.

+

An error occurred while processing your request.

+ +@if (Model.ShowRequestId) +{ +

+ Request ID: @Model.RequestId +

+} + +

Development Mode

+

+ Swapping to the Development environment displays detailed information about the error that occurred. +

+

+ The Development environment shouldn't be enabled for deployed applications. + It can result in displaying sensitive information from exceptions to end users. + For local debugging, enable the Development environment by setting the ASPNETCORE_ENVIRONMENT environment variable to Development + and restarting the app. +

diff --git a/src/Web/Pages/Error.cshtml.cs b/src/Web/Pages/Error.cshtml.cs new file mode 100644 index 0000000..ff5eba0 --- /dev/null +++ b/src/Web/Pages/Error.cshtml.cs @@ -0,0 +1,25 @@ +using System.Diagnostics; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.RazorPages; + +namespace Hutopy.Web.Pages; + +[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)] +public class ErrorModel : PageModel +{ + private readonly ILogger _logger; + + public ErrorModel(ILogger logger) + { + _logger = logger; + } + + public string? RequestId { get; set; } + + public bool ShowRequestId => !string.IsNullOrEmpty(RequestId); + + public void OnGet() + { + RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier; + } +} diff --git a/src/Web/Pages/Shared/_LoginPartial.cshtml b/src/Web/Pages/Shared/_LoginPartial.cshtml new file mode 100644 index 0000000..c16ebd7 --- /dev/null +++ b/src/Web/Pages/Shared/_LoginPartial.cshtml @@ -0,0 +1,36 @@ +@using Hutopy.Infrastructure.Identity +@using Microsoft.AspNetCore.Identity +@inject SignInManager SignInManager +@inject UserManager UserManager + +@{ + string? returnUrl = null; + var query = ViewContext.HttpContext.Request.Query; + if (query.ContainsKey("returnUrl")) + { + returnUrl = query["returnUrl"]; + } +} + + diff --git a/src/Web/Pages/_ViewImports.cshtml b/src/Web/Pages/_ViewImports.cshtml new file mode 100644 index 0000000..315c2e2 --- /dev/null +++ b/src/Web/Pages/_ViewImports.cshtml @@ -0,0 +1,3 @@ +@using Hutopy.Web +@namespace Hutopy.Web.Pages +@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers diff --git a/src/Web/Program.cs b/src/Web/Program.cs new file mode 100644 index 0000000..89e64ee --- /dev/null +++ b/src/Web/Program.cs @@ -0,0 +1,64 @@ +using Hutopy.Infrastructure.Data; + +var builder = WebApplication.CreateBuilder(args); + +builder.Services.AddCors(options => + { + options.AddPolicy("AllowAll", builder => + { + builder.AllowAnyOrigin() + .AllowAnyMethod() + .AllowAnyHeader(); + }); + }); + +// Add services to the container. +builder.Services.AddKeyVaultIfConfigured(builder.Configuration); + +builder.Services.AddApplicationServices(); +builder.Services.AddInfrastructureServices(builder.Configuration); +builder.Services.AddWebServices(); + + +var app = builder.Build(); + +app.UseCors("AllowAll"); + +// Configure the HTTP request pipeline. +if (app.Environment.IsDevelopment()) +{ + await app.InitialiseDatabaseAsync(); +} +else +{ + // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. + app.UseHsts(); +} + +app.UseHealthChecks("/health"); +app.UseHttpsRedirection(); +app.UseStaticFiles(); + +app.UseSwaggerUi(settings => +{ + settings.Path = "/api"; + settings.DocumentPath = "/api/specification.json"; +}); + +app.MapControllerRoute( + name: "default", + pattern: "{controller}/{action=Index}/{id?}"); + +app.MapRazorPages(); + +app.MapFallbackToFile("index.html"); + +app.UseExceptionHandler(options => { }); + +app.Map("/", () => Results.Redirect("/api")); + +app.MapEndpoints(); + +app.Run(); + +public partial class Program { } diff --git a/src/Web/Properties/launchSettings.json b/src/Web/Properties/launchSettings.json new file mode 100644 index 0000000..6ef4f83 --- /dev/null +++ b/src/Web/Properties/launchSettings.json @@ -0,0 +1,27 @@ +{ + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:61846", + "sslPort": 44312 + } + }, + "profiles": { + "Hutopy.Web": { + "commandName": "Project", + "launchBrowser": true, + "applicationUrl": "https://localhost:5001;http://localhost:5000", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} \ No newline at end of file diff --git a/src/Web/Services/CurrentUser.cs b/src/Web/Services/CurrentUser.cs new file mode 100644 index 0000000..45d3365 --- /dev/null +++ b/src/Web/Services/CurrentUser.cs @@ -0,0 +1,17 @@ +using System.Security.Claims; + +using Hutopy.Application.Common.Interfaces; + +namespace Hutopy.Web.Services; + +public class CurrentUser : IUser +{ + private readonly IHttpContextAccessor _httpContextAccessor; + + public CurrentUser(IHttpContextAccessor httpContextAccessor) + { + _httpContextAccessor = httpContextAccessor; + } + + public string? Id => _httpContextAccessor.HttpContext?.User?.FindFirstValue(ClaimTypes.NameIdentifier); +} diff --git a/src/Web/Web.csproj b/src/Web/Web.csproj new file mode 100644 index 0000000..27c2d2d --- /dev/null +++ b/src/Web/Web.csproj @@ -0,0 +1,44 @@ + + + + Hutopy.Web + Hutopy.Web + + + + + + + + + + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + OnBuildSuccess + + + + + + + + + + + + + diff --git a/src/Web/Web.http b/src/Web/Web.http new file mode 100644 index 0000000..105a254 --- /dev/null +++ b/src/Web/Web.http @@ -0,0 +1,139 @@ +# For more info on HTTP files go to https://aka.ms/vs/httpfile +@Web_HostAddress = https://localhost:5001 + +@Email=administrator@localhost +@Password=Administrator1! +@BearerToken= + +# POST Users Register +POST {{Web_HostAddress}}/api/Users/Register +Content-Type: application/json + +{ + "email": "{{Email}}", + "password": "{{Password}}" +} + +### + +# POST Users Login +POST {{Web_HostAddress}}/api/Users/Login +Content-Type: application/json + +{ + "email": "{{Email}}", + "password": "{{Password}}" +} + +### + +# POST Users Refresh +POST {{Web_HostAddress}}/api/Users/Refresh +Authorization: Bearer {{BearerToken}} +Content-Type: application/json + +{ + "refreshToken": "" +} + +### + +# GET WeatherForecast +GET {{Web_HostAddress}}/api/WeatherForecasts +Authorization: Bearer {{BearerToken}} + +### + +# GET TodoLists +GET {{Web_HostAddress}}/api/TodoLists +Authorization: Bearer {{BearerToken}} + +### + +# POST TodoLists +POST {{Web_HostAddress}}/api/TodoLists +Authorization: Bearer {{BearerToken}} +Content-Type: application/json + +// CreateTodoListCommand +{ + "Title": "Backlog" +} + +### + +# PUT TodoLists +PUT {{Web_HostAddress}}/api/TodoLists/1 +Authorization: Bearer {{BearerToken}} +Content-Type: application/json + +// UpdateTodoListCommand +{ + "Id": 1, + "Title": "Product Backlog" +} + +### + +# DELETE TodoLists +DELETE {{Web_HostAddress}}/api/TodoLists/1 +Authorization: Bearer {{BearerToken}} + +### + +# GET TodoItems +@PageNumber = 1 +@PageSize = 10 +GET {{Web_HostAddress}}/api/TodoItems?ListId=1&PageNumber={{PageNumber}}&PageSize={{PageSize}} + +Authorization: Bearer {{BearerToken}} + +### + +# POST TodoItems +POST {{Web_HostAddress}}/api/TodoItems +Authorization: Bearer {{BearerToken}} +Content-Type: application/json + +// CreateTodoItemCommand +{ + "ListId": 1, + "Title": "Eat a burrito 🌯" +} + +### + +#PUT TodoItems UpdateItemDetails +PUT {{Web_HostAddress}}/api/TodoItems/UpdateItemDetails?Id=1 +Authorization: Bearer {{BearerToken}} +Content-Type: application/json + +// UpdateTodoItemDetailCommand +{ + "Id": 1, + "ListId": 1, + "Priority": 3, + "Note": "This is a good idea!" +} + +### + +# PUT TodoItems +PUT {{Web_HostAddress}}/api/TodoItems/1 +Authorization: Bearer {{BearerToken}} +Content-Type: application/json + +// UpdateTodoItemCommand +{ + "Id": 1, + "Title": "Eat a yummy burrito 🌯", + "Done": true +} + +### + +# DELETE TodoItem +DELETE {{Web_HostAddress}}/api/TodoItems/1 +Authorization: Bearer {{BearerToken}} + +### \ No newline at end of file diff --git a/src/Web/appsettings.Development.json b/src/Web/appsettings.Development.json new file mode 100644 index 0000000..84308c9 --- /dev/null +++ b/src/Web/appsettings.Development.json @@ -0,0 +1,10 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft": "Warning", + "Microsoft.AspNetCore.SpaProxy": "Information", + "Microsoft.Hosting.Lifetime": "Information" + } + } +} diff --git a/src/Web/appsettings.json b/src/Web/appsettings.json new file mode 100644 index 0000000..bedce59 --- /dev/null +++ b/src/Web/appsettings.json @@ -0,0 +1,13 @@ +{ + "ConnectionStrings": { + "DefaultConnection": "Server=localhost,1433;Database=TestDeux;User Id=sa;Password={DB_PASSWORD};MultipleActiveResultSets=true;TrustServerCertificate=True" + }, + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft": "Warning", + "Microsoft.Hosting.Lifetime": "Information" + } + }, + "AllowedHosts": "*" +} \ No newline at end of file diff --git a/src/Web/config.nswag b/src/Web/config.nswag new file mode 100644 index 0000000..4af18f2 --- /dev/null +++ b/src/Web/config.nswag @@ -0,0 +1,63 @@ +{ + "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 + } + } +} diff --git a/src/Web/wwwroot/api/specification.json b/src/Web/wwwroot/api/specification.json new file mode 100644 index 0000000..a8d81f4 --- /dev/null +++ b/src/Web/wwwroot/api/specification.json @@ -0,0 +1,1250 @@ +{ + "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/TodoItems": { + "get": { + "tags": [ + "TodoItems" + ], + "operationId": "GetTodoItemsWithPagination", + "parameters": [ + { + "name": "ListId", + "in": "query", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + }, + "x-position": 1 + }, + { + "name": "PageNumber", + "in": "query", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + }, + "x-position": 2 + }, + { + "name": "PageSize", + "in": "query", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + }, + "x-position": 3 + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PaginatedListOfTodoItemBriefDto" + } + } + } + } + }, + "security": [ + { + "JWT": [] + } + ] + }, + "post": { + "tags": [ + "TodoItems" + ], + "operationId": "CreateTodoItem", + "requestBody": { + "x-name": "command", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateTodoItemCommand" + } + } + }, + "required": true, + "x-position": 1 + }, + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "integer", + "format": "int32" + } + } + } + } + }, + "security": [ + { + "JWT": [] + } + ] + } + }, + "/api/TodoItems/{id}": { + "put": { + "tags": [ + "TodoItems" + ], + "operationId": "UpdateTodoItem", + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + }, + "x-position": 1 + } + ], + "requestBody": { + "x-name": "command", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateTodoItemCommand" + } + } + }, + "required": true, + "x-position": 2 + }, + "responses": { + "200": { + "description": "" + } + }, + "security": [ + { + "JWT": [] + } + ] + }, + "delete": { + "tags": [ + "TodoItems" + ], + "operationId": "DeleteTodoItem", + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + }, + "x-position": 1 + } + ], + "responses": { + "200": { + "description": "" + } + }, + "security": [ + { + "JWT": [] + } + ] + } + }, + "/api/TodoItems/UpdateDetail/{id}": { + "put": { + "tags": [ + "TodoItems" + ], + "operationId": "UpdateTodoItemDetail", + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + }, + "x-position": 1 + } + ], + "requestBody": { + "x-name": "command", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateTodoItemDetailCommand" + } + } + }, + "required": true, + "x-position": 2 + }, + "responses": { + "200": { + "description": "" + } + }, + "security": [ + { + "JWT": [] + } + ] + } + }, + "/api/TodoLists": { + "get": { + "tags": [ + "TodoLists" + ], + "operationId": "GetTodoLists", + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TodosVm" + } + } + } + } + }, + "security": [ + { + "JWT": [] + } + ] + }, + "post": { + "tags": [ + "TodoLists" + ], + "operationId": "CreateTodoList", + "requestBody": { + "x-name": "command", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateTodoListCommand" + } + } + }, + "required": true, + "x-position": 1 + }, + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "integer", + "format": "int32" + } + } + } + } + }, + "security": [ + { + "JWT": [] + } + ] + } + }, + "/api/TodoLists/{id}": { + "put": { + "tags": [ + "TodoLists" + ], + "operationId": "UpdateTodoList", + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + }, + "x-position": 1 + } + ], + "requestBody": { + "x-name": "command", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateTodoListCommand" + } + } + }, + "required": true, + "x-position": 2 + }, + "responses": { + "200": { + "description": "" + } + }, + "security": [ + { + "JWT": [] + } + ] + }, + "delete": { + "tags": [ + "TodoLists" + ], + "operationId": "DeleteTodoList", + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + }, + "x-position": 1 + } + ], + "responses": { + "200": { + "description": "" + } + }, + "security": [ + { + "JWT": [] + } + ] + } + }, + "/api/Users/register": { + "post": { + "tags": [ + "Users" + ], + "operationId": "PostApiUsersRegister", + "requestBody": { + "x-name": "registration", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RegisterRequest" + } + } + }, + "x-position": 1 + }, + "responses": { + "200": { + "description": "" + }, + "400": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HttpValidationProblemDetails" + } + } + } + } + } + } + }, + "/api/Users/login": { + "post": { + "tags": [ + "Users" + ], + "operationId": "PostApiUsersLogin", + "parameters": [ + { + "name": "useCookies", + "in": "query", + "schema": { + "type": "boolean", + "nullable": true + }, + "x-position": 2 + }, + { + "name": "useSessionCookies", + "in": "query", + "schema": { + "type": "boolean", + "nullable": true + }, + "x-position": 3 + } + ], + "requestBody": { + "x-name": "login", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/LoginRequest" + } + } + }, + "x-position": 1 + }, + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AccessTokenResponse" + } + } + } + } + } + } + }, + "/api/Users/refresh": { + "post": { + "tags": [ + "Users" + ], + "operationId": "PostApiUsersRefresh", + "requestBody": { + "x-name": "refreshRequest", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RefreshRequest" + } + } + }, + "x-position": 1 + }, + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AccessTokenResponse" + } + } + } + } + } + } + }, + "/api/Users/confirmEmail": { + "get": { + "tags": [ + "Users" + ], + "operationId": "GetApiUsersConfirmEmail", + "parameters": [ + { + "name": "userId", + "in": "query", + "schema": { + "type": "string", + "nullable": true + }, + "x-position": 1 + }, + { + "name": "code", + "in": "query", + "schema": { + "type": "string", + "nullable": true + }, + "x-position": 2 + }, + { + "name": "changedEmail", + "in": "query", + "schema": { + "type": "string", + "nullable": true + }, + "x-position": 3 + } + ], + "responses": { + "200": { + "description": "" + } + } + } + }, + "/api/Users/resendConfirmationEmail": { + "post": { + "tags": [ + "Users" + ], + "operationId": "PostApiUsersResendConfirmationEmail", + "requestBody": { + "x-name": "resendRequest", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ResendConfirmationEmailRequest" + } + } + }, + "x-position": 1 + }, + "responses": { + "200": { + "description": "" + } + } + } + }, + "/api/Users/forgotPassword": { + "post": { + "tags": [ + "Users" + ], + "operationId": "PostApiUsersForgotPassword", + "requestBody": { + "x-name": "resetRequest", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ForgotPasswordRequest" + } + } + }, + "x-position": 1 + }, + "responses": { + "200": { + "description": "" + }, + "400": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HttpValidationProblemDetails" + } + } + } + } + } + } + }, + "/api/Users/resetPassword": { + "post": { + "tags": [ + "Users" + ], + "operationId": "PostApiUsersResetPassword", + "requestBody": { + "x-name": "resetRequest", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ResetPasswordRequest" + } + } + }, + "x-position": 1 + }, + "responses": { + "200": { + "description": "" + }, + "400": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HttpValidationProblemDetails" + } + } + } + } + } + } + }, + "/api/Users/manage/2fa": { + "post": { + "tags": [ + "Users" + ], + "operationId": "PostApiUsersManage2fa", + "requestBody": { + "x-name": "tfaRequest", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TwoFactorRequest" + } + } + }, + "x-position": 1 + }, + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TwoFactorResponse" + } + } + } + }, + "400": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HttpValidationProblemDetails" + } + } + } + }, + "404": { + "description": "" + } + }, + "security": [ + { + "JWT": [] + } + ] + } + }, + "/api/Users/manage/info": { + "get": { + "tags": [ + "Users" + ], + "operationId": "GetApiUsersManageInfo", + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/InfoResponse" + } + } + } + }, + "400": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HttpValidationProblemDetails" + } + } + } + }, + "404": { + "description": "" + } + }, + "security": [ + { + "JWT": [] + } + ] + }, + "post": { + "tags": [ + "Users" + ], + "operationId": "PostApiUsersManageInfo", + "requestBody": { + "x-name": "infoRequest", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/InfoRequest" + } + } + }, + "x-position": 1 + }, + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/InfoResponse" + } + } + } + }, + "400": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HttpValidationProblemDetails" + } + } + } + }, + "404": { + "description": "" + } + }, + "security": [ + { + "JWT": [] + } + ] + } + }, + "/api/WeatherForecasts": { + "get": { + "tags": [ + "WeatherForecasts" + ], + "operationId": "GetWeatherForecasts", + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/WeatherForecast" + } + } + } + } + } + }, + "security": [ + { + "JWT": [] + } + ] + } + } + }, + "components": { + "schemas": { + "PaginatedListOfTodoItemBriefDto": { + "type": "object", + "additionalProperties": false, + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/TodoItemBriefDto" + } + }, + "pageNumber": { + "type": "integer", + "format": "int32" + }, + "totalPages": { + "type": "integer", + "format": "int32" + }, + "totalCount": { + "type": "integer", + "format": "int32" + }, + "hasPreviousPage": { + "type": "boolean" + }, + "hasNextPage": { + "type": "boolean" + } + } + }, + "TodoItemBriefDto": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "integer", + "format": "int32" + }, + "listId": { + "type": "integer", + "format": "int32" + }, + "title": { + "type": "string", + "nullable": true + }, + "done": { + "type": "boolean" + } + } + }, + "CreateTodoItemCommand": { + "type": "object", + "additionalProperties": false, + "properties": { + "listId": { + "type": "integer", + "format": "int32" + }, + "title": { + "type": "string", + "nullable": true + } + } + }, + "UpdateTodoItemCommand": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "integer", + "format": "int32" + }, + "title": { + "type": "string", + "nullable": true + }, + "done": { + "type": "boolean" + } + } + }, + "UpdateTodoItemDetailCommand": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "integer", + "format": "int32" + }, + "listId": { + "type": "integer", + "format": "int32" + }, + "priority": { + "$ref": "#/components/schemas/PriorityLevel" + }, + "note": { + "type": "string", + "nullable": true + } + } + }, + "PriorityLevel": { + "type": "integer", + "description": "", + "x-enumNames": [ + "None", + "Low", + "Medium", + "High" + ], + "enum": [ + 0, + 1, + 2, + 3 + ] + }, + "TodosVm": { + "type": "object", + "additionalProperties": false, + "properties": { + "priorityLevels": { + "type": "array", + "items": { + "$ref": "#/components/schemas/LookupDto" + } + }, + "lists": { + "type": "array", + "items": { + "$ref": "#/components/schemas/TodoListDto" + } + } + } + }, + "LookupDto": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "integer", + "format": "int32" + }, + "title": { + "type": "string", + "nullable": true + } + } + }, + "TodoListDto": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "integer", + "format": "int32" + }, + "title": { + "type": "string", + "nullable": true + }, + "colour": { + "type": "string", + "nullable": true + }, + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/TodoItemDto" + } + } + } + }, + "TodoItemDto": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "integer", + "format": "int32" + }, + "listId": { + "type": "integer", + "format": "int32" + }, + "title": { + "type": "string", + "nullable": true + }, + "done": { + "type": "boolean" + }, + "priority": { + "type": "integer", + "format": "int32" + }, + "note": { + "type": "string", + "nullable": true + } + } + }, + "CreateTodoListCommand": { + "type": "object", + "additionalProperties": false, + "properties": { + "title": { + "type": "string", + "nullable": true + } + } + }, + "UpdateTodoListCommand": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "integer", + "format": "int32" + }, + "title": { + "type": "string", + "nullable": true + } + } + }, + "HttpValidationProblemDetails": { + "allOf": [ + { + "$ref": "#/components/schemas/ProblemDetails" + }, + { + "type": "object", + "additionalProperties": { + "nullable": true + }, + "properties": { + "errors": { + "type": "object", + "additionalProperties": { + "type": "array", + "items": { + "type": "string" + } + } + } + } + } + ] + }, + "ProblemDetails": { + "type": "object", + "additionalProperties": { + "nullable": true + }, + "properties": { + "type": { + "type": "string", + "nullable": true + }, + "title": { + "type": "string", + "nullable": true + }, + "status": { + "type": "integer", + "format": "int32", + "nullable": true + }, + "detail": { + "type": "string", + "nullable": true + }, + "instance": { + "type": "string", + "nullable": true + } + } + }, + "RegisterRequest": { + "type": "object", + "additionalProperties": false, + "properties": { + "email": { + "type": "string" + }, + "password": { + "type": "string" + } + } + }, + "AccessTokenResponse": { + "type": "object", + "additionalProperties": false, + "properties": { + "tokenType": { + "type": "string" + }, + "accessToken": { + "type": "string" + }, + "expiresIn": { + "type": "integer", + "format": "int64" + }, + "refreshToken": { + "type": "string" + } + } + }, + "LoginRequest": { + "type": "object", + "additionalProperties": false, + "properties": { + "email": { + "type": "string" + }, + "password": { + "type": "string" + }, + "twoFactorCode": { + "type": "string", + "nullable": true + }, + "twoFactorRecoveryCode": { + "type": "string", + "nullable": true + } + } + }, + "RefreshRequest": { + "type": "object", + "additionalProperties": false, + "properties": { + "refreshToken": { + "type": "string" + } + } + }, + "ResendConfirmationEmailRequest": { + "type": "object", + "additionalProperties": false, + "properties": { + "email": { + "type": "string" + } + } + }, + "ForgotPasswordRequest": { + "type": "object", + "additionalProperties": false, + "properties": { + "email": { + "type": "string" + } + } + }, + "ResetPasswordRequest": { + "type": "object", + "additionalProperties": false, + "properties": { + "email": { + "type": "string" + }, + "resetCode": { + "type": "string" + }, + "newPassword": { + "type": "string" + } + } + }, + "TwoFactorResponse": { + "type": "object", + "additionalProperties": false, + "properties": { + "sharedKey": { + "type": "string" + }, + "recoveryCodesLeft": { + "type": "integer", + "format": "int32" + }, + "recoveryCodes": { + "type": "array", + "nullable": true, + "items": { + "type": "string" + } + }, + "isTwoFactorEnabled": { + "type": "boolean" + }, + "isMachineRemembered": { + "type": "boolean" + } + } + }, + "TwoFactorRequest": { + "type": "object", + "additionalProperties": false, + "properties": { + "enable": { + "type": "boolean", + "nullable": true + }, + "twoFactorCode": { + "type": "string", + "nullable": true + }, + "resetSharedKey": { + "type": "boolean" + }, + "resetRecoveryCodes": { + "type": "boolean" + }, + "forgetMachine": { + "type": "boolean" + } + } + }, + "InfoResponse": { + "type": "object", + "additionalProperties": false, + "properties": { + "email": { + "type": "string" + }, + "isEmailConfirmed": { + "type": "boolean" + } + } + }, + "InfoRequest": { + "type": "object", + "additionalProperties": false, + "properties": { + "newEmail": { + "type": "string", + "nullable": true + }, + "newPassword": { + "type": "string", + "nullable": true + }, + "oldPassword": { + "type": "string", + "nullable": true + } + } + }, + "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 + } + } + } + }, + "securitySchemes": { + "JWT": { + "type": "apiKey", + "description": "Type into the textbox: Bearer {your JWT token}.", + "name": "Authorization", + "in": "header" + } + } + }, + "security": [ + { + "JWT": [] + } + ] +} \ No newline at end of file diff --git a/src/Web/wwwroot/favicon.ico b/src/Web/wwwroot/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..63e859b476eff5055e0e557aaa151ca8223fbeef GIT binary patch literal 5430 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 + + + Hutopy.Application.FunctionalTests + Hutopy.Application.FunctionalTests + + + + + + + + + PreserveNewest + true + PreserveNewest + + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + + + + + + + diff --git a/tests/Application.FunctionalTests/BaseTestFixture.cs b/tests/Application.FunctionalTests/BaseTestFixture.cs new file mode 100644 index 0000000..27606ee --- /dev/null +++ b/tests/Application.FunctionalTests/BaseTestFixture.cs @@ -0,0 +1,13 @@ +namespace Hutopy.Application.FunctionalTests; + +using static Testing; + +[TestFixture] +public abstract class BaseTestFixture +{ + [SetUp] + public async Task TestSetUp() + { + await ResetState(); + } +} diff --git a/tests/Application.FunctionalTests/CustomWebApplicationFactory.cs b/tests/Application.FunctionalTests/CustomWebApplicationFactory.cs new file mode 100644 index 0000000..d99727f --- /dev/null +++ b/tests/Application.FunctionalTests/CustomWebApplicationFactory.cs @@ -0,0 +1,42 @@ +using System.Data.Common; +using Hutopy.Application.Common.Interfaces; +using Hutopy.Infrastructure.Data; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Mvc.Testing; +using Microsoft.AspNetCore.TestHost; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Diagnostics; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; + +namespace Hutopy.Application.FunctionalTests; + +using static Testing; + +public class CustomWebApplicationFactory : WebApplicationFactory +{ + private readonly DbConnection _connection; + + public CustomWebApplicationFactory(DbConnection connection) + { + _connection = connection; + } + + protected override void ConfigureWebHost(IWebHostBuilder builder) + { + builder.ConfigureTestServices(services => + { + services + .RemoveAll() + .AddTransient(provider => Mock.Of(s => s.Id == GetUserId())); + + services + .RemoveAll>() + .AddDbContext((sp, options) => + { + options.AddInterceptors(sp.GetServices()); + options.UseSqlServer(_connection); + }); + }); + } +} diff --git a/tests/Application.FunctionalTests/GlobalUsings.cs b/tests/Application.FunctionalTests/GlobalUsings.cs new file mode 100644 index 0000000..dd2bce7 --- /dev/null +++ b/tests/Application.FunctionalTests/GlobalUsings.cs @@ -0,0 +1,4 @@ +global using Ardalis.GuardClauses; +global using FluentAssertions; +global using Moq; +global using NUnit.Framework; \ No newline at end of file diff --git a/tests/Application.FunctionalTests/ITestDatabase.cs b/tests/Application.FunctionalTests/ITestDatabase.cs new file mode 100644 index 0000000..b3ffc55 --- /dev/null +++ b/tests/Application.FunctionalTests/ITestDatabase.cs @@ -0,0 +1,14 @@ +using System.Data.Common; + +namespace Hutopy.Application.FunctionalTests; + +public interface ITestDatabase +{ + Task InitialiseAsync(); + + DbConnection GetConnection(); + + Task ResetAsync(); + + Task DisposeAsync(); +} diff --git a/tests/Application.FunctionalTests/SqlServerTestDatabase.cs b/tests/Application.FunctionalTests/SqlServerTestDatabase.cs new file mode 100644 index 0000000..57e7acc --- /dev/null +++ b/tests/Application.FunctionalTests/SqlServerTestDatabase.cs @@ -0,0 +1,62 @@ +using System.Data.Common; +using Hutopy.Infrastructure.Data; +using Microsoft.Data.SqlClient; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Configuration; +using Respawn; + +namespace Hutopy.Application.FunctionalTests; + +public class SqlServerTestDatabase : ITestDatabase +{ + private readonly string _connectionString = null!; + private SqlConnection _connection = null!; + private Respawner _respawner = null!; + + public SqlServerTestDatabase() + { + var configuration = new ConfigurationBuilder() + .AddJsonFile("appsettings.json") + .AddEnvironmentVariables() + .Build(); + + var connectionString = configuration.GetConnectionString("DefaultConnection"); + + Guard.Against.Null(connectionString); + + _connectionString = connectionString; + } + + public async Task InitialiseAsync() + { + _connection = new SqlConnection(_connectionString); + + var options = new DbContextOptionsBuilder() + .UseSqlServer(_connectionString) + .Options; + + var context = new ApplicationDbContext(options); + + context.Database.Migrate(); + + _respawner = await Respawner.CreateAsync(_connectionString, new RespawnerOptions + { + TablesToIgnore = new Respawn.Graph.Table[] { "__EFMigrationsHistory" } + }); + } + + public DbConnection GetConnection() + { + return _connection; + } + + public async Task ResetAsync() + { + await _respawner.ResetAsync(_connectionString); + } + + public async Task DisposeAsync() + { + await _connection.DisposeAsync(); + } +} diff --git a/tests/Application.FunctionalTests/TestDatabaseFactory.cs b/tests/Application.FunctionalTests/TestDatabaseFactory.cs new file mode 100644 index 0000000..0164872 --- /dev/null +++ b/tests/Application.FunctionalTests/TestDatabaseFactory.cs @@ -0,0 +1,13 @@ +namespace Hutopy.Application.FunctionalTests; + +public static class TestDatabaseFactory +{ + public static async Task CreateAsync() + { + var database = new TestcontainersTestDatabase(); + + await database.InitialiseAsync(); + + return database; + } +} diff --git a/tests/Application.FunctionalTests/TestcontainersTestDatabase.cs b/tests/Application.FunctionalTests/TestcontainersTestDatabase.cs new file mode 100644 index 0000000..eaf57f8 --- /dev/null +++ b/tests/Application.FunctionalTests/TestcontainersTestDatabase.cs @@ -0,0 +1,61 @@ +using System.Data.Common; +using Hutopy.Infrastructure.Data; +using Microsoft.Data.SqlClient; +using Microsoft.EntityFrameworkCore; +using Respawn; +using Testcontainers.MsSql; + +namespace Hutopy.Application.FunctionalTests; + +public class TestcontainersTestDatabase : ITestDatabase +{ + private readonly MsSqlContainer _container; + private DbConnection _connection = null!; + private string _connectionString = null!; + private Respawner _respawner = null!; + + public TestcontainersTestDatabase() + { + _container = new MsSqlBuilder() + .WithAutoRemove(true) + .Build(); + } + + public async Task InitialiseAsync() + { + await _container.StartAsync(); + + _connectionString = _container.GetConnectionString(); + + _connection = new SqlConnection(_connectionString); + + var options = new DbContextOptionsBuilder() + .UseSqlServer(_connectionString) + .Options; + + var context = new ApplicationDbContext(options); + + context.Database.Migrate(); + + _respawner = await Respawner.CreateAsync(_connectionString, new RespawnerOptions + { + TablesToIgnore = new Respawn.Graph.Table[] { "__EFMigrationsHistory" } + }); + } + + public DbConnection GetConnection() + { + return _connection; + } + + public async Task ResetAsync() + { + await _respawner.ResetAsync(_connectionString); + } + + public async Task DisposeAsync() + { + await _connection.DisposeAsync(); + await _container.DisposeAsync(); + } +} diff --git a/tests/Application.FunctionalTests/Testing.cs b/tests/Application.FunctionalTests/Testing.cs new file mode 100644 index 0000000..49d8384 --- /dev/null +++ b/tests/Application.FunctionalTests/Testing.cs @@ -0,0 +1,146 @@ +using Hutopy.Domain.Constants; +using Hutopy.Infrastructure.Data; +using Hutopy.Infrastructure.Identity; +using MediatR; +using Microsoft.AspNetCore.Identity; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; + +namespace Hutopy.Application.FunctionalTests; + +[SetUpFixture] +public partial class Testing +{ + private static ITestDatabase _database; + private static CustomWebApplicationFactory _factory = null!; + private static IServiceScopeFactory _scopeFactory = null!; + private static string? _userId; + + [OneTimeSetUp] + public async Task RunBeforeAnyTests() + { + _database = await TestDatabaseFactory.CreateAsync(); + + _factory = new CustomWebApplicationFactory(_database.GetConnection()); + + _scopeFactory = _factory.Services.GetRequiredService(); + } + + public static async Task SendAsync(IRequest request) + { + using var scope = _scopeFactory.CreateScope(); + + var mediator = scope.ServiceProvider.GetRequiredService(); + + return await mediator.Send(request); + } + + public static async Task SendAsync(IBaseRequest request) + { + using var scope = _scopeFactory.CreateScope(); + + var mediator = scope.ServiceProvider.GetRequiredService(); + + await mediator.Send(request); + } + + public static string? GetUserId() + { + return _userId; + } + + public static async Task RunAsDefaultUserAsync() + { + return await RunAsUserAsync("test@local", "Testing1234!", Array.Empty()); + } + + public static async Task RunAsAdministratorAsync() + { + return await RunAsUserAsync("administrator@local", "Administrator1234!", new[] { Roles.Administrator }); + } + + public static async Task RunAsUserAsync(string userName, string password, string[] roles) + { + using var scope = _scopeFactory.CreateScope(); + + var userManager = scope.ServiceProvider.GetRequiredService>(); + + var user = new ApplicationUser { UserName = userName, Email = userName }; + + var result = await userManager.CreateAsync(user, password); + + if (roles.Any()) + { + var roleManager = scope.ServiceProvider.GetRequiredService>(); + + foreach (var role in roles) + { + await roleManager.CreateAsync(new IdentityRole(role)); + } + + await userManager.AddToRolesAsync(user, roles); + } + + if (result.Succeeded) + { + _userId = user.Id; + + return _userId; + } + + var errors = string.Join(Environment.NewLine, result.ToApplicationResult().Errors); + + throw new Exception($"Unable to create {userName}.{Environment.NewLine}{errors}"); + } + + public static async Task ResetState() + { + try + { + await _database.ResetAsync(); + } + catch (Exception) + { + } + + _userId = null; + } + + public static async Task FindAsync(params object[] keyValues) + where TEntity : class + { + using var scope = _scopeFactory.CreateScope(); + + var context = scope.ServiceProvider.GetRequiredService(); + + return await context.FindAsync(keyValues); + } + + public static async Task AddAsync(TEntity entity) + where TEntity : class + { + using var scope = _scopeFactory.CreateScope(); + + var context = scope.ServiceProvider.GetRequiredService(); + + context.Add(entity); + + await context.SaveChangesAsync(); + } + + public static async Task CountAsync() where TEntity : class + { + using var scope = _scopeFactory.CreateScope(); + + var context = scope.ServiceProvider.GetRequiredService(); + + return await context.Set().CountAsync(); + } + + [OneTimeTearDown] + public async Task RunAfterAnyTests() + { + await _database.DisposeAsync(); + await _factory.DisposeAsync(); + } +} diff --git a/tests/Application.FunctionalTests/TodoItems/Commands/CreateTodoItemTests.cs b/tests/Application.FunctionalTests/TodoItems/Commands/CreateTodoItemTests.cs new file mode 100644 index 0000000..b228ab0 --- /dev/null +++ b/tests/Application.FunctionalTests/TodoItems/Commands/CreateTodoItemTests.cs @@ -0,0 +1,49 @@ +using Hutopy.Application.Common.Exceptions; +using Hutopy.Application.TodoItems.Commands.CreateTodoItem; +using Hutopy.Application.TodoLists.Commands.CreateTodoList; +using Hutopy.Domain.Entities; + +namespace Hutopy.Application.FunctionalTests.TodoItems.Commands; + +using static Testing; + +public class CreateTodoItemTests : BaseTestFixture +{ + [Test] + public async Task ShouldRequireMinimumFields() + { + var command = new CreateTodoItemCommand(); + + await FluentActions.Invoking(() => + SendAsync(command)).Should().ThrowAsync(); + } + + [Test] + public async Task ShouldCreateTodoItem() + { + var userId = await RunAsDefaultUserAsync(); + + var listId = await SendAsync(new CreateTodoListCommand + { + Title = "New List" + }); + + var command = new CreateTodoItemCommand + { + ListId = listId, + Title = "Tasks" + }; + + var itemId = await SendAsync(command); + + var item = await FindAsync(itemId); + + item.Should().NotBeNull(); + item!.ListId.Should().Be(command.ListId); + item.Title.Should().Be(command.Title); + item.CreatedBy.Should().Be(userId); + item.Created.Should().BeCloseTo(DateTime.Now, TimeSpan.FromMilliseconds(10000)); + item.LastModifiedBy.Should().Be(userId); + item.LastModified.Should().BeCloseTo(DateTime.Now, TimeSpan.FromMilliseconds(10000)); + } +} diff --git a/tests/Application.FunctionalTests/TodoItems/Commands/DeleteTodoItemTests.cs b/tests/Application.FunctionalTests/TodoItems/Commands/DeleteTodoItemTests.cs new file mode 100644 index 0000000..bb0e1f3 --- /dev/null +++ b/tests/Application.FunctionalTests/TodoItems/Commands/DeleteTodoItemTests.cs @@ -0,0 +1,41 @@ +using Hutopy.Application.TodoItems.Commands.CreateTodoItem; +using Hutopy.Application.TodoItems.Commands.DeleteTodoItem; +using Hutopy.Application.TodoLists.Commands.CreateTodoList; +using Hutopy.Domain.Entities; + +namespace Hutopy.Application.FunctionalTests.TodoItems.Commands; + +using static Testing; + +public class DeleteTodoItemTests : BaseTestFixture +{ + [Test] + public async Task ShouldRequireValidTodoItemId() + { + var command = new DeleteTodoItemCommand(99); + + await FluentActions.Invoking(() => + SendAsync(command)).Should().ThrowAsync(); + } + + [Test] + public async Task ShouldDeleteTodoItem() + { + var listId = await SendAsync(new CreateTodoListCommand + { + Title = "New List" + }); + + var itemId = await SendAsync(new CreateTodoItemCommand + { + ListId = listId, + Title = "New Item" + }); + + await SendAsync(new DeleteTodoItemCommand(itemId)); + + var item = await FindAsync(itemId); + + item.Should().BeNull(); + } +} diff --git a/tests/Application.FunctionalTests/TodoItems/Commands/UpdateTodoItemDetailTests.cs b/tests/Application.FunctionalTests/TodoItems/Commands/UpdateTodoItemDetailTests.cs new file mode 100644 index 0000000..63486bb --- /dev/null +++ b/tests/Application.FunctionalTests/TodoItems/Commands/UpdateTodoItemDetailTests.cs @@ -0,0 +1,57 @@ +using Hutopy.Application.TodoItems.Commands.CreateTodoItem; +using Hutopy.Application.TodoItems.Commands.UpdateTodoItem; +using Hutopy.Application.TodoItems.Commands.UpdateTodoItemDetail; +using Hutopy.Application.TodoLists.Commands.CreateTodoList; +using Hutopy.Domain.Entities; +using Hutopy.Domain.Enums; + +namespace Hutopy.Application.FunctionalTests.TodoItems.Commands; + +using static Testing; + +public class UpdateTodoItemDetailTests : BaseTestFixture +{ + [Test] + public async Task ShouldRequireValidTodoItemId() + { + var command = new UpdateTodoItemCommand { Id = 99, Title = "New Title" }; + await FluentActions.Invoking(() => SendAsync(command)).Should().ThrowAsync(); + } + + [Test] + public async Task ShouldUpdateTodoItem() + { + var userId = await RunAsDefaultUserAsync(); + + var listId = await SendAsync(new CreateTodoListCommand + { + Title = "New List" + }); + + var itemId = await SendAsync(new CreateTodoItemCommand + { + ListId = listId, + Title = "New Item" + }); + + var command = new UpdateTodoItemDetailCommand + { + Id = itemId, + ListId = listId, + Note = "This is the note.", + Priority = PriorityLevel.High + }; + + await SendAsync(command); + + var item = await FindAsync(itemId); + + item.Should().NotBeNull(); + item!.ListId.Should().Be(command.ListId); + item.Note.Should().Be(command.Note); + item.Priority.Should().Be(command.Priority); + item.LastModifiedBy.Should().NotBeNull(); + item.LastModifiedBy.Should().Be(userId); + item.LastModified.Should().BeCloseTo(DateTime.Now, TimeSpan.FromMilliseconds(10000)); + } +} diff --git a/tests/Application.FunctionalTests/TodoItems/Commands/UpdateTodoItemTests.cs b/tests/Application.FunctionalTests/TodoItems/Commands/UpdateTodoItemTests.cs new file mode 100644 index 0000000..b3e3ebf --- /dev/null +++ b/tests/Application.FunctionalTests/TodoItems/Commands/UpdateTodoItemTests.cs @@ -0,0 +1,51 @@ +using Hutopy.Application.TodoItems.Commands.CreateTodoItem; +using Hutopy.Application.TodoItems.Commands.UpdateTodoItem; +using Hutopy.Application.TodoLists.Commands.CreateTodoList; +using Hutopy.Domain.Entities; + +namespace Hutopy.Application.FunctionalTests.TodoItems.Commands; + +using static Testing; + +public class UpdateTodoItemTests : BaseTestFixture +{ + [Test] + public async Task ShouldRequireValidTodoItemId() + { + var command = new UpdateTodoItemCommand { Id = 99, Title = "New Title" }; + await FluentActions.Invoking(() => SendAsync(command)).Should().ThrowAsync(); + } + + [Test] + public async Task ShouldUpdateTodoItem() + { + var userId = await RunAsDefaultUserAsync(); + + var listId = await SendAsync(new CreateTodoListCommand + { + Title = "New List" + }); + + var itemId = await SendAsync(new CreateTodoItemCommand + { + ListId = listId, + Title = "New Item" + }); + + var command = new UpdateTodoItemCommand + { + Id = itemId, + Title = "Updated Item Title" + }; + + await SendAsync(command); + + var item = await FindAsync(itemId); + + item.Should().NotBeNull(); + item!.Title.Should().Be(command.Title); + item.LastModifiedBy.Should().NotBeNull(); + item.LastModifiedBy.Should().Be(userId); + item.LastModified.Should().BeCloseTo(DateTime.Now, TimeSpan.FromMilliseconds(10000)); + } +} diff --git a/tests/Application.FunctionalTests/TodoLists/Commands/CreateTodoListTests.cs b/tests/Application.FunctionalTests/TodoLists/Commands/CreateTodoListTests.cs new file mode 100644 index 0000000..2b6edab --- /dev/null +++ b/tests/Application.FunctionalTests/TodoLists/Commands/CreateTodoListTests.cs @@ -0,0 +1,54 @@ +using Hutopy.Application.Common.Exceptions; +using Hutopy.Application.TodoLists.Commands.CreateTodoList; +using Hutopy.Domain.Entities; + +namespace Hutopy.Application.FunctionalTests.TodoLists.Commands; + +using static Testing; + +public class CreateTodoListTests : BaseTestFixture +{ + [Test] + public async Task ShouldRequireMinimumFields() + { + var command = new CreateTodoListCommand(); + await FluentActions.Invoking(() => SendAsync(command)).Should().ThrowAsync(); + } + + [Test] + public async Task ShouldRequireUniqueTitle() + { + await SendAsync(new CreateTodoListCommand + { + Title = "Shopping" + }); + + var command = new CreateTodoListCommand + { + Title = "Shopping" + }; + + await FluentActions.Invoking(() => + SendAsync(command)).Should().ThrowAsync(); + } + + [Test] + public async Task ShouldCreateTodoList() + { + var userId = await RunAsDefaultUserAsync(); + + var command = new CreateTodoListCommand + { + Title = "Tasks" + }; + + var id = await SendAsync(command); + + var list = await FindAsync(id); + + list.Should().NotBeNull(); + list!.Title.Should().Be(command.Title); + list.CreatedBy.Should().Be(userId); + list.Created.Should().BeCloseTo(DateTime.Now, TimeSpan.FromMilliseconds(10000)); + } +} diff --git a/tests/Application.FunctionalTests/TodoLists/Commands/DeleteTodoListTests.cs b/tests/Application.FunctionalTests/TodoLists/Commands/DeleteTodoListTests.cs new file mode 100644 index 0000000..446992c --- /dev/null +++ b/tests/Application.FunctionalTests/TodoLists/Commands/DeleteTodoListTests.cs @@ -0,0 +1,32 @@ +using Hutopy.Application.TodoLists.Commands.CreateTodoList; +using Hutopy.Application.TodoLists.Commands.DeleteTodoList; +using Hutopy.Domain.Entities; + +namespace Hutopy.Application.FunctionalTests.TodoLists.Commands; + +using static Testing; + +public class DeleteTodoListTests : BaseTestFixture +{ + [Test] + public async Task ShouldRequireValidTodoListId() + { + var command = new DeleteTodoListCommand(99); + await FluentActions.Invoking(() => SendAsync(command)).Should().ThrowAsync(); + } + + [Test] + public async Task ShouldDeleteTodoList() + { + var listId = await SendAsync(new CreateTodoListCommand + { + Title = "New List" + }); + + await SendAsync(new DeleteTodoListCommand(listId)); + + var list = await FindAsync(listId); + + list.Should().BeNull(); + } +} diff --git a/tests/Application.FunctionalTests/TodoLists/Commands/PurgeTodoListsTests.cs b/tests/Application.FunctionalTests/TodoLists/Commands/PurgeTodoListsTests.cs new file mode 100644 index 0000000..7b92631 --- /dev/null +++ b/tests/Application.FunctionalTests/TodoLists/Commands/PurgeTodoListsTests.cs @@ -0,0 +1,75 @@ +using Hutopy.Application.Common.Exceptions; +using Hutopy.Application.Common.Security; +using Hutopy.Application.TodoLists.Commands.CreateTodoList; +using Hutopy.Application.TodoLists.Commands.PurgeTodoLists; +using Hutopy.Domain.Entities; + +namespace Hutopy.Application.FunctionalTests.TodoLists.Commands; + +using static Testing; + +public class PurgeTodoListsTests : BaseTestFixture +{ + [Test] + public async Task ShouldDenyAnonymousUser() + { + var command = new PurgeTodoListsCommand(); + + command.GetType().Should().BeDecoratedWith(); + + var action = () => SendAsync(command); + + await action.Should().ThrowAsync(); + } + + [Test] + public async Task ShouldDenyNonAdministrator() + { + await RunAsDefaultUserAsync(); + + var command = new PurgeTodoListsCommand(); + + var action = () => SendAsync(command); + + await action.Should().ThrowAsync(); + } + + [Test] + public async Task ShouldAllowAdministrator() + { + await RunAsAdministratorAsync(); + + var command = new PurgeTodoListsCommand(); + + var action = () => SendAsync(command); + + await action.Should().NotThrowAsync(); + } + + [Test] + public async Task ShouldDeleteAllLists() + { + await RunAsAdministratorAsync(); + + await SendAsync(new CreateTodoListCommand + { + Title = "New List #1" + }); + + await SendAsync(new CreateTodoListCommand + { + Title = "New List #2" + }); + + await SendAsync(new CreateTodoListCommand + { + Title = "New List #3" + }); + + await SendAsync(new PurgeTodoListsCommand()); + + var count = await CountAsync(); + + count.Should().Be(0); + } +} diff --git a/tests/Application.FunctionalTests/TodoLists/Commands/UpdateTodoListTests.cs b/tests/Application.FunctionalTests/TodoLists/Commands/UpdateTodoListTests.cs new file mode 100644 index 0000000..37d46d2 --- /dev/null +++ b/tests/Application.FunctionalTests/TodoLists/Commands/UpdateTodoListTests.cs @@ -0,0 +1,70 @@ +using Hutopy.Application.Common.Exceptions; +using Hutopy.Application.TodoLists.Commands.CreateTodoList; +using Hutopy.Application.TodoLists.Commands.UpdateTodoList; +using Hutopy.Domain.Entities; + +namespace Hutopy.Application.FunctionalTests.TodoLists.Commands; + +using static Testing; + +public class UpdateTodoListTests : BaseTestFixture +{ + [Test] + public async Task ShouldRequireValidTodoListId() + { + var command = new UpdateTodoListCommand { Id = 99, Title = "New Title" }; + await FluentActions.Invoking(() => SendAsync(command)).Should().ThrowAsync(); + } + + [Test] + public async Task ShouldRequireUniqueTitle() + { + var listId = await SendAsync(new CreateTodoListCommand + { + Title = "New List" + }); + + await SendAsync(new CreateTodoListCommand + { + Title = "Other List" + }); + + var command = new UpdateTodoListCommand + { + Id = listId, + Title = "Other List" + }; + + (await FluentActions.Invoking(() => + SendAsync(command)) + .Should().ThrowAsync().Where(ex => ex.Errors.ContainsKey("Title"))) + .And.Errors["Title"].Should().Contain("'Title' must be unique."); + } + + [Test] + public async Task ShouldUpdateTodoList() + { + var userId = await RunAsDefaultUserAsync(); + + var listId = await SendAsync(new CreateTodoListCommand + { + Title = "New List" + }); + + var command = new UpdateTodoListCommand + { + Id = listId, + Title = "Updated List Title" + }; + + await SendAsync(command); + + var list = await FindAsync(listId); + + list.Should().NotBeNull(); + list!.Title.Should().Be(command.Title); + list.LastModifiedBy.Should().NotBeNull(); + list.LastModifiedBy.Should().Be(userId); + list.LastModified.Should().BeCloseTo(DateTime.Now, TimeSpan.FromMilliseconds(10000)); + } +} diff --git a/tests/Application.FunctionalTests/TodoLists/Queries/GetTodosTests.cs b/tests/Application.FunctionalTests/TodoLists/Queries/GetTodosTests.cs new file mode 100644 index 0000000..2de1eda --- /dev/null +++ b/tests/Application.FunctionalTests/TodoLists/Queries/GetTodosTests.cs @@ -0,0 +1,61 @@ +using Hutopy.Application.TodoLists.Queries.GetTodos; +using Hutopy.Domain.Entities; +using Hutopy.Domain.ValueObjects; + +namespace Hutopy.Application.FunctionalTests.TodoLists.Queries; + +using static Testing; + +public class GetTodosTests : BaseTestFixture +{ + [Test] + public async Task ShouldReturnPriorityLevels() + { + await RunAsDefaultUserAsync(); + + var query = new GetTodosQuery(); + + var result = await SendAsync(query); + + result.PriorityLevels.Should().NotBeEmpty(); + } + + [Test] + public async Task ShouldReturnAllListsAndItems() + { + await RunAsDefaultUserAsync(); + + await AddAsync(new TodoList + { + Title = "Shopping", + Colour = Colour.Blue, + Items = + { + new TodoItem { Title = "Apples", Done = true }, + new TodoItem { Title = "Milk", Done = true }, + new TodoItem { Title = "Bread", Done = true }, + new TodoItem { Title = "Toilet paper" }, + new TodoItem { Title = "Pasta" }, + new TodoItem { Title = "Tissues" }, + new TodoItem { Title = "Tuna" } + } + }); + + var query = new GetTodosQuery(); + + var result = await SendAsync(query); + + result.Lists.Should().HaveCount(1); + result.Lists.First().Items.Should().HaveCount(7); + } + + [Test] + public async Task ShouldDenyAnonymousUser() + { + var query = new GetTodosQuery(); + + var action = () => SendAsync(query); + + await action.Should().ThrowAsync(); + } +} diff --git a/tests/Application.FunctionalTests/appsettings.json b/tests/Application.FunctionalTests/appsettings.json new file mode 100644 index 0000000..ea0855a --- /dev/null +++ b/tests/Application.FunctionalTests/appsettings.json @@ -0,0 +1,5 @@ +{ + "ConnectionStrings": { + "DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=HutopyTestDb;Trusted_Connection=True;MultipleActiveResultSets=true" + } +} diff --git a/tests/Application.UnitTests/Application.UnitTests.csproj b/tests/Application.UnitTests/Application.UnitTests.csproj new file mode 100644 index 0000000..805128b --- /dev/null +++ b/tests/Application.UnitTests/Application.UnitTests.csproj @@ -0,0 +1,26 @@ + + + + Hutopy.Application.UnitTests + Hutopy.Application.UnitTests + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + + + + + + diff --git a/tests/Application.UnitTests/Common/Behaviours/RequestLoggerTests.cs b/tests/Application.UnitTests/Common/Behaviours/RequestLoggerTests.cs new file mode 100644 index 0000000..31ee2a5 --- /dev/null +++ b/tests/Application.UnitTests/Common/Behaviours/RequestLoggerTests.cs @@ -0,0 +1,45 @@ +using Hutopy.Application.Common.Behaviours; +using Hutopy.Application.Common.Interfaces; +using Hutopy.Application.TodoItems.Commands.CreateTodoItem; +using Microsoft.Extensions.Logging; +using Moq; +using NUnit.Framework; + +namespace Hutopy.Application.UnitTests.Common.Behaviours; + +public class RequestLoggerTests +{ + private Mock> _logger = null!; + private Mock _user = null!; + private Mock _identityService = null!; + + [SetUp] + public void Setup() + { + _logger = new Mock>(); + _user = new Mock(); + _identityService = new Mock(); + } + + [Test] + public async Task ShouldCallGetUserNameAsyncOnceIfAuthenticated() + { + _user.Setup(x => x.Id).Returns(Guid.NewGuid().ToString()); + + var requestLogger = new LoggingBehaviour(_logger.Object, _user.Object, _identityService.Object); + + await requestLogger.Process(new CreateTodoItemCommand { ListId = 1, Title = "title" }, new CancellationToken()); + + _identityService.Verify(i => i.GetUserNameAsync(It.IsAny()), Times.Once); + } + + [Test] + public async Task ShouldNotCallGetUserNameAsyncOnceIfUnauthenticated() + { + var requestLogger = new LoggingBehaviour(_logger.Object, _user.Object, _identityService.Object); + + await requestLogger.Process(new CreateTodoItemCommand { ListId = 1, Title = "title" }, new CancellationToken()); + + _identityService.Verify(i => i.GetUserNameAsync(It.IsAny()), Times.Never); + } +} diff --git a/tests/Application.UnitTests/Common/Exceptions/ValidationExceptionTests.cs b/tests/Application.UnitTests/Common/Exceptions/ValidationExceptionTests.cs new file mode 100644 index 0000000..c4fcbb4 --- /dev/null +++ b/tests/Application.UnitTests/Common/Exceptions/ValidationExceptionTests.cs @@ -0,0 +1,63 @@ +using Hutopy.Application.Common.Exceptions; +using FluentAssertions; +using FluentValidation.Results; +using NUnit.Framework; + +namespace Hutopy.Application.UnitTests.Common.Exceptions; + +public class ValidationExceptionTests +{ + [Test] + public void DefaultConstructorCreatesAnEmptyErrorDictionary() + { + var actual = new ValidationException().Errors; + + actual.Keys.Should().BeEquivalentTo(Array.Empty()); + } + + [Test] + public void SingleValidationFailureCreatesASingleElementErrorDictionary() + { + var failures = new List + { + new ValidationFailure("Age", "must be over 18"), + }; + + var actual = new ValidationException(failures).Errors; + + actual.Keys.Should().BeEquivalentTo(new string[] { "Age" }); + actual["Age"].Should().BeEquivalentTo(new string[] { "must be over 18" }); + } + + [Test] + public void MulitpleValidationFailureForMultiplePropertiesCreatesAMultipleElementErrorDictionaryEachWithMultipleValues() + { + var failures = new List + { + new ValidationFailure("Age", "must be 18 or older"), + new ValidationFailure("Age", "must be 25 or younger"), + new ValidationFailure("Password", "must contain at least 8 characters"), + new ValidationFailure("Password", "must contain a digit"), + new ValidationFailure("Password", "must contain upper case letter"), + new ValidationFailure("Password", "must contain lower case letter"), + }; + + var actual = new ValidationException(failures).Errors; + + actual.Keys.Should().BeEquivalentTo(new string[] { "Password", "Age" }); + + actual["Age"].Should().BeEquivalentTo(new string[] + { + "must be 25 or younger", + "must be 18 or older", + }); + + actual["Password"].Should().BeEquivalentTo(new string[] + { + "must contain lower case letter", + "must contain upper case letter", + "must contain at least 8 characters", + "must contain a digit", + }); + } +} diff --git a/tests/Application.UnitTests/Common/Mappings/MappingTests.cs b/tests/Application.UnitTests/Common/Mappings/MappingTests.cs new file mode 100644 index 0000000..70b23d6 --- /dev/null +++ b/tests/Application.UnitTests/Common/Mappings/MappingTests.cs @@ -0,0 +1,53 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using AutoMapper; +using Hutopy.Application.Common.Interfaces; +using Hutopy.Application.Common.Models; +using Hutopy.Application.TodoItems.Queries.GetTodoItemsWithPagination; +using Hutopy.Application.TodoLists.Queries.GetTodos; +using Hutopy.Domain.Entities; +using NUnit.Framework; + +namespace Hutopy.Application.UnitTests.Common.Mappings; + +public class MappingTests +{ + private readonly IConfigurationProvider _configuration; + private readonly IMapper _mapper; + + public MappingTests() + { + _configuration = new MapperConfiguration(config => + config.AddMaps(Assembly.GetAssembly(typeof(IApplicationDbContext)))); + + _mapper = _configuration.CreateMapper(); + } + + [Test] + public void ShouldHaveValidConfiguration() + { + _configuration.AssertConfigurationIsValid(); + } + + [Test] + [TestCase(typeof(TodoList), typeof(TodoListDto))] + [TestCase(typeof(TodoItem), typeof(TodoItemDto))] + [TestCase(typeof(TodoList), typeof(LookupDto))] + [TestCase(typeof(TodoItem), typeof(LookupDto))] + [TestCase(typeof(TodoItem), typeof(TodoItemBriefDto))] + public void ShouldSupportMappingFromSourceToDestination(Type source, Type destination) + { + var instance = GetInstanceOf(source); + + _mapper.Map(instance, source, destination); + } + + private object GetInstanceOf(Type type) + { + if (type.GetConstructor(Type.EmptyTypes) != null) + return Activator.CreateInstance(type)!; + + // Type without parameterless constructor + return RuntimeHelpers.GetUninitializedObject(type); + } +} diff --git a/tests/Domain.UnitTests/Domain.UnitTests.csproj b/tests/Domain.UnitTests/Domain.UnitTests.csproj new file mode 100644 index 0000000..e400eb6 --- /dev/null +++ b/tests/Domain.UnitTests/Domain.UnitTests.csproj @@ -0,0 +1,24 @@ + + + + Hutopy.Domain.UnitTests + Hutopy.Domain.UnitTests + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + + + + diff --git a/tests/Domain.UnitTests/ValueObjects/ColourTests.cs b/tests/Domain.UnitTests/ValueObjects/ColourTests.cs new file mode 100644 index 0000000..50e7785 --- /dev/null +++ b/tests/Domain.UnitTests/ValueObjects/ColourTests.cs @@ -0,0 +1,50 @@ +using Hutopy.Domain.Exceptions; +using Hutopy.Domain.ValueObjects; +using FluentAssertions; +using NUnit.Framework; + +namespace Hutopy.Domain.UnitTests.ValueObjects; + +public class ColourTests +{ + [Test] + public void ShouldReturnCorrectColourCode() + { + var code = "#FFFFFF"; + + var colour = Colour.From(code); + + colour.Code.Should().Be(code); + } + + [Test] + public void ToStringReturnsCode() + { + var colour = Colour.White; + + colour.ToString().Should().Be(colour.Code); + } + + [Test] + public void ShouldPerformImplicitConversionToColourCodeString() + { + string code = Colour.White; + + code.Should().Be("#FFFFFF"); + } + + [Test] + public void ShouldPerformExplicitConversionGivenSupportedColourCode() + { + var colour = (Colour)"#FFFFFF"; + + colour.Should().Be(Colour.White); + } + + [Test] + public void ShouldThrowUnsupportedColourExceptionGivenNotSupportedColourCode() + { + FluentActions.Invoking(() => Colour.From("##FF33CC")) + .Should().Throw(); + } +} diff --git a/tests/Infrastructure.IntegrationTests/GlobalUsings.cs b/tests/Infrastructure.IntegrationTests/GlobalUsings.cs new file mode 100644 index 0000000..cefced4 --- /dev/null +++ b/tests/Infrastructure.IntegrationTests/GlobalUsings.cs @@ -0,0 +1 @@ +global using NUnit.Framework; \ No newline at end of file diff --git a/tests/Infrastructure.IntegrationTests/Infrastructure.IntegrationTests.csproj b/tests/Infrastructure.IntegrationTests/Infrastructure.IntegrationTests.csproj new file mode 100644 index 0000000..52d7836 --- /dev/null +++ b/tests/Infrastructure.IntegrationTests/Infrastructure.IntegrationTests.csproj @@ -0,0 +1,19 @@ + + + + Hutopy.Infrastructure.IntegrationTests + Hutopy.Infrastructure.IntegrationTests + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + From c4bd8e7a61f49e5d7fbe1205f1e78f1c85f6f416 Mon Sep 17 00:00:00 2001 From: Kamigen <46357922+Edouard127@users.noreply.github.com> Date: Sun, 10 Mar 2024 15:40:05 -0400 Subject: [PATCH 002/229] Additional gitignore for IDEs --- .gitignore | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.gitignore b/.gitignore index 75f22e3..258dd2c 100644 --- a/.gitignore +++ b/.gitignore @@ -478,3 +478,7 @@ $RECYCLE.BIN/ # Vim temporary swap files *.swp + +# Other IDE files +.vscode/ +.idea/ From 796d60a410bbf2b9c4bc624685fdba621e70431c Mon Sep 17 00:00:00 2001 From: Dominic Villemure Date: Sat, 16 Mar 2024 13:26:29 -0400 Subject: [PATCH 003/229] dotnet version change, readme, script for ef --- Directory.Packages.props | 28 +++++++++++++---------- Ef.ps1 | 1 + README.md | 6 +++-- global.json | 2 +- src/Infrastructure/DependencyInjection.cs | 2 +- src/Infrastructure/Infrastructure.csproj | 22 +++++++++--------- src/Web/.config/dotnet-tools.json | 12 ++++++++++ 7 files changed, 46 insertions(+), 27 deletions(-) create mode 100644 Ef.ps1 create mode 100644 src/Web/.config/dotnet-tools.json diff --git a/Directory.Packages.props b/Directory.Packages.props index 864c732..ba78a5d 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -13,18 +13,22 @@ - - - - - - - - - - - - + + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + diff --git a/Ef.ps1 b/Ef.ps1 new file mode 100644 index 0000000..da8240b --- /dev/null +++ b/Ef.ps1 @@ -0,0 +1 @@ +dotnet ef $args --startup-project ./src/Web/Web.csproj --project ./src/Infrastructure/Infrastructure.csproj \ No newline at end of file diff --git a/README.md b/README.md index 2c86832..3c9281a 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,10 @@ # Hutopy -## Pattern used -- Clean Architecture +## Patterns / strategy used +- Clean Architecture ( with Infrastructure, Domain, Application and Web layers ) +- Minimal API endpoints. - Guards ( Fail fast ) : https://github.com/ardalis/GuardClauses +- ## Tools - Install Docker : https://www.docker.com/get-started/ diff --git a/global.json b/global.json index 501e79a..4e08f95 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,6 @@ { "sdk": { - "version": "8.0.100", + "version": "8.0.300", "rollForward": "latestFeature" } } \ No newline at end of file diff --git a/src/Infrastructure/DependencyInjection.cs b/src/Infrastructure/DependencyInjection.cs index 3a2b7a8..f466e8f 100644 --- a/src/Infrastructure/DependencyInjection.cs +++ b/src/Infrastructure/DependencyInjection.cs @@ -28,7 +28,6 @@ public static class DependencyInjection services.AddDbContext((sp, options) => { options.AddInterceptors(sp.GetServices()); - options.UseSqlServer(connectionString); }); @@ -41,6 +40,7 @@ public static class DependencyInjection services.AddAuthorizationBuilder(); + // Might need to change and use AddIdentity() when we need to integrate connection via third party ( facebook, google ) services .AddIdentityCore() .AddRoles() diff --git a/src/Infrastructure/Infrastructure.csproj b/src/Infrastructure/Infrastructure.csproj index f68f7c8..581d24f 100644 --- a/src/Infrastructure/Infrastructure.csproj +++ b/src/Infrastructure/Infrastructure.csproj @@ -1,20 +1,20 @@ - - + Hutopy.Infrastructure Hutopy.Infrastructure - - - - - - + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + - - + - diff --git a/src/Web/.config/dotnet-tools.json b/src/Web/.config/dotnet-tools.json new file mode 100644 index 0000000..d9d129c --- /dev/null +++ b/src/Web/.config/dotnet-tools.json @@ -0,0 +1,12 @@ +{ + "version": 1, + "isRoot": true, + "tools": { + "dotnet-ef": { + "version": "8.0.3", + "commands": [ + "dotnet-ef" + ] + } + } +} \ No newline at end of file From 954dc6c2c851667901222b6e449e41f0ed771e8c Mon Sep 17 00:00:00 2001 From: Dominic Villemure Date: Sat, 16 Mar 2024 13:56:53 -0400 Subject: [PATCH 004/229] Fix versions --- Directory.Packages.props | 26 +++++++++++++------------- global.json | 2 +- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index ba78a5d..0db7a9f 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -13,22 +13,22 @@ - - - - - - - + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive all - - - - - - + + + + + + diff --git a/global.json b/global.json index 4e08f95..282c5a8 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,6 @@ { "sdk": { - "version": "8.0.300", + "version": "8.0.203", "rollForward": "latestFeature" } } \ No newline at end of file From 78605ec840b0c8e330bca44b6f3adb14c143b77f Mon Sep 17 00:00:00 2001 From: Dominic Villemure Date: Sat, 16 Mar 2024 14:05:54 -0400 Subject: [PATCH 005/229] Started FuturCreator --- .../Interfaces/IApplicationDbContext.cs | 2 + .../Commands/CreateFuturCreator.cs | 43 +++++++++++++++++++ src/Domain/Entities/FuturCreator.cs | 9 ++++ .../Data/ApplicationDbContext.cs | 3 ++ 4 files changed, 57 insertions(+) create mode 100644 src/Application/FuturCreator/Commands/CreateFuturCreator.cs create mode 100644 src/Domain/Entities/FuturCreator.cs diff --git a/src/Application/Common/Interfaces/IApplicationDbContext.cs b/src/Application/Common/Interfaces/IApplicationDbContext.cs index 5b7e5d9..c393783 100644 --- a/src/Application/Common/Interfaces/IApplicationDbContext.cs +++ b/src/Application/Common/Interfaces/IApplicationDbContext.cs @@ -8,5 +8,7 @@ public interface IApplicationDbContext DbSet TodoItems { get; } + DbSet FuturCreator { get; } + Task SaveChangesAsync(CancellationToken cancellationToken); } diff --git a/src/Application/FuturCreator/Commands/CreateFuturCreator.cs b/src/Application/FuturCreator/Commands/CreateFuturCreator.cs new file mode 100644 index 0000000..82db619 --- /dev/null +++ b/src/Application/FuturCreator/Commands/CreateFuturCreator.cs @@ -0,0 +1,43 @@ +using Hutopy.Application.Common.Interfaces; + +namespace Hutopy.Application.TodoItems.Commands.CreateFuturCreator; + +public record CreateFuturCreatorCommand : IRequest +{ + public required string FirstName { get; init; } + public required string LastName { get; init; } + public required string EmailAddress { get; init; } + public required string PhoneNumber { get; init; } + public required string SocialNetworkAccount { get; init; } + public required string ReasonToJoin { get; init; } +} + +public class CreateFuturCreatorCommandHandler : IRequestHandler +{ + private readonly IApplicationDbContext _context; + + + public CreateFuturCreatorCommandHandler(IApplicationDbContext context) + { + _context = context; + } + + public async Task Handle(CreateFuturCreatorCommand request, CancellationToken cancellationToken) + { + var entity = new FuturCreator() + { + FirstName = request.FirstName, + LastName = request.LastName, + EmailAddress = request.EmailAddress, + PhoneNumber = request.PhoneNumber, + SocialNetworkAccount = request.SocialNetworkAccount, + ReasonToJoin = request.ReasonToJoin, + }; + + _context.FuturCreator.Add(entity); + + await _context.SaveChangesAsync(cancellationToken); + + return entity.Id; + } +} diff --git a/src/Domain/Entities/FuturCreator.cs b/src/Domain/Entities/FuturCreator.cs new file mode 100644 index 0000000..4b405a5 --- /dev/null +++ b/src/Domain/Entities/FuturCreator.cs @@ -0,0 +1,9 @@ +public class FuturCreator : BaseAuditableEntity +{ + public required string FirstName { get; set; } + public required string LastName { get; set; } + public required string EmailAddress { get; set; } + public required string PhoneNumber { get; set; } + public required string SocialNetworkAccount { get; set; } + public required string ReasonToJoin { get; set; } +} \ No newline at end of file diff --git a/src/Infrastructure/Data/ApplicationDbContext.cs b/src/Infrastructure/Data/ApplicationDbContext.cs index 721bf1b..0071352 100644 --- a/src/Infrastructure/Data/ApplicationDbContext.cs +++ b/src/Infrastructure/Data/ApplicationDbContext.cs @@ -2,6 +2,7 @@ using Hutopy.Application.Common.Interfaces; using Hutopy.Domain.Entities; using Hutopy.Infrastructure.Identity; +using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Identity.EntityFrameworkCore; using Microsoft.EntityFrameworkCore; @@ -15,6 +16,8 @@ public class ApplicationDbContext : IdentityDbContext, IApplica public DbSet TodoItems => Set(); + public DbSet FuturCreator => Set(); + protected override void OnModelCreating(ModelBuilder builder) { base.OnModelCreating(builder); From 0f7cdb3abd153c09f83a3fc9a080351dd49a46e0 Mon Sep 17 00:00:00 2001 From: Dominic Villemure Date: Sun, 17 Mar 2024 16:20:43 -0400 Subject: [PATCH 006/229] Fixed dotnet ef problem, Added a script to start the project and one for Ef --- Directory.Build.props | 1 - Directory.Packages.props | 26 +- Start.ps1 | 18 + global.json | 2 +- ...20240317201728_AddFuturCreator.Designer.cs | 444 +++++++++++ .../20240317201728_AddFuturCreator.cs | 116 +++ .../ApplicationDbContextModelSnapshot.cs | 747 ++++++++++-------- src/Infrastructure/Infrastructure.csproj | 1 + src/Web/Web.csproj | 4 + src/Web/appsettings.json | 2 +- 10 files changed, 994 insertions(+), 367 deletions(-) create mode 100644 Start.ps1 create mode 100644 src/Infrastructure/Data/Migrations/20240317201728_AddFuturCreator.Designer.cs create mode 100644 src/Infrastructure/Data/Migrations/20240317201728_AddFuturCreator.cs diff --git a/Directory.Build.props b/Directory.Build.props index 63a87da..ffa84fe 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -3,7 +3,6 @@ net8.0 true - $(MSBuildThisFileDirectory)artifacts enable enable diff --git a/Directory.Packages.props b/Directory.Packages.props index 0db7a9f..ba78a5d 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -13,22 +13,22 @@ - - - - - - - + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive all - - - - - - + + + + + + diff --git a/Start.ps1 b/Start.ps1 new file mode 100644 index 0000000..4724463 --- /dev/null +++ b/Start.ps1 @@ -0,0 +1,18 @@ +$password = $null + +# Manually parse arguments for a "-p" flag +for ($i = 0; $i -lt $args.Count; $i++) { + if ($args[$i] -eq "-p" -and $args.Count -gt $i + 1) { + $password = $args[$i + 1] + break + } +} + +# Check if we got a value for our environment variable +if ($null -ne $password) { + $Env:DB_PASSWORD = $password +} + +# Run the app in the web dir. +Set-Location -Path ./src/Web +dotnet watch run \ No newline at end of file diff --git a/global.json b/global.json index 282c5a8..622dcbb 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,6 @@ { "sdk": { - "version": "8.0.203", + "version": "8.0.3", "rollForward": "latestFeature" } } \ No newline at end of file diff --git a/src/Infrastructure/Data/Migrations/20240317201728_AddFuturCreator.Designer.cs b/src/Infrastructure/Data/Migrations/20240317201728_AddFuturCreator.Designer.cs new file mode 100644 index 0000000..12219ef --- /dev/null +++ b/src/Infrastructure/Data/Migrations/20240317201728_AddFuturCreator.Designer.cs @@ -0,0 +1,444 @@ +// +using System; +using Hutopy.Infrastructure.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Hutopy.Infrastructure.Data.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + [Migration("20240317201728_AddFuturCreator")] + partial class AddFuturCreator + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.3") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("FuturCreator", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Created") + .HasColumnType("datetimeoffset"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("EmailAddress") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("FirstName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("LastModified") + .HasColumnType("datetimeoffset"); + + b.Property("LastModifiedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("LastName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumber") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("ReasonToJoin") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("SocialNetworkAccount") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("FuturCreator"); + }); + + modelBuilder.Entity("Hutopy.Domain.Entities.TodoItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Created") + .HasColumnType("datetimeoffset"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("Done") + .HasColumnType("bit"); + + b.Property("LastModified") + .HasColumnType("datetimeoffset"); + + b.Property("LastModifiedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("ListId") + .HasColumnType("int"); + + b.Property("Note") + .HasColumnType("nvarchar(max)"); + + b.Property("Priority") + .HasColumnType("int"); + + b.Property("Reminder") + .HasColumnType("datetime2"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.HasKey("Id"); + + b.HasIndex("ListId"); + + b.ToTable("TodoItems"); + }); + + modelBuilder.Entity("Hutopy.Domain.Entities.TodoList", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Created") + .HasColumnType("datetimeoffset"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("LastModified") + .HasColumnType("datetimeoffset"); + + b.Property("LastModifiedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.HasKey("Id"); + + b.ToTable("TodoLists"); + }); + + modelBuilder.Entity("Hutopy.Infrastructure.Identity.ApplicationUser", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("AccessFailedCount") + .HasColumnType("int"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("nvarchar(max)"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("EmailConfirmed") + .HasColumnType("bit"); + + b.Property("LockoutEnabled") + .HasColumnType("bit"); + + b.Property("LockoutEnd") + .HasColumnType("datetimeoffset"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("PasswordHash") + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumber") + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("bit"); + + b.Property("SecurityStamp") + .HasColumnType("nvarchar(max)"); + + b.Property("TwoFactorEnabled") + .HasColumnType("bit"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex") + .HasFilter("[NormalizedUserName] IS NOT NULL"); + + b.ToTable("AspNetUsers", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("nvarchar(max)"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex") + .HasFilter("[NormalizedName] IS NOT NULL"); + + b.ToTable("AspNetRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("nvarchar(max)"); + + b.Property("ClaimValue") + .HasColumnType("nvarchar(max)"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("nvarchar(max)"); + + b.Property("ClaimValue") + .HasColumnType("nvarchar(max)"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("nvarchar(450)"); + + b.Property("ProviderKey") + .HasColumnType("nvarchar(450)"); + + b.Property("ProviderDisplayName") + .HasColumnType("nvarchar(max)"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("nvarchar(450)"); + + b.Property("RoleId") + .HasColumnType("nvarchar(450)"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("nvarchar(450)"); + + b.Property("LoginProvider") + .HasColumnType("nvarchar(450)"); + + b.Property("Name") + .HasColumnType("nvarchar(450)"); + + b.Property("Value") + .HasColumnType("nvarchar(max)"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens", (string)null); + }); + + modelBuilder.Entity("Hutopy.Domain.Entities.TodoItem", b => + { + b.HasOne("Hutopy.Domain.Entities.TodoList", "List") + .WithMany("Items") + .HasForeignKey("ListId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("List"); + }); + + modelBuilder.Entity("Hutopy.Domain.Entities.TodoList", b => + { + b.OwnsOne("Hutopy.Domain.ValueObjects.Colour", "Colour", b1 => + { + b1.Property("TodoListId") + .HasColumnType("int"); + + b1.Property("Code") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.HasKey("TodoListId"); + + b1.ToTable("TodoLists"); + + b1.WithOwner() + .HasForeignKey("TodoListId"); + }); + + b.Navigation("Colour") + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Hutopy.Domain.Entities.TodoList", b => + { + b.Navigation("Items"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Infrastructure/Data/Migrations/20240317201728_AddFuturCreator.cs b/src/Infrastructure/Data/Migrations/20240317201728_AddFuturCreator.cs new file mode 100644 index 0000000..21a742f --- /dev/null +++ b/src/Infrastructure/Data/Migrations/20240317201728_AddFuturCreator.cs @@ -0,0 +1,116 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Hutopy.Infrastructure.Data.Migrations +{ + /// + public partial class AddFuturCreator : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AlterColumn( + name: "Name", + table: "AspNetUserTokens", + type: "nvarchar(450)", + nullable: false, + oldClrType: typeof(string), + oldType: "nvarchar(128)", + oldMaxLength: 128); + + migrationBuilder.AlterColumn( + name: "LoginProvider", + table: "AspNetUserTokens", + type: "nvarchar(450)", + nullable: false, + oldClrType: typeof(string), + oldType: "nvarchar(128)", + oldMaxLength: 128); + + migrationBuilder.AlterColumn( + name: "ProviderKey", + table: "AspNetUserLogins", + type: "nvarchar(450)", + nullable: false, + oldClrType: typeof(string), + oldType: "nvarchar(128)", + oldMaxLength: 128); + + migrationBuilder.AlterColumn( + name: "LoginProvider", + table: "AspNetUserLogins", + type: "nvarchar(450)", + nullable: false, + oldClrType: typeof(string), + oldType: "nvarchar(128)", + oldMaxLength: 128); + + migrationBuilder.CreateTable( + name: "FuturCreator", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + FirstName = table.Column(type: "nvarchar(max)", nullable: false), + LastName = table.Column(type: "nvarchar(max)", nullable: false), + EmailAddress = table.Column(type: "nvarchar(max)", nullable: false), + PhoneNumber = table.Column(type: "nvarchar(max)", nullable: false), + SocialNetworkAccount = table.Column(type: "nvarchar(max)", nullable: false), + ReasonToJoin = table.Column(type: "nvarchar(max)", nullable: false), + Created = table.Column(type: "datetimeoffset", nullable: false), + CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), + LastModified = table.Column(type: "datetimeoffset", nullable: false), + LastModifiedBy = table.Column(type: "nvarchar(max)", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_FuturCreator", x => x.Id); + }); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "FuturCreator"); + + migrationBuilder.AlterColumn( + name: "Name", + table: "AspNetUserTokens", + type: "nvarchar(128)", + maxLength: 128, + nullable: false, + oldClrType: typeof(string), + oldType: "nvarchar(450)"); + + migrationBuilder.AlterColumn( + name: "LoginProvider", + table: "AspNetUserTokens", + type: "nvarchar(128)", + maxLength: 128, + nullable: false, + oldClrType: typeof(string), + oldType: "nvarchar(450)"); + + migrationBuilder.AlterColumn( + name: "ProviderKey", + table: "AspNetUserLogins", + type: "nvarchar(128)", + maxLength: 128, + nullable: false, + oldClrType: typeof(string), + oldType: "nvarchar(450)"); + + migrationBuilder.AlterColumn( + name: "LoginProvider", + table: "AspNetUserLogins", + type: "nvarchar(128)", + maxLength: 128, + nullable: false, + oldClrType: typeof(string), + oldType: "nvarchar(450)"); + } + } +} diff --git a/src/Infrastructure/Data/Migrations/ApplicationDbContextModelSnapshot.cs b/src/Infrastructure/Data/Migrations/ApplicationDbContextModelSnapshot.cs index 7a9ffa0..7a0ef22 100644 --- a/src/Infrastructure/Data/Migrations/ApplicationDbContextModelSnapshot.cs +++ b/src/Infrastructure/Data/Migrations/ApplicationDbContextModelSnapshot.cs @@ -17,379 +17,424 @@ namespace Hutopy.Infrastructure.Data.Migrations { #pragma warning disable 612, 618 modelBuilder - .HasAnnotation("ProductVersion", "8.0.0-preview.6.23329.4") + .HasAnnotation("ProductVersion", "8.0.3") .HasAnnotation("Relational:MaxIdentifierLength", 128); SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); - modelBuilder.Entity("Hutopy.Domain.Entities.TodoItem", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("Created") - .HasColumnType("datetimeoffset"); - - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("Done") - .HasColumnType("bit"); - - b.Property("LastModified") - .HasColumnType("datetimeoffset"); - - b.Property("LastModifiedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("ListId") - .HasColumnType("int"); - - b.Property("Note") - .HasColumnType("nvarchar(max)"); - - b.Property("Priority") - .HasColumnType("int"); - - b.Property("Reminder") - .HasColumnType("datetime2"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.HasKey("Id"); - - b.HasIndex("ListId"); - - b.ToTable("TodoItems"); - }); - - modelBuilder.Entity("Hutopy.Domain.Entities.TodoList", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("Created") - .HasColumnType("datetimeoffset"); - - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("LastModified") - .HasColumnType("datetimeoffset"); - - b.Property("LastModifiedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.HasKey("Id"); - - b.ToTable("TodoLists"); - }); - - modelBuilder.Entity("Hutopy.Infrastructure.Identity.ApplicationUser", b => - { - b.Property("Id") - .HasColumnType("nvarchar(450)"); - - b.Property("AccessFailedCount") - .HasColumnType("int"); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnType("nvarchar(max)"); - - b.Property("Email") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("EmailConfirmed") - .HasColumnType("bit"); - - b.Property("LockoutEnabled") - .HasColumnType("bit"); - - b.Property("LockoutEnd") - .HasColumnType("datetimeoffset"); - - b.Property("NormalizedEmail") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("NormalizedUserName") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("PasswordHash") - .HasColumnType("nvarchar(max)"); - - b.Property("PhoneNumber") - .HasColumnType("nvarchar(max)"); - - b.Property("PhoneNumberConfirmed") - .HasColumnType("bit"); - - b.Property("SecurityStamp") - .HasColumnType("nvarchar(max)"); - - b.Property("TwoFactorEnabled") - .HasColumnType("bit"); - - b.Property("UserName") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.HasKey("Id"); - - b.HasIndex("NormalizedEmail") - .HasDatabaseName("EmailIndex"); - - b.HasIndex("NormalizedUserName") - .IsUnique() - .HasDatabaseName("UserNameIndex") - .HasFilter("[NormalizedUserName] IS NOT NULL"); - - b.ToTable("AspNetUsers", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => - { - b.Property("Id") - .HasColumnType("nvarchar(450)"); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnType("nvarchar(max)"); - - b.Property("Name") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("NormalizedName") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.HasKey("Id"); - - b.HasIndex("NormalizedName") - .IsUnique() - .HasDatabaseName("RoleNameIndex") - .HasFilter("[NormalizedName] IS NOT NULL"); - - b.ToTable("AspNetRoles", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ClaimType") - .HasColumnType("nvarchar(max)"); - - b.Property("ClaimValue") - .HasColumnType("nvarchar(max)"); - - b.Property("RoleId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("Id"); - - b.HasIndex("RoleId"); - - b.ToTable("AspNetRoleClaims", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ClaimType") - .HasColumnType("nvarchar(max)"); - - b.Property("ClaimValue") - .HasColumnType("nvarchar(max)"); - - b.Property("UserId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("AspNetUserClaims", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => - { - b.Property("LoginProvider") - .HasMaxLength(128) - .HasColumnType("nvarchar(128)"); - - b.Property("ProviderKey") - .HasMaxLength(128) - .HasColumnType("nvarchar(128)"); - - b.Property("ProviderDisplayName") - .HasColumnType("nvarchar(max)"); - - b.Property("UserId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("LoginProvider", "ProviderKey"); - - b.HasIndex("UserId"); - - b.ToTable("AspNetUserLogins", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => - { - b.Property("UserId") - .HasColumnType("nvarchar(450)"); - - b.Property("RoleId") - .HasColumnType("nvarchar(450)"); - - b.HasKey("UserId", "RoleId"); - - b.HasIndex("RoleId"); - - b.ToTable("AspNetUserRoles", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => - { - b.Property("UserId") - .HasColumnType("nvarchar(450)"); - - b.Property("LoginProvider") - .HasMaxLength(128) - .HasColumnType("nvarchar(128)"); - - b.Property("Name") - .HasMaxLength(128) - .HasColumnType("nvarchar(128)"); - - b.Property("Value") - .HasColumnType("nvarchar(max)"); - - b.HasKey("UserId", "LoginProvider", "Name"); - - b.ToTable("AspNetUserTokens", (string)null); - }); - - modelBuilder.Entity("Hutopy.Domain.Entities.TodoItem", b => - { - b.HasOne("Hutopy.Domain.Entities.TodoList", "List") - .WithMany("Items") - .HasForeignKey("ListId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("List"); - }); - - modelBuilder.Entity("Hutopy.Domain.Entities.TodoList", b => - { - b.OwnsOne("Hutopy.Domain.ValueObjects.Colour", "Colour", b1 => + modelBuilder.Entity("FuturCreator", b => { - b1.Property("TodoListId") + b.Property("Id") + .ValueGeneratedOnAdd() .HasColumnType("int"); - b1.Property("Code") + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Created") + .HasColumnType("datetimeoffset"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("EmailAddress") .IsRequired() .HasColumnType("nvarchar(max)"); - b1.HasKey("TodoListId"); + b.Property("FirstName") + .IsRequired() + .HasColumnType("nvarchar(max)"); - b1.ToTable("TodoLists"); + b.Property("LastModified") + .HasColumnType("datetimeoffset"); - b1.WithOwner() - .HasForeignKey("TodoListId"); + b.Property("LastModifiedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("LastName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumber") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("ReasonToJoin") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("SocialNetworkAccount") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("FuturCreator"); }); - b.Navigation("Colour") - .IsRequired(); - }); + modelBuilder.Entity("Hutopy.Domain.Entities.TodoItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) - .WithMany() - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => - { - b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); + b.Property("Created") + .HasColumnType("datetimeoffset"); - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => - { - b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) - .WithMany() - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); + b.Property("Done") + .HasColumnType("bit"); - b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); + b.Property("LastModified") + .HasColumnType("datetimeoffset"); - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => - { - b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); + b.Property("LastModifiedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("ListId") + .HasColumnType("int"); + + b.Property("Note") + .HasColumnType("nvarchar(max)"); + + b.Property("Priority") + .HasColumnType("int"); + + b.Property("Reminder") + .HasColumnType("datetime2"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.HasKey("Id"); + + b.HasIndex("ListId"); + + b.ToTable("TodoItems"); + }); modelBuilder.Entity("Hutopy.Domain.Entities.TodoList", b => - { - b.Navigation("Items"); - }); + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Created") + .HasColumnType("datetimeoffset"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("LastModified") + .HasColumnType("datetimeoffset"); + + b.Property("LastModifiedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.HasKey("Id"); + + b.ToTable("TodoLists"); + }); + + modelBuilder.Entity("Hutopy.Infrastructure.Identity.ApplicationUser", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("AccessFailedCount") + .HasColumnType("int"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("nvarchar(max)"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("EmailConfirmed") + .HasColumnType("bit"); + + b.Property("LockoutEnabled") + .HasColumnType("bit"); + + b.Property("LockoutEnd") + .HasColumnType("datetimeoffset"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("PasswordHash") + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumber") + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("bit"); + + b.Property("SecurityStamp") + .HasColumnType("nvarchar(max)"); + + b.Property("TwoFactorEnabled") + .HasColumnType("bit"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex") + .HasFilter("[NormalizedUserName] IS NOT NULL"); + + b.ToTable("AspNetUsers", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("nvarchar(max)"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex") + .HasFilter("[NormalizedName] IS NOT NULL"); + + b.ToTable("AspNetRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("nvarchar(max)"); + + b.Property("ClaimValue") + .HasColumnType("nvarchar(max)"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("nvarchar(max)"); + + b.Property("ClaimValue") + .HasColumnType("nvarchar(max)"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("nvarchar(450)"); + + b.Property("ProviderKey") + .HasColumnType("nvarchar(450)"); + + b.Property("ProviderDisplayName") + .HasColumnType("nvarchar(max)"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("nvarchar(450)"); + + b.Property("RoleId") + .HasColumnType("nvarchar(450)"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("nvarchar(450)"); + + b.Property("LoginProvider") + .HasColumnType("nvarchar(450)"); + + b.Property("Name") + .HasColumnType("nvarchar(450)"); + + b.Property("Value") + .HasColumnType("nvarchar(max)"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens", (string)null); + }); + + modelBuilder.Entity("Hutopy.Domain.Entities.TodoItem", b => + { + b.HasOne("Hutopy.Domain.Entities.TodoList", "List") + .WithMany("Items") + .HasForeignKey("ListId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("List"); + }); + + modelBuilder.Entity("Hutopy.Domain.Entities.TodoList", b => + { + b.OwnsOne("Hutopy.Domain.ValueObjects.Colour", "Colour", b1 => + { + b1.Property("TodoListId") + .HasColumnType("int"); + + b1.Property("Code") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.HasKey("TodoListId"); + + b1.ToTable("TodoLists"); + + b1.WithOwner() + .HasForeignKey("TodoListId"); + }); + + b.Navigation("Colour") + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Hutopy.Domain.Entities.TodoList", b => + { + b.Navigation("Items"); + }); #pragma warning restore 612, 618 } } diff --git a/src/Infrastructure/Infrastructure.csproj b/src/Infrastructure/Infrastructure.csproj index 581d24f..ab862ba 100644 --- a/src/Infrastructure/Infrastructure.csproj +++ b/src/Infrastructure/Infrastructure.csproj @@ -11,6 +11,7 @@ all + diff --git a/src/Web/Web.csproj b/src/Web/Web.csproj index 27c2d2d..14b1052 100644 --- a/src/Web/Web.csproj +++ b/src/Web/Web.csproj @@ -18,6 +18,10 @@ + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/Web/appsettings.json b/src/Web/appsettings.json index bedce59..84c0835 100644 --- a/src/Web/appsettings.json +++ b/src/Web/appsettings.json @@ -1,6 +1,6 @@ { "ConnectionStrings": { - "DefaultConnection": "Server=localhost,1433;Database=TestDeux;User Id=sa;Password={DB_PASSWORD};MultipleActiveResultSets=true;TrustServerCertificate=True" + "DefaultConnection": "Server=localhost,1433;Database=HutopyLocal;User Id=sa;Password={DB_PASSWORD};MultipleActiveResultSets=true;TrustServerCertificate=True" }, "Logging": { "LogLevel": { From d565d0c98ba4776a471dee4356ccda7cf454cb41 Mon Sep 17 00:00:00 2001 From: Dominic Villemure Date: Sun, 17 Mar 2024 16:59:20 -0400 Subject: [PATCH 007/229] CleanUp and added migration --- Directory.Build.props | 2 +- .../Interfaces/IApplicationDbContext.cs | 2 +- .../Commands/CreateFuturCreator.cs | 5 +- src/Domain/Entities/FuturCreator.cs | 2 + .../Data/ApplicationDbContext.cs | 2 +- ...20240317201728_AddFuturCreator.Designer.cs | 8 +-- .../20240317201728_AddFuturCreator.cs | 8 +-- src/Web/Endpoints/FuturCreators.cs | 18 ++++++ src/Web/wwwroot/api/specification.json | 62 +++++++++++++++++++ 9 files changed, 96 insertions(+), 13 deletions(-) rename src/Application/{FuturCreator => FuturCreators}/Commands/CreateFuturCreator.cs (89%) create mode 100644 src/Web/Endpoints/FuturCreators.cs diff --git a/Directory.Build.props b/Directory.Build.props index ffa84fe..fad896c 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -2,7 +2,7 @@ net8.0 - true + false enable enable diff --git a/src/Application/Common/Interfaces/IApplicationDbContext.cs b/src/Application/Common/Interfaces/IApplicationDbContext.cs index c393783..4e5f1fa 100644 --- a/src/Application/Common/Interfaces/IApplicationDbContext.cs +++ b/src/Application/Common/Interfaces/IApplicationDbContext.cs @@ -8,7 +8,7 @@ public interface IApplicationDbContext DbSet TodoItems { get; } - DbSet FuturCreator { get; } + DbSet FuturCreators { get; } Task SaveChangesAsync(CancellationToken cancellationToken); } diff --git a/src/Application/FuturCreator/Commands/CreateFuturCreator.cs b/src/Application/FuturCreators/Commands/CreateFuturCreator.cs similarity index 89% rename from src/Application/FuturCreator/Commands/CreateFuturCreator.cs rename to src/Application/FuturCreators/Commands/CreateFuturCreator.cs index 82db619..857a440 100644 --- a/src/Application/FuturCreator/Commands/CreateFuturCreator.cs +++ b/src/Application/FuturCreators/Commands/CreateFuturCreator.cs @@ -1,6 +1,7 @@ using Hutopy.Application.Common.Interfaces; +using Hutopy.Domain.Entities; -namespace Hutopy.Application.TodoItems.Commands.CreateFuturCreator; +namespace Hutopy.Application.FuturCreators.Commands.CreateFuturCreator; public record CreateFuturCreatorCommand : IRequest { @@ -34,7 +35,7 @@ public class CreateFuturCreatorCommandHandler : IRequestHandler, IApplica public DbSet TodoItems => Set(); - public DbSet FuturCreator => Set(); + public DbSet FuturCreators => Set(); protected override void OnModelCreating(ModelBuilder builder) { diff --git a/src/Infrastructure/Data/Migrations/20240317201728_AddFuturCreator.Designer.cs b/src/Infrastructure/Data/Migrations/20240317201728_AddFuturCreator.Designer.cs index 12219ef..9244599 100644 --- a/src/Infrastructure/Data/Migrations/20240317201728_AddFuturCreator.Designer.cs +++ b/src/Infrastructure/Data/Migrations/20240317201728_AddFuturCreator.Designer.cs @@ -12,8 +12,8 @@ using Microsoft.EntityFrameworkCore.Storage.ValueConversion; namespace Hutopy.Infrastructure.Data.Migrations { [DbContext(typeof(ApplicationDbContext))] - [Migration("20240317201728_AddFuturCreator")] - partial class AddFuturCreator + [Migration("20240317201728_AddFuturCreators")] + partial class AddfuturCreators { /// protected override void BuildTargetModel(ModelBuilder modelBuilder) @@ -25,7 +25,7 @@ namespace Hutopy.Infrastructure.Data.Migrations SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); - modelBuilder.Entity("FuturCreator", b => + modelBuilder.Entity("FuturCreators", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -71,7 +71,7 @@ namespace Hutopy.Infrastructure.Data.Migrations b.HasKey("Id"); - b.ToTable("FuturCreator"); + b.ToTable("FuturCreators"); }); modelBuilder.Entity("Hutopy.Domain.Entities.TodoItem", b => diff --git a/src/Infrastructure/Data/Migrations/20240317201728_AddFuturCreator.cs b/src/Infrastructure/Data/Migrations/20240317201728_AddFuturCreator.cs index 21a742f..d2de5c0 100644 --- a/src/Infrastructure/Data/Migrations/20240317201728_AddFuturCreator.cs +++ b/src/Infrastructure/Data/Migrations/20240317201728_AddFuturCreator.cs @@ -6,7 +6,7 @@ using Microsoft.EntityFrameworkCore.Migrations; namespace Hutopy.Infrastructure.Data.Migrations { /// - public partial class AddFuturCreator : Migration + public partial class AddFuturCreators : Migration { /// protected override void Up(MigrationBuilder migrationBuilder) @@ -48,7 +48,7 @@ namespace Hutopy.Infrastructure.Data.Migrations oldMaxLength: 128); migrationBuilder.CreateTable( - name: "FuturCreator", + name: "FuturCreators", columns: table => new { Id = table.Column(type: "int", nullable: false) @@ -66,7 +66,7 @@ namespace Hutopy.Infrastructure.Data.Migrations }, constraints: table => { - table.PrimaryKey("PK_FuturCreator", x => x.Id); + table.PrimaryKey("PK_FuturCreators", x => x.Id); }); } @@ -74,7 +74,7 @@ namespace Hutopy.Infrastructure.Data.Migrations protected override void Down(MigrationBuilder migrationBuilder) { migrationBuilder.DropTable( - name: "FuturCreator"); + name: "FuturCreators"); migrationBuilder.AlterColumn( name: "Name", diff --git a/src/Web/Endpoints/FuturCreators.cs b/src/Web/Endpoints/FuturCreators.cs new file mode 100644 index 0000000..383862a --- /dev/null +++ b/src/Web/Endpoints/FuturCreators.cs @@ -0,0 +1,18 @@ +using Hutopy.Application.FuturCreators.Commands.CreateFuturCreator; + +namespace Hutopy.Web.Endpoints; + +public class FuturCreators : EndpointGroupBase +{ + public override void Map(WebApplication app) + { + app.MapGroup(this) + .RequireAuthorization() + .MapPost(CreateFuturCreator); + } + + public Task CreateFuturCreator(ISender sender, CreateFuturCreatorCommand command) + { + return sender.Send(command); + } +} diff --git a/src/Web/wwwroot/api/specification.json b/src/Web/wwwroot/api/specification.json index a8d81f4..2794485 100644 --- a/src/Web/wwwroot/api/specification.json +++ b/src/Web/wwwroot/api/specification.json @@ -6,6 +6,44 @@ "version": "1.0.0" }, "paths": { + "/api/FuturCreators": { + "post": { + "tags": [ + "FuturCreators" + ], + "operationId": "CreateFuturCreator", + "requestBody": { + "x-name": "command", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateFuturCreatorCommand" + } + } + }, + "required": true, + "x-position": 1 + }, + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "integer", + "format": "int32" + } + } + } + } + }, + "security": [ + { + "JWT": [] + } + ] + } + }, "/api/TodoItems": { "get": { "tags": [ @@ -757,6 +795,30 @@ }, "components": { "schemas": { + "CreateFuturCreatorCommand": { + "type": "object", + "additionalProperties": false, + "properties": { + "firstName": { + "type": "string" + }, + "lastName": { + "type": "string" + }, + "emailAddress": { + "type": "string" + }, + "phoneNumber": { + "type": "string" + }, + "socialNetworkAccount": { + "type": "string" + }, + "reasonToJoin": { + "type": "string" + } + } + }, "PaginatedListOfTodoItemBriefDto": { "type": "object", "additionalProperties": false, From a58afc774f7ee299e9ad14e94567cf90467faf4c Mon Sep 17 00:00:00 2001 From: Dominic Villemure Date: Sun, 17 Mar 2024 17:00:43 -0400 Subject: [PATCH 008/229] Fixed typo --- .../Data/Migrations/20240317201728_AddFuturCreator.Designer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Infrastructure/Data/Migrations/20240317201728_AddFuturCreator.Designer.cs b/src/Infrastructure/Data/Migrations/20240317201728_AddFuturCreator.Designer.cs index 9244599..a33f51b 100644 --- a/src/Infrastructure/Data/Migrations/20240317201728_AddFuturCreator.Designer.cs +++ b/src/Infrastructure/Data/Migrations/20240317201728_AddFuturCreator.Designer.cs @@ -13,7 +13,7 @@ namespace Hutopy.Infrastructure.Data.Migrations { [DbContext(typeof(ApplicationDbContext))] [Migration("20240317201728_AddFuturCreators")] - partial class AddfuturCreators + partial class AddFuturCreators { /// protected override void BuildTargetModel(ModelBuilder modelBuilder) From 775d25d31d68f3f5ed0a6192aa2fc5f29801c570 Mon Sep 17 00:00:00 2001 From: Dominic Villemure Date: Sun, 17 Mar 2024 17:03:35 -0400 Subject: [PATCH 009/229] Fix snapshot --- .../Data/Migrations/ApplicationDbContextModelSnapshot.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Infrastructure/Data/Migrations/ApplicationDbContextModelSnapshot.cs b/src/Infrastructure/Data/Migrations/ApplicationDbContextModelSnapshot.cs index 7a0ef22..4b12eb4 100644 --- a/src/Infrastructure/Data/Migrations/ApplicationDbContextModelSnapshot.cs +++ b/src/Infrastructure/Data/Migrations/ApplicationDbContextModelSnapshot.cs @@ -22,7 +22,7 @@ namespace Hutopy.Infrastructure.Data.Migrations SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); - modelBuilder.Entity("FuturCreator", b => + modelBuilder.Entity("Hutopy.Domain.Entities.FuturCreator", b => { b.Property("Id") .ValueGeneratedOnAdd() From fca3d26aa7bed09e6e844e23b88400e5d401ebfd Mon Sep 17 00:00:00 2001 From: Kamigen <46357922+Edouard127@users.noreply.github.com> Date: Sun, 17 Mar 2024 21:02:41 -0400 Subject: [PATCH 010/229] Fix: Invalid .NET version --- global.json | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/global.json b/global.json index 622dcbb..05cf0d8 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,7 @@ { "sdk": { - "version": "8.0.3", - "rollForward": "latestFeature" + "version": "8.0.203", + "rollForward": "latestFeature", + "allowPrerelease": true } } \ No newline at end of file From b7ec5a69a9cf6a16b07c5b98cfb8429a7afffba0 Mon Sep 17 00:00:00 2001 From: Kamigen <46357922+Edouard127@users.noreply.github.com> Date: Sun, 17 Mar 2024 21:03:08 -0400 Subject: [PATCH 011/229] Feature: Join us api call --- .../Common/Interfaces/IApplicationDbContext.cs | 2 +- src/Application/DependencyInjection.cs | 1 - .../Commands/CreateFutureCreator.cs} | 12 ++++++------ src/Domain/Entities/FuturCreator.cs | 11 ----------- src/Domain/Entities/FutureCreator.cs | 11 +++++++++++ .../Data/ApplicationDbContext.cs | 2 +- .../20240317201728_AddFuturCreator.cs | 4 ++-- .../ApplicationDbContextModelSnapshot.cs | 4 ++-- src/Web/Endpoints/FuturCreators.cs | 18 ------------------ src/Web/Endpoints/JoinUs.cs | 17 +++++++++++++++++ src/Web/wwwroot/api/specification.json | 17 ++++++----------- 11 files changed, 46 insertions(+), 53 deletions(-) rename src/Application/{FuturCreators/Commands/CreateFuturCreator.cs => FutureCreators/Commands/CreateFutureCreator.cs} (75%) delete mode 100644 src/Domain/Entities/FuturCreator.cs create mode 100644 src/Domain/Entities/FutureCreator.cs delete mode 100644 src/Web/Endpoints/FuturCreators.cs create mode 100644 src/Web/Endpoints/JoinUs.cs diff --git a/src/Application/Common/Interfaces/IApplicationDbContext.cs b/src/Application/Common/Interfaces/IApplicationDbContext.cs index 4e5f1fa..9e35843 100644 --- a/src/Application/Common/Interfaces/IApplicationDbContext.cs +++ b/src/Application/Common/Interfaces/IApplicationDbContext.cs @@ -8,7 +8,7 @@ public interface IApplicationDbContext DbSet TodoItems { get; } - DbSet FuturCreators { get; } + DbSet FutureCreators { get; } Task SaveChangesAsync(CancellationToken cancellationToken); } diff --git a/src/Application/DependencyInjection.cs b/src/Application/DependencyInjection.cs index ebbe093..3ff3e1e 100644 --- a/src/Application/DependencyInjection.cs +++ b/src/Application/DependencyInjection.cs @@ -1,5 +1,4 @@ using System.Reflection; -using Hutopy.Application.Common.Behaviours; namespace Microsoft.Extensions.DependencyInjection; diff --git a/src/Application/FuturCreators/Commands/CreateFuturCreator.cs b/src/Application/FutureCreators/Commands/CreateFutureCreator.cs similarity index 75% rename from src/Application/FuturCreators/Commands/CreateFuturCreator.cs rename to src/Application/FutureCreators/Commands/CreateFutureCreator.cs index 857a440..54f4e70 100644 --- a/src/Application/FuturCreators/Commands/CreateFuturCreator.cs +++ b/src/Application/FutureCreators/Commands/CreateFutureCreator.cs @@ -1,9 +1,9 @@ using Hutopy.Application.Common.Interfaces; using Hutopy.Domain.Entities; -namespace Hutopy.Application.FuturCreators.Commands.CreateFuturCreator; +namespace Hutopy.Application.FutureCreators.Commands; -public record CreateFuturCreatorCommand : IRequest +public record CreateFutureCreatorCommand : IRequest { public required string FirstName { get; init; } public required string LastName { get; init; } @@ -13,7 +13,7 @@ public record CreateFuturCreatorCommand : IRequest public required string ReasonToJoin { get; init; } } -public class CreateFuturCreatorCommandHandler : IRequestHandler +public class CreateFuturCreatorCommandHandler : IRequestHandler { private readonly IApplicationDbContext _context; @@ -23,9 +23,9 @@ public class CreateFuturCreatorCommandHandler : IRequestHandler Handle(CreateFuturCreatorCommand request, CancellationToken cancellationToken) + public async Task Handle(CreateFutureCreatorCommand request, CancellationToken cancellationToken) { - var entity = new FuturCreator() + var entity = new FutureCreator { FirstName = request.FirstName, LastName = request.LastName, @@ -35,7 +35,7 @@ public class CreateFuturCreatorCommandHandler : IRequestHandler, IApplica public DbSet TodoItems => Set(); - public DbSet FuturCreators => Set(); + public DbSet FutureCreators => Set(); protected override void OnModelCreating(ModelBuilder builder) { diff --git a/src/Infrastructure/Data/Migrations/20240317201728_AddFuturCreator.cs b/src/Infrastructure/Data/Migrations/20240317201728_AddFuturCreator.cs index d2de5c0..a65203a 100644 --- a/src/Infrastructure/Data/Migrations/20240317201728_AddFuturCreator.cs +++ b/src/Infrastructure/Data/Migrations/20240317201728_AddFuturCreator.cs @@ -48,7 +48,7 @@ namespace Hutopy.Infrastructure.Data.Migrations oldMaxLength: 128); migrationBuilder.CreateTable( - name: "FuturCreators", + name: "FutureCreators", columns: table => new { Id = table.Column(type: "int", nullable: false) @@ -74,7 +74,7 @@ namespace Hutopy.Infrastructure.Data.Migrations protected override void Down(MigrationBuilder migrationBuilder) { migrationBuilder.DropTable( - name: "FuturCreators"); + name: "FutureCreators"); migrationBuilder.AlterColumn( name: "Name", diff --git a/src/Infrastructure/Data/Migrations/ApplicationDbContextModelSnapshot.cs b/src/Infrastructure/Data/Migrations/ApplicationDbContextModelSnapshot.cs index 4b12eb4..0eb80ef 100644 --- a/src/Infrastructure/Data/Migrations/ApplicationDbContextModelSnapshot.cs +++ b/src/Infrastructure/Data/Migrations/ApplicationDbContextModelSnapshot.cs @@ -22,7 +22,7 @@ namespace Hutopy.Infrastructure.Data.Migrations SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); - modelBuilder.Entity("Hutopy.Domain.Entities.FuturCreator", b => + modelBuilder.Entity("Hutopy.Domain.Entities.FutureCreator", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -68,7 +68,7 @@ namespace Hutopy.Infrastructure.Data.Migrations b.HasKey("Id"); - b.ToTable("FuturCreator"); + b.ToTable("FutureCreator"); }); modelBuilder.Entity("Hutopy.Domain.Entities.TodoItem", b => diff --git a/src/Web/Endpoints/FuturCreators.cs b/src/Web/Endpoints/FuturCreators.cs deleted file mode 100644 index 383862a..0000000 --- a/src/Web/Endpoints/FuturCreators.cs +++ /dev/null @@ -1,18 +0,0 @@ -using Hutopy.Application.FuturCreators.Commands.CreateFuturCreator; - -namespace Hutopy.Web.Endpoints; - -public class FuturCreators : EndpointGroupBase -{ - public override void Map(WebApplication app) - { - app.MapGroup(this) - .RequireAuthorization() - .MapPost(CreateFuturCreator); - } - - public Task CreateFuturCreator(ISender sender, CreateFuturCreatorCommand command) - { - return sender.Send(command); - } -} diff --git a/src/Web/Endpoints/JoinUs.cs b/src/Web/Endpoints/JoinUs.cs new file mode 100644 index 0000000..d49265f --- /dev/null +++ b/src/Web/Endpoints/JoinUs.cs @@ -0,0 +1,17 @@ +using Hutopy.Application.FutureCreators.Commands; + +namespace Hutopy.Web.Endpoints; + +public class JoinUs : EndpointGroupBase +{ + public override void Map(WebApplication app) + { + app.MapGroup(this) + .MapPost(CreateFutureCreator); + } + + public Task CreateFutureCreator(ISender sender, CreateFutureCreatorCommand command) + { + return sender.Send(command); + } +} diff --git a/src/Web/wwwroot/api/specification.json b/src/Web/wwwroot/api/specification.json index 2794485..c4ab40c 100644 --- a/src/Web/wwwroot/api/specification.json +++ b/src/Web/wwwroot/api/specification.json @@ -6,18 +6,18 @@ "version": "1.0.0" }, "paths": { - "/api/FuturCreators": { + "/api/JoinUs": { "post": { "tags": [ - "FuturCreators" + "JoinUs" ], - "operationId": "CreateFuturCreator", + "operationId": "CreateFutureCreator", "requestBody": { "x-name": "command", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/CreateFuturCreatorCommand" + "$ref": "#/components/schemas/CreateFutureCreatorCommand" } } }, @@ -36,12 +36,7 @@ } } } - }, - "security": [ - { - "JWT": [] - } - ] + } } }, "/api/TodoItems": { @@ -795,7 +790,7 @@ }, "components": { "schemas": { - "CreateFuturCreatorCommand": { + "CreateFutureCreatorCommand": { "type": "object", "additionalProperties": false, "properties": { From cc26d104d15817909418fa477f624549a715b747 Mon Sep 17 00:00:00 2001 From: Dominic Villemure Date: Mon, 18 Mar 2024 21:25:28 -0400 Subject: [PATCH 012/229] Removed useless using --- src/Infrastructure/Data/ApplicationDbContext.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Infrastructure/Data/ApplicationDbContext.cs b/src/Infrastructure/Data/ApplicationDbContext.cs index 6860e86..1a41916 100644 --- a/src/Infrastructure/Data/ApplicationDbContext.cs +++ b/src/Infrastructure/Data/ApplicationDbContext.cs @@ -2,7 +2,6 @@ using Hutopy.Application.Common.Interfaces; using Hutopy.Domain.Entities; using Hutopy.Infrastructure.Identity; -using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Identity.EntityFrameworkCore; using Microsoft.EntityFrameworkCore; From 2b810772b3c0bcd773d5e28425893fa9f83fa686 Mon Sep 17 00:00:00 2001 From: Dominic Villemure Date: Wed, 20 Mar 2024 01:10:44 -0400 Subject: [PATCH 013/229] Added endpoint to create a sessionCheckout with stripe --- Directory.Packages.props | 1 + .../Common/Interfaces/IStripeService.cs | 7 +++ .../Commands/CreateSessionCheckoutCommand.cs | 31 +++++++++++++ src/Infrastructure/DependencyInjection.cs | 2 + src/Infrastructure/Infrastructure.csproj | 15 +++--- src/Infrastructure/Stripe/StripeService.cs | 46 +++++++++++++++++++ src/Web/Endpoints/Stripe.cs | 17 +++++++ src/Web/wwwroot/api/specification.json | 45 ++++++++++++++++++ 8 files changed, 157 insertions(+), 7 deletions(-) create mode 100644 src/Application/Common/Interfaces/IStripeService.cs create mode 100644 src/Application/Stripe/Commands/CreateSessionCheckoutCommand.cs create mode 100644 src/Infrastructure/Stripe/StripeService.cs create mode 100644 src/Web/Endpoints/Stripe.cs diff --git a/Directory.Packages.props b/Directory.Packages.props index ba78a5d..74620e0 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -37,6 +37,7 @@ + \ No newline at end of file diff --git a/src/Application/Common/Interfaces/IStripeService.cs b/src/Application/Common/Interfaces/IStripeService.cs new file mode 100644 index 0000000..1231a8e --- /dev/null +++ b/src/Application/Common/Interfaces/IStripeService.cs @@ -0,0 +1,7 @@ +namespace Hutopy.Application.Common.Interfaces; + + +public interface IStripeService +{ + public Task CreateCheckoutSession(int price, string currency); +} diff --git a/src/Application/Stripe/Commands/CreateSessionCheckoutCommand.cs b/src/Application/Stripe/Commands/CreateSessionCheckoutCommand.cs new file mode 100644 index 0000000..3fa96c0 --- /dev/null +++ b/src/Application/Stripe/Commands/CreateSessionCheckoutCommand.cs @@ -0,0 +1,31 @@ +using Hutopy.Application.Common.Interfaces; + + +namespace Hutopy.Application.Stripe.Commands; +public record CreateSessionCheckoutCommand : IRequest +{ + public required int Price { get; init; } + + public string Currency { get; init; } = "cad"; +} + + +public class CreateSessionCheckoutCommandHandler : IRequestHandler +{ + private readonly IApplicationDbContext _context; + private readonly IStripeService _stripeService; + + + public CreateSessionCheckoutCommandHandler(IApplicationDbContext context, IStripeService stripeService) + { + _context = context; + _stripeService = stripeService; + } + + public async Task Handle(CreateSessionCheckoutCommand request, CancellationToken cancellationToken) + { + var stripeSecret = await _stripeService.CreateCheckoutSession(request.Price, request.Currency); + + return stripeSecret; + } +} diff --git a/src/Infrastructure/DependencyInjection.cs b/src/Infrastructure/DependencyInjection.cs index f466e8f..7481df3 100644 --- a/src/Infrastructure/DependencyInjection.cs +++ b/src/Infrastructure/DependencyInjection.cs @@ -3,6 +3,7 @@ using Hutopy.Domain.Constants; using Hutopy.Infrastructure.Data; using Hutopy.Infrastructure.Data.Interceptors; using Hutopy.Infrastructure.Identity; +using Hutopy.Infrastructure.Stripe; using Microsoft.AspNetCore.Identity; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Diagnostics; @@ -49,6 +50,7 @@ public static class DependencyInjection services.AddSingleton(TimeProvider.System); services.AddTransient(); + services.AddTransient(); services.AddAuthorization(options => options.AddPolicy(Policies.CanPurge, policy => policy.RequireRole(Roles.Administrator))); diff --git a/src/Infrastructure/Infrastructure.csproj b/src/Infrastructure/Infrastructure.csproj index ab862ba..2958bd6 100644 --- a/src/Infrastructure/Infrastructure.csproj +++ b/src/Infrastructure/Infrastructure.csproj @@ -4,18 +4,19 @@ Hutopy.Infrastructure - - + + runtime; build; native; contentfiles; analyzers; buildtransitive all - - - - + + + + + - + diff --git a/src/Infrastructure/Stripe/StripeService.cs b/src/Infrastructure/Stripe/StripeService.cs new file mode 100644 index 0000000..dc18c62 --- /dev/null +++ b/src/Infrastructure/Stripe/StripeService.cs @@ -0,0 +1,46 @@ +using Stripe; +using Stripe.Checkout; +using Hutopy.Application.Common.Interfaces; + + +namespace Hutopy.Infrastructure.Stripe; + +public class StripeService : IStripeService +{ + public StripeService() + { + // I removed the key to push. Will need to be in config. + StripeConfiguration.ApiKey = ""; + } + + public async Task CreateCheckoutSession(int price, string currency = "cad") + { + var options = new SessionCreateOptions + { + LineItems = new List + { + new SessionLineItemOptions + { + PriceData = new SessionLineItemPriceDataOptions + { + UnitAmount = price, + Currency = currency, + ProductData = new SessionLineItemPriceDataProductDataOptions + { + Name = "Tip", + }, + }, + Quantity = 1, + }, + }, + Mode = "payment", + UiMode = "embedded", + ReturnUrl = "http://localhost:5174", + }; + + var service = new SessionService(); + Session session = await service.CreateAsync(options); + + return session.ClientSecret; + } +} diff --git a/src/Web/Endpoints/Stripe.cs b/src/Web/Endpoints/Stripe.cs new file mode 100644 index 0000000..c7753b0 --- /dev/null +++ b/src/Web/Endpoints/Stripe.cs @@ -0,0 +1,17 @@ +using Hutopy.Application.Stripe.Commands; + +namespace Hutopy.Web.Endpoints; + +public class Stripe : EndpointGroupBase +{ + public override void Map(WebApplication app) + { + app.MapGroup(this) + .MapPost(CreateSessionCheckout); + } + + public Task CreateSessionCheckout(ISender sender, CreateSessionCheckoutCommand command) + { + return sender.Send(command); + } +} diff --git a/src/Web/wwwroot/api/specification.json b/src/Web/wwwroot/api/specification.json index c4ab40c..158be32 100644 --- a/src/Web/wwwroot/api/specification.json +++ b/src/Web/wwwroot/api/specification.json @@ -39,6 +39,38 @@ } } }, + "/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/TodoItems": { "get": { "tags": [ @@ -814,6 +846,19 @@ } } }, + "CreateSessionCheckoutCommand": { + "type": "object", + "additionalProperties": false, + "properties": { + "price": { + "type": "integer", + "format": "int32" + }, + "currency": { + "type": "string" + } + } + }, "PaginatedListOfTodoItemBriefDto": { "type": "object", "additionalProperties": false, From 7540d4437f276c10968838c7b8c04a914c435d10 Mon Sep 17 00:00:00 2001 From: Dominic Villemure Date: Wed, 27 Mar 2024 23:53:56 -0400 Subject: [PATCH 014/229] Added info in readme and a new redirect --- README.md | 12 ++++++++++++ src/Infrastructure/Stripe/StripeService.cs | 3 +-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 3c9281a..e923dc0 100644 --- a/README.md +++ b/README.md @@ -22,6 +22,18 @@ docker run -e 'ACCEPT_EULA=Y' -e 'MSSQL_SA_PASSWORD=' -p 1433:1433 Set your password in an env var for the connection string. Windows : $Env:DB_PASSWORD = "YourPassword" +## Entity Framework + +Create a new migration : +``` +./Ef.ps1 migrations add NomDeLaMigration +``` + +Update database : +``` +./Ef.ps1 database update +``` + ## Build Run `dotnet build -tl` to build the solution. diff --git a/src/Infrastructure/Stripe/StripeService.cs b/src/Infrastructure/Stripe/StripeService.cs index dc18c62..3cfb7ff 100644 --- a/src/Infrastructure/Stripe/StripeService.cs +++ b/src/Infrastructure/Stripe/StripeService.cs @@ -2,7 +2,6 @@ using Stripe; using Stripe.Checkout; using Hutopy.Application.Common.Interfaces; - namespace Hutopy.Infrastructure.Stripe; public class StripeService : IStripeService @@ -35,7 +34,7 @@ public class StripeService : IStripeService }, Mode = "payment", UiMode = "embedded", - ReturnUrl = "http://localhost:5174", + ReturnUrl = $"http://localhost:5173/creatorfolio", }; var service = new SessionService(); From 8f58311283a2d6e9a4a43c0f541ea3100822de1c Mon Sep 17 00:00:00 2001 From: Kamigen <46357922+Edouard127@users.noreply.github.com> Date: Sat, 30 Mar 2024 20:59:17 -0400 Subject: [PATCH 015/229] Style: C# 12 Primary constructor --- .../Behaviours/AuthorizationBehaviour.cs | 23 +++----- .../Common/Behaviours/LoggingBehaviour.cs | 22 ++++---- .../Common/Behaviours/PerformanceBehaviour.cs | 44 ++++++--------- .../Behaviours/UnhandledExceptionBehaviour.cs | 14 ++--- .../Common/Behaviours/ValidationBehaviour.cs | 37 ++++++------- .../Common/Exceptions/ValidationException.cs | 11 ++-- .../Common/Models/PaginatedList.cs | 22 ++++---- src/Application/Common/Models/Result.cs | 14 ++--- .../Common/Security/AuthorizeAttribute.cs | 2 +- src/Application/DependencyInjection.cs | 3 +- .../Commands/CreateFutureCreator.cs | 18 +++---- .../Commands/CreateSessionCheckoutCommand.cs | 21 +++----- .../Commands/CreateTodoItem/CreateTodoItem.cs | 15 ++---- .../Commands/DeleteTodoItem/DeleteTodoItem.cs | 17 +++--- .../Commands/UpdateTodoItem/UpdateTodoItem.cs | 15 ++---- .../UpdateTodoItemDetail.cs | 15 ++---- .../TodoItemCompletedEventHandler.cs | 13 ++--- .../TodoItemCreatedEventHandler.cs | 13 ++--- .../GetTodoItemsWithPagination.cs | 20 +++---- .../Commands/CreateTodoList/CreateTodoList.cs | 19 +++---- .../Commands/DeleteTodoList/DeleteTodoList.cs | 17 +++--- .../Commands/PurgeTodoLists/PurgeTodoLists.cs | 15 ++---- .../Commands/UpdateTodoList/UpdateTodoList.cs | 15 ++---- .../UpdateTodoListCommandValidator.cs | 2 +- .../TodoLists/Queries/GetTodos/GetTodos.cs | 18 +++---- .../TodoLists/Queries/GetTodos/TodoListDto.cs | 7 +-- src/Domain/Common/BaseEntity.cs | 4 +- src/Domain/Common/ValueObject.cs | 2 +- src/Domain/Events/TodoItemCompletedEvent.cs | 11 ++-- src/Domain/Events/TodoItemCreatedEvent.cs | 11 ++-- src/Domain/Events/TodoItemDeletedEvent.cs | 11 ++-- .../Exceptions/UnsupportedColourException.cs | 9 +--- src/Domain/ValueObjects/Colour.cs | 2 +- .../Data/ApplicationDbContext.cs | 6 +-- ....cs => ApplicationDbContextInitializer.cs} | 54 ++++++++----------- .../AuditableEntityInterceptor.cs | 21 +++----- .../DispatchDomainEventsInterceptor.cs | 13 ++--- src/Infrastructure/DependencyInjection.cs | 5 +- .../Identity/IdentityService.cs | 38 +++++-------- src/Infrastructure/Stripe/StripeService.cs | 22 ++++---- src/Web/DependencyInjection.cs | 3 +- src/Web/Endpoints/JoinUs.cs | 4 +- src/Web/Endpoints/Stripe.cs | 2 +- src/Web/Endpoints/TodoItems.cs | 10 ++-- src/Web/Endpoints/TodoLists.cs | 10 ++-- src/Web/Endpoints/WeatherForecasts.cs | 2 +- .../Infrastructure/CustomExceptionHandler.cs | 22 ++++---- .../Infrastructure/MethodInfoExtensions.cs | 4 +- src/Web/Program.cs | 5 +- src/Web/Services/CurrentUser.cs | 13 ++--- 50 files changed, 267 insertions(+), 449 deletions(-) rename src/Infrastructure/Data/{ApplicationDbContextInitialiser.cs => ApplicationDbContextInitializer.cs} (50%) diff --git a/src/Application/Common/Behaviours/AuthorizationBehaviour.cs b/src/Application/Common/Behaviours/AuthorizationBehaviour.cs index 2b0378f..30de73f 100644 --- a/src/Application/Common/Behaviours/AuthorizationBehaviour.cs +++ b/src/Application/Common/Behaviours/AuthorizationBehaviour.cs @@ -5,19 +5,12 @@ using Hutopy.Application.Common.Security; namespace Hutopy.Application.Common.Behaviours; -public class AuthorizationBehaviour : IPipelineBehavior where TRequest : notnull +public class AuthorizationBehaviour( + IUser user, + IIdentityService identityService) + : IPipelineBehavior + where TRequest : notnull { - private readonly IUser _user; - private readonly IIdentityService _identityService; - - public AuthorizationBehaviour( - IUser user, - IIdentityService identityService) - { - _user = user; - _identityService = identityService; - } - public async Task Handle(TRequest request, RequestHandlerDelegate next, CancellationToken cancellationToken) { var authorizeAttributes = request.GetType().GetCustomAttributes(); @@ -25,7 +18,7 @@ public class AuthorizationBehaviour : IPipelineBehavior : IPipelineBehavior : IPipelineBehavior a.Policy)) { - var authorized = await _identityService.AuthorizeAsync(_user.Id, policy); + var authorized = await identityService.AuthorizeAsync(user.Id, policy); if (!authorized) { diff --git a/src/Application/Common/Behaviours/LoggingBehaviour.cs b/src/Application/Common/Behaviours/LoggingBehaviour.cs index 70812ca..07814ca 100644 --- a/src/Application/Common/Behaviours/LoggingBehaviour.cs +++ b/src/Application/Common/Behaviours/LoggingBehaviour.cs @@ -4,28 +4,24 @@ using Microsoft.Extensions.Logging; namespace Hutopy.Application.Common.Behaviours; -public class LoggingBehaviour : IRequestPreProcessor where TRequest : notnull +public class LoggingBehaviour( + ILogger logger, + IUser user, + IIdentityService identityService) + : IRequestPreProcessor + where TRequest : notnull { - private readonly ILogger _logger; - private readonly IUser _user; - private readonly IIdentityService _identityService; - - public LoggingBehaviour(ILogger logger, IUser user, IIdentityService identityService) - { - _logger = logger; - _user = user; - _identityService = identityService; - } + private readonly ILogger _logger = logger; public async Task Process(TRequest request, CancellationToken cancellationToken) { var requestName = typeof(TRequest).Name; - var userId = _user.Id ?? string.Empty; + var userId = user.Id ?? string.Empty; string? userName = string.Empty; if (!string.IsNullOrEmpty(userId)) { - userName = await _identityService.GetUserNameAsync(userId); + userName = await identityService.GetUserNameAsync(userId); } _logger.LogInformation("Hutopy Request: {Name} {@UserId} {@UserName} {@Request}", diff --git a/src/Application/Common/Behaviours/PerformanceBehaviour.cs b/src/Application/Common/Behaviours/PerformanceBehaviour.cs index 64e9b55..ada438a 100644 --- a/src/Application/Common/Behaviours/PerformanceBehaviour.cs +++ b/src/Application/Common/Behaviours/PerformanceBehaviour.cs @@ -4,24 +4,14 @@ using Microsoft.Extensions.Logging; namespace Hutopy.Application.Common.Behaviours; -public class PerformanceBehaviour : IPipelineBehavior where TRequest : notnull +public class PerformanceBehaviour( + ILogger logger, + IUser user, + IIdentityService identityService) + : IPipelineBehavior + where TRequest : notnull { - private readonly Stopwatch _timer; - private readonly ILogger _logger; - private readonly IUser _user; - private readonly IIdentityService _identityService; - - public PerformanceBehaviour( - ILogger logger, - IUser user, - IIdentityService identityService) - { - _timer = new Stopwatch(); - - _logger = logger; - _user = user; - _identityService = identityService; - } + private readonly Stopwatch _timer = new(); public async Task Handle(TRequest request, RequestHandlerDelegate next, CancellationToken cancellationToken) { @@ -33,20 +23,16 @@ public class PerformanceBehaviour : IPipelineBehavior 500) - { - var requestName = typeof(TRequest).Name; - var userId = _user.Id ?? string.Empty; - var userName = string.Empty; + if (elapsedMilliseconds <= 500) return response; - if (!string.IsNullOrEmpty(userId)) - { - userName = await _identityService.GetUserNameAsync(userId); - } + var requestName = typeof(TRequest).Name; + var userId = user.Id ?? string.Empty; + var userName = string.Empty; - _logger.LogWarning("Hutopy Long Running Request: {Name} ({ElapsedMilliseconds} milliseconds) {@UserId} {@UserName} {@Request}", - requestName, elapsedMilliseconds, userId, userName, request); - } + if (!string.IsNullOrEmpty(userId)) userName = await identityService.GetUserNameAsync(userId); + + logger.LogWarning("Hutopy Long Running Request: {Name} ({ElapsedMilliseconds} milliseconds) {@UserId} {@UserName} {@Request}", + requestName, elapsedMilliseconds, userId, userName, request); return response; } diff --git a/src/Application/Common/Behaviours/UnhandledExceptionBehaviour.cs b/src/Application/Common/Behaviours/UnhandledExceptionBehaviour.cs index a79558a..28d2a94 100644 --- a/src/Application/Common/Behaviours/UnhandledExceptionBehaviour.cs +++ b/src/Application/Common/Behaviours/UnhandledExceptionBehaviour.cs @@ -2,15 +2,11 @@ namespace Hutopy.Application.Common.Behaviours; -public class UnhandledExceptionBehaviour : IPipelineBehavior where TRequest : notnull +public class UnhandledExceptionBehaviour( + ILogger logger) + : IPipelineBehavior + where TRequest : notnull { - private readonly ILogger _logger; - - public UnhandledExceptionBehaviour(ILogger logger) - { - _logger = logger; - } - public async Task Handle(TRequest request, RequestHandlerDelegate next, CancellationToken cancellationToken) { try @@ -21,7 +17,7 @@ public class UnhandledExceptionBehaviour : IPipelineBehavio { var requestName = typeof(TRequest).Name; - _logger.LogError(ex, "Hutopy Request: Unhandled Exception for Request {Name} {@Request}", requestName, request); + logger.LogError(ex, "Hutopy Request: Unhandled Exception for Request {Name} {@Request}", requestName, request); throw; } diff --git a/src/Application/Common/Behaviours/ValidationBehaviour.cs b/src/Application/Common/Behaviours/ValidationBehaviour.cs index 262fce7..a564099 100644 --- a/src/Application/Common/Behaviours/ValidationBehaviour.cs +++ b/src/Application/Common/Behaviours/ValidationBehaviour.cs @@ -2,34 +2,27 @@ namespace Hutopy.Application.Common.Behaviours; -public class ValidationBehaviour : IPipelineBehavior - where TRequest : notnull +public class ValidationBehaviour(IEnumerable> validators) + : IPipelineBehavior + where TRequest : notnull { - private readonly IEnumerable> _validators; - - public ValidationBehaviour(IEnumerable> validators) - { - _validators = validators; - } - public async Task Handle(TRequest request, RequestHandlerDelegate next, CancellationToken cancellationToken) { - if (_validators.Any()) - { - var context = new ValidationContext(request); + if (!validators.Any()) return await next(); - var validationResults = await Task.WhenAll( - _validators.Select(v => - v.ValidateAsync(context, cancellationToken))); + var context = new ValidationContext(request); - var failures = validationResults - .Where(r => r.Errors.Any()) - .SelectMany(r => r.Errors) - .ToList(); + var validationResults = await Task.WhenAll( + validators.Select(v => + v.ValidateAsync(context, cancellationToken))); - if (failures.Any()) - throw new ValidationException(failures); - } + var failures = validationResults + .Where(r => r.Errors.Any()) + .SelectMany(r => r.Errors) + .ToList(); + + if (failures.Count != 0) throw new ValidationException(failures); + return await next(); } } diff --git a/src/Application/Common/Exceptions/ValidationException.cs b/src/Application/Common/Exceptions/ValidationException.cs index 1570fbc..f167275 100644 --- a/src/Application/Common/Exceptions/ValidationException.cs +++ b/src/Application/Common/Exceptions/ValidationException.cs @@ -2,14 +2,9 @@ namespace Hutopy.Application.Common.Exceptions; -public class ValidationException : Exception +public class ValidationException() + : Exception("One or more validation failures have occurred.") { - public ValidationException() - : base("One or more validation failures have occurred.") - { - Errors = new Dictionary(); - } - public ValidationException(IEnumerable failures) : this() { @@ -18,5 +13,5 @@ public class ValidationException : Exception .ToDictionary(failureGroup => failureGroup.Key, failureGroup => failureGroup.ToArray()); } - public IDictionary Errors { get; } + public IDictionary Errors { get; } = new Dictionary(); } diff --git a/src/Application/Common/Models/PaginatedList.cs b/src/Application/Common/Models/PaginatedList.cs index 53636fa..e0a4e59 100644 --- a/src/Application/Common/Models/PaginatedList.cs +++ b/src/Application/Common/Models/PaginatedList.cs @@ -1,19 +1,15 @@ namespace Hutopy.Application.Common.Models; -public class PaginatedList +public class PaginatedList( + IReadOnlyCollection items, + int count, + int pageNumber, + int pageSize) { - public IReadOnlyCollection Items { get; } - public int PageNumber { get; } - public int TotalPages { get; } - public int TotalCount { get; } - - public PaginatedList(IReadOnlyCollection items, int count, int pageNumber, int pageSize) - { - PageNumber = pageNumber; - TotalPages = (int)Math.Ceiling(count / (double)pageSize); - TotalCount = count; - Items = items; - } + public IReadOnlyCollection Items { get; } = items; + public int PageNumber { get; } = pageNumber; + public int TotalPages { get; } = (int)Math.Ceiling(count / (double)pageSize); + public int TotalCount { get; } = count; public bool HasPreviousPage => PageNumber > 1; diff --git a/src/Application/Common/Models/Result.cs b/src/Application/Common/Models/Result.cs index f052240..f99bb27 100644 --- a/src/Application/Common/Models/Result.cs +++ b/src/Application/Common/Models/Result.cs @@ -1,16 +1,12 @@ namespace Hutopy.Application.Common.Models; -public class Result +public class Result( + bool succeeded, + IEnumerable errors) { - internal Result(bool succeeded, IEnumerable errors) - { - Succeeded = succeeded; - Errors = errors.ToArray(); - } + public bool Succeeded { get; init; } = succeeded; - public bool Succeeded { get; init; } - - public string[] Errors { get; init; } + public string[] Errors { get; init; } = errors.ToArray(); public static Result Success() { diff --git a/src/Application/Common/Security/AuthorizeAttribute.cs b/src/Application/Common/Security/AuthorizeAttribute.cs index 6a8a965..ad2e1e1 100644 --- a/src/Application/Common/Security/AuthorizeAttribute.cs +++ b/src/Application/Common/Security/AuthorizeAttribute.cs @@ -3,7 +3,7 @@ /// /// Specifies the class this attribute is applied to requires authorization. /// -[AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)] +[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] public class AuthorizeAttribute : Attribute { /// diff --git a/src/Application/DependencyInjection.cs b/src/Application/DependencyInjection.cs index 3ff3e1e..d65e206 100644 --- a/src/Application/DependencyInjection.cs +++ b/src/Application/DependencyInjection.cs @@ -1,6 +1,7 @@ using System.Reflection; +using Microsoft.Extensions.DependencyInjection; -namespace Microsoft.Extensions.DependencyInjection; +namespace Hutopy.Application; public static class DependencyInjection { diff --git a/src/Application/FutureCreators/Commands/CreateFutureCreator.cs b/src/Application/FutureCreators/Commands/CreateFutureCreator.cs index 54f4e70..d1f412e 100644 --- a/src/Application/FutureCreators/Commands/CreateFutureCreator.cs +++ b/src/Application/FutureCreators/Commands/CreateFutureCreator.cs @@ -3,7 +3,7 @@ using Hutopy.Domain.Entities; namespace Hutopy.Application.FutureCreators.Commands; -public record CreateFutureCreatorCommand : IRequest +public abstract record CreateFutureCreatorCommand : IRequest { public required string FirstName { get; init; } public required string LastName { get; init; } @@ -13,16 +13,10 @@ public record CreateFutureCreatorCommand : IRequest public required string ReasonToJoin { get; init; } } -public class CreateFuturCreatorCommandHandler : IRequestHandler +public class CreateFutureCreatorCommandHandler( + IApplicationDbContext context) + : IRequestHandler { - private readonly IApplicationDbContext _context; - - - public CreateFuturCreatorCommandHandler(IApplicationDbContext context) - { - _context = context; - } - public async Task Handle(CreateFutureCreatorCommand request, CancellationToken cancellationToken) { var entity = new FutureCreator @@ -35,9 +29,9 @@ public class CreateFuturCreatorCommandHandler : IRequestHandler +public abstract record CreateSessionCheckoutCommand : IRequest { public required int Price { get; init; } @@ -10,21 +10,16 @@ public record CreateSessionCheckoutCommand : IRequest } -public class CreateSessionCheckoutCommandHandler : IRequestHandler +public class CreateSessionCheckoutCommandHandler( + IApplicationDbContext context, + IStripeService stripeService) + : IRequestHandler { - private readonly IApplicationDbContext _context; - private readonly IStripeService _stripeService; - - - public CreateSessionCheckoutCommandHandler(IApplicationDbContext context, IStripeService stripeService) - { - _context = context; - _stripeService = stripeService; - } - + private readonly IApplicationDbContext _context = context; + public async Task Handle(CreateSessionCheckoutCommand request, CancellationToken cancellationToken) { - var stripeSecret = await _stripeService.CreateCheckoutSession(request.Price, request.Currency); + var stripeSecret = await stripeService.CreateCheckoutSession(request.Price, request.Currency); return stripeSecret; } diff --git a/src/Application/TodoItems/Commands/CreateTodoItem/CreateTodoItem.cs b/src/Application/TodoItems/Commands/CreateTodoItem/CreateTodoItem.cs index a560109..c4a448a 100644 --- a/src/Application/TodoItems/Commands/CreateTodoItem/CreateTodoItem.cs +++ b/src/Application/TodoItems/Commands/CreateTodoItem/CreateTodoItem.cs @@ -11,15 +11,10 @@ public record CreateTodoItemCommand : IRequest public string? Title { get; init; } } -public class CreateTodoItemCommandHandler : IRequestHandler +public class CreateTodoItemCommandHandler( + IApplicationDbContext context) + : IRequestHandler { - private readonly IApplicationDbContext _context; - - public CreateTodoItemCommandHandler(IApplicationDbContext context) - { - _context = context; - } - public async Task Handle(CreateTodoItemCommand request, CancellationToken cancellationToken) { var entity = new TodoItem @@ -31,9 +26,9 @@ public class CreateTodoItemCommandHandler : IRequestHandler +public class DeleteTodoItemCommandHandler( + IApplicationDbContext context) + : IRequestHandler { - private readonly IApplicationDbContext _context; - - public DeleteTodoItemCommandHandler(IApplicationDbContext context) - { - _context = context; - } - public async Task Handle(DeleteTodoItemCommand request, CancellationToken cancellationToken) { - var entity = await _context.TodoItems + var entity = await context.TodoItems .FindAsync(new object[] { request.Id }, cancellationToken); Guard.Against.NotFound(request.Id, entity); - _context.TodoItems.Remove(entity); + context.TodoItems.Remove(entity); entity.AddDomainEvent(new TodoItemDeletedEvent(entity)); - await _context.SaveChangesAsync(cancellationToken); + await context.SaveChangesAsync(cancellationToken); } } diff --git a/src/Application/TodoItems/Commands/UpdateTodoItem/UpdateTodoItem.cs b/src/Application/TodoItems/Commands/UpdateTodoItem/UpdateTodoItem.cs index 9699859..68ad4e5 100644 --- a/src/Application/TodoItems/Commands/UpdateTodoItem/UpdateTodoItem.cs +++ b/src/Application/TodoItems/Commands/UpdateTodoItem/UpdateTodoItem.cs @@ -11,18 +11,13 @@ public record UpdateTodoItemCommand : IRequest public bool Done { get; init; } } -public class UpdateTodoItemCommandHandler : IRequestHandler +public class UpdateTodoItemCommandHandler( + IApplicationDbContext context) + : IRequestHandler { - private readonly IApplicationDbContext _context; - - public UpdateTodoItemCommandHandler(IApplicationDbContext context) - { - _context = context; - } - public async Task Handle(UpdateTodoItemCommand request, CancellationToken cancellationToken) { - var entity = await _context.TodoItems + var entity = await context.TodoItems .FindAsync(new object[] { request.Id }, cancellationToken); Guard.Against.NotFound(request.Id, entity); @@ -30,6 +25,6 @@ public class UpdateTodoItemCommandHandler : IRequestHandler +public class UpdateTodoItemDetailCommandHandler( + IApplicationDbContext context) + : IRequestHandler { - private readonly IApplicationDbContext _context; - - public UpdateTodoItemDetailCommandHandler(IApplicationDbContext context) - { - _context = context; - } - public async Task Handle(UpdateTodoItemDetailCommand request, CancellationToken cancellationToken) { - var entity = await _context.TodoItems + var entity = await context.TodoItems .FindAsync(new object[] { request.Id }, cancellationToken); Guard.Against.NotFound(request.Id, entity); @@ -34,6 +29,6 @@ public class UpdateTodoItemDetailCommandHandler : IRequestHandler +public class TodoItemCompletedEventHandler( + ILogger logger) + : INotificationHandler { - private readonly ILogger _logger; - - public TodoItemCompletedEventHandler(ILogger logger) - { - _logger = logger; - } - public Task Handle(TodoItemCompletedEvent notification, CancellationToken cancellationToken) { - _logger.LogInformation("Hutopy Domain Event: {DomainEvent}", notification.GetType().Name); + logger.LogInformation("Hutopy Domain Event: {DomainEvent}", notification.GetType().Name); return Task.CompletedTask; } diff --git a/src/Application/TodoItems/EventHandlers/TodoItemCreatedEventHandler.cs b/src/Application/TodoItems/EventHandlers/TodoItemCreatedEventHandler.cs index 7e20348..8aba373 100644 --- a/src/Application/TodoItems/EventHandlers/TodoItemCreatedEventHandler.cs +++ b/src/Application/TodoItems/EventHandlers/TodoItemCreatedEventHandler.cs @@ -3,18 +3,13 @@ using Microsoft.Extensions.Logging; namespace Hutopy.Application.TodoItems.EventHandlers; -public class TodoItemCreatedEventHandler : INotificationHandler +public class TodoItemCreatedEventHandler( + ILogger logger) + : INotificationHandler { - private readonly ILogger _logger; - - public TodoItemCreatedEventHandler(ILogger logger) - { - _logger = logger; - } - public Task Handle(TodoItemCreatedEvent notification, CancellationToken cancellationToken) { - _logger.LogInformation("Hutopy Domain Event: {DomainEvent}", notification.GetType().Name); + logger.LogInformation("Hutopy Domain Event: {DomainEvent}", notification.GetType().Name); return Task.CompletedTask; } diff --git a/src/Application/TodoItems/Queries/GetTodoItemsWithPagination/GetTodoItemsWithPagination.cs b/src/Application/TodoItems/Queries/GetTodoItemsWithPagination/GetTodoItemsWithPagination.cs index a34f162..b0ece59 100644 --- a/src/Application/TodoItems/Queries/GetTodoItemsWithPagination/GetTodoItemsWithPagination.cs +++ b/src/Application/TodoItems/Queries/GetTodoItemsWithPagination/GetTodoItemsWithPagination.cs @@ -4,31 +4,25 @@ using Hutopy.Application.Common.Models; namespace Hutopy.Application.TodoItems.Queries.GetTodoItemsWithPagination; -public record GetTodoItemsWithPaginationQuery : IRequest> +public abstract record GetTodoItemsWithPaginationQuery : IRequest> { public int ListId { get; init; } public int PageNumber { get; init; } = 1; public int PageSize { get; init; } = 10; } -public class GetTodoItemsWithPaginationQueryHandler : IRequestHandler> +public class GetTodoItemsWithPaginationQueryHandler( + IApplicationDbContext context, + IMapper mapper) + : IRequestHandler> { - private readonly IApplicationDbContext _context; - private readonly IMapper _mapper; - - public GetTodoItemsWithPaginationQueryHandler(IApplicationDbContext context, IMapper mapper) - { - _context = context; - _mapper = mapper; - } - public async Task> Handle(GetTodoItemsWithPaginationQuery request, CancellationToken cancellationToken) { Console.WriteLine(request); - return await _context.TodoItems + return await context.TodoItems .Where(x => x.ListId == request.ListId) .OrderBy(x => x.Title) - .ProjectTo(_mapper.ConfigurationProvider) + .ProjectTo(mapper.ConfigurationProvider) .PaginatedListAsync(request.PageNumber, request.PageSize); } } diff --git a/src/Application/TodoLists/Commands/CreateTodoList/CreateTodoList.cs b/src/Application/TodoLists/Commands/CreateTodoList/CreateTodoList.cs index c557f94..cf95696 100644 --- a/src/Application/TodoLists/Commands/CreateTodoList/CreateTodoList.cs +++ b/src/Application/TodoLists/Commands/CreateTodoList/CreateTodoList.cs @@ -8,24 +8,17 @@ public record CreateTodoListCommand : IRequest public string? Title { get; init; } } -public class CreateTodoListCommandHandler : IRequestHandler +public class CreateTodoListCommandHandler( + IApplicationDbContext context) + : IRequestHandler { - private readonly IApplicationDbContext _context; - - public CreateTodoListCommandHandler(IApplicationDbContext context) - { - _context = context; - } - public async Task Handle(CreateTodoListCommand request, CancellationToken cancellationToken) { - var entity = new TodoList(); + var entity = new TodoList { Title = request.Title }; - entity.Title = request.Title; + context.TodoLists.Add(entity); - _context.TodoLists.Add(entity); - - await _context.SaveChangesAsync(cancellationToken); + await context.SaveChangesAsync(cancellationToken); return entity.Id; } diff --git a/src/Application/TodoLists/Commands/DeleteTodoList/DeleteTodoList.cs b/src/Application/TodoLists/Commands/DeleteTodoList/DeleteTodoList.cs index a5c3634..3339e8a 100644 --- a/src/Application/TodoLists/Commands/DeleteTodoList/DeleteTodoList.cs +++ b/src/Application/TodoLists/Commands/DeleteTodoList/DeleteTodoList.cs @@ -4,25 +4,20 @@ namespace Hutopy.Application.TodoLists.Commands.DeleteTodoList; public record DeleteTodoListCommand(int Id) : IRequest; -public class DeleteTodoListCommandHandler : IRequestHandler +public class DeleteTodoListCommandHandler( + IApplicationDbContext context) + : IRequestHandler { - private readonly IApplicationDbContext _context; - - public DeleteTodoListCommandHandler(IApplicationDbContext context) - { - _context = context; - } - public async Task Handle(DeleteTodoListCommand request, CancellationToken cancellationToken) { - var entity = await _context.TodoLists + var entity = await context.TodoLists .Where(l => l.Id == request.Id) .SingleOrDefaultAsync(cancellationToken); Guard.Against.NotFound(request.Id, entity); - _context.TodoLists.Remove(entity); + context.TodoLists.Remove(entity); - await _context.SaveChangesAsync(cancellationToken); + await context.SaveChangesAsync(cancellationToken); } } diff --git a/src/Application/TodoLists/Commands/PurgeTodoLists/PurgeTodoLists.cs b/src/Application/TodoLists/Commands/PurgeTodoLists/PurgeTodoLists.cs index 9778b6a..1e75661 100644 --- a/src/Application/TodoLists/Commands/PurgeTodoLists/PurgeTodoLists.cs +++ b/src/Application/TodoLists/Commands/PurgeTodoLists/PurgeTodoLists.cs @@ -8,19 +8,14 @@ namespace Hutopy.Application.TodoLists.Commands.PurgeTodoLists; [Authorize(Policy = Policies.CanPurge)] public record PurgeTodoListsCommand : IRequest; -public class PurgeTodoListsCommandHandler : IRequestHandler +public class PurgeTodoListsCommandHandler( + IApplicationDbContext context) + : IRequestHandler { - private readonly IApplicationDbContext _context; - - public PurgeTodoListsCommandHandler(IApplicationDbContext context) - { - _context = context; - } - public async Task Handle(PurgeTodoListsCommand request, CancellationToken cancellationToken) { - _context.TodoLists.RemoveRange(_context.TodoLists); + context.TodoLists.RemoveRange(context.TodoLists); - await _context.SaveChangesAsync(cancellationToken); + await context.SaveChangesAsync(cancellationToken); } } diff --git a/src/Application/TodoLists/Commands/UpdateTodoList/UpdateTodoList.cs b/src/Application/TodoLists/Commands/UpdateTodoList/UpdateTodoList.cs index 98b44e9..8418030 100644 --- a/src/Application/TodoLists/Commands/UpdateTodoList/UpdateTodoList.cs +++ b/src/Application/TodoLists/Commands/UpdateTodoList/UpdateTodoList.cs @@ -9,25 +9,20 @@ public record UpdateTodoListCommand : IRequest public string? Title { get; init; } } -public class UpdateTodoListCommandHandler : IRequestHandler +public class UpdateTodoListCommandHandler( + IApplicationDbContext context) + : IRequestHandler { - private readonly IApplicationDbContext _context; - - public UpdateTodoListCommandHandler(IApplicationDbContext context) - { - _context = context; - } - public async Task Handle(UpdateTodoListCommand request, CancellationToken cancellationToken) { - var entity = await _context.TodoLists + var entity = await context.TodoLists .FindAsync(new object[] { request.Id }, cancellationToken); Guard.Against.NotFound(request.Id, entity); entity.Title = request.Title; - await _context.SaveChangesAsync(cancellationToken); + await context.SaveChangesAsync(cancellationToken); } } diff --git a/src/Application/TodoLists/Commands/UpdateTodoList/UpdateTodoListCommandValidator.cs b/src/Application/TodoLists/Commands/UpdateTodoList/UpdateTodoListCommandValidator.cs index 2e7ef97..ba008d6 100644 --- a/src/Application/TodoLists/Commands/UpdateTodoList/UpdateTodoListCommandValidator.cs +++ b/src/Application/TodoLists/Commands/UpdateTodoList/UpdateTodoListCommandValidator.cs @@ -18,7 +18,7 @@ public class UpdateTodoListCommandValidator : AbstractValidator BeUniqueTitle(UpdateTodoListCommand model, string title, CancellationToken cancellationToken) + private async Task BeUniqueTitle(UpdateTodoListCommand model, string title, CancellationToken cancellationToken) { return await _context.TodoLists .Where(l => l.Id != model.Id) diff --git a/src/Application/TodoLists/Queries/GetTodos/GetTodos.cs b/src/Application/TodoLists/Queries/GetTodos/GetTodos.cs index cb44450..9d4d32f 100644 --- a/src/Application/TodoLists/Queries/GetTodos/GetTodos.cs +++ b/src/Application/TodoLists/Queries/GetTodos/GetTodos.cs @@ -8,17 +8,11 @@ namespace Hutopy.Application.TodoLists.Queries.GetTodos; [Authorize] public record GetTodosQuery : IRequest; -public class GetTodosQueryHandler : IRequestHandler +public class GetTodosQueryHandler( + IApplicationDbContext context, + IMapper mapper) + : IRequestHandler { - private readonly IApplicationDbContext _context; - private readonly IMapper _mapper; - - public GetTodosQueryHandler(IApplicationDbContext context, IMapper mapper) - { - _context = context; - _mapper = mapper; - } - public async Task Handle(GetTodosQuery request, CancellationToken cancellationToken) { return new TodosVm @@ -28,9 +22,9 @@ public class GetTodosQueryHandler : IRequestHandler .Select(p => new LookupDto { Id = (int)p, Title = p.ToString() }) .ToList(), - Lists = await _context.TodoLists + Lists = await context.TodoLists .AsNoTracking() - .ProjectTo(_mapper.ConfigurationProvider) + .ProjectTo(mapper.ConfigurationProvider) .OrderBy(t => t.Title) .ToListAsync(cancellationToken) }; diff --git a/src/Application/TodoLists/Queries/GetTodos/TodoListDto.cs b/src/Application/TodoLists/Queries/GetTodos/TodoListDto.cs index 6236f9a..c0a84dc 100644 --- a/src/Application/TodoLists/Queries/GetTodos/TodoListDto.cs +++ b/src/Application/TodoLists/Queries/GetTodos/TodoListDto.cs @@ -4,18 +4,13 @@ namespace Hutopy.Application.TodoLists.Queries.GetTodos; public class TodoListDto { - public TodoListDto() - { - Items = Array.Empty(); - } - public int Id { get; init; } public string? Title { get; init; } public string? Colour { get; init; } - public IReadOnlyCollection Items { get; init; } + public IReadOnlyCollection Items { get; init; } = Array.Empty(); private class Mapping : Profile { diff --git a/src/Domain/Common/BaseEntity.cs b/src/Domain/Common/BaseEntity.cs index 2ecc1fe..388a3ce 100644 --- a/src/Domain/Common/BaseEntity.cs +++ b/src/Domain/Common/BaseEntity.cs @@ -8,10 +8,10 @@ public abstract class BaseEntity // Using non-generic integer types for simplicity public int Id { get; set; } - private readonly List _domainEvents = new(); + private readonly List _domainEvents = []; [NotMapped] - public IReadOnlyCollection DomainEvents => _domainEvents.AsReadOnly(); + public IEnumerable DomainEvents => _domainEvents.AsReadOnly(); public void AddDomainEvent(BaseEvent domainEvent) { diff --git a/src/Domain/Common/ValueObject.cs b/src/Domain/Common/ValueObject.cs index e419f3e..6604643 100644 --- a/src/Domain/Common/ValueObject.cs +++ b/src/Domain/Common/ValueObject.cs @@ -3,7 +3,7 @@ // Learn more: https://docs.microsoft.com/en-us/dotnet/standard/microservices-architecture/microservice-ddd-cqrs-patterns/implement-value-objects public abstract class ValueObject { - protected static bool EqualOperator(ValueObject left, ValueObject right) + private static bool EqualOperator(ValueObject left, ValueObject right) { if (left is null ^ right is null) { diff --git a/src/Domain/Events/TodoItemCompletedEvent.cs b/src/Domain/Events/TodoItemCompletedEvent.cs index b44c3ea..8d7cad1 100644 --- a/src/Domain/Events/TodoItemCompletedEvent.cs +++ b/src/Domain/Events/TodoItemCompletedEvent.cs @@ -1,11 +1,8 @@ namespace Hutopy.Domain.Events; -public class TodoItemCompletedEvent : BaseEvent +public class TodoItemCompletedEvent( + TodoItem item) + : BaseEvent { - public TodoItemCompletedEvent(TodoItem item) - { - Item = item; - } - - public TodoItem Item { get; } + public TodoItem Item { get; } = item; } diff --git a/src/Domain/Events/TodoItemCreatedEvent.cs b/src/Domain/Events/TodoItemCreatedEvent.cs index 35db47f..4f87e92 100644 --- a/src/Domain/Events/TodoItemCreatedEvent.cs +++ b/src/Domain/Events/TodoItemCreatedEvent.cs @@ -1,11 +1,8 @@ namespace Hutopy.Domain.Events; -public class TodoItemCreatedEvent : BaseEvent +public class TodoItemCreatedEvent( + TodoItem item) + : BaseEvent { - public TodoItemCreatedEvent(TodoItem item) - { - Item = item; - } - - public TodoItem Item { get; } + public TodoItem Item { get; } = item; } diff --git a/src/Domain/Events/TodoItemDeletedEvent.cs b/src/Domain/Events/TodoItemDeletedEvent.cs index d65711d..1340b00 100644 --- a/src/Domain/Events/TodoItemDeletedEvent.cs +++ b/src/Domain/Events/TodoItemDeletedEvent.cs @@ -1,11 +1,8 @@ namespace Hutopy.Domain.Events; -public class TodoItemDeletedEvent : BaseEvent +public class TodoItemDeletedEvent( + TodoItem item) + : BaseEvent { - public TodoItemDeletedEvent(TodoItem item) - { - Item = item; - } - - public TodoItem Item { get; } + public TodoItem Item { get; } = item; } diff --git a/src/Domain/Exceptions/UnsupportedColourException.cs b/src/Domain/Exceptions/UnsupportedColourException.cs index 3946c28..676bbc7 100644 --- a/src/Domain/Exceptions/UnsupportedColourException.cs +++ b/src/Domain/Exceptions/UnsupportedColourException.cs @@ -1,9 +1,4 @@ namespace Hutopy.Domain.Exceptions; -public class UnsupportedColourException : Exception -{ - public UnsupportedColourException(string code) - : base($"Colour \"{code}\" is unsupported.") - { - } -} +public class UnsupportedColourException( + string code) : Exception($"Colour \"{code}\" is unsupported."); diff --git a/src/Domain/ValueObjects/Colour.cs b/src/Domain/ValueObjects/Colour.cs index cf3d5ab..7bd2590 100644 --- a/src/Domain/ValueObjects/Colour.cs +++ b/src/Domain/ValueObjects/Colour.cs @@ -47,7 +47,7 @@ public class Colour(string code) : ValueObject return Code; } - protected static IEnumerable SupportedColours + private static IEnumerable SupportedColours { get { diff --git a/src/Infrastructure/Data/ApplicationDbContext.cs b/src/Infrastructure/Data/ApplicationDbContext.cs index 1a41916..e565b11 100644 --- a/src/Infrastructure/Data/ApplicationDbContext.cs +++ b/src/Infrastructure/Data/ApplicationDbContext.cs @@ -7,10 +7,10 @@ using Microsoft.EntityFrameworkCore; namespace Hutopy.Infrastructure.Data; -public class ApplicationDbContext : IdentityDbContext, IApplicationDbContext +public class ApplicationDbContext( + DbContextOptions options) + : IdentityDbContext(options), IApplicationDbContext { - public ApplicationDbContext(DbContextOptions options) : base(options) { } - public DbSet TodoLists => Set(); public DbSet TodoItems => Set(); diff --git a/src/Infrastructure/Data/ApplicationDbContextInitialiser.cs b/src/Infrastructure/Data/ApplicationDbContextInitializer.cs similarity index 50% rename from src/Infrastructure/Data/ApplicationDbContextInitialiser.cs rename to src/Infrastructure/Data/ApplicationDbContextInitializer.cs index eb7b336..b595c1e 100644 --- a/src/Infrastructure/Data/ApplicationDbContextInitialiser.cs +++ b/src/Infrastructure/Data/ApplicationDbContextInitializer.cs @@ -1,5 +1,4 @@ -using System.Runtime.InteropServices; -using Hutopy.Domain.Constants; +using Hutopy.Domain.Constants; using Hutopy.Domain.Entities; using Hutopy.Infrastructure.Identity; using Microsoft.AspNetCore.Builder; @@ -10,44 +9,35 @@ using Microsoft.Extensions.Logging; namespace Hutopy.Infrastructure.Data; -public static class InitialiserExtensions +public static class InitializerExtensions { public static async Task InitialiseDatabaseAsync(this WebApplication app) { using var scope = app.Services.CreateScope(); - var initialiser = scope.ServiceProvider.GetRequiredService(); + var initializer = scope.ServiceProvider.GetRequiredService(); - await initialiser.InitialiseAsync(); + await initializer.InitialiseAsync(); - await initialiser.SeedAsync(); + await initializer.SeedAsync(); } } -public class ApplicationDbContextInitialiser +public class ApplicationDbContextInitializer( + ILogger logger, + ApplicationDbContext context, + UserManager userManager, + RoleManager roleManager) { - private readonly ILogger _logger; - private readonly ApplicationDbContext _context; - private readonly UserManager _userManager; - private readonly RoleManager _roleManager; - - public ApplicationDbContextInitialiser(ILogger logger, ApplicationDbContext context, UserManager userManager, RoleManager roleManager) - { - _logger = logger; - _context = context; - _userManager = userManager; - _roleManager = roleManager; - } - public async Task InitialiseAsync() { try { - await _context.Database.MigrateAsync(); + await context.Database.MigrateAsync(); } catch (Exception ex) { - _logger.LogError(ex, "An error occurred while initialising the database."); + logger.LogError(ex, "An error occurred while initialising the database."); throw; } } @@ -60,38 +50,38 @@ public class ApplicationDbContextInitialiser } catch (Exception ex) { - _logger.LogError(ex, "An error occurred while seeding the database."); + logger.LogError(ex, "An error occurred while seeding the database."); throw; } } - public async Task TrySeedAsync() + private async Task TrySeedAsync() { // Default roles var administratorRole = new IdentityRole(Roles.Administrator); - if (_roleManager.Roles.All(r => r.Name != administratorRole.Name)) + if (roleManager.Roles.All(r => r.Name != administratorRole.Name)) { - await _roleManager.CreateAsync(administratorRole); + await roleManager.CreateAsync(administratorRole); } // Default users var administrator = new ApplicationUser { UserName = "administrator@localhost", Email = "administrator@localhost" }; - if (_userManager.Users.All(u => u.UserName != administrator.UserName)) + if (userManager.Users.All(u => u.UserName != administrator.UserName)) { - await _userManager.CreateAsync(administrator, "Administrator1!"); + await userManager.CreateAsync(administrator, "Administrator1!"); if (!string.IsNullOrWhiteSpace(administratorRole.Name)) { - await _userManager.AddToRolesAsync(administrator, new [] { administratorRole.Name }); + await userManager.AddToRolesAsync(administrator, new [] { administratorRole.Name }); } } // Default data // Seed, if necessary - if (!_context.TodoLists.Any()) + if (!context.TodoLists.Any()) { - _context.TodoLists.Add(new TodoList + context.TodoLists.Add(new TodoList { Title = "Todo List", Items = @@ -103,7 +93,7 @@ public class ApplicationDbContextInitialiser } }); - await _context.SaveChangesAsync(); + await context.SaveChangesAsync(); } } } diff --git a/src/Infrastructure/Data/Interceptors/AuditableEntityInterceptor.cs b/src/Infrastructure/Data/Interceptors/AuditableEntityInterceptor.cs index 9d4b202..f38d7b5 100644 --- a/src/Infrastructure/Data/Interceptors/AuditableEntityInterceptor.cs +++ b/src/Infrastructure/Data/Interceptors/AuditableEntityInterceptor.cs @@ -6,19 +6,10 @@ using Microsoft.EntityFrameworkCore.Diagnostics; namespace Hutopy.Infrastructure.Data.Interceptors; -public class AuditableEntityInterceptor : SaveChangesInterceptor +public class AuditableEntityInterceptor( + IUser user, + TimeProvider dateTime) : SaveChangesInterceptor { - private readonly IUser _user; - private readonly TimeProvider _dateTime; - - public AuditableEntityInterceptor( - IUser user, - TimeProvider dateTime) - { - _user = user; - _dateTime = dateTime; - } - public override InterceptionResult SavingChanges(DbContextEventData eventData, InterceptionResult result) { UpdateEntities(eventData.Context); @@ -41,13 +32,13 @@ public class AuditableEntityInterceptor : SaveChangesInterceptor { if (entry.State is EntityState.Added or EntityState.Modified || entry.HasChangedOwnedEntities()) { - var utcNow = _dateTime.GetUtcNow(); + var utcNow = dateTime.GetUtcNow(); if (entry.State == EntityState.Added) { - entry.Entity.CreatedBy = _user.Id; + entry.Entity.CreatedBy = user.Id; entry.Entity.Created = utcNow; } - entry.Entity.LastModifiedBy = _user.Id; + entry.Entity.LastModifiedBy = user.Id; entry.Entity.LastModified = utcNow; } } diff --git a/src/Infrastructure/Data/Interceptors/DispatchDomainEventsInterceptor.cs b/src/Infrastructure/Data/Interceptors/DispatchDomainEventsInterceptor.cs index 3664dd3..3123ee7 100644 --- a/src/Infrastructure/Data/Interceptors/DispatchDomainEventsInterceptor.cs +++ b/src/Infrastructure/Data/Interceptors/DispatchDomainEventsInterceptor.cs @@ -5,15 +5,10 @@ using Microsoft.EntityFrameworkCore.Diagnostics; namespace Hutopy.Infrastructure.Data.Interceptors; -public class DispatchDomainEventsInterceptor : SaveChangesInterceptor +public class DispatchDomainEventsInterceptor( + IPublisher mediator) + : SaveChangesInterceptor { - private readonly IMediator _mediator; - - public DispatchDomainEventsInterceptor(IMediator mediator) - { - _mediator = mediator; - } - public override InterceptionResult SavingChanges(DbContextEventData eventData, InterceptionResult result) { DispatchDomainEvents(eventData.Context).GetAwaiter().GetResult(); @@ -45,6 +40,6 @@ public class DispatchDomainEventsInterceptor : SaveChangesInterceptor entities.ToList().ForEach(e => e.ClearDomainEvents()); foreach (var domainEvent in domainEvents) - await _mediator.Publish(domainEvent); + await mediator.Publish(domainEvent); } } diff --git a/src/Infrastructure/DependencyInjection.cs b/src/Infrastructure/DependencyInjection.cs index 7481df3..0651486 100644 --- a/src/Infrastructure/DependencyInjection.cs +++ b/src/Infrastructure/DependencyInjection.cs @@ -8,8 +8,9 @@ using Microsoft.AspNetCore.Identity; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; -namespace Microsoft.Extensions.DependencyInjection; +namespace Hutopy.Infrastructure; public static class DependencyInjection { @@ -34,7 +35,7 @@ public static class DependencyInjection services.AddScoped(provider => provider.GetRequiredService()); - services.AddScoped(); + services.AddScoped(); services.AddAuthentication() .AddBearerToken(IdentityConstants.BearerScheme); diff --git a/src/Infrastructure/Identity/IdentityService.cs b/src/Infrastructure/Identity/IdentityService.cs index 015100b..71a3886 100644 --- a/src/Infrastructure/Identity/IdentityService.cs +++ b/src/Infrastructure/Identity/IdentityService.cs @@ -5,25 +5,15 @@ using Microsoft.AspNetCore.Identity; namespace Hutopy.Infrastructure.Identity; -public class IdentityService : IIdentityService +public class IdentityService( + UserManager userManager, + IUserClaimsPrincipalFactory userClaimsPrincipalFactory, + IAuthorizationService authorizationService) + : IIdentityService { - private readonly UserManager _userManager; - private readonly IUserClaimsPrincipalFactory _userClaimsPrincipalFactory; - private readonly IAuthorizationService _authorizationService; - - public IdentityService( - UserManager userManager, - IUserClaimsPrincipalFactory userClaimsPrincipalFactory, - IAuthorizationService authorizationService) - { - _userManager = userManager; - _userClaimsPrincipalFactory = userClaimsPrincipalFactory; - _authorizationService = authorizationService; - } - public async Task GetUserNameAsync(string userId) { - var user = await _userManager.FindByIdAsync(userId); + var user = await userManager.FindByIdAsync(userId); return user?.UserName; } @@ -36,44 +26,44 @@ public class IdentityService : IIdentityService Email = userName, }; - var result = await _userManager.CreateAsync(user, password); + var result = await userManager.CreateAsync(user, password); return (result.ToApplicationResult(), user.Id); } public async Task IsInRoleAsync(string userId, string role) { - var user = await _userManager.FindByIdAsync(userId); + var user = await userManager.FindByIdAsync(userId); - return user != null && await _userManager.IsInRoleAsync(user, role); + return user != null && await userManager.IsInRoleAsync(user, role); } public async Task AuthorizeAsync(string userId, string policyName) { - var user = await _userManager.FindByIdAsync(userId); + var user = await userManager.FindByIdAsync(userId); if (user == null) { return false; } - var principal = await _userClaimsPrincipalFactory.CreateAsync(user); + var principal = await userClaimsPrincipalFactory.CreateAsync(user); - var result = await _authorizationService.AuthorizeAsync(principal, policyName); + var result = await authorizationService.AuthorizeAsync(principal, policyName); return result.Succeeded; } public async Task DeleteUserAsync(string userId) { - var user = await _userManager.FindByIdAsync(userId); + var user = await userManager.FindByIdAsync(userId); return user != null ? await DeleteUserAsync(user) : Result.Success(); } public async Task DeleteUserAsync(ApplicationUser user) { - var result = await _userManager.DeleteAsync(user); + var result = await userManager.DeleteAsync(user); return result.ToApplicationResult(); } diff --git a/src/Infrastructure/Stripe/StripeService.cs b/src/Infrastructure/Stripe/StripeService.cs index 3cfb7ff..f54fda4 100644 --- a/src/Infrastructure/Stripe/StripeService.cs +++ b/src/Infrastructure/Stripe/StripeService.cs @@ -16,22 +16,20 @@ public class StripeService : IStripeService { var options = new SessionCreateOptions { - LineItems = new List - { + LineItems = + [ new SessionLineItemOptions { - PriceData = new SessionLineItemPriceDataOptions - { - UnitAmount = price, - Currency = currency, - ProductData = new SessionLineItemPriceDataProductDataOptions + PriceData = new SessionLineItemPriceDataOptions { - Name = "Tip", + UnitAmount = price, + Currency = currency, + ProductData = new SessionLineItemPriceDataProductDataOptions { Name = "Tip", }, }, - }, - Quantity = 1, - }, - }, + Quantity = 1, + } + + ], Mode = "payment", UiMode = "embedded", ReturnUrl = $"http://localhost:5173/creatorfolio", diff --git a/src/Web/DependencyInjection.cs b/src/Web/DependencyInjection.cs index a7dbc86..f8ede38 100644 --- a/src/Web/DependencyInjection.cs +++ b/src/Web/DependencyInjection.cs @@ -3,11 +3,10 @@ using Hutopy.Application.Common.Interfaces; using Hutopy.Infrastructure.Data; using Hutopy.Web.Services; using Microsoft.AspNetCore.Mvc; - using NSwag; using NSwag.Generation.Processors.Security; -namespace Microsoft.Extensions.DependencyInjection; +namespace Hutopy.Web; public static class DependencyInjection { diff --git a/src/Web/Endpoints/JoinUs.cs b/src/Web/Endpoints/JoinUs.cs index d49265f..9cd917b 100644 --- a/src/Web/Endpoints/JoinUs.cs +++ b/src/Web/Endpoints/JoinUs.cs @@ -9,8 +9,8 @@ public class JoinUs : EndpointGroupBase app.MapGroup(this) .MapPost(CreateFutureCreator); } - - public Task CreateFutureCreator(ISender sender, CreateFutureCreatorCommand command) + + private static Task CreateFutureCreator(ISender sender, CreateFutureCreatorCommand command) { return sender.Send(command); } diff --git a/src/Web/Endpoints/Stripe.cs b/src/Web/Endpoints/Stripe.cs index c7753b0..b5c4a6a 100644 --- a/src/Web/Endpoints/Stripe.cs +++ b/src/Web/Endpoints/Stripe.cs @@ -10,7 +10,7 @@ public class Stripe : EndpointGroupBase .MapPost(CreateSessionCheckout); } - public Task CreateSessionCheckout(ISender sender, CreateSessionCheckoutCommand command) + private static Task CreateSessionCheckout(ISender sender, CreateSessionCheckoutCommand command) { return sender.Send(command); } diff --git a/src/Web/Endpoints/TodoItems.cs b/src/Web/Endpoints/TodoItems.cs index 7cb1fa4..cc62ff8 100644 --- a/src/Web/Endpoints/TodoItems.cs +++ b/src/Web/Endpoints/TodoItems.cs @@ -20,31 +20,31 @@ public class TodoItems : EndpointGroupBase .MapDelete(DeleteTodoItem, "{id}"); } - public Task> GetTodoItemsWithPagination(ISender sender, [AsParameters] GetTodoItemsWithPaginationQuery query) + private static Task> GetTodoItemsWithPagination(ISender sender, [AsParameters] GetTodoItemsWithPaginationQuery query) { return sender.Send(query); } - public Task CreateTodoItem(ISender sender, CreateTodoItemCommand command) + private static Task CreateTodoItem(ISender sender, CreateTodoItemCommand command) { return sender.Send(command); } - public async Task UpdateTodoItem(ISender sender, int id, UpdateTodoItemCommand command) + private static async Task UpdateTodoItem(ISender sender, int id, UpdateTodoItemCommand command) { if (id != command.Id) return Results.BadRequest(); await sender.Send(command); return Results.NoContent(); } - public async Task UpdateTodoItemDetail(ISender sender, int id, UpdateTodoItemDetailCommand command) + private static async Task UpdateTodoItemDetail(ISender sender, int id, UpdateTodoItemDetailCommand command) { if (id != command.Id) return Results.BadRequest(); await sender.Send(command); return Results.NoContent(); } - public async Task DeleteTodoItem(ISender sender, int id) + private static async Task DeleteTodoItem(ISender sender, int id) { await sender.Send(new DeleteTodoItemCommand(id)); return Results.NoContent(); diff --git a/src/Web/Endpoints/TodoLists.cs b/src/Web/Endpoints/TodoLists.cs index fafd341..a191421 100644 --- a/src/Web/Endpoints/TodoLists.cs +++ b/src/Web/Endpoints/TodoLists.cs @@ -17,24 +17,24 @@ public class TodoLists : EndpointGroupBase .MapDelete(DeleteTodoList, "{id}"); } - public Task GetTodoLists(ISender sender) + private static Task GetTodoLists(ISender sender) { - return sender.Send(new GetTodosQuery()); + return sender.Send(new GetTodosQuery()); } - public Task CreateTodoList(ISender sender, CreateTodoListCommand command) + private static Task CreateTodoList(ISender sender, CreateTodoListCommand command) { return sender.Send(command); } - public async Task UpdateTodoList(ISender sender, int id, UpdateTodoListCommand command) + private static async Task UpdateTodoList(ISender sender, int id, UpdateTodoListCommand command) { if (id != command.Id) return Results.BadRequest(); await sender.Send(command); return Results.NoContent(); } - public async Task DeleteTodoList(ISender sender, int id) + private static async Task DeleteTodoList(ISender sender, int id) { await sender.Send(new DeleteTodoListCommand(id)); return Results.NoContent(); diff --git a/src/Web/Endpoints/WeatherForecasts.cs b/src/Web/Endpoints/WeatherForecasts.cs index 8eef1fd..75f26c4 100644 --- a/src/Web/Endpoints/WeatherForecasts.cs +++ b/src/Web/Endpoints/WeatherForecasts.cs @@ -11,7 +11,7 @@ public class WeatherForecasts : EndpointGroupBase .MapGet(GetWeatherForecasts); } - public async Task> GetWeatherForecasts(ISender sender) + private static async Task> GetWeatherForecasts(ISender sender) { return await sender.Send(new GetWeatherForecastsQuery()); } diff --git a/src/Web/Infrastructure/CustomExceptionHandler.cs b/src/Web/Infrastructure/CustomExceptionHandler.cs index e49063b..a94d865 100644 --- a/src/Web/Infrastructure/CustomExceptionHandler.cs +++ b/src/Web/Infrastructure/CustomExceptionHandler.cs @@ -11,8 +11,8 @@ public class CustomExceptionHandler : IExceptionHandler public CustomExceptionHandler() { // Register known exception types and handlers. - _exceptionHandlers = new() - { + _exceptionHandlers = new Dictionary> + { { typeof(ValidationException), HandleValidationException }, { typeof(NotFoundException), HandleNotFoundException }, { typeof(UnauthorizedAccessException), HandleUnauthorizedAccessException }, @@ -24,16 +24,14 @@ public class CustomExceptionHandler : IExceptionHandler { var exceptionType = exception.GetType(); - if (_exceptionHandlers.ContainsKey(exceptionType)) - { - await _exceptionHandlers[exceptionType].Invoke(httpContext, exception); - return true; - } + if (!_exceptionHandlers.TryGetValue(exceptionType, out Func? value)) return false; + + await value.Invoke(httpContext, exception); + return true; - return false; } - private async Task HandleValidationException(HttpContext httpContext, Exception ex) + private static async Task HandleValidationException(HttpContext httpContext, Exception ex) { var exception = (ValidationException)ex; @@ -46,7 +44,7 @@ public class CustomExceptionHandler : IExceptionHandler }); } - private async Task HandleNotFoundException(HttpContext httpContext, Exception ex) + private static async Task HandleNotFoundException(HttpContext httpContext, Exception ex) { var exception = (NotFoundException)ex; @@ -61,7 +59,7 @@ public class CustomExceptionHandler : IExceptionHandler }); } - private async Task HandleUnauthorizedAccessException(HttpContext httpContext, Exception ex) + private static async Task HandleUnauthorizedAccessException(HttpContext httpContext, Exception ex) { httpContext.Response.StatusCode = StatusCodes.Status401Unauthorized; @@ -73,7 +71,7 @@ public class CustomExceptionHandler : IExceptionHandler }); } - private async Task HandleForbiddenAccessException(HttpContext httpContext, Exception ex) + private static async Task HandleForbiddenAccessException(HttpContext httpContext, Exception ex) { httpContext.Response.StatusCode = StatusCodes.Status403Forbidden; diff --git a/src/Web/Infrastructure/MethodInfoExtensions.cs b/src/Web/Infrastructure/MethodInfoExtensions.cs index d526cb4..342edc4 100644 --- a/src/Web/Infrastructure/MethodInfoExtensions.cs +++ b/src/Web/Infrastructure/MethodInfoExtensions.cs @@ -4,7 +4,7 @@ namespace Hutopy.Web.Infrastructure; public static class MethodInfoExtensions { - public static bool IsAnonymous(this MethodInfo method) + private static bool IsAnonymous(this MethodInfo method) { var invalidChars = new[] { '<', '>' }; return method.Name.Any(invalidChars.Contains); @@ -15,4 +15,4 @@ public static class MethodInfoExtensions if (input.Method.IsAnonymous()) throw new ArgumentException("The endpoint name must be specified when using anonymous handlers."); } -} \ No newline at end of file +} diff --git a/src/Web/Program.cs b/src/Web/Program.cs index 89e64ee..85dbf27 100644 --- a/src/Web/Program.cs +++ b/src/Web/Program.cs @@ -1,4 +1,7 @@ +using Hutopy.Application; +using Hutopy.Infrastructure; using Hutopy.Infrastructure.Data; +using Hutopy.Web; var builder = WebApplication.CreateBuilder(args); @@ -61,4 +64,4 @@ app.MapEndpoints(); app.Run(); -public partial class Program { } +public abstract partial class Program { } diff --git a/src/Web/Services/CurrentUser.cs b/src/Web/Services/CurrentUser.cs index 45d3365..50a502a 100644 --- a/src/Web/Services/CurrentUser.cs +++ b/src/Web/Services/CurrentUser.cs @@ -4,14 +4,9 @@ using Hutopy.Application.Common.Interfaces; namespace Hutopy.Web.Services; -public class CurrentUser : IUser +public class CurrentUser( + IHttpContextAccessor httpContextAccessor) + : IUser { - private readonly IHttpContextAccessor _httpContextAccessor; - - public CurrentUser(IHttpContextAccessor httpContextAccessor) - { - _httpContextAccessor = httpContextAccessor; - } - - public string? Id => _httpContextAccessor.HttpContext?.User?.FindFirstValue(ClaimTypes.NameIdentifier); + public string? Id => httpContextAccessor.HttpContext?.User?.FindFirstValue(ClaimTypes.NameIdentifier); } From 1f795c53bbdbb821ffbb43c63ed58a587c8b6403 Mon Sep 17 00:00:00 2001 From: Dominic Villemure Date: Wed, 3 Apr 2024 23:57:01 -0400 Subject: [PATCH 016/229] Removed todos and added User endpoint combined with register. Id changed to guid --- .../Interfaces/IApplicationDbContext.cs | 6 +- src/Application/Common/Models/LookupDto.cs | 19 - .../Commands/CreateFutureCreator.cs | 6 +- .../Queries/FutureCreatorListDto.cs | 20 + .../Queries/GetFutureCreatorList.cs | 27 + .../Commands/CreateTodoItem/CreateTodoItem.cs | 35 - .../CreateTodoItemCommandValidator.cs | 11 - .../Commands/DeleteTodoItem/DeleteTodoItem.cs | 30 - .../Commands/UpdateTodoItem/UpdateTodoItem.cs | 30 - .../UpdateTodoItemCommandValidator.cs | 11 - .../UpdateTodoItemDetail.cs | 34 - .../TodoItemCompletedEventHandler.cs | 16 - .../TodoItemCreatedEventHandler.cs | 16 - .../GetTodoItemsWithPagination.cs | 28 - ...etTodoItemsWithPaginationQueryValidator.cs | 16 - .../TodoItemBriefDto.cs | 22 - .../Commands/CreateTodoList/CreateTodoList.cs | 25 - .../CreateTodoListCommandValidator.cs | 26 - .../Commands/DeleteTodoList/DeleteTodoList.cs | 23 - .../Commands/PurgeTodoLists/PurgeTodoLists.cs | 21 - .../Commands/UpdateTodoList/UpdateTodoList.cs | 28 - .../UpdateTodoListCommandValidator.cs | 27 - .../TodoLists/Queries/GetTodos/GetTodos.cs | 32 - .../TodoLists/Queries/GetTodos/TodoItemDto.cs | 27 - .../TodoLists/Queries/GetTodos/TodoListDto.cs | 22 - .../TodoLists/Queries/GetTodos/TodosVm.cs | 10 - src/Application/Users/Commands/CreateUser.cs | 39 ++ src/Domain/Common/BaseEntity.cs | 2 +- src/Domain/Entities/TodoItem.cs | 31 - src/Domain/Entities/TodoList.cs | 10 - src/Domain/Entities/User.cs | 10 + src/Domain/Events/TodoItemCompletedEvent.cs | 8 - src/Domain/Events/TodoItemCreatedEvent.cs | 8 - src/Domain/Events/TodoItemDeletedEvent.cs | 8 - src/Domain/GlobalUsings.cs | 1 - src/Domain/Interfaces/IUserService.cs | 7 + .../Data/ApplicationDbContext.cs | 6 +- .../Data/ApplicationDbContextInitializer.cs | 21 +- .../Configurations/TodoItemConfiguration.cs | 15 - .../Configurations/TodoListConfiguration.cs | 18 - .../20240404013754_AddDomainUser.Designer.cs | 492 ++++++++++++++ .../20240404013754_AddDomainUser.cs | 44 ++ ...ChangeIdsToGuidsAndRemoveTodos.Designer.cs | 372 ++++++++++ ...04023737_ChangeIdsToGuidsAndRemoveTodos.cs | 149 ++++ ...2_RemovePasswordFromDomainUser.Designer.cs | 368 ++++++++++ ...0404030232_RemovePasswordFromDomainUser.cs | 29 + .../ApplicationDbContextModelSnapshot.cs | 118 +--- src/Infrastructure/DependencyInjection.cs | 4 + src/Infrastructure/Services/UserService.cs | 24 + src/Web/DependencyInjection.cs | 4 + src/Web/Endpoints/JoinUs.cs | 12 +- src/Web/Endpoints/TodoItems.cs | 52 -- src/Web/Endpoints/TodoLists.cs | 42 -- src/Web/Endpoints/Users.cs | 11 +- src/Web/Program.cs | 3 + src/Web/wwwroot/api/specification.json | 637 +++--------------- .../TodoItems/Commands/CreateTodoItemTests.cs | 49 -- .../TodoItems/Commands/DeleteTodoItemTests.cs | 41 -- .../Commands/UpdateTodoItemDetailTests.cs | 57 -- .../TodoItems/Commands/UpdateTodoItemTests.cs | 51 -- .../TodoLists/Commands/CreateTodoListTests.cs | 54 -- .../TodoLists/Commands/DeleteTodoListTests.cs | 32 - .../TodoLists/Commands/PurgeTodoListsTests.cs | 75 --- .../TodoLists/Commands/UpdateTodoListTests.cs | 70 -- .../TodoLists/Queries/GetTodosTests.cs | 61 -- .../Common/Behaviours/RequestLoggerTests.cs | 25 - .../Common/Mappings/MappingTests.cs | 17 +- 67 files changed, 1750 insertions(+), 1895 deletions(-) delete mode 100644 src/Application/Common/Models/LookupDto.cs create mode 100644 src/Application/FutureCreators/Queries/FutureCreatorListDto.cs create mode 100644 src/Application/FutureCreators/Queries/GetFutureCreatorList.cs delete mode 100644 src/Application/TodoItems/Commands/CreateTodoItem/CreateTodoItem.cs delete mode 100644 src/Application/TodoItems/Commands/CreateTodoItem/CreateTodoItemCommandValidator.cs delete mode 100644 src/Application/TodoItems/Commands/DeleteTodoItem/DeleteTodoItem.cs delete mode 100644 src/Application/TodoItems/Commands/UpdateTodoItem/UpdateTodoItem.cs delete mode 100644 src/Application/TodoItems/Commands/UpdateTodoItem/UpdateTodoItemCommandValidator.cs delete mode 100644 src/Application/TodoItems/Commands/UpdateTodoItemDetail/UpdateTodoItemDetail.cs delete mode 100644 src/Application/TodoItems/EventHandlers/TodoItemCompletedEventHandler.cs delete mode 100644 src/Application/TodoItems/EventHandlers/TodoItemCreatedEventHandler.cs delete mode 100644 src/Application/TodoItems/Queries/GetTodoItemsWithPagination/GetTodoItemsWithPagination.cs delete mode 100644 src/Application/TodoItems/Queries/GetTodoItemsWithPagination/GetTodoItemsWithPaginationQueryValidator.cs delete mode 100644 src/Application/TodoItems/Queries/GetTodoItemsWithPagination/TodoItemBriefDto.cs delete mode 100644 src/Application/TodoLists/Commands/CreateTodoList/CreateTodoList.cs delete mode 100644 src/Application/TodoLists/Commands/CreateTodoList/CreateTodoListCommandValidator.cs delete mode 100644 src/Application/TodoLists/Commands/DeleteTodoList/DeleteTodoList.cs delete mode 100644 src/Application/TodoLists/Commands/PurgeTodoLists/PurgeTodoLists.cs delete mode 100644 src/Application/TodoLists/Commands/UpdateTodoList/UpdateTodoList.cs delete mode 100644 src/Application/TodoLists/Commands/UpdateTodoList/UpdateTodoListCommandValidator.cs delete mode 100644 src/Application/TodoLists/Queries/GetTodos/GetTodos.cs delete mode 100644 src/Application/TodoLists/Queries/GetTodos/TodoItemDto.cs delete mode 100644 src/Application/TodoLists/Queries/GetTodos/TodoListDto.cs delete mode 100644 src/Application/TodoLists/Queries/GetTodos/TodosVm.cs create mode 100644 src/Application/Users/Commands/CreateUser.cs delete mode 100644 src/Domain/Entities/TodoItem.cs delete mode 100644 src/Domain/Entities/TodoList.cs create mode 100644 src/Domain/Entities/User.cs delete mode 100644 src/Domain/Events/TodoItemCompletedEvent.cs delete mode 100644 src/Domain/Events/TodoItemCreatedEvent.cs delete mode 100644 src/Domain/Events/TodoItemDeletedEvent.cs create mode 100644 src/Domain/Interfaces/IUserService.cs delete mode 100644 src/Infrastructure/Data/Configurations/TodoItemConfiguration.cs delete mode 100644 src/Infrastructure/Data/Configurations/TodoListConfiguration.cs create mode 100644 src/Infrastructure/Data/Migrations/20240404013754_AddDomainUser.Designer.cs create mode 100644 src/Infrastructure/Data/Migrations/20240404013754_AddDomainUser.cs create mode 100644 src/Infrastructure/Data/Migrations/20240404023737_ChangeIdsToGuidsAndRemoveTodos.Designer.cs create mode 100644 src/Infrastructure/Data/Migrations/20240404023737_ChangeIdsToGuidsAndRemoveTodos.cs create mode 100644 src/Infrastructure/Data/Migrations/20240404030232_RemovePasswordFromDomainUser.Designer.cs create mode 100644 src/Infrastructure/Data/Migrations/20240404030232_RemovePasswordFromDomainUser.cs create mode 100644 src/Infrastructure/Services/UserService.cs delete mode 100644 src/Web/Endpoints/TodoItems.cs delete mode 100644 src/Web/Endpoints/TodoLists.cs delete mode 100644 tests/Application.FunctionalTests/TodoItems/Commands/CreateTodoItemTests.cs delete mode 100644 tests/Application.FunctionalTests/TodoItems/Commands/DeleteTodoItemTests.cs delete mode 100644 tests/Application.FunctionalTests/TodoItems/Commands/UpdateTodoItemDetailTests.cs delete mode 100644 tests/Application.FunctionalTests/TodoItems/Commands/UpdateTodoItemTests.cs delete mode 100644 tests/Application.FunctionalTests/TodoLists/Commands/CreateTodoListTests.cs delete mode 100644 tests/Application.FunctionalTests/TodoLists/Commands/DeleteTodoListTests.cs delete mode 100644 tests/Application.FunctionalTests/TodoLists/Commands/PurgeTodoListsTests.cs delete mode 100644 tests/Application.FunctionalTests/TodoLists/Commands/UpdateTodoListTests.cs delete mode 100644 tests/Application.FunctionalTests/TodoLists/Queries/GetTodosTests.cs diff --git a/src/Application/Common/Interfaces/IApplicationDbContext.cs b/src/Application/Common/Interfaces/IApplicationDbContext.cs index 9e35843..ef5afaa 100644 --- a/src/Application/Common/Interfaces/IApplicationDbContext.cs +++ b/src/Application/Common/Interfaces/IApplicationDbContext.cs @@ -4,11 +4,9 @@ namespace Hutopy.Application.Common.Interfaces; public interface IApplicationDbContext { - DbSet TodoLists { get; } - - DbSet TodoItems { get; } - DbSet FutureCreators { get; } + DbSet DomainUsers { get; } + Task SaveChangesAsync(CancellationToken cancellationToken); } diff --git a/src/Application/Common/Models/LookupDto.cs b/src/Application/Common/Models/LookupDto.cs deleted file mode 100644 index bde00c2..0000000 --- a/src/Application/Common/Models/LookupDto.cs +++ /dev/null @@ -1,19 +0,0 @@ -using Hutopy.Domain.Entities; - -namespace Hutopy.Application.Common.Models; - -public class LookupDto -{ - public int Id { get; init; } - - public string? Title { get; init; } - - private class Mapping : Profile - { - public Mapping() - { - CreateMap(); - CreateMap(); - } - } -} diff --git a/src/Application/FutureCreators/Commands/CreateFutureCreator.cs b/src/Application/FutureCreators/Commands/CreateFutureCreator.cs index d1f412e..7aa7f50 100644 --- a/src/Application/FutureCreators/Commands/CreateFutureCreator.cs +++ b/src/Application/FutureCreators/Commands/CreateFutureCreator.cs @@ -3,7 +3,7 @@ using Hutopy.Domain.Entities; namespace Hutopy.Application.FutureCreators.Commands; -public abstract record CreateFutureCreatorCommand : IRequest +public record CreateFutureCreatorCommand : IRequest { public required string FirstName { get; init; } public required string LastName { get; init; } @@ -15,9 +15,9 @@ public abstract record CreateFutureCreatorCommand : IRequest public class CreateFutureCreatorCommandHandler( IApplicationDbContext context) - : IRequestHandler + : IRequestHandler { - public async Task Handle(CreateFutureCreatorCommand request, CancellationToken cancellationToken) + public async Task Handle(CreateFutureCreatorCommand request, CancellationToken cancellationToken) { var entity = new FutureCreator { diff --git a/src/Application/FutureCreators/Queries/FutureCreatorListDto.cs b/src/Application/FutureCreators/Queries/FutureCreatorListDto.cs new file mode 100644 index 0000000..13d95ba --- /dev/null +++ b/src/Application/FutureCreators/Queries/FutureCreatorListDto.cs @@ -0,0 +1,20 @@ +using Hutopy.Domain.Entities; + +namespace Hutopy.Application.FutureCreators.Queries; + +public class FutureCreatorListDto +{ + public Guid Id { get; init; } + + public required string FirstName { get; init; } + + public required string LastName { get; init; } + + private class Mapping : Profile + { + public Mapping() + { + CreateMap(); + } + } +} diff --git a/src/Application/FutureCreators/Queries/GetFutureCreatorList.cs b/src/Application/FutureCreators/Queries/GetFutureCreatorList.cs new file mode 100644 index 0000000..e7a8128 --- /dev/null +++ b/src/Application/FutureCreators/Queries/GetFutureCreatorList.cs @@ -0,0 +1,27 @@ + +using Hutopy.Application.Common.Interfaces; +using Hutopy.Application.Common.Mappings; +using Hutopy.Application.Common.Models; + +namespace Hutopy.Application.FutureCreators.Queries; + +public record GetFutureCreatorListQuery : IRequest> +{ + public int PageNumber { get; init; } = 1; + public int PageSize { get; init; } = 10; +} + +public class GetFutureCreatorListQueryHandler( + IApplicationDbContext context, + IMapper mapper) + : IRequestHandler> +{ + public async Task> Handle(GetFutureCreatorListQuery request, CancellationToken cancellationToken) + { + Console.WriteLine(request); + return await context.FutureCreators + .OrderBy(x => x.FirstName) + .ProjectTo(mapper.ConfigurationProvider) + .PaginatedListAsync(request.PageNumber, request.PageSize); + } +} diff --git a/src/Application/TodoItems/Commands/CreateTodoItem/CreateTodoItem.cs b/src/Application/TodoItems/Commands/CreateTodoItem/CreateTodoItem.cs deleted file mode 100644 index c4a448a..0000000 --- a/src/Application/TodoItems/Commands/CreateTodoItem/CreateTodoItem.cs +++ /dev/null @@ -1,35 +0,0 @@ -using Hutopy.Application.Common.Interfaces; -using Hutopy.Domain.Entities; -using Hutopy.Domain.Events; - -namespace Hutopy.Application.TodoItems.Commands.CreateTodoItem; - -public record CreateTodoItemCommand : IRequest -{ - public int ListId { get; init; } - - public string? Title { get; init; } -} - -public class CreateTodoItemCommandHandler( - IApplicationDbContext context) - : IRequestHandler -{ - public async Task Handle(CreateTodoItemCommand request, CancellationToken cancellationToken) - { - var entity = new TodoItem - { - ListId = request.ListId, - Title = request.Title, - Done = false - }; - - entity.AddDomainEvent(new TodoItemCreatedEvent(entity)); - - context.TodoItems.Add(entity); - - await context.SaveChangesAsync(cancellationToken); - - return entity.Id; - } -} diff --git a/src/Application/TodoItems/Commands/CreateTodoItem/CreateTodoItemCommandValidator.cs b/src/Application/TodoItems/Commands/CreateTodoItem/CreateTodoItemCommandValidator.cs deleted file mode 100644 index e6d876a..0000000 --- a/src/Application/TodoItems/Commands/CreateTodoItem/CreateTodoItemCommandValidator.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace Hutopy.Application.TodoItems.Commands.CreateTodoItem; - -public class CreateTodoItemCommandValidator : AbstractValidator -{ - public CreateTodoItemCommandValidator() - { - RuleFor(v => v.Title) - .MaximumLength(200) - .NotEmpty(); - } -} diff --git a/src/Application/TodoItems/Commands/DeleteTodoItem/DeleteTodoItem.cs b/src/Application/TodoItems/Commands/DeleteTodoItem/DeleteTodoItem.cs deleted file mode 100644 index 3039681..0000000 --- a/src/Application/TodoItems/Commands/DeleteTodoItem/DeleteTodoItem.cs +++ /dev/null @@ -1,30 +0,0 @@ -using Hutopy.Application.Common.Interfaces; -using Hutopy.Domain.Events; -using Hutopy.Application.Common.Security; -using Hutopy.Domain.Constants; - -namespace Hutopy.Application.TodoItems.Commands.DeleteTodoItem; - -[Authorize(Roles = Roles.Administrator)] -[Authorize(Policy = Policies.CanDelete)] -public record DeleteTodoItemCommand(int Id) : IRequest; - -public class DeleteTodoItemCommandHandler( - IApplicationDbContext context) - : IRequestHandler -{ - public async Task Handle(DeleteTodoItemCommand request, CancellationToken cancellationToken) - { - var entity = await context.TodoItems - .FindAsync(new object[] { request.Id }, cancellationToken); - - Guard.Against.NotFound(request.Id, entity); - - context.TodoItems.Remove(entity); - - entity.AddDomainEvent(new TodoItemDeletedEvent(entity)); - - await context.SaveChangesAsync(cancellationToken); - } - -} diff --git a/src/Application/TodoItems/Commands/UpdateTodoItem/UpdateTodoItem.cs b/src/Application/TodoItems/Commands/UpdateTodoItem/UpdateTodoItem.cs deleted file mode 100644 index 68ad4e5..0000000 --- a/src/Application/TodoItems/Commands/UpdateTodoItem/UpdateTodoItem.cs +++ /dev/null @@ -1,30 +0,0 @@ -using Hutopy.Application.Common.Interfaces; - -namespace Hutopy.Application.TodoItems.Commands.UpdateTodoItem; - -public record UpdateTodoItemCommand : IRequest -{ - public int Id { get; init; } - - public string? Title { get; init; } - - public bool Done { get; init; } -} - -public class UpdateTodoItemCommandHandler( - IApplicationDbContext context) - : IRequestHandler -{ - public async Task Handle(UpdateTodoItemCommand request, CancellationToken cancellationToken) - { - var entity = await context.TodoItems - .FindAsync(new object[] { request.Id }, cancellationToken); - - Guard.Against.NotFound(request.Id, entity); - - entity.Title = request.Title; - entity.Done = request.Done; - - await context.SaveChangesAsync(cancellationToken); - } -} diff --git a/src/Application/TodoItems/Commands/UpdateTodoItem/UpdateTodoItemCommandValidator.cs b/src/Application/TodoItems/Commands/UpdateTodoItem/UpdateTodoItemCommandValidator.cs deleted file mode 100644 index 38383c6..0000000 --- a/src/Application/TodoItems/Commands/UpdateTodoItem/UpdateTodoItemCommandValidator.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace Hutopy.Application.TodoItems.Commands.UpdateTodoItem; - -public class UpdateTodoItemCommandValidator : AbstractValidator -{ - public UpdateTodoItemCommandValidator() - { - RuleFor(v => v.Title) - .MaximumLength(200) - .NotEmpty(); - } -} diff --git a/src/Application/TodoItems/Commands/UpdateTodoItemDetail/UpdateTodoItemDetail.cs b/src/Application/TodoItems/Commands/UpdateTodoItemDetail/UpdateTodoItemDetail.cs deleted file mode 100644 index 078a278..0000000 --- a/src/Application/TodoItems/Commands/UpdateTodoItemDetail/UpdateTodoItemDetail.cs +++ /dev/null @@ -1,34 +0,0 @@ -using Hutopy.Application.Common.Interfaces; -using Hutopy.Domain.Enums; - -namespace Hutopy.Application.TodoItems.Commands.UpdateTodoItemDetail; - -public record UpdateTodoItemDetailCommand : IRequest -{ - public int Id { get; init; } - - public int ListId { get; init; } - - public PriorityLevel Priority { get; init; } - - public string? Note { get; init; } -} - -public class UpdateTodoItemDetailCommandHandler( - IApplicationDbContext context) - : IRequestHandler -{ - public async Task Handle(UpdateTodoItemDetailCommand request, CancellationToken cancellationToken) - { - var entity = await context.TodoItems - .FindAsync(new object[] { request.Id }, cancellationToken); - - Guard.Against.NotFound(request.Id, entity); - - entity.ListId = request.ListId; - entity.Priority = request.Priority; - entity.Note = request.Note; - - await context.SaveChangesAsync(cancellationToken); - } -} diff --git a/src/Application/TodoItems/EventHandlers/TodoItemCompletedEventHandler.cs b/src/Application/TodoItems/EventHandlers/TodoItemCompletedEventHandler.cs deleted file mode 100644 index b16a60d..0000000 --- a/src/Application/TodoItems/EventHandlers/TodoItemCompletedEventHandler.cs +++ /dev/null @@ -1,16 +0,0 @@ -using Hutopy.Domain.Events; -using Microsoft.Extensions.Logging; - -namespace Hutopy.Application.TodoItems.EventHandlers; - -public class TodoItemCompletedEventHandler( - ILogger logger) - : INotificationHandler -{ - public Task Handle(TodoItemCompletedEvent notification, CancellationToken cancellationToken) - { - logger.LogInformation("Hutopy Domain Event: {DomainEvent}", notification.GetType().Name); - - return Task.CompletedTask; - } -} diff --git a/src/Application/TodoItems/EventHandlers/TodoItemCreatedEventHandler.cs b/src/Application/TodoItems/EventHandlers/TodoItemCreatedEventHandler.cs deleted file mode 100644 index 8aba373..0000000 --- a/src/Application/TodoItems/EventHandlers/TodoItemCreatedEventHandler.cs +++ /dev/null @@ -1,16 +0,0 @@ -using Hutopy.Domain.Events; -using Microsoft.Extensions.Logging; - -namespace Hutopy.Application.TodoItems.EventHandlers; - -public class TodoItemCreatedEventHandler( - ILogger logger) - : INotificationHandler -{ - public Task Handle(TodoItemCreatedEvent notification, CancellationToken cancellationToken) - { - logger.LogInformation("Hutopy Domain Event: {DomainEvent}", notification.GetType().Name); - - return Task.CompletedTask; - } -} diff --git a/src/Application/TodoItems/Queries/GetTodoItemsWithPagination/GetTodoItemsWithPagination.cs b/src/Application/TodoItems/Queries/GetTodoItemsWithPagination/GetTodoItemsWithPagination.cs deleted file mode 100644 index b0ece59..0000000 --- a/src/Application/TodoItems/Queries/GetTodoItemsWithPagination/GetTodoItemsWithPagination.cs +++ /dev/null @@ -1,28 +0,0 @@ -using Hutopy.Application.Common.Interfaces; -using Hutopy.Application.Common.Mappings; -using Hutopy.Application.Common.Models; - -namespace Hutopy.Application.TodoItems.Queries.GetTodoItemsWithPagination; - -public abstract record GetTodoItemsWithPaginationQuery : IRequest> -{ - public int ListId { get; init; } - public int PageNumber { get; init; } = 1; - public int PageSize { get; init; } = 10; -} - -public class GetTodoItemsWithPaginationQueryHandler( - IApplicationDbContext context, - IMapper mapper) - : IRequestHandler> -{ - public async Task> Handle(GetTodoItemsWithPaginationQuery request, CancellationToken cancellationToken) - { - Console.WriteLine(request); - return await context.TodoItems - .Where(x => x.ListId == request.ListId) - .OrderBy(x => x.Title) - .ProjectTo(mapper.ConfigurationProvider) - .PaginatedListAsync(request.PageNumber, request.PageSize); - } -} diff --git a/src/Application/TodoItems/Queries/GetTodoItemsWithPagination/GetTodoItemsWithPaginationQueryValidator.cs b/src/Application/TodoItems/Queries/GetTodoItemsWithPagination/GetTodoItemsWithPaginationQueryValidator.cs deleted file mode 100644 index 99bfd24..0000000 --- a/src/Application/TodoItems/Queries/GetTodoItemsWithPagination/GetTodoItemsWithPaginationQueryValidator.cs +++ /dev/null @@ -1,16 +0,0 @@ -namespace Hutopy.Application.TodoItems.Queries.GetTodoItemsWithPagination; - -public class GetTodoItemsWithPaginationQueryValidator : AbstractValidator -{ - public GetTodoItemsWithPaginationQueryValidator() - { - RuleFor(x => x.ListId) - .NotEmpty().WithMessage("ListId is required."); - - RuleFor(x => x.PageNumber) - .GreaterThanOrEqualTo(1).WithMessage("PageNumber at least greater than or equal to 1."); - - RuleFor(x => x.PageSize) - .GreaterThanOrEqualTo(1).WithMessage("PageSize at least greater than or equal to 1."); - } -} diff --git a/src/Application/TodoItems/Queries/GetTodoItemsWithPagination/TodoItemBriefDto.cs b/src/Application/TodoItems/Queries/GetTodoItemsWithPagination/TodoItemBriefDto.cs deleted file mode 100644 index b7c40a3..0000000 --- a/src/Application/TodoItems/Queries/GetTodoItemsWithPagination/TodoItemBriefDto.cs +++ /dev/null @@ -1,22 +0,0 @@ -using Hutopy.Domain.Entities; - -namespace Hutopy.Application.TodoItems.Queries.GetTodoItemsWithPagination; - -public class TodoItemBriefDto -{ - public int Id { get; init; } - - public int ListId { get; init; } - - public string? Title { get; init; } - - public bool Done { get; init; } - - private class Mapping : Profile - { - public Mapping() - { - CreateMap(); - } - } -} diff --git a/src/Application/TodoLists/Commands/CreateTodoList/CreateTodoList.cs b/src/Application/TodoLists/Commands/CreateTodoList/CreateTodoList.cs deleted file mode 100644 index cf95696..0000000 --- a/src/Application/TodoLists/Commands/CreateTodoList/CreateTodoList.cs +++ /dev/null @@ -1,25 +0,0 @@ -using Hutopy.Application.Common.Interfaces; -using Hutopy.Domain.Entities; - -namespace Hutopy.Application.TodoLists.Commands.CreateTodoList; - -public record CreateTodoListCommand : IRequest -{ - public string? Title { get; init; } -} - -public class CreateTodoListCommandHandler( - IApplicationDbContext context) - : IRequestHandler -{ - public async Task Handle(CreateTodoListCommand request, CancellationToken cancellationToken) - { - var entity = new TodoList { Title = request.Title }; - - context.TodoLists.Add(entity); - - await context.SaveChangesAsync(cancellationToken); - - return entity.Id; - } -} diff --git a/src/Application/TodoLists/Commands/CreateTodoList/CreateTodoListCommandValidator.cs b/src/Application/TodoLists/Commands/CreateTodoList/CreateTodoListCommandValidator.cs deleted file mode 100644 index 4c627b4..0000000 --- a/src/Application/TodoLists/Commands/CreateTodoList/CreateTodoListCommandValidator.cs +++ /dev/null @@ -1,26 +0,0 @@ -using Hutopy.Application.Common.Interfaces; - -namespace Hutopy.Application.TodoLists.Commands.CreateTodoList; - -public class CreateTodoListCommandValidator : AbstractValidator -{ - private readonly IApplicationDbContext _context; - - public CreateTodoListCommandValidator(IApplicationDbContext context) - { - _context = context; - - RuleFor(v => v.Title) - .NotEmpty() - .MaximumLength(200) - .MustAsync(BeUniqueTitle) - .WithMessage("'{PropertyName}' must be unique.") - .WithErrorCode("Unique"); - } - - public async Task BeUniqueTitle(string title, CancellationToken cancellationToken) - { - return await _context.TodoLists - .AllAsync(l => l.Title != title, cancellationToken); - } -} diff --git a/src/Application/TodoLists/Commands/DeleteTodoList/DeleteTodoList.cs b/src/Application/TodoLists/Commands/DeleteTodoList/DeleteTodoList.cs deleted file mode 100644 index 3339e8a..0000000 --- a/src/Application/TodoLists/Commands/DeleteTodoList/DeleteTodoList.cs +++ /dev/null @@ -1,23 +0,0 @@ -using Hutopy.Application.Common.Interfaces; - -namespace Hutopy.Application.TodoLists.Commands.DeleteTodoList; - -public record DeleteTodoListCommand(int Id) : IRequest; - -public class DeleteTodoListCommandHandler( - IApplicationDbContext context) - : IRequestHandler -{ - public async Task Handle(DeleteTodoListCommand request, CancellationToken cancellationToken) - { - var entity = await context.TodoLists - .Where(l => l.Id == request.Id) - .SingleOrDefaultAsync(cancellationToken); - - Guard.Against.NotFound(request.Id, entity); - - context.TodoLists.Remove(entity); - - await context.SaveChangesAsync(cancellationToken); - } -} diff --git a/src/Application/TodoLists/Commands/PurgeTodoLists/PurgeTodoLists.cs b/src/Application/TodoLists/Commands/PurgeTodoLists/PurgeTodoLists.cs deleted file mode 100644 index 1e75661..0000000 --- a/src/Application/TodoLists/Commands/PurgeTodoLists/PurgeTodoLists.cs +++ /dev/null @@ -1,21 +0,0 @@ -using Hutopy.Application.Common.Interfaces; -using Hutopy.Application.Common.Security; -using Hutopy.Domain.Constants; - -namespace Hutopy.Application.TodoLists.Commands.PurgeTodoLists; - -[Authorize(Roles = Roles.Administrator)] -[Authorize(Policy = Policies.CanPurge)] -public record PurgeTodoListsCommand : IRequest; - -public class PurgeTodoListsCommandHandler( - IApplicationDbContext context) - : IRequestHandler -{ - public async Task Handle(PurgeTodoListsCommand request, CancellationToken cancellationToken) - { - context.TodoLists.RemoveRange(context.TodoLists); - - await context.SaveChangesAsync(cancellationToken); - } -} diff --git a/src/Application/TodoLists/Commands/UpdateTodoList/UpdateTodoList.cs b/src/Application/TodoLists/Commands/UpdateTodoList/UpdateTodoList.cs deleted file mode 100644 index 8418030..0000000 --- a/src/Application/TodoLists/Commands/UpdateTodoList/UpdateTodoList.cs +++ /dev/null @@ -1,28 +0,0 @@ -using Hutopy.Application.Common.Interfaces; - -namespace Hutopy.Application.TodoLists.Commands.UpdateTodoList; - -public record UpdateTodoListCommand : IRequest -{ - public int Id { get; init; } - - public string? Title { get; init; } -} - -public class UpdateTodoListCommandHandler( - IApplicationDbContext context) - : IRequestHandler -{ - public async Task Handle(UpdateTodoListCommand request, CancellationToken cancellationToken) - { - var entity = await context.TodoLists - .FindAsync(new object[] { request.Id }, cancellationToken); - - Guard.Against.NotFound(request.Id, entity); - - entity.Title = request.Title; - - await context.SaveChangesAsync(cancellationToken); - - } -} diff --git a/src/Application/TodoLists/Commands/UpdateTodoList/UpdateTodoListCommandValidator.cs b/src/Application/TodoLists/Commands/UpdateTodoList/UpdateTodoListCommandValidator.cs deleted file mode 100644 index ba008d6..0000000 --- a/src/Application/TodoLists/Commands/UpdateTodoList/UpdateTodoListCommandValidator.cs +++ /dev/null @@ -1,27 +0,0 @@ -using Hutopy.Application.Common.Interfaces; - -namespace Hutopy.Application.TodoLists.Commands.UpdateTodoList; - -public class UpdateTodoListCommandValidator : AbstractValidator -{ - private readonly IApplicationDbContext _context; - - public UpdateTodoListCommandValidator(IApplicationDbContext context) - { - _context = context; - - RuleFor(v => v.Title) - .NotEmpty() - .MaximumLength(200) - .MustAsync(BeUniqueTitle) - .WithMessage("'{PropertyName}' must be unique.") - .WithErrorCode("Unique"); - } - - private async Task BeUniqueTitle(UpdateTodoListCommand model, string title, CancellationToken cancellationToken) - { - return await _context.TodoLists - .Where(l => l.Id != model.Id) - .AllAsync(l => l.Title != title, cancellationToken); - } -} diff --git a/src/Application/TodoLists/Queries/GetTodos/GetTodos.cs b/src/Application/TodoLists/Queries/GetTodos/GetTodos.cs deleted file mode 100644 index 9d4d32f..0000000 --- a/src/Application/TodoLists/Queries/GetTodos/GetTodos.cs +++ /dev/null @@ -1,32 +0,0 @@ -using Hutopy.Application.Common.Interfaces; -using Hutopy.Application.Common.Models; -using Hutopy.Application.Common.Security; -using Hutopy.Domain.Enums; - -namespace Hutopy.Application.TodoLists.Queries.GetTodos; - -[Authorize] -public record GetTodosQuery : IRequest; - -public class GetTodosQueryHandler( - IApplicationDbContext context, - IMapper mapper) - : IRequestHandler -{ - public async Task Handle(GetTodosQuery request, CancellationToken cancellationToken) - { - return new TodosVm - { - PriorityLevels = Enum.GetValues(typeof(PriorityLevel)) - .Cast() - .Select(p => new LookupDto { Id = (int)p, Title = p.ToString() }) - .ToList(), - - Lists = await context.TodoLists - .AsNoTracking() - .ProjectTo(mapper.ConfigurationProvider) - .OrderBy(t => t.Title) - .ToListAsync(cancellationToken) - }; - } -} diff --git a/src/Application/TodoLists/Queries/GetTodos/TodoItemDto.cs b/src/Application/TodoLists/Queries/GetTodos/TodoItemDto.cs deleted file mode 100644 index 18d86a3..0000000 --- a/src/Application/TodoLists/Queries/GetTodos/TodoItemDto.cs +++ /dev/null @@ -1,27 +0,0 @@ -using Hutopy.Domain.Entities; - -namespace Hutopy.Application.TodoLists.Queries.GetTodos; - -public class TodoItemDto -{ - public int Id { get; init; } - - public int ListId { get; init; } - - public string? Title { get; init; } - - public bool Done { get; init; } - - public int Priority { get; init; } - - public string? Note { get; init; } - - private class Mapping : Profile - { - public Mapping() - { - CreateMap().ForMember(d => d.Priority, - opt => opt.MapFrom(s => (int)s.Priority)); - } - } -} diff --git a/src/Application/TodoLists/Queries/GetTodos/TodoListDto.cs b/src/Application/TodoLists/Queries/GetTodos/TodoListDto.cs deleted file mode 100644 index c0a84dc..0000000 --- a/src/Application/TodoLists/Queries/GetTodos/TodoListDto.cs +++ /dev/null @@ -1,22 +0,0 @@ -using Hutopy.Domain.Entities; - -namespace Hutopy.Application.TodoLists.Queries.GetTodos; - -public class TodoListDto -{ - public int Id { get; init; } - - public string? Title { get; init; } - - public string? Colour { get; init; } - - public IReadOnlyCollection Items { get; init; } = Array.Empty(); - - private class Mapping : Profile - { - public Mapping() - { - CreateMap(); - } - } -} diff --git a/src/Application/TodoLists/Queries/GetTodos/TodosVm.cs b/src/Application/TodoLists/Queries/GetTodos/TodosVm.cs deleted file mode 100644 index 6bff5af..0000000 --- a/src/Application/TodoLists/Queries/GetTodos/TodosVm.cs +++ /dev/null @@ -1,10 +0,0 @@ -using Hutopy.Application.Common.Models; - -namespace Hutopy.Application.TodoLists.Queries.GetTodos; - -public class TodosVm -{ - public IReadOnlyCollection PriorityLevels { get; init; } = Array.Empty(); - - public IReadOnlyCollection Lists { get; init; } = Array.Empty(); -} diff --git a/src/Application/Users/Commands/CreateUser.cs b/src/Application/Users/Commands/CreateUser.cs new file mode 100644 index 0000000..be18e30 --- /dev/null +++ b/src/Application/Users/Commands/CreateUser.cs @@ -0,0 +1,39 @@ +using Hutopy.Application.Common.Interfaces; +using Hutopy.Domain.Entities; + +namespace Hutopy.Application.Users.Commands; +public record CreateUserCommand : IRequest +{ + public required string FirstName { get; init; } + public required string LastName { get; init; } + public required string EmailAddress { get; init; } + public required string UserName { get; init; } + public required string Password { get; init; } +} + +public class CreateUserCommandHandler : IRequestHandler +{ + private readonly IApplicationDbContext _context; + + public CreateUserCommandHandler(IApplicationDbContext context) + { + _context = context; + } + + public async Task Handle(CreateUserCommand request, CancellationToken cancellationToken) + { + var entity = new User + { + FirstName = request.FirstName, + LastName = request.LastName, + EmailAddress = request.EmailAddress, + UserName = request.UserName, + }; + + _context.DomainUsers.Add(entity); + + await _context.SaveChangesAsync(cancellationToken); + + return entity.Id; + } +} \ No newline at end of file diff --git a/src/Domain/Common/BaseEntity.cs b/src/Domain/Common/BaseEntity.cs index 388a3ce..080e1d4 100644 --- a/src/Domain/Common/BaseEntity.cs +++ b/src/Domain/Common/BaseEntity.cs @@ -6,7 +6,7 @@ public abstract class BaseEntity { // This can easily be modified to be BaseEntity and public T Id to support different key types. // Using non-generic integer types for simplicity - public int Id { get; set; } + public Guid Id { get; set; } private readonly List _domainEvents = []; diff --git a/src/Domain/Entities/TodoItem.cs b/src/Domain/Entities/TodoItem.cs deleted file mode 100644 index e10f25b..0000000 --- a/src/Domain/Entities/TodoItem.cs +++ /dev/null @@ -1,31 +0,0 @@ -namespace Hutopy.Domain.Entities; - -public class TodoItem : BaseAuditableEntity -{ - public int ListId { get; set; } - - public string? Title { get; set; } - - public string? Note { get; set; } - - public PriorityLevel Priority { get; set; } - - public DateTime? Reminder { get; set; } - - private bool _done; - public bool Done - { - get => _done; - set - { - if (value && !_done) - { - AddDomainEvent(new TodoItemCompletedEvent(this)); - } - - _done = value; - } - } - - public TodoList List { get; set; } = null!; -} diff --git a/src/Domain/Entities/TodoList.cs b/src/Domain/Entities/TodoList.cs deleted file mode 100644 index 365525e..0000000 --- a/src/Domain/Entities/TodoList.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace Hutopy.Domain.Entities; - -public class TodoList : BaseAuditableEntity -{ - public string? Title { get; set; } - - public Colour Colour { get; set; } = Colour.White; - - public IList Items { get; private set; } = new List(); -} diff --git a/src/Domain/Entities/User.cs b/src/Domain/Entities/User.cs new file mode 100644 index 0000000..d848021 --- /dev/null +++ b/src/Domain/Entities/User.cs @@ -0,0 +1,10 @@ +namespace Hutopy.Domain.Entities; + +public class User : BaseAuditableEntity +{ + public Guid IdentityUserId { get; set; } + public required string FirstName { get; set; } + public required string LastName { get; set; } + public required string UserName { get; set; } + public required string EmailAddress { get; set; } +} diff --git a/src/Domain/Events/TodoItemCompletedEvent.cs b/src/Domain/Events/TodoItemCompletedEvent.cs deleted file mode 100644 index 8d7cad1..0000000 --- a/src/Domain/Events/TodoItemCompletedEvent.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace Hutopy.Domain.Events; - -public class TodoItemCompletedEvent( - TodoItem item) - : BaseEvent -{ - public TodoItem Item { get; } = item; -} diff --git a/src/Domain/Events/TodoItemCreatedEvent.cs b/src/Domain/Events/TodoItemCreatedEvent.cs deleted file mode 100644 index 4f87e92..0000000 --- a/src/Domain/Events/TodoItemCreatedEvent.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace Hutopy.Domain.Events; - -public class TodoItemCreatedEvent( - TodoItem item) - : BaseEvent -{ - public TodoItem Item { get; } = item; -} diff --git a/src/Domain/Events/TodoItemDeletedEvent.cs b/src/Domain/Events/TodoItemDeletedEvent.cs deleted file mode 100644 index 1340b00..0000000 --- a/src/Domain/Events/TodoItemDeletedEvent.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace Hutopy.Domain.Events; - -public class TodoItemDeletedEvent( - TodoItem item) - : BaseEvent -{ - public TodoItem Item { get; } = item; -} diff --git a/src/Domain/GlobalUsings.cs b/src/Domain/GlobalUsings.cs index a15ae6d..e312629 100644 --- a/src/Domain/GlobalUsings.cs +++ b/src/Domain/GlobalUsings.cs @@ -1,6 +1,5 @@ global using Hutopy.Domain.Common; global using Hutopy.Domain.Entities; global using Hutopy.Domain.Enums; -global using Hutopy.Domain.Events; global using Hutopy.Domain.Exceptions; global using Hutopy.Domain.ValueObjects; \ No newline at end of file diff --git a/src/Domain/Interfaces/IUserService.cs b/src/Domain/Interfaces/IUserService.cs new file mode 100644 index 0000000..4048f93 --- /dev/null +++ b/src/Domain/Interfaces/IUserService.cs @@ -0,0 +1,7 @@ +namespace Hutopy.Domain.Interfaces; + +public interface IUserService +{ + Task CreateUserAsync(string email, string userName, string password); + +} diff --git a/src/Infrastructure/Data/ApplicationDbContext.cs b/src/Infrastructure/Data/ApplicationDbContext.cs index e565b11..c348dc4 100644 --- a/src/Infrastructure/Data/ApplicationDbContext.cs +++ b/src/Infrastructure/Data/ApplicationDbContext.cs @@ -11,12 +11,10 @@ public class ApplicationDbContext( DbContextOptions options) : IdentityDbContext(options), IApplicationDbContext { - public DbSet TodoLists => Set(); - - public DbSet TodoItems => Set(); - public DbSet FutureCreators => Set(); + public DbSet DomainUsers => Set(); + protected override void OnModelCreating(ModelBuilder builder) { base.OnModelCreating(builder); diff --git a/src/Infrastructure/Data/ApplicationDbContextInitializer.cs b/src/Infrastructure/Data/ApplicationDbContextInitializer.cs index b595c1e..cbabbeb 100644 --- a/src/Infrastructure/Data/ApplicationDbContextInitializer.cs +++ b/src/Infrastructure/Data/ApplicationDbContextInitializer.cs @@ -73,27 +73,8 @@ public class ApplicationDbContextInitializer( await userManager.CreateAsync(administrator, "Administrator1!"); if (!string.IsNullOrWhiteSpace(administratorRole.Name)) { - await userManager.AddToRolesAsync(administrator, new [] { administratorRole.Name }); + await userManager.AddToRolesAsync(administrator, new[] { administratorRole.Name }); } } - - // Default data - // Seed, if necessary - if (!context.TodoLists.Any()) - { - context.TodoLists.Add(new TodoList - { - Title = "Todo List", - Items = - { - new TodoItem { Title = "Make a todo list 📃" }, - new TodoItem { Title = "Check off the first item ✅" }, - new TodoItem { Title = "Realise you've already done two things on the list! 🤯"}, - new TodoItem { Title = "Reward yourself with a nice, long nap 🏆" }, - } - }); - - await context.SaveChangesAsync(); - } } } diff --git a/src/Infrastructure/Data/Configurations/TodoItemConfiguration.cs b/src/Infrastructure/Data/Configurations/TodoItemConfiguration.cs deleted file mode 100644 index c6f9a2f..0000000 --- a/src/Infrastructure/Data/Configurations/TodoItemConfiguration.cs +++ /dev/null @@ -1,15 +0,0 @@ -using Hutopy.Domain.Entities; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Metadata.Builders; - -namespace Hutopy.Infrastructure.Data.Configurations; - -public class TodoItemConfiguration : IEntityTypeConfiguration -{ - public void Configure(EntityTypeBuilder builder) - { - builder.Property(t => t.Title) - .HasMaxLength(200) - .IsRequired(); - } -} diff --git a/src/Infrastructure/Data/Configurations/TodoListConfiguration.cs b/src/Infrastructure/Data/Configurations/TodoListConfiguration.cs deleted file mode 100644 index 3350621..0000000 --- a/src/Infrastructure/Data/Configurations/TodoListConfiguration.cs +++ /dev/null @@ -1,18 +0,0 @@ -using Hutopy.Domain.Entities; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Metadata.Builders; - -namespace Hutopy.Infrastructure.Data.Configurations; - -public class TodoListConfiguration : IEntityTypeConfiguration -{ - public void Configure(EntityTypeBuilder builder) - { - builder.Property(t => t.Title) - .HasMaxLength(200) - .IsRequired(); - - builder - .OwnsOne(b => b.Colour); - } -} diff --git a/src/Infrastructure/Data/Migrations/20240404013754_AddDomainUser.Designer.cs b/src/Infrastructure/Data/Migrations/20240404013754_AddDomainUser.Designer.cs new file mode 100644 index 0000000..efb1b0d --- /dev/null +++ b/src/Infrastructure/Data/Migrations/20240404013754_AddDomainUser.Designer.cs @@ -0,0 +1,492 @@ +// +using System; +using Hutopy.Infrastructure.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Hutopy.Infrastructure.Data.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + [Migration("20240404013754_AddDomainUser")] + partial class AddDomainUser + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.3") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("Hutopy.Domain.Entities.FutureCreator", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Created") + .HasColumnType("datetimeoffset"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("EmailAddress") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("FirstName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("LastModified") + .HasColumnType("datetimeoffset"); + + b.Property("LastModifiedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("LastName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumber") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("ReasonToJoin") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("SocialNetworkAccount") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("FutureCreators"); + }); + + modelBuilder.Entity("Hutopy.Domain.Entities.TodoItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Created") + .HasColumnType("datetimeoffset"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("Done") + .HasColumnType("bit"); + + b.Property("LastModified") + .HasColumnType("datetimeoffset"); + + b.Property("LastModifiedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("ListId") + .HasColumnType("int"); + + b.Property("Note") + .HasColumnType("nvarchar(max)"); + + b.Property("Priority") + .HasColumnType("int"); + + b.Property("Reminder") + .HasColumnType("datetime2"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.HasKey("Id"); + + b.HasIndex("ListId"); + + b.ToTable("TodoItems"); + }); + + modelBuilder.Entity("Hutopy.Domain.Entities.TodoList", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Created") + .HasColumnType("datetimeoffset"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("LastModified") + .HasColumnType("datetimeoffset"); + + b.Property("LastModifiedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.HasKey("Id"); + + b.ToTable("TodoLists"); + }); + + modelBuilder.Entity("Hutopy.Domain.Entities.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Created") + .HasColumnType("datetimeoffset"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("EmailAddress") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("FirstName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("IdentityUserId") + .HasColumnType("uniqueidentifier"); + + b.Property("LastModified") + .HasColumnType("datetimeoffset"); + + b.Property("LastModifiedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("LastName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Password") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("UserName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("DomainUsers"); + }); + + modelBuilder.Entity("Hutopy.Infrastructure.Identity.ApplicationUser", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("AccessFailedCount") + .HasColumnType("int"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("nvarchar(max)"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("EmailConfirmed") + .HasColumnType("bit"); + + b.Property("LockoutEnabled") + .HasColumnType("bit"); + + b.Property("LockoutEnd") + .HasColumnType("datetimeoffset"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("PasswordHash") + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumber") + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("bit"); + + b.Property("SecurityStamp") + .HasColumnType("nvarchar(max)"); + + b.Property("TwoFactorEnabled") + .HasColumnType("bit"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex") + .HasFilter("[NormalizedUserName] IS NOT NULL"); + + b.ToTable("AspNetUsers", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("nvarchar(max)"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex") + .HasFilter("[NormalizedName] IS NOT NULL"); + + b.ToTable("AspNetRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("nvarchar(max)"); + + b.Property("ClaimValue") + .HasColumnType("nvarchar(max)"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("nvarchar(max)"); + + b.Property("ClaimValue") + .HasColumnType("nvarchar(max)"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("nvarchar(450)"); + + b.Property("ProviderKey") + .HasColumnType("nvarchar(450)"); + + b.Property("ProviderDisplayName") + .HasColumnType("nvarchar(max)"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("nvarchar(450)"); + + b.Property("RoleId") + .HasColumnType("nvarchar(450)"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("nvarchar(450)"); + + b.Property("LoginProvider") + .HasColumnType("nvarchar(450)"); + + b.Property("Name") + .HasColumnType("nvarchar(450)"); + + b.Property("Value") + .HasColumnType("nvarchar(max)"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens", (string)null); + }); + + modelBuilder.Entity("Hutopy.Domain.Entities.TodoItem", b => + { + b.HasOne("Hutopy.Domain.Entities.TodoList", "List") + .WithMany("Items") + .HasForeignKey("ListId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("List"); + }); + + modelBuilder.Entity("Hutopy.Domain.Entities.TodoList", b => + { + b.OwnsOne("Hutopy.Domain.ValueObjects.Colour", "Colour", b1 => + { + b1.Property("TodoListId") + .HasColumnType("int"); + + b1.Property("Code") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.HasKey("TodoListId"); + + b1.ToTable("TodoLists"); + + b1.WithOwner() + .HasForeignKey("TodoListId"); + }); + + b.Navigation("Colour") + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Hutopy.Domain.Entities.TodoList", b => + { + b.Navigation("Items"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Infrastructure/Data/Migrations/20240404013754_AddDomainUser.cs b/src/Infrastructure/Data/Migrations/20240404013754_AddDomainUser.cs new file mode 100644 index 0000000..c459b92 --- /dev/null +++ b/src/Infrastructure/Data/Migrations/20240404013754_AddDomainUser.cs @@ -0,0 +1,44 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Hutopy.Infrastructure.Data.Migrations +{ + /// + public partial class AddDomainUser : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "DomainUsers", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + IdentityUserId = table.Column(type: "uniqueidentifier", nullable: false), + FirstName = table.Column(type: "nvarchar(max)", nullable: false), + LastName = table.Column(type: "nvarchar(max)", nullable: false), + UserName = table.Column(type: "nvarchar(max)", nullable: false), + EmailAddress = table.Column(type: "nvarchar(max)", nullable: false), + Password = table.Column(type: "nvarchar(max)", nullable: false), + Created = table.Column(type: "datetimeoffset", nullable: false), + CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), + LastModified = table.Column(type: "datetimeoffset", nullable: false), + LastModifiedBy = table.Column(type: "nvarchar(max)", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_DomainUsers", x => x.Id); + }); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "DomainUsers"); + } + } +} diff --git a/src/Infrastructure/Data/Migrations/20240404023737_ChangeIdsToGuidsAndRemoveTodos.Designer.cs b/src/Infrastructure/Data/Migrations/20240404023737_ChangeIdsToGuidsAndRemoveTodos.Designer.cs new file mode 100644 index 0000000..4fb2eff --- /dev/null +++ b/src/Infrastructure/Data/Migrations/20240404023737_ChangeIdsToGuidsAndRemoveTodos.Designer.cs @@ -0,0 +1,372 @@ +// +using System; +using Hutopy.Infrastructure.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Hutopy.Infrastructure.Data.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + [Migration("20240404023737_ChangeIdsToGuidsAndRemoveTodos")] + partial class ChangeIdsToGuidsAndRemoveTodos + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.3") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("Hutopy.Domain.Entities.FutureCreator", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Created") + .HasColumnType("datetimeoffset"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("EmailAddress") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("FirstName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("LastModified") + .HasColumnType("datetimeoffset"); + + b.Property("LastModifiedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("LastName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumber") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("ReasonToJoin") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("SocialNetworkAccount") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("FutureCreators"); + }); + + modelBuilder.Entity("Hutopy.Domain.Entities.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Created") + .HasColumnType("datetimeoffset"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("EmailAddress") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("FirstName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("IdentityUserId") + .HasColumnType("uniqueidentifier"); + + b.Property("LastModified") + .HasColumnType("datetimeoffset"); + + b.Property("LastModifiedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("LastName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Password") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("UserName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("DomainUsers"); + }); + + modelBuilder.Entity("Hutopy.Infrastructure.Identity.ApplicationUser", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("AccessFailedCount") + .HasColumnType("int"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("nvarchar(max)"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("EmailConfirmed") + .HasColumnType("bit"); + + b.Property("LockoutEnabled") + .HasColumnType("bit"); + + b.Property("LockoutEnd") + .HasColumnType("datetimeoffset"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("PasswordHash") + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumber") + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("bit"); + + b.Property("SecurityStamp") + .HasColumnType("nvarchar(max)"); + + b.Property("TwoFactorEnabled") + .HasColumnType("bit"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex") + .HasFilter("[NormalizedUserName] IS NOT NULL"); + + b.ToTable("AspNetUsers", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("nvarchar(max)"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex") + .HasFilter("[NormalizedName] IS NOT NULL"); + + b.ToTable("AspNetRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("nvarchar(max)"); + + b.Property("ClaimValue") + .HasColumnType("nvarchar(max)"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("nvarchar(max)"); + + b.Property("ClaimValue") + .HasColumnType("nvarchar(max)"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("nvarchar(450)"); + + b.Property("ProviderKey") + .HasColumnType("nvarchar(450)"); + + b.Property("ProviderDisplayName") + .HasColumnType("nvarchar(max)"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("nvarchar(450)"); + + b.Property("RoleId") + .HasColumnType("nvarchar(450)"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("nvarchar(450)"); + + b.Property("LoginProvider") + .HasColumnType("nvarchar(450)"); + + b.Property("Name") + .HasColumnType("nvarchar(450)"); + + b.Property("Value") + .HasColumnType("nvarchar(max)"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Infrastructure/Data/Migrations/20240404023737_ChangeIdsToGuidsAndRemoveTodos.cs b/src/Infrastructure/Data/Migrations/20240404023737_ChangeIdsToGuidsAndRemoveTodos.cs new file mode 100644 index 0000000..6ef89a3 --- /dev/null +++ b/src/Infrastructure/Data/Migrations/20240404023737_ChangeIdsToGuidsAndRemoveTodos.cs @@ -0,0 +1,149 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Hutopy.Infrastructure.Data.Migrations +{ + /// + public partial class ChangeIdsToGuidsAndRemoveTodos : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "TodoItems"); + + migrationBuilder.DropTable( + name: "TodoLists"); + + migrationBuilder.DropPrimaryKey( + name: "PK_FuturCreators", + table: "FutureCreators"); + + migrationBuilder.DropPrimaryKey( + name: "PK_DomainUsers", + table: "DomainUsers"); + + migrationBuilder.DropColumn( + name: "Id", + table: "FutureCreators"); + + migrationBuilder.DropColumn( + name: "Id", + table: "DomainUsers"); + + migrationBuilder.AddColumn( + name: "Id", + table: "FutureCreators", + type: "uniqueidentifier", + nullable: false, + defaultValueSql: "NEWID()" + ); + + migrationBuilder.AddColumn( + name: "Id", + table: "DomainUsers", + type: "uniqueidentifier", + nullable: false, + defaultValueSql: "NEWID()" + ); + + migrationBuilder.AddPrimaryKey( + name: "PK_FutureCreators", + table: "FutureCreators", + column: "Id"); + + migrationBuilder.AddPrimaryKey( + name: "PK_DomainUsers", + table: "DomainUsers", + column: "Id"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropPrimaryKey( + name: "PK_FutureCreators", + table: "FutureCreators"); + + migrationBuilder.RenameTable( + name: "FutureCreators", + newName: "FutureCreator"); + + migrationBuilder.AlterColumn( + name: "Id", + table: "DomainUsers", + type: "int", + nullable: false, + oldClrType: typeof(Guid), + oldType: "uniqueidentifier") + .Annotation("SqlServer:Identity", "1, 1"); + + migrationBuilder.AlterColumn( + name: "Id", + table: "FutureCreator", + type: "int", + nullable: false, + oldClrType: typeof(Guid), + oldType: "uniqueidentifier") + .Annotation("SqlServer:Identity", "1, 1"); + + migrationBuilder.AddPrimaryKey( + name: "PK_FutureCreator", + table: "FutureCreator", + column: "Id"); + + migrationBuilder.CreateTable( + name: "TodoLists", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + Created = table.Column(type: "datetimeoffset", nullable: false), + CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), + LastModified = table.Column(type: "datetimeoffset", nullable: false), + LastModifiedBy = table.Column(type: "nvarchar(max)", nullable: true), + Title = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: false), + Colour_Code = table.Column(type: "nvarchar(max)", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_TodoLists", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "TodoItems", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + ListId = table.Column(type: "int", nullable: false), + Created = table.Column(type: "datetimeoffset", nullable: false), + CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), + Done = table.Column(type: "bit", nullable: false), + LastModified = table.Column(type: "datetimeoffset", nullable: false), + LastModifiedBy = table.Column(type: "nvarchar(max)", nullable: true), + Note = table.Column(type: "nvarchar(max)", nullable: true), + Priority = table.Column(type: "int", nullable: false), + Reminder = table.Column(type: "datetime2", nullable: true), + Title = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_TodoItems", x => x.Id); + table.ForeignKey( + name: "FK_TodoItems_TodoLists_ListId", + column: x => x.ListId, + principalTable: "TodoLists", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "IX_TodoItems_ListId", + table: "TodoItems", + column: "ListId"); + } + } +} diff --git a/src/Infrastructure/Data/Migrations/20240404030232_RemovePasswordFromDomainUser.Designer.cs b/src/Infrastructure/Data/Migrations/20240404030232_RemovePasswordFromDomainUser.Designer.cs new file mode 100644 index 0000000..a58545e --- /dev/null +++ b/src/Infrastructure/Data/Migrations/20240404030232_RemovePasswordFromDomainUser.Designer.cs @@ -0,0 +1,368 @@ +// +using System; +using Hutopy.Infrastructure.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Hutopy.Infrastructure.Data.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + [Migration("20240404030232_RemovePasswordFromDomainUser")] + partial class RemovePasswordFromDomainUser + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.3") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("Hutopy.Domain.Entities.FutureCreator", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Created") + .HasColumnType("datetimeoffset"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("EmailAddress") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("FirstName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("LastModified") + .HasColumnType("datetimeoffset"); + + b.Property("LastModifiedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("LastName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumber") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("ReasonToJoin") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("SocialNetworkAccount") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("FutureCreators"); + }); + + modelBuilder.Entity("Hutopy.Domain.Entities.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Created") + .HasColumnType("datetimeoffset"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("EmailAddress") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("FirstName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("IdentityUserId") + .HasColumnType("uniqueidentifier"); + + b.Property("LastModified") + .HasColumnType("datetimeoffset"); + + b.Property("LastModifiedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("LastName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("UserName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("DomainUsers"); + }); + + modelBuilder.Entity("Hutopy.Infrastructure.Identity.ApplicationUser", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("AccessFailedCount") + .HasColumnType("int"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("nvarchar(max)"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("EmailConfirmed") + .HasColumnType("bit"); + + b.Property("LockoutEnabled") + .HasColumnType("bit"); + + b.Property("LockoutEnd") + .HasColumnType("datetimeoffset"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("PasswordHash") + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumber") + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("bit"); + + b.Property("SecurityStamp") + .HasColumnType("nvarchar(max)"); + + b.Property("TwoFactorEnabled") + .HasColumnType("bit"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex") + .HasFilter("[NormalizedUserName] IS NOT NULL"); + + b.ToTable("AspNetUsers", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("nvarchar(max)"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex") + .HasFilter("[NormalizedName] IS NOT NULL"); + + b.ToTable("AspNetRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("nvarchar(max)"); + + b.Property("ClaimValue") + .HasColumnType("nvarchar(max)"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("nvarchar(max)"); + + b.Property("ClaimValue") + .HasColumnType("nvarchar(max)"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("nvarchar(450)"); + + b.Property("ProviderKey") + .HasColumnType("nvarchar(450)"); + + b.Property("ProviderDisplayName") + .HasColumnType("nvarchar(max)"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("nvarchar(450)"); + + b.Property("RoleId") + .HasColumnType("nvarchar(450)"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("nvarchar(450)"); + + b.Property("LoginProvider") + .HasColumnType("nvarchar(450)"); + + b.Property("Name") + .HasColumnType("nvarchar(450)"); + + b.Property("Value") + .HasColumnType("nvarchar(max)"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Infrastructure/Data/Migrations/20240404030232_RemovePasswordFromDomainUser.cs b/src/Infrastructure/Data/Migrations/20240404030232_RemovePasswordFromDomainUser.cs new file mode 100644 index 0000000..66d0ef3 --- /dev/null +++ b/src/Infrastructure/Data/Migrations/20240404030232_RemovePasswordFromDomainUser.cs @@ -0,0 +1,29 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Hutopy.Infrastructure.Data.Migrations +{ + /// + public partial class RemovePasswordFromDomainUser : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "Password", + table: "DomainUsers"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "Password", + table: "DomainUsers", + type: "nvarchar(max)", + nullable: false, + defaultValue: ""); + } + } +} diff --git a/src/Infrastructure/Data/Migrations/ApplicationDbContextModelSnapshot.cs b/src/Infrastructure/Data/Migrations/ApplicationDbContextModelSnapshot.cs index 0eb80ef..0be5962 100644 --- a/src/Infrastructure/Data/Migrations/ApplicationDbContextModelSnapshot.cs +++ b/src/Infrastructure/Data/Migrations/ApplicationDbContextModelSnapshot.cs @@ -24,11 +24,9 @@ namespace Hutopy.Infrastructure.Data.Migrations modelBuilder.Entity("Hutopy.Domain.Entities.FutureCreator", b => { - b.Property("Id") + b.Property("Id") .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + .HasColumnType("uniqueidentifier"); b.Property("Created") .HasColumnType("datetimeoffset"); @@ -68,16 +66,14 @@ namespace Hutopy.Infrastructure.Data.Migrations b.HasKey("Id"); - b.ToTable("FutureCreator"); + b.ToTable("FutureCreators"); }); - modelBuilder.Entity("Hutopy.Domain.Entities.TodoItem", b => + modelBuilder.Entity("Hutopy.Domain.Entities.User", b => { - b.Property("Id") + b.Property("Id") .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + .HasColumnType("uniqueidentifier"); b.Property("Created") .HasColumnType("datetimeoffset"); @@ -85,8 +81,16 @@ namespace Hutopy.Infrastructure.Data.Migrations b.Property("CreatedBy") .HasColumnType("nvarchar(max)"); - b.Property("Done") - .HasColumnType("bit"); + b.Property("EmailAddress") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("FirstName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("IdentityUserId") + .HasColumnType("uniqueidentifier"); b.Property("LastModified") .HasColumnType("datetimeoffset"); @@ -94,58 +98,17 @@ namespace Hutopy.Infrastructure.Data.Migrations b.Property("LastModifiedBy") .HasColumnType("nvarchar(max)"); - b.Property("ListId") - .HasColumnType("int"); - - b.Property("Note") + b.Property("LastName") + .IsRequired() .HasColumnType("nvarchar(max)"); - b.Property("Priority") - .HasColumnType("int"); - - b.Property("Reminder") - .HasColumnType("datetime2"); - - b.Property("Title") + b.Property("UserName") .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); + .HasColumnType("nvarchar(max)"); b.HasKey("Id"); - b.HasIndex("ListId"); - - b.ToTable("TodoItems"); - }); - - modelBuilder.Entity("Hutopy.Domain.Entities.TodoList", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("Created") - .HasColumnType("datetimeoffset"); - - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("LastModified") - .HasColumnType("datetimeoffset"); - - b.Property("LastModifiedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.HasKey("Id"); - - b.ToTable("TodoLists"); + b.ToTable("DomainUsers"); }); modelBuilder.Entity("Hutopy.Infrastructure.Identity.ApplicationUser", b => @@ -346,40 +309,6 @@ namespace Hutopy.Infrastructure.Data.Migrations b.ToTable("AspNetUserTokens", (string)null); }); - modelBuilder.Entity("Hutopy.Domain.Entities.TodoItem", b => - { - b.HasOne("Hutopy.Domain.Entities.TodoList", "List") - .WithMany("Items") - .HasForeignKey("ListId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("List"); - }); - - modelBuilder.Entity("Hutopy.Domain.Entities.TodoList", b => - { - b.OwnsOne("Hutopy.Domain.ValueObjects.Colour", "Colour", b1 => - { - b1.Property("TodoListId") - .HasColumnType("int"); - - b1.Property("Code") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.HasKey("TodoListId"); - - b1.ToTable("TodoLists"); - - b1.WithOwner() - .HasForeignKey("TodoListId"); - }); - - b.Navigation("Colour") - .IsRequired(); - }); - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => { b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) @@ -430,11 +359,6 @@ namespace Hutopy.Infrastructure.Data.Migrations .OnDelete(DeleteBehavior.Cascade) .IsRequired(); }); - - modelBuilder.Entity("Hutopy.Domain.Entities.TodoList", b => - { - b.Navigation("Items"); - }); #pragma warning restore 612, 618 } } diff --git a/src/Infrastructure/DependencyInjection.cs b/src/Infrastructure/DependencyInjection.cs index 0651486..3aabf8c 100644 --- a/src/Infrastructure/DependencyInjection.cs +++ b/src/Infrastructure/DependencyInjection.cs @@ -1,8 +1,10 @@ using Hutopy.Application.Common.Interfaces; using Hutopy.Domain.Constants; +using Hutopy.Domain.Interfaces; using Hutopy.Infrastructure.Data; using Hutopy.Infrastructure.Data.Interceptors; using Hutopy.Infrastructure.Identity; +using Hutopy.Infrastructure.Services; using Hutopy.Infrastructure.Stripe; using Microsoft.AspNetCore.Identity; using Microsoft.EntityFrameworkCore; @@ -41,6 +43,8 @@ public static class DependencyInjection .AddBearerToken(IdentityConstants.BearerScheme); services.AddAuthorizationBuilder(); + services.AddScoped(); + // Might need to change and use AddIdentity() when we need to integrate connection via third party ( facebook, google ) services diff --git a/src/Infrastructure/Services/UserService.cs b/src/Infrastructure/Services/UserService.cs new file mode 100644 index 0000000..08860cc --- /dev/null +++ b/src/Infrastructure/Services/UserService.cs @@ -0,0 +1,24 @@ +using Hutopy.Domain.Interfaces; +using Hutopy.Infrastructure.Identity; +using Microsoft.AspNetCore.Identity; + +namespace Hutopy.Infrastructure.Services; + +public class UserService(UserManager userManager, SignInManager signInManager) : IUserService +{ + private readonly UserManager _userManager = userManager; + private readonly SignInManager _signInManager = signInManager; + + + public async Task CreateUserAsync(string email, string userName, string password) + { + var applicationUser = new ApplicationUser + { + UserName = userName, + Email = email, + }; + + await _userManager.CreateAsync(applicationUser, password); + } +} + diff --git a/src/Web/DependencyInjection.cs b/src/Web/DependencyInjection.cs index f8ede38..fe6aab9 100644 --- a/src/Web/DependencyInjection.cs +++ b/src/Web/DependencyInjection.cs @@ -1,6 +1,8 @@ using Azure.Identity; using Hutopy.Application.Common.Interfaces; +using Hutopy.Domain.Interfaces; using Hutopy.Infrastructure.Data; +using Hutopy.Infrastructure.Services; using Hutopy.Web.Services; using Microsoft.AspNetCore.Mvc; using NSwag; @@ -15,6 +17,8 @@ public static class DependencyInjection services.AddDatabaseDeveloperPageExceptionFilter(); services.AddScoped(); + services.AddScoped(); + services.AddHttpContextAccessor(); diff --git a/src/Web/Endpoints/JoinUs.cs b/src/Web/Endpoints/JoinUs.cs index 9cd917b..2f1d1a5 100644 --- a/src/Web/Endpoints/JoinUs.cs +++ b/src/Web/Endpoints/JoinUs.cs @@ -1,4 +1,6 @@ -using Hutopy.Application.FutureCreators.Commands; +using Hutopy.Application.Common.Models; +using Hutopy.Application.FutureCreators.Commands; +using Hutopy.Application.FutureCreators.Queries; namespace Hutopy.Web.Endpoints; @@ -7,11 +9,17 @@ public class JoinUs : EndpointGroupBase public override void Map(WebApplication app) { app.MapGroup(this) + .MapGet(GetFutureCreators) .MapPost(CreateFutureCreator); } - private static Task CreateFutureCreator(ISender sender, CreateFutureCreatorCommand command) + private static Task CreateFutureCreator(ISender sender, CreateFutureCreatorCommand command) { return sender.Send(command); } + + private static Task> GetFutureCreators(ISender sender, [AsParameters] GetFutureCreatorListQuery query) + { + return sender.Send(query); + } } diff --git a/src/Web/Endpoints/TodoItems.cs b/src/Web/Endpoints/TodoItems.cs deleted file mode 100644 index cc62ff8..0000000 --- a/src/Web/Endpoints/TodoItems.cs +++ /dev/null @@ -1,52 +0,0 @@ -using Hutopy.Application.Common.Models; -using Hutopy.Application.TodoItems.Commands.CreateTodoItem; -using Hutopy.Application.TodoItems.Commands.DeleteTodoItem; -using Hutopy.Application.TodoItems.Commands.UpdateTodoItem; -using Hutopy.Application.TodoItems.Commands.UpdateTodoItemDetail; -using Hutopy.Application.TodoItems.Queries.GetTodoItemsWithPagination; - -namespace Hutopy.Web.Endpoints; - -public class TodoItems : EndpointGroupBase -{ - public override void Map(WebApplication app) - { - app.MapGroup(this) - .RequireAuthorization() - .MapGet(GetTodoItemsWithPagination) - .MapPost(CreateTodoItem) - .MapPut(UpdateTodoItem, "{id}") - .MapPut(UpdateTodoItemDetail, "UpdateDetail/{id}") - .MapDelete(DeleteTodoItem, "{id}"); - } - - private static Task> GetTodoItemsWithPagination(ISender sender, [AsParameters] GetTodoItemsWithPaginationQuery query) - { - return sender.Send(query); - } - - private static Task CreateTodoItem(ISender sender, CreateTodoItemCommand command) - { - return sender.Send(command); - } - - private static async Task UpdateTodoItem(ISender sender, int id, UpdateTodoItemCommand command) - { - if (id != command.Id) return Results.BadRequest(); - await sender.Send(command); - return Results.NoContent(); - } - - private static async Task UpdateTodoItemDetail(ISender sender, int id, UpdateTodoItemDetailCommand command) - { - if (id != command.Id) return Results.BadRequest(); - await sender.Send(command); - return Results.NoContent(); - } - - private static async Task DeleteTodoItem(ISender sender, int id) - { - await sender.Send(new DeleteTodoItemCommand(id)); - return Results.NoContent(); - } -} diff --git a/src/Web/Endpoints/TodoLists.cs b/src/Web/Endpoints/TodoLists.cs deleted file mode 100644 index a191421..0000000 --- a/src/Web/Endpoints/TodoLists.cs +++ /dev/null @@ -1,42 +0,0 @@ -using Hutopy.Application.TodoLists.Commands.CreateTodoList; -using Hutopy.Application.TodoLists.Commands.DeleteTodoList; -using Hutopy.Application.TodoLists.Commands.UpdateTodoList; -using Hutopy.Application.TodoLists.Queries.GetTodos; - -namespace Hutopy.Web.Endpoints; - -public class TodoLists : EndpointGroupBase -{ - public override void Map(WebApplication app) - { - app.MapGroup(this) - .RequireAuthorization() - .MapGet(GetTodoLists) - .MapPost(CreateTodoList) - .MapPut(UpdateTodoList, "{id}") - .MapDelete(DeleteTodoList, "{id}"); - } - - private static Task GetTodoLists(ISender sender) - { - return sender.Send(new GetTodosQuery()); - } - - private static Task CreateTodoList(ISender sender, CreateTodoListCommand command) - { - return sender.Send(command); - } - - private static async Task UpdateTodoList(ISender sender, int id, UpdateTodoListCommand command) - { - if (id != command.Id) return Results.BadRequest(); - await sender.Send(command); - return Results.NoContent(); - } - - private static async Task DeleteTodoList(ISender sender, int id) - { - await sender.Send(new DeleteTodoListCommand(id)); - return Results.NoContent(); - } -} diff --git a/src/Web/Endpoints/Users.cs b/src/Web/Endpoints/Users.cs index c27114b..63749c4 100644 --- a/src/Web/Endpoints/Users.cs +++ b/src/Web/Endpoints/Users.cs @@ -1,4 +1,6 @@ -using Hutopy.Infrastructure.Identity; +using Hutopy.Application.Users.Commands; +using Hutopy.Domain.Interfaces; +using Hutopy.Infrastructure.Identity; namespace Hutopy.Web.Endpoints; @@ -7,6 +9,13 @@ public class Users : EndpointGroupBase public override void Map(WebApplication app) { app.MapGroup(this) + .MapPost(CreateUser) .MapIdentityApi(); } + + public async Task CreateUser(ISender sender, CreateUserCommand command, IUserService userService) + { + await userService.CreateUserAsync(command.EmailAddress, command.UserName, command.Password); + return await sender.Send(command); + } } diff --git a/src/Web/Program.cs b/src/Web/Program.cs index 85dbf27..803e8f0 100644 --- a/src/Web/Program.cs +++ b/src/Web/Program.cs @@ -1,6 +1,8 @@ using Hutopy.Application; +using Hutopy.Domain.Interfaces; using Hutopy.Infrastructure; using Hutopy.Infrastructure.Data; +using Hutopy.Infrastructure.Services; using Hutopy.Web; var builder = WebApplication.CreateBuilder(args); @@ -22,6 +24,7 @@ builder.Services.AddApplicationServices(); builder.Services.AddInfrastructureServices(builder.Configuration); builder.Services.AddWebServices(); +builder.Services.AddScoped(); var app = builder.Build(); diff --git a/src/Web/wwwroot/api/specification.json b/src/Web/wwwroot/api/specification.json index 158be32..944608b 100644 --- a/src/Web/wwwroot/api/specification.json +++ b/src/Web/wwwroot/api/specification.json @@ -7,6 +7,46 @@ }, "paths": { "/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" @@ -30,8 +70,8 @@ "content": { "application/json": { "schema": { - "type": "integer", - "format": "int32" + "type": "string", + "format": "guid" } } } @@ -71,73 +111,18 @@ } } }, - "/api/TodoItems": { - "get": { - "tags": [ - "TodoItems" - ], - "operationId": "GetTodoItemsWithPagination", - "parameters": [ - { - "name": "ListId", - "in": "query", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - }, - "x-position": 1 - }, - { - "name": "PageNumber", - "in": "query", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - }, - "x-position": 2 - }, - { - "name": "PageSize", - "in": "query", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - }, - "x-position": 3 - } - ], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/PaginatedListOfTodoItemBriefDto" - } - } - } - } - }, - "security": [ - { - "JWT": [] - } - ] - }, + "/api/Users": { "post": { "tags": [ - "TodoItems" + "Users" ], - "operationId": "CreateTodoItem", + "operationId": "CreateUser", "requestBody": { "x-name": "command", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/CreateTodoItemCommand" + "$ref": "#/components/schemas/CreateUserCommand" } } }, @@ -150,261 +135,13 @@ "content": { "application/json": { "schema": { - "type": "integer", - "format": "int32" + "type": "string", + "format": "guid" } } } } - }, - "security": [ - { - "JWT": [] - } - ] - } - }, - "/api/TodoItems/{id}": { - "put": { - "tags": [ - "TodoItems" - ], - "operationId": "UpdateTodoItem", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - }, - "x-position": 1 - } - ], - "requestBody": { - "x-name": "command", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateTodoItemCommand" - } - } - }, - "required": true, - "x-position": 2 - }, - "responses": { - "200": { - "description": "" - } - }, - "security": [ - { - "JWT": [] - } - ] - }, - "delete": { - "tags": [ - "TodoItems" - ], - "operationId": "DeleteTodoItem", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - }, - "x-position": 1 - } - ], - "responses": { - "200": { - "description": "" - } - }, - "security": [ - { - "JWT": [] - } - ] - } - }, - "/api/TodoItems/UpdateDetail/{id}": { - "put": { - "tags": [ - "TodoItems" - ], - "operationId": "UpdateTodoItemDetail", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - }, - "x-position": 1 - } - ], - "requestBody": { - "x-name": "command", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateTodoItemDetailCommand" - } - } - }, - "required": true, - "x-position": 2 - }, - "responses": { - "200": { - "description": "" - } - }, - "security": [ - { - "JWT": [] - } - ] - } - }, - "/api/TodoLists": { - "get": { - "tags": [ - "TodoLists" - ], - "operationId": "GetTodoLists", - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/TodosVm" - } - } - } - } - }, - "security": [ - { - "JWT": [] - } - ] - }, - "post": { - "tags": [ - "TodoLists" - ], - "operationId": "CreateTodoList", - "requestBody": { - "x-name": "command", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateTodoListCommand" - } - } - }, - "required": true, - "x-position": 1 - }, - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "type": "integer", - "format": "int32" - } - } - } - } - }, - "security": [ - { - "JWT": [] - } - ] - } - }, - "/api/TodoLists/{id}": { - "put": { - "tags": [ - "TodoLists" - ], - "operationId": "UpdateTodoList", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - }, - "x-position": 1 - } - ], - "requestBody": { - "x-name": "command", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateTodoListCommand" - } - } - }, - "required": true, - "x-position": 2 - }, - "responses": { - "200": { - "description": "" - } - }, - "security": [ - { - "JWT": [] - } - ] - }, - "delete": { - "tags": [ - "TodoLists" - ], - "operationId": "DeleteTodoList", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - }, - "x-position": 1 - } - ], - "responses": { - "200": { - "description": "" - } - }, - "security": [ - { - "JWT": [] - } - ] + } } }, "/api/Users/register": { @@ -822,6 +559,52 @@ }, "components": { "schemas": { + "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, @@ -848,6 +631,7 @@ }, "CreateSessionCheckoutCommand": { "type": "object", + "x-abstract": true, "additionalProperties": false, "properties": { "price": { @@ -859,231 +643,24 @@ } } }, - "PaginatedListOfTodoItemBriefDto": { + "CreateUserCommand": { "type": "object", "additionalProperties": false, "properties": { - "items": { - "type": "array", - "items": { - "$ref": "#/components/schemas/TodoItemBriefDto" - } + "firstName": { + "type": "string" }, - "pageNumber": { - "type": "integer", - "format": "int32" + "lastName": { + "type": "string" }, - "totalPages": { - "type": "integer", - "format": "int32" + "emailAddress": { + "type": "string" }, - "totalCount": { - "type": "integer", - "format": "int32" + "userName": { + "type": "string" }, - "hasPreviousPage": { - "type": "boolean" - }, - "hasNextPage": { - "type": "boolean" - } - } - }, - "TodoItemBriefDto": { - "type": "object", - "additionalProperties": false, - "properties": { - "id": { - "type": "integer", - "format": "int32" - }, - "listId": { - "type": "integer", - "format": "int32" - }, - "title": { - "type": "string", - "nullable": true - }, - "done": { - "type": "boolean" - } - } - }, - "CreateTodoItemCommand": { - "type": "object", - "additionalProperties": false, - "properties": { - "listId": { - "type": "integer", - "format": "int32" - }, - "title": { - "type": "string", - "nullable": true - } - } - }, - "UpdateTodoItemCommand": { - "type": "object", - "additionalProperties": false, - "properties": { - "id": { - "type": "integer", - "format": "int32" - }, - "title": { - "type": "string", - "nullable": true - }, - "done": { - "type": "boolean" - } - } - }, - "UpdateTodoItemDetailCommand": { - "type": "object", - "additionalProperties": false, - "properties": { - "id": { - "type": "integer", - "format": "int32" - }, - "listId": { - "type": "integer", - "format": "int32" - }, - "priority": { - "$ref": "#/components/schemas/PriorityLevel" - }, - "note": { - "type": "string", - "nullable": true - } - } - }, - "PriorityLevel": { - "type": "integer", - "description": "", - "x-enumNames": [ - "None", - "Low", - "Medium", - "High" - ], - "enum": [ - 0, - 1, - 2, - 3 - ] - }, - "TodosVm": { - "type": "object", - "additionalProperties": false, - "properties": { - "priorityLevels": { - "type": "array", - "items": { - "$ref": "#/components/schemas/LookupDto" - } - }, - "lists": { - "type": "array", - "items": { - "$ref": "#/components/schemas/TodoListDto" - } - } - } - }, - "LookupDto": { - "type": "object", - "additionalProperties": false, - "properties": { - "id": { - "type": "integer", - "format": "int32" - }, - "title": { - "type": "string", - "nullable": true - } - } - }, - "TodoListDto": { - "type": "object", - "additionalProperties": false, - "properties": { - "id": { - "type": "integer", - "format": "int32" - }, - "title": { - "type": "string", - "nullable": true - }, - "colour": { - "type": "string", - "nullable": true - }, - "items": { - "type": "array", - "items": { - "$ref": "#/components/schemas/TodoItemDto" - } - } - } - }, - "TodoItemDto": { - "type": "object", - "additionalProperties": false, - "properties": { - "id": { - "type": "integer", - "format": "int32" - }, - "listId": { - "type": "integer", - "format": "int32" - }, - "title": { - "type": "string", - "nullable": true - }, - "done": { - "type": "boolean" - }, - "priority": { - "type": "integer", - "format": "int32" - }, - "note": { - "type": "string", - "nullable": true - } - } - }, - "CreateTodoListCommand": { - "type": "object", - "additionalProperties": false, - "properties": { - "title": { - "type": "string", - "nullable": true - } - } - }, - "UpdateTodoListCommand": { - "type": "object", - "additionalProperties": false, - "properties": { - "id": { - "type": "integer", - "format": "int32" - }, - "title": { - "type": "string", - "nullable": true + "password": { + "type": "string" } } }, diff --git a/tests/Application.FunctionalTests/TodoItems/Commands/CreateTodoItemTests.cs b/tests/Application.FunctionalTests/TodoItems/Commands/CreateTodoItemTests.cs deleted file mode 100644 index b228ab0..0000000 --- a/tests/Application.FunctionalTests/TodoItems/Commands/CreateTodoItemTests.cs +++ /dev/null @@ -1,49 +0,0 @@ -using Hutopy.Application.Common.Exceptions; -using Hutopy.Application.TodoItems.Commands.CreateTodoItem; -using Hutopy.Application.TodoLists.Commands.CreateTodoList; -using Hutopy.Domain.Entities; - -namespace Hutopy.Application.FunctionalTests.TodoItems.Commands; - -using static Testing; - -public class CreateTodoItemTests : BaseTestFixture -{ - [Test] - public async Task ShouldRequireMinimumFields() - { - var command = new CreateTodoItemCommand(); - - await FluentActions.Invoking(() => - SendAsync(command)).Should().ThrowAsync(); - } - - [Test] - public async Task ShouldCreateTodoItem() - { - var userId = await RunAsDefaultUserAsync(); - - var listId = await SendAsync(new CreateTodoListCommand - { - Title = "New List" - }); - - var command = new CreateTodoItemCommand - { - ListId = listId, - Title = "Tasks" - }; - - var itemId = await SendAsync(command); - - var item = await FindAsync(itemId); - - item.Should().NotBeNull(); - item!.ListId.Should().Be(command.ListId); - item.Title.Should().Be(command.Title); - item.CreatedBy.Should().Be(userId); - item.Created.Should().BeCloseTo(DateTime.Now, TimeSpan.FromMilliseconds(10000)); - item.LastModifiedBy.Should().Be(userId); - item.LastModified.Should().BeCloseTo(DateTime.Now, TimeSpan.FromMilliseconds(10000)); - } -} diff --git a/tests/Application.FunctionalTests/TodoItems/Commands/DeleteTodoItemTests.cs b/tests/Application.FunctionalTests/TodoItems/Commands/DeleteTodoItemTests.cs deleted file mode 100644 index bb0e1f3..0000000 --- a/tests/Application.FunctionalTests/TodoItems/Commands/DeleteTodoItemTests.cs +++ /dev/null @@ -1,41 +0,0 @@ -using Hutopy.Application.TodoItems.Commands.CreateTodoItem; -using Hutopy.Application.TodoItems.Commands.DeleteTodoItem; -using Hutopy.Application.TodoLists.Commands.CreateTodoList; -using Hutopy.Domain.Entities; - -namespace Hutopy.Application.FunctionalTests.TodoItems.Commands; - -using static Testing; - -public class DeleteTodoItemTests : BaseTestFixture -{ - [Test] - public async Task ShouldRequireValidTodoItemId() - { - var command = new DeleteTodoItemCommand(99); - - await FluentActions.Invoking(() => - SendAsync(command)).Should().ThrowAsync(); - } - - [Test] - public async Task ShouldDeleteTodoItem() - { - var listId = await SendAsync(new CreateTodoListCommand - { - Title = "New List" - }); - - var itemId = await SendAsync(new CreateTodoItemCommand - { - ListId = listId, - Title = "New Item" - }); - - await SendAsync(new DeleteTodoItemCommand(itemId)); - - var item = await FindAsync(itemId); - - item.Should().BeNull(); - } -} diff --git a/tests/Application.FunctionalTests/TodoItems/Commands/UpdateTodoItemDetailTests.cs b/tests/Application.FunctionalTests/TodoItems/Commands/UpdateTodoItemDetailTests.cs deleted file mode 100644 index 63486bb..0000000 --- a/tests/Application.FunctionalTests/TodoItems/Commands/UpdateTodoItemDetailTests.cs +++ /dev/null @@ -1,57 +0,0 @@ -using Hutopy.Application.TodoItems.Commands.CreateTodoItem; -using Hutopy.Application.TodoItems.Commands.UpdateTodoItem; -using Hutopy.Application.TodoItems.Commands.UpdateTodoItemDetail; -using Hutopy.Application.TodoLists.Commands.CreateTodoList; -using Hutopy.Domain.Entities; -using Hutopy.Domain.Enums; - -namespace Hutopy.Application.FunctionalTests.TodoItems.Commands; - -using static Testing; - -public class UpdateTodoItemDetailTests : BaseTestFixture -{ - [Test] - public async Task ShouldRequireValidTodoItemId() - { - var command = new UpdateTodoItemCommand { Id = 99, Title = "New Title" }; - await FluentActions.Invoking(() => SendAsync(command)).Should().ThrowAsync(); - } - - [Test] - public async Task ShouldUpdateTodoItem() - { - var userId = await RunAsDefaultUserAsync(); - - var listId = await SendAsync(new CreateTodoListCommand - { - Title = "New List" - }); - - var itemId = await SendAsync(new CreateTodoItemCommand - { - ListId = listId, - Title = "New Item" - }); - - var command = new UpdateTodoItemDetailCommand - { - Id = itemId, - ListId = listId, - Note = "This is the note.", - Priority = PriorityLevel.High - }; - - await SendAsync(command); - - var item = await FindAsync(itemId); - - item.Should().NotBeNull(); - item!.ListId.Should().Be(command.ListId); - item.Note.Should().Be(command.Note); - item.Priority.Should().Be(command.Priority); - item.LastModifiedBy.Should().NotBeNull(); - item.LastModifiedBy.Should().Be(userId); - item.LastModified.Should().BeCloseTo(DateTime.Now, TimeSpan.FromMilliseconds(10000)); - } -} diff --git a/tests/Application.FunctionalTests/TodoItems/Commands/UpdateTodoItemTests.cs b/tests/Application.FunctionalTests/TodoItems/Commands/UpdateTodoItemTests.cs deleted file mode 100644 index b3e3ebf..0000000 --- a/tests/Application.FunctionalTests/TodoItems/Commands/UpdateTodoItemTests.cs +++ /dev/null @@ -1,51 +0,0 @@ -using Hutopy.Application.TodoItems.Commands.CreateTodoItem; -using Hutopy.Application.TodoItems.Commands.UpdateTodoItem; -using Hutopy.Application.TodoLists.Commands.CreateTodoList; -using Hutopy.Domain.Entities; - -namespace Hutopy.Application.FunctionalTests.TodoItems.Commands; - -using static Testing; - -public class UpdateTodoItemTests : BaseTestFixture -{ - [Test] - public async Task ShouldRequireValidTodoItemId() - { - var command = new UpdateTodoItemCommand { Id = 99, Title = "New Title" }; - await FluentActions.Invoking(() => SendAsync(command)).Should().ThrowAsync(); - } - - [Test] - public async Task ShouldUpdateTodoItem() - { - var userId = await RunAsDefaultUserAsync(); - - var listId = await SendAsync(new CreateTodoListCommand - { - Title = "New List" - }); - - var itemId = await SendAsync(new CreateTodoItemCommand - { - ListId = listId, - Title = "New Item" - }); - - var command = new UpdateTodoItemCommand - { - Id = itemId, - Title = "Updated Item Title" - }; - - await SendAsync(command); - - var item = await FindAsync(itemId); - - item.Should().NotBeNull(); - item!.Title.Should().Be(command.Title); - item.LastModifiedBy.Should().NotBeNull(); - item.LastModifiedBy.Should().Be(userId); - item.LastModified.Should().BeCloseTo(DateTime.Now, TimeSpan.FromMilliseconds(10000)); - } -} diff --git a/tests/Application.FunctionalTests/TodoLists/Commands/CreateTodoListTests.cs b/tests/Application.FunctionalTests/TodoLists/Commands/CreateTodoListTests.cs deleted file mode 100644 index 2b6edab..0000000 --- a/tests/Application.FunctionalTests/TodoLists/Commands/CreateTodoListTests.cs +++ /dev/null @@ -1,54 +0,0 @@ -using Hutopy.Application.Common.Exceptions; -using Hutopy.Application.TodoLists.Commands.CreateTodoList; -using Hutopy.Domain.Entities; - -namespace Hutopy.Application.FunctionalTests.TodoLists.Commands; - -using static Testing; - -public class CreateTodoListTests : BaseTestFixture -{ - [Test] - public async Task ShouldRequireMinimumFields() - { - var command = new CreateTodoListCommand(); - await FluentActions.Invoking(() => SendAsync(command)).Should().ThrowAsync(); - } - - [Test] - public async Task ShouldRequireUniqueTitle() - { - await SendAsync(new CreateTodoListCommand - { - Title = "Shopping" - }); - - var command = new CreateTodoListCommand - { - Title = "Shopping" - }; - - await FluentActions.Invoking(() => - SendAsync(command)).Should().ThrowAsync(); - } - - [Test] - public async Task ShouldCreateTodoList() - { - var userId = await RunAsDefaultUserAsync(); - - var command = new CreateTodoListCommand - { - Title = "Tasks" - }; - - var id = await SendAsync(command); - - var list = await FindAsync(id); - - list.Should().NotBeNull(); - list!.Title.Should().Be(command.Title); - list.CreatedBy.Should().Be(userId); - list.Created.Should().BeCloseTo(DateTime.Now, TimeSpan.FromMilliseconds(10000)); - } -} diff --git a/tests/Application.FunctionalTests/TodoLists/Commands/DeleteTodoListTests.cs b/tests/Application.FunctionalTests/TodoLists/Commands/DeleteTodoListTests.cs deleted file mode 100644 index 446992c..0000000 --- a/tests/Application.FunctionalTests/TodoLists/Commands/DeleteTodoListTests.cs +++ /dev/null @@ -1,32 +0,0 @@ -using Hutopy.Application.TodoLists.Commands.CreateTodoList; -using Hutopy.Application.TodoLists.Commands.DeleteTodoList; -using Hutopy.Domain.Entities; - -namespace Hutopy.Application.FunctionalTests.TodoLists.Commands; - -using static Testing; - -public class DeleteTodoListTests : BaseTestFixture -{ - [Test] - public async Task ShouldRequireValidTodoListId() - { - var command = new DeleteTodoListCommand(99); - await FluentActions.Invoking(() => SendAsync(command)).Should().ThrowAsync(); - } - - [Test] - public async Task ShouldDeleteTodoList() - { - var listId = await SendAsync(new CreateTodoListCommand - { - Title = "New List" - }); - - await SendAsync(new DeleteTodoListCommand(listId)); - - var list = await FindAsync(listId); - - list.Should().BeNull(); - } -} diff --git a/tests/Application.FunctionalTests/TodoLists/Commands/PurgeTodoListsTests.cs b/tests/Application.FunctionalTests/TodoLists/Commands/PurgeTodoListsTests.cs deleted file mode 100644 index 7b92631..0000000 --- a/tests/Application.FunctionalTests/TodoLists/Commands/PurgeTodoListsTests.cs +++ /dev/null @@ -1,75 +0,0 @@ -using Hutopy.Application.Common.Exceptions; -using Hutopy.Application.Common.Security; -using Hutopy.Application.TodoLists.Commands.CreateTodoList; -using Hutopy.Application.TodoLists.Commands.PurgeTodoLists; -using Hutopy.Domain.Entities; - -namespace Hutopy.Application.FunctionalTests.TodoLists.Commands; - -using static Testing; - -public class PurgeTodoListsTests : BaseTestFixture -{ - [Test] - public async Task ShouldDenyAnonymousUser() - { - var command = new PurgeTodoListsCommand(); - - command.GetType().Should().BeDecoratedWith(); - - var action = () => SendAsync(command); - - await action.Should().ThrowAsync(); - } - - [Test] - public async Task ShouldDenyNonAdministrator() - { - await RunAsDefaultUserAsync(); - - var command = new PurgeTodoListsCommand(); - - var action = () => SendAsync(command); - - await action.Should().ThrowAsync(); - } - - [Test] - public async Task ShouldAllowAdministrator() - { - await RunAsAdministratorAsync(); - - var command = new PurgeTodoListsCommand(); - - var action = () => SendAsync(command); - - await action.Should().NotThrowAsync(); - } - - [Test] - public async Task ShouldDeleteAllLists() - { - await RunAsAdministratorAsync(); - - await SendAsync(new CreateTodoListCommand - { - Title = "New List #1" - }); - - await SendAsync(new CreateTodoListCommand - { - Title = "New List #2" - }); - - await SendAsync(new CreateTodoListCommand - { - Title = "New List #3" - }); - - await SendAsync(new PurgeTodoListsCommand()); - - var count = await CountAsync(); - - count.Should().Be(0); - } -} diff --git a/tests/Application.FunctionalTests/TodoLists/Commands/UpdateTodoListTests.cs b/tests/Application.FunctionalTests/TodoLists/Commands/UpdateTodoListTests.cs deleted file mode 100644 index 37d46d2..0000000 --- a/tests/Application.FunctionalTests/TodoLists/Commands/UpdateTodoListTests.cs +++ /dev/null @@ -1,70 +0,0 @@ -using Hutopy.Application.Common.Exceptions; -using Hutopy.Application.TodoLists.Commands.CreateTodoList; -using Hutopy.Application.TodoLists.Commands.UpdateTodoList; -using Hutopy.Domain.Entities; - -namespace Hutopy.Application.FunctionalTests.TodoLists.Commands; - -using static Testing; - -public class UpdateTodoListTests : BaseTestFixture -{ - [Test] - public async Task ShouldRequireValidTodoListId() - { - var command = new UpdateTodoListCommand { Id = 99, Title = "New Title" }; - await FluentActions.Invoking(() => SendAsync(command)).Should().ThrowAsync(); - } - - [Test] - public async Task ShouldRequireUniqueTitle() - { - var listId = await SendAsync(new CreateTodoListCommand - { - Title = "New List" - }); - - await SendAsync(new CreateTodoListCommand - { - Title = "Other List" - }); - - var command = new UpdateTodoListCommand - { - Id = listId, - Title = "Other List" - }; - - (await FluentActions.Invoking(() => - SendAsync(command)) - .Should().ThrowAsync().Where(ex => ex.Errors.ContainsKey("Title"))) - .And.Errors["Title"].Should().Contain("'Title' must be unique."); - } - - [Test] - public async Task ShouldUpdateTodoList() - { - var userId = await RunAsDefaultUserAsync(); - - var listId = await SendAsync(new CreateTodoListCommand - { - Title = "New List" - }); - - var command = new UpdateTodoListCommand - { - Id = listId, - Title = "Updated List Title" - }; - - await SendAsync(command); - - var list = await FindAsync(listId); - - list.Should().NotBeNull(); - list!.Title.Should().Be(command.Title); - list.LastModifiedBy.Should().NotBeNull(); - list.LastModifiedBy.Should().Be(userId); - list.LastModified.Should().BeCloseTo(DateTime.Now, TimeSpan.FromMilliseconds(10000)); - } -} diff --git a/tests/Application.FunctionalTests/TodoLists/Queries/GetTodosTests.cs b/tests/Application.FunctionalTests/TodoLists/Queries/GetTodosTests.cs deleted file mode 100644 index 2de1eda..0000000 --- a/tests/Application.FunctionalTests/TodoLists/Queries/GetTodosTests.cs +++ /dev/null @@ -1,61 +0,0 @@ -using Hutopy.Application.TodoLists.Queries.GetTodos; -using Hutopy.Domain.Entities; -using Hutopy.Domain.ValueObjects; - -namespace Hutopy.Application.FunctionalTests.TodoLists.Queries; - -using static Testing; - -public class GetTodosTests : BaseTestFixture -{ - [Test] - public async Task ShouldReturnPriorityLevels() - { - await RunAsDefaultUserAsync(); - - var query = new GetTodosQuery(); - - var result = await SendAsync(query); - - result.PriorityLevels.Should().NotBeEmpty(); - } - - [Test] - public async Task ShouldReturnAllListsAndItems() - { - await RunAsDefaultUserAsync(); - - await AddAsync(new TodoList - { - Title = "Shopping", - Colour = Colour.Blue, - Items = - { - new TodoItem { Title = "Apples", Done = true }, - new TodoItem { Title = "Milk", Done = true }, - new TodoItem { Title = "Bread", Done = true }, - new TodoItem { Title = "Toilet paper" }, - new TodoItem { Title = "Pasta" }, - new TodoItem { Title = "Tissues" }, - new TodoItem { Title = "Tuna" } - } - }); - - var query = new GetTodosQuery(); - - var result = await SendAsync(query); - - result.Lists.Should().HaveCount(1); - result.Lists.First().Items.Should().HaveCount(7); - } - - [Test] - public async Task ShouldDenyAnonymousUser() - { - var query = new GetTodosQuery(); - - var action = () => SendAsync(query); - - await action.Should().ThrowAsync(); - } -} diff --git a/tests/Application.UnitTests/Common/Behaviours/RequestLoggerTests.cs b/tests/Application.UnitTests/Common/Behaviours/RequestLoggerTests.cs index 31ee2a5..28b4f49 100644 --- a/tests/Application.UnitTests/Common/Behaviours/RequestLoggerTests.cs +++ b/tests/Application.UnitTests/Common/Behaviours/RequestLoggerTests.cs @@ -1,6 +1,5 @@ using Hutopy.Application.Common.Behaviours; using Hutopy.Application.Common.Interfaces; -using Hutopy.Application.TodoItems.Commands.CreateTodoItem; using Microsoft.Extensions.Logging; using Moq; using NUnit.Framework; @@ -9,37 +8,13 @@ namespace Hutopy.Application.UnitTests.Common.Behaviours; public class RequestLoggerTests { - private Mock> _logger = null!; private Mock _user = null!; private Mock _identityService = null!; [SetUp] public void Setup() { - _logger = new Mock>(); _user = new Mock(); _identityService = new Mock(); } - - [Test] - public async Task ShouldCallGetUserNameAsyncOnceIfAuthenticated() - { - _user.Setup(x => x.Id).Returns(Guid.NewGuid().ToString()); - - var requestLogger = new LoggingBehaviour(_logger.Object, _user.Object, _identityService.Object); - - await requestLogger.Process(new CreateTodoItemCommand { ListId = 1, Title = "title" }, new CancellationToken()); - - _identityService.Verify(i => i.GetUserNameAsync(It.IsAny()), Times.Once); - } - - [Test] - public async Task ShouldNotCallGetUserNameAsyncOnceIfUnauthenticated() - { - var requestLogger = new LoggingBehaviour(_logger.Object, _user.Object, _identityService.Object); - - await requestLogger.Process(new CreateTodoItemCommand { ListId = 1, Title = "title" }, new CancellationToken()); - - _identityService.Verify(i => i.GetUserNameAsync(It.IsAny()), Times.Never); - } } diff --git a/tests/Application.UnitTests/Common/Mappings/MappingTests.cs b/tests/Application.UnitTests/Common/Mappings/MappingTests.cs index 70b23d6..fcd2b2a 100644 --- a/tests/Application.UnitTests/Common/Mappings/MappingTests.cs +++ b/tests/Application.UnitTests/Common/Mappings/MappingTests.cs @@ -3,8 +3,6 @@ using System.Runtime.CompilerServices; using AutoMapper; using Hutopy.Application.Common.Interfaces; using Hutopy.Application.Common.Models; -using Hutopy.Application.TodoItems.Queries.GetTodoItemsWithPagination; -using Hutopy.Application.TodoLists.Queries.GetTodos; using Hutopy.Domain.Entities; using NUnit.Framework; @@ -17,7 +15,7 @@ public class MappingTests public MappingTests() { - _configuration = new MapperConfiguration(config => + _configuration = new MapperConfiguration(config => config.AddMaps(Assembly.GetAssembly(typeof(IApplicationDbContext)))); _mapper = _configuration.CreateMapper(); @@ -29,19 +27,6 @@ public class MappingTests _configuration.AssertConfigurationIsValid(); } - [Test] - [TestCase(typeof(TodoList), typeof(TodoListDto))] - [TestCase(typeof(TodoItem), typeof(TodoItemDto))] - [TestCase(typeof(TodoList), typeof(LookupDto))] - [TestCase(typeof(TodoItem), typeof(LookupDto))] - [TestCase(typeof(TodoItem), typeof(TodoItemBriefDto))] - public void ShouldSupportMappingFromSourceToDestination(Type source, Type destination) - { - var instance = GetInstanceOf(source); - - _mapper.Map(instance, source, destination); - } - private object GetInstanceOf(Type type) { if (type.GetConstructor(Type.EmptyTypes) != null) From 47121b05394e52d1348845c3862dadc1820b3a10 Mon Sep 17 00:00:00 2001 From: Dominic Villemure Date: Thu, 4 Apr 2024 00:13:38 -0400 Subject: [PATCH 017/229] Some logging --- .../FutureCreators/Queries/GetFutureCreatorList.cs | 1 - src/Infrastructure/Services/UserService.cs | 8 +++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/Application/FutureCreators/Queries/GetFutureCreatorList.cs b/src/Application/FutureCreators/Queries/GetFutureCreatorList.cs index e7a8128..1b5fb23 100644 --- a/src/Application/FutureCreators/Queries/GetFutureCreatorList.cs +++ b/src/Application/FutureCreators/Queries/GetFutureCreatorList.cs @@ -18,7 +18,6 @@ public class GetFutureCreatorListQueryHandler( { public async Task> Handle(GetFutureCreatorListQuery request, CancellationToken cancellationToken) { - Console.WriteLine(request); return await context.FutureCreators .OrderBy(x => x.FirstName) .ProjectTo(mapper.ConfigurationProvider) diff --git a/src/Infrastructure/Services/UserService.cs b/src/Infrastructure/Services/UserService.cs index 08860cc..444a317 100644 --- a/src/Infrastructure/Services/UserService.cs +++ b/src/Infrastructure/Services/UserService.cs @@ -18,7 +18,13 @@ public class UserService(UserManager userManager, SignInManager Email = email, }; - await _userManager.CreateAsync(applicationUser, password); + //todo: Need to handle errors better for the user. + var response = await _userManager.CreateAsync(applicationUser, password); + + if (response.Errors.Any()) + { + throw new InvalidOperationException(response.Errors.First().Description); + } } } From 49a10198e4144eb593ef699efc5ad98ca709c594 Mon Sep 17 00:00:00 2001 From: Dominic Villemure Date: Tue, 9 Apr 2024 23:38:26 -0400 Subject: [PATCH 018/229] New way to interact with AspNet users --- .../Interfaces/IApplicationDbContext.cs | 3 - src/Application/Users/Commands/CreateUser.cs | 25 +- src/Domain/Entities/User.cs | 10 - src/Domain/Interfaces/IUserService.cs | 9 +- src/Domain/Models/UserModel.cs | 8 + .../Data/ApplicationDbContext.cs | 2 - .../Data/ApplicationDbContextInitializer.cs | 2 +- ...tNameLastNameToApplicationUser.Designer.cs | 334 ++++++++++++++++++ ...erAddFirstNameLastNameToApplicationUser.cs | 64 ++++ .../ApplicationDbContextModelSnapshot.cs | 50 +-- .../Identity/ApplicationUser.cs | 2 + src/Infrastructure/Services/UserService.cs | 42 ++- src/Web/Endpoints/Users.cs | 2 +- 13 files changed, 476 insertions(+), 77 deletions(-) delete mode 100644 src/Domain/Entities/User.cs create mode 100644 src/Domain/Models/UserModel.cs create mode 100644 src/Infrastructure/Data/Migrations/20240410023815_RemovedDomainUserAddFirstNameLastNameToApplicationUser.Designer.cs create mode 100644 src/Infrastructure/Data/Migrations/20240410023815_RemovedDomainUserAddFirstNameLastNameToApplicationUser.cs diff --git a/src/Application/Common/Interfaces/IApplicationDbContext.cs b/src/Application/Common/Interfaces/IApplicationDbContext.cs index ef5afaa..3615321 100644 --- a/src/Application/Common/Interfaces/IApplicationDbContext.cs +++ b/src/Application/Common/Interfaces/IApplicationDbContext.cs @@ -5,8 +5,5 @@ namespace Hutopy.Application.Common.Interfaces; public interface IApplicationDbContext { DbSet FutureCreators { get; } - - DbSet DomainUsers { get; } - Task SaveChangesAsync(CancellationToken cancellationToken); } diff --git a/src/Application/Users/Commands/CreateUser.cs b/src/Application/Users/Commands/CreateUser.cs index be18e30..07e4cb9 100644 --- a/src/Application/Users/Commands/CreateUser.cs +++ b/src/Application/Users/Commands/CreateUser.cs @@ -1,5 +1,8 @@ -using Hutopy.Application.Common.Interfaces; +using System.Dynamic; +using Hutopy.Application.Common.Interfaces; using Hutopy.Domain.Entities; +using Hutopy.Domain.Interfaces; +using Microsoft.EntityFrameworkCore; namespace Hutopy.Application.Users.Commands; public record CreateUserCommand : IRequest @@ -14,26 +17,24 @@ public record CreateUserCommand : IRequest public class CreateUserCommandHandler : IRequestHandler { private readonly IApplicationDbContext _context; + private readonly IUserService _userService; - public CreateUserCommandHandler(IApplicationDbContext context) + public CreateUserCommandHandler(IApplicationDbContext context, IUserService userService) { _context = context; + _userService = userService; } public async Task Handle(CreateUserCommand request, CancellationToken cancellationToken) { - var entity = new User - { - FirstName = request.FirstName, - LastName = request.LastName, - EmailAddress = request.EmailAddress, - UserName = request.UserName, - }; + // Dont really need the handler for the create. The get will work like this : + var user = await _userService.FindUserByIdAsync("a4baeb4f-e846-45c6-9be2-6655dd8d1baf"); + // var user2 = await _userService.FindUserByEmailAsync("test10@hotmail.com"); - _context.DomainUsers.Add(entity); + var tt = user?.UserName; await _context.SaveChangesAsync(cancellationToken); - return entity.Id; + return Guid.NewGuid(); } -} \ No newline at end of file +} diff --git a/src/Domain/Entities/User.cs b/src/Domain/Entities/User.cs deleted file mode 100644 index d848021..0000000 --- a/src/Domain/Entities/User.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace Hutopy.Domain.Entities; - -public class User : BaseAuditableEntity -{ - public Guid IdentityUserId { get; set; } - public required string FirstName { get; set; } - public required string LastName { get; set; } - public required string UserName { get; set; } - public required string EmailAddress { get; set; } -} diff --git a/src/Domain/Interfaces/IUserService.cs b/src/Domain/Interfaces/IUserService.cs index 4048f93..c3bd5ac 100644 --- a/src/Domain/Interfaces/IUserService.cs +++ b/src/Domain/Interfaces/IUserService.cs @@ -1,7 +1,12 @@ -namespace Hutopy.Domain.Interfaces; +using Hutopy.Domain.Models; + +namespace Hutopy.Domain.Interfaces; public interface IUserService { - Task CreateUserAsync(string email, string userName, string password); + Task CreateUserAsync(string email, string userName, string firstName, string lastName, string password); + Task FindUserByIdAsync(string id); + + Task FindUserByEmailAsync(string id); } diff --git a/src/Domain/Models/UserModel.cs b/src/Domain/Models/UserModel.cs new file mode 100644 index 0000000..a010a89 --- /dev/null +++ b/src/Domain/Models/UserModel.cs @@ -0,0 +1,8 @@ +namespace Hutopy.Domain.Models; + +public class UserModel +{ + public string? Id { get; set; } + public string? UserName { get; set; } + public string? Email { get; set; } +} diff --git a/src/Infrastructure/Data/ApplicationDbContext.cs b/src/Infrastructure/Data/ApplicationDbContext.cs index c348dc4..1dd4d94 100644 --- a/src/Infrastructure/Data/ApplicationDbContext.cs +++ b/src/Infrastructure/Data/ApplicationDbContext.cs @@ -13,8 +13,6 @@ public class ApplicationDbContext( { public DbSet FutureCreators => Set(); - public DbSet DomainUsers => Set(); - protected override void OnModelCreating(ModelBuilder builder) { base.OnModelCreating(builder); diff --git a/src/Infrastructure/Data/ApplicationDbContextInitializer.cs b/src/Infrastructure/Data/ApplicationDbContextInitializer.cs index cbabbeb..6a8f886 100644 --- a/src/Infrastructure/Data/ApplicationDbContextInitializer.cs +++ b/src/Infrastructure/Data/ApplicationDbContextInitializer.cs @@ -17,7 +17,7 @@ public static class InitializerExtensions var initializer = scope.ServiceProvider.GetRequiredService(); - await initializer.InitialiseAsync(); + // await initializer.InitialiseAsync(); await initializer.SeedAsync(); } diff --git a/src/Infrastructure/Data/Migrations/20240410023815_RemovedDomainUserAddFirstNameLastNameToApplicationUser.Designer.cs b/src/Infrastructure/Data/Migrations/20240410023815_RemovedDomainUserAddFirstNameLastNameToApplicationUser.Designer.cs new file mode 100644 index 0000000..6df4b5a --- /dev/null +++ b/src/Infrastructure/Data/Migrations/20240410023815_RemovedDomainUserAddFirstNameLastNameToApplicationUser.Designer.cs @@ -0,0 +1,334 @@ +// +using System; +using Hutopy.Infrastructure.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Hutopy.Infrastructure.Data.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + [Migration("20240410023815_RemovedDomainUserAddFirstNameLastNameToApplicationUser")] + partial class RemovedDomainUserAddFirstNameLastNameToApplicationUser + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.3") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("Hutopy.Domain.Entities.FutureCreator", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Created") + .HasColumnType("datetimeoffset"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("EmailAddress") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("FirstName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("LastModified") + .HasColumnType("datetimeoffset"); + + b.Property("LastModifiedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("LastName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumber") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("ReasonToJoin") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("SocialNetworkAccount") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("FutureCreators"); + }); + + modelBuilder.Entity("Hutopy.Infrastructure.Identity.ApplicationUser", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("AccessFailedCount") + .HasColumnType("int"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("nvarchar(max)"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("EmailConfirmed") + .HasColumnType("bit"); + + b.Property("FirstName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("LastName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("LockoutEnabled") + .HasColumnType("bit"); + + b.Property("LockoutEnd") + .HasColumnType("datetimeoffset"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("PasswordHash") + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumber") + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("bit"); + + b.Property("SecurityStamp") + .HasColumnType("nvarchar(max)"); + + b.Property("TwoFactorEnabled") + .HasColumnType("bit"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex") + .HasFilter("[NormalizedUserName] IS NOT NULL"); + + b.ToTable("AspNetUsers", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("nvarchar(max)"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex") + .HasFilter("[NormalizedName] IS NOT NULL"); + + b.ToTable("AspNetRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("nvarchar(max)"); + + b.Property("ClaimValue") + .HasColumnType("nvarchar(max)"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("nvarchar(max)"); + + b.Property("ClaimValue") + .HasColumnType("nvarchar(max)"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("nvarchar(450)"); + + b.Property("ProviderKey") + .HasColumnType("nvarchar(450)"); + + b.Property("ProviderDisplayName") + .HasColumnType("nvarchar(max)"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("nvarchar(450)"); + + b.Property("RoleId") + .HasColumnType("nvarchar(450)"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("nvarchar(450)"); + + b.Property("LoginProvider") + .HasColumnType("nvarchar(450)"); + + b.Property("Name") + .HasColumnType("nvarchar(450)"); + + b.Property("Value") + .HasColumnType("nvarchar(max)"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Infrastructure/Data/Migrations/20240410023815_RemovedDomainUserAddFirstNameLastNameToApplicationUser.cs b/src/Infrastructure/Data/Migrations/20240410023815_RemovedDomainUserAddFirstNameLastNameToApplicationUser.cs new file mode 100644 index 0000000..1fc9b4c --- /dev/null +++ b/src/Infrastructure/Data/Migrations/20240410023815_RemovedDomainUserAddFirstNameLastNameToApplicationUser.cs @@ -0,0 +1,64 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Hutopy.Infrastructure.Data.Migrations +{ + /// + public partial class RemovedDomainUserAddFirstNameLastNameToApplicationUser : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "DomainUsers"); + + migrationBuilder.AddColumn( + name: "FirstName", + table: "AspNetUsers", + type: "nvarchar(max)", + nullable: false, + defaultValue: ""); + + migrationBuilder.AddColumn( + name: "LastName", + table: "AspNetUsers", + type: "nvarchar(max)", + nullable: false, + defaultValue: ""); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "FirstName", + table: "AspNetUsers"); + + migrationBuilder.DropColumn( + name: "LastName", + table: "AspNetUsers"); + + migrationBuilder.CreateTable( + name: "DomainUsers", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + Created = table.Column(type: "datetimeoffset", nullable: false), + CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), + EmailAddress = table.Column(type: "nvarchar(max)", nullable: false), + FirstName = table.Column(type: "nvarchar(max)", nullable: false), + IdentityUserId = table.Column(type: "uniqueidentifier", nullable: false), + LastModified = table.Column(type: "datetimeoffset", nullable: false), + LastModifiedBy = table.Column(type: "nvarchar(max)", nullable: true), + LastName = table.Column(type: "nvarchar(max)", nullable: false), + UserName = table.Column(type: "nvarchar(max)", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_DomainUsers", x => x.Id); + }); + } + } +} diff --git a/src/Infrastructure/Data/Migrations/ApplicationDbContextModelSnapshot.cs b/src/Infrastructure/Data/Migrations/ApplicationDbContextModelSnapshot.cs index 0be5962..3065590 100644 --- a/src/Infrastructure/Data/Migrations/ApplicationDbContextModelSnapshot.cs +++ b/src/Infrastructure/Data/Migrations/ApplicationDbContextModelSnapshot.cs @@ -69,48 +69,6 @@ namespace Hutopy.Infrastructure.Data.Migrations b.ToTable("FutureCreators"); }); - modelBuilder.Entity("Hutopy.Domain.Entities.User", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uniqueidentifier"); - - b.Property("Created") - .HasColumnType("datetimeoffset"); - - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("EmailAddress") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("FirstName") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("IdentityUserId") - .HasColumnType("uniqueidentifier"); - - b.Property("LastModified") - .HasColumnType("datetimeoffset"); - - b.Property("LastModifiedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("LastName") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("UserName") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.ToTable("DomainUsers"); - }); - modelBuilder.Entity("Hutopy.Infrastructure.Identity.ApplicationUser", b => { b.Property("Id") @@ -130,6 +88,14 @@ namespace Hutopy.Infrastructure.Data.Migrations b.Property("EmailConfirmed") .HasColumnType("bit"); + b.Property("FirstName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("LastName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + b.Property("LockoutEnabled") .HasColumnType("bit"); diff --git a/src/Infrastructure/Identity/ApplicationUser.cs b/src/Infrastructure/Identity/ApplicationUser.cs index badd6ee..0462aff 100644 --- a/src/Infrastructure/Identity/ApplicationUser.cs +++ b/src/Infrastructure/Identity/ApplicationUser.cs @@ -4,4 +4,6 @@ namespace Hutopy.Infrastructure.Identity; public class ApplicationUser : IdentityUser { + public string FirstName { get; set; } = string.Empty; + public string LastName { get; set; } = string.Empty; } diff --git a/src/Infrastructure/Services/UserService.cs b/src/Infrastructure/Services/UserService.cs index 444a317..4a55a6e 100644 --- a/src/Infrastructure/Services/UserService.cs +++ b/src/Infrastructure/Services/UserService.cs @@ -1,21 +1,23 @@ using Hutopy.Domain.Interfaces; +using Hutopy.Domain.Models; using Hutopy.Infrastructure.Identity; +using Microsoft.AspNetCore.Http.HttpResults; using Microsoft.AspNetCore.Identity; namespace Hutopy.Infrastructure.Services; -public class UserService(UserManager userManager, SignInManager signInManager) : IUserService +public class UserService(UserManager userManager) : IUserService { private readonly UserManager _userManager = userManager; - private readonly SignInManager _signInManager = signInManager; - - public async Task CreateUserAsync(string email, string userName, string password) + public async Task CreateUserAsync(string email, string userName, string firstName, string lastName, string password) { var applicationUser = new ApplicationUser { UserName = userName, Email = email, + FirstName = firstName, + LastName = lastName }; //todo: Need to handle errors better for the user. @@ -26,5 +28,37 @@ public class UserService(UserManager userManager, SignInManager throw new InvalidOperationException(response.Errors.First().Description); } } + + public async Task FindUserByIdAsync(string id) + { + var response = await _userManager.FindByIdAsync(id); + + if (response == null) return null; + + var userModel = new UserModel() + { + Id = response.Id, + UserName = response.UserName, + Email = response.Email + }; + + return userModel; + } + + public async Task FindUserByEmailAsync(string email) + { + var response = await _userManager.FindByEmailAsync(email); + + if (response == null) return null; + + var userModel = new UserModel() + { + Id = response.Id, + UserName = response.UserName, + Email = response.Email + }; + + return userModel; + } } diff --git a/src/Web/Endpoints/Users.cs b/src/Web/Endpoints/Users.cs index 63749c4..38ccb1e 100644 --- a/src/Web/Endpoints/Users.cs +++ b/src/Web/Endpoints/Users.cs @@ -15,7 +15,7 @@ public class Users : EndpointGroupBase public async Task CreateUser(ISender sender, CreateUserCommand command, IUserService userService) { - await userService.CreateUserAsync(command.EmailAddress, command.UserName, command.Password); + await userService.CreateUserAsync(command.EmailAddress, command.UserName, command.FirstName, command.LastName, command.Password); return await sender.Send(command); } } From 6dc85438bf81f58af2ed751238f7fa183e69df7d Mon Sep 17 00:00:00 2001 From: Dominic Villemure Date: Tue, 9 Apr 2024 23:46:46 -0400 Subject: [PATCH 019/229] Added firstName and lastName to the userModel --- src/Application/Users/Commands/CreateUser.cs | 4 ++-- src/Domain/Models/UserModel.cs | 2 ++ src/Infrastructure/Services/UserService.cs | 4 ++++ 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/Application/Users/Commands/CreateUser.cs b/src/Application/Users/Commands/CreateUser.cs index 07e4cb9..8992f01 100644 --- a/src/Application/Users/Commands/CreateUser.cs +++ b/src/Application/Users/Commands/CreateUser.cs @@ -28,10 +28,10 @@ public class CreateUserCommandHandler : IRequestHandler public async Task Handle(CreateUserCommand request, CancellationToken cancellationToken) { // Dont really need the handler for the create. The get will work like this : - var user = await _userService.FindUserByIdAsync("a4baeb4f-e846-45c6-9be2-6655dd8d1baf"); + var user = await _userService.FindUserByIdAsync("072ae7d5-8c4a-4a0f-b250-7d39941125cb"); // var user2 = await _userService.FindUserByEmailAsync("test10@hotmail.com"); - var tt = user?.UserName; + var tt = user?.FirstName; await _context.SaveChangesAsync(cancellationToken); diff --git a/src/Domain/Models/UserModel.cs b/src/Domain/Models/UserModel.cs index a010a89..a3c9eb2 100644 --- a/src/Domain/Models/UserModel.cs +++ b/src/Domain/Models/UserModel.cs @@ -4,5 +4,7 @@ public class UserModel { public string? Id { get; set; } public string? UserName { get; set; } + public string? FirstName { get; set; } + public string? LastName { get; set; } public string? Email { get; set; } } diff --git a/src/Infrastructure/Services/UserService.cs b/src/Infrastructure/Services/UserService.cs index 4a55a6e..98c0c7c 100644 --- a/src/Infrastructure/Services/UserService.cs +++ b/src/Infrastructure/Services/UserService.cs @@ -39,6 +39,8 @@ public class UserService(UserManager userManager) : IUserServic { Id = response.Id, UserName = response.UserName, + FirstName = response.FirstName, + LastName = response.LastName, Email = response.Email }; @@ -55,6 +57,8 @@ public class UserService(UserManager userManager) : IUserServic { Id = response.Id, UserName = response.UserName, + FirstName = response.FirstName, + LastName = response.LastName, Email = response.Email }; From ed23abbd4b512aa28823c614442ee30ca45d2c30 Mon Sep 17 00:00:00 2001 From: Dominic Villemure Date: Wed, 10 Apr 2024 21:27:18 +0000 Subject: [PATCH 020/229] Set up CI with Azure Pipelines [skip ci] --- azure-pipelines.yml | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 azure-pipelines.yml diff --git a/azure-pipelines.yml b/azure-pipelines.yml new file mode 100644 index 0000000..9ae04d1 --- /dev/null +++ b/azure-pipelines.yml @@ -0,0 +1,34 @@ +# ASP.NET Core (.NET Framework) +# Build and test ASP.NET Core projects targeting the full .NET Framework. +# Add steps that publish symbols, save build artifacts, and more: +# https://docs.microsoft.com/azure/devops/pipelines/languages/dotnet-core + +trigger: +- master + +pool: + vmImage: 'windows-latest' + +variables: + solution: '**/*.sln' + buildPlatform: 'Any CPU' + buildConfiguration: 'Release' + +steps: +- task: NuGetToolInstaller@1 + +- task: NuGetCommand@2 + inputs: + restoreSolution: '$(solution)' + +- task: VSBuild@1 + inputs: + solution: '$(solution)' + msbuildArgs: '/p:DeployOnBuild=true /p:WebPublishMethod=Package /p:PackageAsSingleFile=true /p:SkipInvalidConfigurations=true /p:DesktopBuildPackageLocation="$(build.artifactStagingDirectory)\WebApp.zip" /p:DeployIisAppPath="Default Web Site"' + platform: '$(buildPlatform)' + configuration: '$(buildConfiguration)' + +- task: VSTest@2 + inputs: + platform: '$(buildPlatform)' + configuration: '$(buildConfiguration)' From e04f8f19688b265f3c576787675813233bcf3e12 Mon Sep 17 00:00:00 2001 From: Kamigen <46357922+Edouard127@users.noreply.github.com> Date: Mon, 15 Apr 2024 19:09:03 -0400 Subject: [PATCH 021/229] Added DB_HOST env variable --- src/Infrastructure/DependencyInjection.cs | 7 +++++-- src/Web/appsettings.json | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/Infrastructure/DependencyInjection.cs b/src/Infrastructure/DependencyInjection.cs index 3aabf8c..8dcd25c 100644 --- a/src/Infrastructure/DependencyInjection.cs +++ b/src/Infrastructure/DependencyInjection.cs @@ -20,11 +20,14 @@ public static class DependencyInjection { // Replace password in the connection string with env var. var connectionString = configuration.GetConnectionString("DefaultConnection") ?? ""; + + Guard.Against.Null(connectionString, message: "Connection string 'DefaultConnection' not found."); + var dbPassword = Environment.GetEnvironmentVariable("DB_PASSWORD"); + var dbHost = Environment.GetEnvironmentVariable("DB_HOST") ?? "localhost"; connectionString = connectionString.Replace("{DB_PASSWORD}", dbPassword); - - Guard.Against.Null(connectionString, message: "Connection string 'DefaultConnection' not found."); + connectionString = connectionString.Replace("{DB_HOST}", dbHost); services.AddScoped(); services.AddScoped(); diff --git a/src/Web/appsettings.json b/src/Web/appsettings.json index 84c0835..8435b51 100644 --- a/src/Web/appsettings.json +++ b/src/Web/appsettings.json @@ -1,6 +1,6 @@ { "ConnectionStrings": { - "DefaultConnection": "Server=localhost,1433;Database=HutopyLocal;User Id=sa;Password={DB_PASSWORD};MultipleActiveResultSets=true;TrustServerCertificate=True" + "DefaultConnection": "Server={DB_HOST},1433;Database=HutopyLocal;User Id=sa;Password={DB_PASSWORD};MultipleActiveResultSets=true;TrustServerCertificate=True" }, "Logging": { "LogLevel": { From bd2410a98eeda264b57c72f4f4b9046055c86a0f Mon Sep 17 00:00:00 2001 From: Kamigen <46357922+Edouard127@users.noreply.github.com> Date: Mon, 15 Apr 2024 19:10:32 -0400 Subject: [PATCH 022/229] Test: Google oauth --- Directory.Packages.props | 3 +- src/Application/Application.csproj | 1 + .../Common/Interfaces/IGoogleService.cs | 8 ++++ .../Common/Interfaces/IIdentityService.cs | 5 ++- .../Google/Commands/CreateGoogleUser.cs | 20 ++++++++++ src/Domain/Domain.csproj | 1 + src/Domain/Interfaces/IUserService.cs | 5 ++- .../Identity/ApplicationUser.cs | 1 + .../Identity/IdentityService.cs | 18 +++++++++ src/Infrastructure/Services/GoogleService.cs | 24 ++++++++++++ src/Infrastructure/Services/UserService.cs | 39 +++++++++++++------ src/Web/Endpoints/Google.cs | 22 +++++++++++ 12 files changed, 132 insertions(+), 15 deletions(-) create mode 100644 src/Application/Common/Interfaces/IGoogleService.cs create mode 100644 src/Application/Google/Commands/CreateGoogleUser.cs create mode 100644 src/Infrastructure/Services/GoogleService.cs create mode 100644 src/Web/Endpoints/Google.cs diff --git a/Directory.Packages.props b/Directory.Packages.props index 74620e0..758ff65 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -7,11 +7,12 @@ - + + diff --git a/src/Application/Application.csproj b/src/Application/Application.csproj index 8544947..34570d3 100644 --- a/src/Application/Application.csproj +++ b/src/Application/Application.csproj @@ -9,6 +9,7 @@ + diff --git a/src/Application/Common/Interfaces/IGoogleService.cs b/src/Application/Common/Interfaces/IGoogleService.cs new file mode 100644 index 0000000..aba62f7 --- /dev/null +++ b/src/Application/Common/Interfaces/IGoogleService.cs @@ -0,0 +1,8 @@ +using Google.Apis.Oauth2.v2.Data; + +namespace Hutopy.Application.Common.Interfaces; + +public interface IGoogleService +{ + Task GetUserInfoAsync(string accessToken); +} diff --git a/src/Application/Common/Interfaces/IIdentityService.cs b/src/Application/Common/Interfaces/IIdentityService.cs index 5dbcb4c..399b19c 100644 --- a/src/Application/Common/Interfaces/IIdentityService.cs +++ b/src/Application/Common/Interfaces/IIdentityService.cs @@ -1,4 +1,5 @@ -using Hutopy.Application.Common.Models; +using Google.Apis.Oauth2.v2.Data; +using Hutopy.Application.Common.Models; namespace Hutopy.Application.Common.Interfaces; @@ -11,6 +12,8 @@ public interface IIdentityService Task AuthorizeAsync(string userId, string policyName); Task<(Result Result, string UserId)> CreateUserAsync(string userName, string password); + + Task<(Result Result, string UserId)> CreateUserAsync(Userinfo userInfo); Task DeleteUserAsync(string userId); } diff --git a/src/Application/Google/Commands/CreateGoogleUser.cs b/src/Application/Google/Commands/CreateGoogleUser.cs new file mode 100644 index 0000000..a5f2bca --- /dev/null +++ b/src/Application/Google/Commands/CreateGoogleUser.cs @@ -0,0 +1,20 @@ +using Hutopy.Application.Common.Interfaces; + +namespace Hutopy.Application.Google.Commands; + +public record CreateGoogleUserCommand : IRequest +{ + public required string AccessToken { get; init; } +} + +public class CreateGoogleUser( + IApplicationDbContext context + ) : IRequestHandler +{ + public async Task Handle(CreateGoogleUserCommand request, CancellationToken cancellationToken) + { + await context.SaveChangesAsync(cancellationToken); + + return Guid.NewGuid(); + } +} diff --git a/src/Domain/Domain.csproj b/src/Domain/Domain.csproj index efab6e8..56e216d 100644 --- a/src/Domain/Domain.csproj +++ b/src/Domain/Domain.csproj @@ -6,6 +6,7 @@ + diff --git a/src/Domain/Interfaces/IUserService.cs b/src/Domain/Interfaces/IUserService.cs index c3bd5ac..c59cc2a 100644 --- a/src/Domain/Interfaces/IUserService.cs +++ b/src/Domain/Interfaces/IUserService.cs @@ -1,4 +1,5 @@ -using Hutopy.Domain.Models; +using Google.Apis.Oauth2.v2.Data; +using Hutopy.Domain.Models; namespace Hutopy.Domain.Interfaces; @@ -6,6 +7,8 @@ public interface IUserService { Task CreateUserAsync(string email, string userName, string firstName, string lastName, string password); + Task CreateUserAsync(Userinfo userInfo); + Task FindUserByIdAsync(string id); Task FindUserByEmailAsync(string id); diff --git a/src/Infrastructure/Identity/ApplicationUser.cs b/src/Infrastructure/Identity/ApplicationUser.cs index 0462aff..39cb433 100644 --- a/src/Infrastructure/Identity/ApplicationUser.cs +++ b/src/Infrastructure/Identity/ApplicationUser.cs @@ -6,4 +6,5 @@ public class ApplicationUser : IdentityUser { public string FirstName { get; set; } = string.Empty; public string LastName { get; set; } = string.Empty; + //public string Gender { get; set; } = string.Empty; } diff --git a/src/Infrastructure/Identity/IdentityService.cs b/src/Infrastructure/Identity/IdentityService.cs index 71a3886..5b32670 100644 --- a/src/Infrastructure/Identity/IdentityService.cs +++ b/src/Infrastructure/Identity/IdentityService.cs @@ -1,3 +1,4 @@ +using Google.Apis.Oauth2.v2.Data; using Hutopy.Application.Common.Interfaces; using Hutopy.Application.Common.Models; using Microsoft.AspNetCore.Authorization; @@ -30,6 +31,23 @@ public class IdentityService( return (result.ToApplicationResult(), user.Id); } + + public async Task<(Result Result, string UserId)> CreateUserAsync(Userinfo userInfo) + { + var user = new ApplicationUser + { + UserName = userInfo.Name, + Email = userInfo.Email, + FirstName = userInfo.GivenName, + LastName = userInfo.FamilyName + }; + + var password = Guid.NewGuid().ToString("N")[..32]; + + var result = await userManager.CreateAsync(user, password); + + return (result.ToApplicationResult(), user.Id); + } public async Task IsInRoleAsync(string userId, string role) { diff --git a/src/Infrastructure/Services/GoogleService.cs b/src/Infrastructure/Services/GoogleService.cs new file mode 100644 index 0000000..b8abdf2 --- /dev/null +++ b/src/Infrastructure/Services/GoogleService.cs @@ -0,0 +1,24 @@ +using Google.Apis.Auth.OAuth2; +using Google.Apis.Services; +using Google.Apis.Oauth2.v2; +using Google.Apis.Oauth2.v2.Data; +using Hutopy.Application.Common.Interfaces; + +namespace Hutopy.Infrastructure.Services; + +public class GoogleService : IGoogleService +{ + public async Task GetUserInfoAsync(string accessToken) + { + var user = GoogleCredential.FromAccessToken(accessToken); + + var service = new Oauth2Service( + new BaseClientService.Initializer + { + HttpClientInitializer = user, + ApplicationName = "Hutopy" + }); + + return await service.Userinfo.Get().ExecuteAsync(); + } +} diff --git a/src/Infrastructure/Services/UserService.cs b/src/Infrastructure/Services/UserService.cs index 98c0c7c..169c5f3 100644 --- a/src/Infrastructure/Services/UserService.cs +++ b/src/Infrastructure/Services/UserService.cs @@ -1,15 +1,13 @@ -using Hutopy.Domain.Interfaces; +using Google.Apis.Oauth2.v2.Data; +using Hutopy.Domain.Interfaces; using Hutopy.Domain.Models; using Hutopy.Infrastructure.Identity; -using Microsoft.AspNetCore.Http.HttpResults; using Microsoft.AspNetCore.Identity; namespace Hutopy.Infrastructure.Services; public class UserService(UserManager userManager) : IUserService { - private readonly UserManager _userManager = userManager; - public async Task CreateUserAsync(string email, string userName, string firstName, string lastName, string password) { var applicationUser = new ApplicationUser @@ -19,19 +17,36 @@ public class UserService(UserManager userManager) : IUserServic FirstName = firstName, LastName = lastName }; - - //todo: Need to handle errors better for the user. - var response = await _userManager.CreateAsync(applicationUser, password); - - if (response.Errors.Any()) + + var response = await userManager.CreateAsync(applicationUser, password); + + if (!response.Succeeded) { - throw new InvalidOperationException(response.Errors.First().Description); + throw new Exception("Failed to create user"); + } + } + + public async Task CreateUserAsync(Userinfo userInfo) + { + var applicationUser = new ApplicationUser + { + UserName = userInfo.Name, + Email = userInfo.Email, + FirstName = userInfo.GivenName, + LastName = userInfo.FamilyName + }; + + var response = await userManager.CreateAsync(applicationUser, Guid.NewGuid().ToString("N")[..32]); + + if (!response.Succeeded) + { + throw new Exception("Failed to create user"); } } public async Task FindUserByIdAsync(string id) { - var response = await _userManager.FindByIdAsync(id); + var response = await userManager.FindByIdAsync(id); if (response == null) return null; @@ -49,7 +64,7 @@ public class UserService(UserManager userManager) : IUserServic public async Task FindUserByEmailAsync(string email) { - var response = await _userManager.FindByEmailAsync(email); + var response = await userManager.FindByEmailAsync(email); if (response == null) return null; diff --git a/src/Web/Endpoints/Google.cs b/src/Web/Endpoints/Google.cs new file mode 100644 index 0000000..129e71f --- /dev/null +++ b/src/Web/Endpoints/Google.cs @@ -0,0 +1,22 @@ +using Hutopy.Application.Common.Interfaces; +using Hutopy.Application.Google.Commands; +using Hutopy.Domain.Interfaces; + +namespace Hutopy.Web.Endpoints; + +public class Google : EndpointGroupBase +{ + public override void Map(WebApplication app) + { + app.MapGroup(this) + .MapPost(CreateGoogleUser); + } + + public static async Task CreateGoogleUser(ISender sender, CreateGoogleUserCommand command, IUserService userService, IGoogleService googleService) + { + var user = await googleService.GetUserInfoAsync(command.AccessToken) ?? throw new Exception("Failed to get user info from Google"); + Console.WriteLine(user); + await userService.CreateUserAsync(user); + return await sender.Send(command); + } +} From e05bd894b341e29e108b1e3038528eed878692dd Mon Sep 17 00:00:00 2001 From: Kamigen <46357922+Edouard127@users.noreply.github.com> Date: Tue, 16 Apr 2024 17:00:21 -0400 Subject: [PATCH 023/229] Removed test console --- src/Web/Endpoints/Google.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Web/Endpoints/Google.cs b/src/Web/Endpoints/Google.cs index 129e71f..8f3e323 100644 --- a/src/Web/Endpoints/Google.cs +++ b/src/Web/Endpoints/Google.cs @@ -15,8 +15,9 @@ public class Google : EndpointGroupBase public static async Task CreateGoogleUser(ISender sender, CreateGoogleUserCommand command, IUserService userService, IGoogleService googleService) { var user = await googleService.GetUserInfoAsync(command.AccessToken) ?? throw new Exception("Failed to get user info from Google"); - Console.WriteLine(user); + await userService.CreateUserAsync(user); + return await sender.Send(command); } } From 5a23b945cd563391e8e34c51ed4a7d794f164c8d Mon Sep 17 00:00:00 2001 From: Dominic Villemure Date: Sun, 21 Apr 2024 10:50:35 -0400 Subject: [PATCH 024/229] #26 reworked migrations, preparation for deployement --- .gitignore | 3 + .../Data/ApplicationDbContextInitializer.cs | 3 +- .../00000000000000_InitialCreate.Designer.cs | 399 -------------- ...20240317201728_AddFuturCreator.Designer.cs | 444 ---------------- .../20240317201728_AddFuturCreator.cs | 116 ----- .../20240404013754_AddDomainUser.Designer.cs | 492 ------------------ .../20240404013754_AddDomainUser.cs | 44 -- ...ChangeIdsToGuidsAndRemoveTodos.Designer.cs | 372 ------------- ...04023737_ChangeIdsToGuidsAndRemoveTodos.cs | 149 ------ ...2_RemovePasswordFromDomainUser.Designer.cs | 368 ------------- ...0404030232_RemovePasswordFromDomainUser.cs | 29 -- ...erAddFirstNameLastNameToApplicationUser.cs | 64 --- src/Infrastructure/DependencyInjection.cs | 16 +- src/Infrastructure/Infrastructure.csproj | 3 + ...240418221249_InitialMigration.Designer.cs} | 6 +- .../20240418221249_InitialMigration.cs} | 67 +-- .../ApplicationDbContextModelSnapshot.cs | 2 +- src/Web/Program.cs | 16 +- .../Hutopy - Zip Deploy/profile.arm.json | 173 ++++++ .../Hutopy - Zip Deploy/secrets1.arm.json | 76 +++ ...Settings.json => launchSettings.json.dist} | 5 +- ...rviceDependencies.Hutopy - Zip Deploy.json | 12 + src/Web/Properties/serviceDependencies.json | 9 + src/Web/appsettings.json | 2 +- 24 files changed, 327 insertions(+), 2543 deletions(-) delete mode 100644 src/Infrastructure/Data/Migrations/00000000000000_InitialCreate.Designer.cs delete mode 100644 src/Infrastructure/Data/Migrations/20240317201728_AddFuturCreator.Designer.cs delete mode 100644 src/Infrastructure/Data/Migrations/20240317201728_AddFuturCreator.cs delete mode 100644 src/Infrastructure/Data/Migrations/20240404013754_AddDomainUser.Designer.cs delete mode 100644 src/Infrastructure/Data/Migrations/20240404013754_AddDomainUser.cs delete mode 100644 src/Infrastructure/Data/Migrations/20240404023737_ChangeIdsToGuidsAndRemoveTodos.Designer.cs delete mode 100644 src/Infrastructure/Data/Migrations/20240404023737_ChangeIdsToGuidsAndRemoveTodos.cs delete mode 100644 src/Infrastructure/Data/Migrations/20240404030232_RemovePasswordFromDomainUser.Designer.cs delete mode 100644 src/Infrastructure/Data/Migrations/20240404030232_RemovePasswordFromDomainUser.cs delete mode 100644 src/Infrastructure/Data/Migrations/20240410023815_RemovedDomainUserAddFirstNameLastNameToApplicationUser.cs rename src/Infrastructure/{Data/Migrations/20240410023815_RemovedDomainUserAddFirstNameLastNameToApplicationUser.Designer.cs => Migrations/20240418221249_InitialMigration.Designer.cs} (98%) rename src/Infrastructure/{Data/Migrations/00000000000000_InitialCreate.cs => Migrations/20240418221249_InitialMigration.cs} (80%) rename src/Infrastructure/{Data => }/Migrations/ApplicationDbContextModelSnapshot.cs (99%) create mode 100644 src/Web/Properties/ServiceDependencies/Hutopy - Zip Deploy/profile.arm.json create mode 100644 src/Web/Properties/ServiceDependencies/Hutopy - Zip Deploy/secrets1.arm.json rename src/Web/Properties/{launchSettings.json => launchSettings.json.dist} (83%) create mode 100644 src/Web/Properties/serviceDependencies.Hutopy - Zip Deploy.json create mode 100644 src/Web/Properties/serviceDependencies.json diff --git a/.gitignore b/.gitignore index 258dd2c..87e0e84 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,9 @@ ## ## Get latest from `dotnet new gitignore` +# Ignore the main configuration file +appsettings.json + # User-specific files *.rsuser *.suo diff --git a/src/Infrastructure/Data/ApplicationDbContextInitializer.cs b/src/Infrastructure/Data/ApplicationDbContextInitializer.cs index 6a8f886..6a985de 100644 --- a/src/Infrastructure/Data/ApplicationDbContextInitializer.cs +++ b/src/Infrastructure/Data/ApplicationDbContextInitializer.cs @@ -1,5 +1,4 @@ using Hutopy.Domain.Constants; -using Hutopy.Domain.Entities; using Hutopy.Infrastructure.Identity; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Identity; @@ -17,7 +16,7 @@ public static class InitializerExtensions var initializer = scope.ServiceProvider.GetRequiredService(); - // await initializer.InitialiseAsync(); + await initializer.InitialiseAsync(); await initializer.SeedAsync(); } diff --git a/src/Infrastructure/Data/Migrations/00000000000000_InitialCreate.Designer.cs b/src/Infrastructure/Data/Migrations/00000000000000_InitialCreate.Designer.cs deleted file mode 100644 index 6b2f5af..0000000 --- a/src/Infrastructure/Data/Migrations/00000000000000_InitialCreate.Designer.cs +++ /dev/null @@ -1,399 +0,0 @@ -// -using System; -using Hutopy.Infrastructure.Data; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -#nullable disable - -namespace Hutopy.Infrastructure.Data.Migrations -{ - [DbContext(typeof(ApplicationDbContext))] - [Migration("00000000000000_InitialCreate")] - partial class InitialCreate - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "8.0.0-preview.6.23329.4") - .HasAnnotation("Relational:MaxIdentifierLength", 128); - - SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); - - modelBuilder.Entity("Hutopy.Domain.Entities.TodoItem", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("Created") - .HasColumnType("datetimeoffset"); - - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("Done") - .HasColumnType("bit"); - - b.Property("LastModified") - .HasColumnType("datetimeoffset"); - - b.Property("LastModifiedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("ListId") - .HasColumnType("int"); - - b.Property("Note") - .HasColumnType("nvarchar(max)"); - - b.Property("Priority") - .HasColumnType("int"); - - b.Property("Reminder") - .HasColumnType("datetime2"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.HasKey("Id"); - - b.HasIndex("ListId"); - - b.ToTable("TodoItems"); - }); - - modelBuilder.Entity("Hutopy.Domain.Entities.TodoList", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("Created") - .HasColumnType("datetimeoffset"); - - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("LastModified") - .HasColumnType("datetimeoffset"); - - b.Property("LastModifiedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.HasKey("Id"); - - b.ToTable("TodoLists"); - }); - - modelBuilder.Entity("Hutopy.Infrastructure.Identity.ApplicationUser", b => - { - b.Property("Id") - .HasColumnType("nvarchar(450)"); - - b.Property("AccessFailedCount") - .HasColumnType("int"); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnType("nvarchar(max)"); - - b.Property("Email") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("EmailConfirmed") - .HasColumnType("bit"); - - b.Property("LockoutEnabled") - .HasColumnType("bit"); - - b.Property("LockoutEnd") - .HasColumnType("datetimeoffset"); - - b.Property("NormalizedEmail") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("NormalizedUserName") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("PasswordHash") - .HasColumnType("nvarchar(max)"); - - b.Property("PhoneNumber") - .HasColumnType("nvarchar(max)"); - - b.Property("PhoneNumberConfirmed") - .HasColumnType("bit"); - - b.Property("SecurityStamp") - .HasColumnType("nvarchar(max)"); - - b.Property("TwoFactorEnabled") - .HasColumnType("bit"); - - b.Property("UserName") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.HasKey("Id"); - - b.HasIndex("NormalizedEmail") - .HasDatabaseName("EmailIndex"); - - b.HasIndex("NormalizedUserName") - .IsUnique() - .HasDatabaseName("UserNameIndex") - .HasFilter("[NormalizedUserName] IS NOT NULL"); - - b.ToTable("AspNetUsers", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => - { - b.Property("Id") - .HasColumnType("nvarchar(450)"); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnType("nvarchar(max)"); - - b.Property("Name") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("NormalizedName") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.HasKey("Id"); - - b.HasIndex("NormalizedName") - .IsUnique() - .HasDatabaseName("RoleNameIndex") - .HasFilter("[NormalizedName] IS NOT NULL"); - - b.ToTable("AspNetRoles", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ClaimType") - .HasColumnType("nvarchar(max)"); - - b.Property("ClaimValue") - .HasColumnType("nvarchar(max)"); - - b.Property("RoleId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("Id"); - - b.HasIndex("RoleId"); - - b.ToTable("AspNetRoleClaims", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ClaimType") - .HasColumnType("nvarchar(max)"); - - b.Property("ClaimValue") - .HasColumnType("nvarchar(max)"); - - b.Property("UserId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("AspNetUserClaims", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => - { - b.Property("LoginProvider") - .HasMaxLength(128) - .HasColumnType("nvarchar(128)"); - - b.Property("ProviderKey") - .HasMaxLength(128) - .HasColumnType("nvarchar(128)"); - - b.Property("ProviderDisplayName") - .HasColumnType("nvarchar(max)"); - - b.Property("UserId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("LoginProvider", "ProviderKey"); - - b.HasIndex("UserId"); - - b.ToTable("AspNetUserLogins", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => - { - b.Property("UserId") - .HasColumnType("nvarchar(450)"); - - b.Property("RoleId") - .HasColumnType("nvarchar(450)"); - - b.HasKey("UserId", "RoleId"); - - b.HasIndex("RoleId"); - - b.ToTable("AspNetUserRoles", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => - { - b.Property("UserId") - .HasColumnType("nvarchar(450)"); - - b.Property("LoginProvider") - .HasMaxLength(128) - .HasColumnType("nvarchar(128)"); - - b.Property("Name") - .HasMaxLength(128) - .HasColumnType("nvarchar(128)"); - - b.Property("Value") - .HasColumnType("nvarchar(max)"); - - b.HasKey("UserId", "LoginProvider", "Name"); - - b.ToTable("AspNetUserTokens", (string)null); - }); - - modelBuilder.Entity("Hutopy.Domain.Entities.TodoItem", b => - { - b.HasOne("Hutopy.Domain.Entities.TodoList", "List") - .WithMany("Items") - .HasForeignKey("ListId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("List"); - }); - - modelBuilder.Entity("Hutopy.Domain.Entities.TodoList", b => - { - b.OwnsOne("Hutopy.Domain.ValueObjects.Colour", "Colour", b1 => - { - b1.Property("TodoListId") - .HasColumnType("int"); - - b1.Property("Code") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.HasKey("TodoListId"); - - b1.ToTable("TodoLists"); - - b1.WithOwner() - .HasForeignKey("TodoListId"); - }); - - b.Navigation("Colour") - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) - .WithMany() - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => - { - b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => - { - b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) - .WithMany() - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => - { - b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Hutopy.Domain.Entities.TodoList", b => - { - b.Navigation("Items"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Infrastructure/Data/Migrations/20240317201728_AddFuturCreator.Designer.cs b/src/Infrastructure/Data/Migrations/20240317201728_AddFuturCreator.Designer.cs deleted file mode 100644 index a33f51b..0000000 --- a/src/Infrastructure/Data/Migrations/20240317201728_AddFuturCreator.Designer.cs +++ /dev/null @@ -1,444 +0,0 @@ -// -using System; -using Hutopy.Infrastructure.Data; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -#nullable disable - -namespace Hutopy.Infrastructure.Data.Migrations -{ - [DbContext(typeof(ApplicationDbContext))] - [Migration("20240317201728_AddFuturCreators")] - partial class AddFuturCreators - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "8.0.3") - .HasAnnotation("Relational:MaxIdentifierLength", 128); - - SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); - - modelBuilder.Entity("FuturCreators", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("Created") - .HasColumnType("datetimeoffset"); - - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("EmailAddress") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("FirstName") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("LastModified") - .HasColumnType("datetimeoffset"); - - b.Property("LastModifiedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("LastName") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("PhoneNumber") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("ReasonToJoin") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("SocialNetworkAccount") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.ToTable("FuturCreators"); - }); - - modelBuilder.Entity("Hutopy.Domain.Entities.TodoItem", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("Created") - .HasColumnType("datetimeoffset"); - - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("Done") - .HasColumnType("bit"); - - b.Property("LastModified") - .HasColumnType("datetimeoffset"); - - b.Property("LastModifiedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("ListId") - .HasColumnType("int"); - - b.Property("Note") - .HasColumnType("nvarchar(max)"); - - b.Property("Priority") - .HasColumnType("int"); - - b.Property("Reminder") - .HasColumnType("datetime2"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.HasKey("Id"); - - b.HasIndex("ListId"); - - b.ToTable("TodoItems"); - }); - - modelBuilder.Entity("Hutopy.Domain.Entities.TodoList", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("Created") - .HasColumnType("datetimeoffset"); - - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("LastModified") - .HasColumnType("datetimeoffset"); - - b.Property("LastModifiedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.HasKey("Id"); - - b.ToTable("TodoLists"); - }); - - modelBuilder.Entity("Hutopy.Infrastructure.Identity.ApplicationUser", b => - { - b.Property("Id") - .HasColumnType("nvarchar(450)"); - - b.Property("AccessFailedCount") - .HasColumnType("int"); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnType("nvarchar(max)"); - - b.Property("Email") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("EmailConfirmed") - .HasColumnType("bit"); - - b.Property("LockoutEnabled") - .HasColumnType("bit"); - - b.Property("LockoutEnd") - .HasColumnType("datetimeoffset"); - - b.Property("NormalizedEmail") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("NormalizedUserName") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("PasswordHash") - .HasColumnType("nvarchar(max)"); - - b.Property("PhoneNumber") - .HasColumnType("nvarchar(max)"); - - b.Property("PhoneNumberConfirmed") - .HasColumnType("bit"); - - b.Property("SecurityStamp") - .HasColumnType("nvarchar(max)"); - - b.Property("TwoFactorEnabled") - .HasColumnType("bit"); - - b.Property("UserName") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.HasKey("Id"); - - b.HasIndex("NormalizedEmail") - .HasDatabaseName("EmailIndex"); - - b.HasIndex("NormalizedUserName") - .IsUnique() - .HasDatabaseName("UserNameIndex") - .HasFilter("[NormalizedUserName] IS NOT NULL"); - - b.ToTable("AspNetUsers", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => - { - b.Property("Id") - .HasColumnType("nvarchar(450)"); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnType("nvarchar(max)"); - - b.Property("Name") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("NormalizedName") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.HasKey("Id"); - - b.HasIndex("NormalizedName") - .IsUnique() - .HasDatabaseName("RoleNameIndex") - .HasFilter("[NormalizedName] IS NOT NULL"); - - b.ToTable("AspNetRoles", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ClaimType") - .HasColumnType("nvarchar(max)"); - - b.Property("ClaimValue") - .HasColumnType("nvarchar(max)"); - - b.Property("RoleId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("Id"); - - b.HasIndex("RoleId"); - - b.ToTable("AspNetRoleClaims", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ClaimType") - .HasColumnType("nvarchar(max)"); - - b.Property("ClaimValue") - .HasColumnType("nvarchar(max)"); - - b.Property("UserId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("AspNetUserClaims", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => - { - b.Property("LoginProvider") - .HasColumnType("nvarchar(450)"); - - b.Property("ProviderKey") - .HasColumnType("nvarchar(450)"); - - b.Property("ProviderDisplayName") - .HasColumnType("nvarchar(max)"); - - b.Property("UserId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("LoginProvider", "ProviderKey"); - - b.HasIndex("UserId"); - - b.ToTable("AspNetUserLogins", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => - { - b.Property("UserId") - .HasColumnType("nvarchar(450)"); - - b.Property("RoleId") - .HasColumnType("nvarchar(450)"); - - b.HasKey("UserId", "RoleId"); - - b.HasIndex("RoleId"); - - b.ToTable("AspNetUserRoles", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => - { - b.Property("UserId") - .HasColumnType("nvarchar(450)"); - - b.Property("LoginProvider") - .HasColumnType("nvarchar(450)"); - - b.Property("Name") - .HasColumnType("nvarchar(450)"); - - b.Property("Value") - .HasColumnType("nvarchar(max)"); - - b.HasKey("UserId", "LoginProvider", "Name"); - - b.ToTable("AspNetUserTokens", (string)null); - }); - - modelBuilder.Entity("Hutopy.Domain.Entities.TodoItem", b => - { - b.HasOne("Hutopy.Domain.Entities.TodoList", "List") - .WithMany("Items") - .HasForeignKey("ListId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("List"); - }); - - modelBuilder.Entity("Hutopy.Domain.Entities.TodoList", b => - { - b.OwnsOne("Hutopy.Domain.ValueObjects.Colour", "Colour", b1 => - { - b1.Property("TodoListId") - .HasColumnType("int"); - - b1.Property("Code") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.HasKey("TodoListId"); - - b1.ToTable("TodoLists"); - - b1.WithOwner() - .HasForeignKey("TodoListId"); - }); - - b.Navigation("Colour") - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) - .WithMany() - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => - { - b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => - { - b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) - .WithMany() - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => - { - b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Hutopy.Domain.Entities.TodoList", b => - { - b.Navigation("Items"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Infrastructure/Data/Migrations/20240317201728_AddFuturCreator.cs b/src/Infrastructure/Data/Migrations/20240317201728_AddFuturCreator.cs deleted file mode 100644 index a65203a..0000000 --- a/src/Infrastructure/Data/Migrations/20240317201728_AddFuturCreator.cs +++ /dev/null @@ -1,116 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace Hutopy.Infrastructure.Data.Migrations -{ - /// - public partial class AddFuturCreators : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.AlterColumn( - name: "Name", - table: "AspNetUserTokens", - type: "nvarchar(450)", - nullable: false, - oldClrType: typeof(string), - oldType: "nvarchar(128)", - oldMaxLength: 128); - - migrationBuilder.AlterColumn( - name: "LoginProvider", - table: "AspNetUserTokens", - type: "nvarchar(450)", - nullable: false, - oldClrType: typeof(string), - oldType: "nvarchar(128)", - oldMaxLength: 128); - - migrationBuilder.AlterColumn( - name: "ProviderKey", - table: "AspNetUserLogins", - type: "nvarchar(450)", - nullable: false, - oldClrType: typeof(string), - oldType: "nvarchar(128)", - oldMaxLength: 128); - - migrationBuilder.AlterColumn( - name: "LoginProvider", - table: "AspNetUserLogins", - type: "nvarchar(450)", - nullable: false, - oldClrType: typeof(string), - oldType: "nvarchar(128)", - oldMaxLength: 128); - - migrationBuilder.CreateTable( - name: "FutureCreators", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - FirstName = table.Column(type: "nvarchar(max)", nullable: false), - LastName = table.Column(type: "nvarchar(max)", nullable: false), - EmailAddress = table.Column(type: "nvarchar(max)", nullable: false), - PhoneNumber = table.Column(type: "nvarchar(max)", nullable: false), - SocialNetworkAccount = table.Column(type: "nvarchar(max)", nullable: false), - ReasonToJoin = table.Column(type: "nvarchar(max)", nullable: false), - Created = table.Column(type: "datetimeoffset", nullable: false), - CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), - LastModified = table.Column(type: "datetimeoffset", nullable: false), - LastModifiedBy = table.Column(type: "nvarchar(max)", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_FuturCreators", x => x.Id); - }); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "FutureCreators"); - - migrationBuilder.AlterColumn( - name: "Name", - table: "AspNetUserTokens", - type: "nvarchar(128)", - maxLength: 128, - nullable: false, - oldClrType: typeof(string), - oldType: "nvarchar(450)"); - - migrationBuilder.AlterColumn( - name: "LoginProvider", - table: "AspNetUserTokens", - type: "nvarchar(128)", - maxLength: 128, - nullable: false, - oldClrType: typeof(string), - oldType: "nvarchar(450)"); - - migrationBuilder.AlterColumn( - name: "ProviderKey", - table: "AspNetUserLogins", - type: "nvarchar(128)", - maxLength: 128, - nullable: false, - oldClrType: typeof(string), - oldType: "nvarchar(450)"); - - migrationBuilder.AlterColumn( - name: "LoginProvider", - table: "AspNetUserLogins", - type: "nvarchar(128)", - maxLength: 128, - nullable: false, - oldClrType: typeof(string), - oldType: "nvarchar(450)"); - } - } -} diff --git a/src/Infrastructure/Data/Migrations/20240404013754_AddDomainUser.Designer.cs b/src/Infrastructure/Data/Migrations/20240404013754_AddDomainUser.Designer.cs deleted file mode 100644 index efb1b0d..0000000 --- a/src/Infrastructure/Data/Migrations/20240404013754_AddDomainUser.Designer.cs +++ /dev/null @@ -1,492 +0,0 @@ -// -using System; -using Hutopy.Infrastructure.Data; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -#nullable disable - -namespace Hutopy.Infrastructure.Data.Migrations -{ - [DbContext(typeof(ApplicationDbContext))] - [Migration("20240404013754_AddDomainUser")] - partial class AddDomainUser - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "8.0.3") - .HasAnnotation("Relational:MaxIdentifierLength", 128); - - SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); - - modelBuilder.Entity("Hutopy.Domain.Entities.FutureCreator", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("Created") - .HasColumnType("datetimeoffset"); - - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("EmailAddress") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("FirstName") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("LastModified") - .HasColumnType("datetimeoffset"); - - b.Property("LastModifiedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("LastName") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("PhoneNumber") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("ReasonToJoin") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("SocialNetworkAccount") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.ToTable("FutureCreators"); - }); - - modelBuilder.Entity("Hutopy.Domain.Entities.TodoItem", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("Created") - .HasColumnType("datetimeoffset"); - - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("Done") - .HasColumnType("bit"); - - b.Property("LastModified") - .HasColumnType("datetimeoffset"); - - b.Property("LastModifiedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("ListId") - .HasColumnType("int"); - - b.Property("Note") - .HasColumnType("nvarchar(max)"); - - b.Property("Priority") - .HasColumnType("int"); - - b.Property("Reminder") - .HasColumnType("datetime2"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.HasKey("Id"); - - b.HasIndex("ListId"); - - b.ToTable("TodoItems"); - }); - - modelBuilder.Entity("Hutopy.Domain.Entities.TodoList", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("Created") - .HasColumnType("datetimeoffset"); - - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("LastModified") - .HasColumnType("datetimeoffset"); - - b.Property("LastModifiedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.HasKey("Id"); - - b.ToTable("TodoLists"); - }); - - modelBuilder.Entity("Hutopy.Domain.Entities.User", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("Created") - .HasColumnType("datetimeoffset"); - - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("EmailAddress") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("FirstName") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("IdentityUserId") - .HasColumnType("uniqueidentifier"); - - b.Property("LastModified") - .HasColumnType("datetimeoffset"); - - b.Property("LastModifiedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("LastName") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("Password") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("UserName") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.ToTable("DomainUsers"); - }); - - modelBuilder.Entity("Hutopy.Infrastructure.Identity.ApplicationUser", b => - { - b.Property("Id") - .HasColumnType("nvarchar(450)"); - - b.Property("AccessFailedCount") - .HasColumnType("int"); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnType("nvarchar(max)"); - - b.Property("Email") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("EmailConfirmed") - .HasColumnType("bit"); - - b.Property("LockoutEnabled") - .HasColumnType("bit"); - - b.Property("LockoutEnd") - .HasColumnType("datetimeoffset"); - - b.Property("NormalizedEmail") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("NormalizedUserName") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("PasswordHash") - .HasColumnType("nvarchar(max)"); - - b.Property("PhoneNumber") - .HasColumnType("nvarchar(max)"); - - b.Property("PhoneNumberConfirmed") - .HasColumnType("bit"); - - b.Property("SecurityStamp") - .HasColumnType("nvarchar(max)"); - - b.Property("TwoFactorEnabled") - .HasColumnType("bit"); - - b.Property("UserName") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.HasKey("Id"); - - b.HasIndex("NormalizedEmail") - .HasDatabaseName("EmailIndex"); - - b.HasIndex("NormalizedUserName") - .IsUnique() - .HasDatabaseName("UserNameIndex") - .HasFilter("[NormalizedUserName] IS NOT NULL"); - - b.ToTable("AspNetUsers", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => - { - b.Property("Id") - .HasColumnType("nvarchar(450)"); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnType("nvarchar(max)"); - - b.Property("Name") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("NormalizedName") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.HasKey("Id"); - - b.HasIndex("NormalizedName") - .IsUnique() - .HasDatabaseName("RoleNameIndex") - .HasFilter("[NormalizedName] IS NOT NULL"); - - b.ToTable("AspNetRoles", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ClaimType") - .HasColumnType("nvarchar(max)"); - - b.Property("ClaimValue") - .HasColumnType("nvarchar(max)"); - - b.Property("RoleId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("Id"); - - b.HasIndex("RoleId"); - - b.ToTable("AspNetRoleClaims", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ClaimType") - .HasColumnType("nvarchar(max)"); - - b.Property("ClaimValue") - .HasColumnType("nvarchar(max)"); - - b.Property("UserId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("AspNetUserClaims", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => - { - b.Property("LoginProvider") - .HasColumnType("nvarchar(450)"); - - b.Property("ProviderKey") - .HasColumnType("nvarchar(450)"); - - b.Property("ProviderDisplayName") - .HasColumnType("nvarchar(max)"); - - b.Property("UserId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("LoginProvider", "ProviderKey"); - - b.HasIndex("UserId"); - - b.ToTable("AspNetUserLogins", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => - { - b.Property("UserId") - .HasColumnType("nvarchar(450)"); - - b.Property("RoleId") - .HasColumnType("nvarchar(450)"); - - b.HasKey("UserId", "RoleId"); - - b.HasIndex("RoleId"); - - b.ToTable("AspNetUserRoles", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => - { - b.Property("UserId") - .HasColumnType("nvarchar(450)"); - - b.Property("LoginProvider") - .HasColumnType("nvarchar(450)"); - - b.Property("Name") - .HasColumnType("nvarchar(450)"); - - b.Property("Value") - .HasColumnType("nvarchar(max)"); - - b.HasKey("UserId", "LoginProvider", "Name"); - - b.ToTable("AspNetUserTokens", (string)null); - }); - - modelBuilder.Entity("Hutopy.Domain.Entities.TodoItem", b => - { - b.HasOne("Hutopy.Domain.Entities.TodoList", "List") - .WithMany("Items") - .HasForeignKey("ListId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("List"); - }); - - modelBuilder.Entity("Hutopy.Domain.Entities.TodoList", b => - { - b.OwnsOne("Hutopy.Domain.ValueObjects.Colour", "Colour", b1 => - { - b1.Property("TodoListId") - .HasColumnType("int"); - - b1.Property("Code") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.HasKey("TodoListId"); - - b1.ToTable("TodoLists"); - - b1.WithOwner() - .HasForeignKey("TodoListId"); - }); - - b.Navigation("Colour") - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) - .WithMany() - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => - { - b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => - { - b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) - .WithMany() - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => - { - b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Hutopy.Domain.Entities.TodoList", b => - { - b.Navigation("Items"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Infrastructure/Data/Migrations/20240404013754_AddDomainUser.cs b/src/Infrastructure/Data/Migrations/20240404013754_AddDomainUser.cs deleted file mode 100644 index c459b92..0000000 --- a/src/Infrastructure/Data/Migrations/20240404013754_AddDomainUser.cs +++ /dev/null @@ -1,44 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace Hutopy.Infrastructure.Data.Migrations -{ - /// - public partial class AddDomainUser : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.CreateTable( - name: "DomainUsers", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - IdentityUserId = table.Column(type: "uniqueidentifier", nullable: false), - FirstName = table.Column(type: "nvarchar(max)", nullable: false), - LastName = table.Column(type: "nvarchar(max)", nullable: false), - UserName = table.Column(type: "nvarchar(max)", nullable: false), - EmailAddress = table.Column(type: "nvarchar(max)", nullable: false), - Password = table.Column(type: "nvarchar(max)", nullable: false), - Created = table.Column(type: "datetimeoffset", nullable: false), - CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), - LastModified = table.Column(type: "datetimeoffset", nullable: false), - LastModifiedBy = table.Column(type: "nvarchar(max)", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_DomainUsers", x => x.Id); - }); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "DomainUsers"); - } - } -} diff --git a/src/Infrastructure/Data/Migrations/20240404023737_ChangeIdsToGuidsAndRemoveTodos.Designer.cs b/src/Infrastructure/Data/Migrations/20240404023737_ChangeIdsToGuidsAndRemoveTodos.Designer.cs deleted file mode 100644 index 4fb2eff..0000000 --- a/src/Infrastructure/Data/Migrations/20240404023737_ChangeIdsToGuidsAndRemoveTodos.Designer.cs +++ /dev/null @@ -1,372 +0,0 @@ -// -using System; -using Hutopy.Infrastructure.Data; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -#nullable disable - -namespace Hutopy.Infrastructure.Data.Migrations -{ - [DbContext(typeof(ApplicationDbContext))] - [Migration("20240404023737_ChangeIdsToGuidsAndRemoveTodos")] - partial class ChangeIdsToGuidsAndRemoveTodos - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "8.0.3") - .HasAnnotation("Relational:MaxIdentifierLength", 128); - - SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); - - modelBuilder.Entity("Hutopy.Domain.Entities.FutureCreator", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uniqueidentifier"); - - b.Property("Created") - .HasColumnType("datetimeoffset"); - - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("EmailAddress") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("FirstName") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("LastModified") - .HasColumnType("datetimeoffset"); - - b.Property("LastModifiedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("LastName") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("PhoneNumber") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("ReasonToJoin") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("SocialNetworkAccount") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.ToTable("FutureCreators"); - }); - - modelBuilder.Entity("Hutopy.Domain.Entities.User", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uniqueidentifier"); - - b.Property("Created") - .HasColumnType("datetimeoffset"); - - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("EmailAddress") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("FirstName") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("IdentityUserId") - .HasColumnType("uniqueidentifier"); - - b.Property("LastModified") - .HasColumnType("datetimeoffset"); - - b.Property("LastModifiedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("LastName") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("Password") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("UserName") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.ToTable("DomainUsers"); - }); - - modelBuilder.Entity("Hutopy.Infrastructure.Identity.ApplicationUser", b => - { - b.Property("Id") - .HasColumnType("nvarchar(450)"); - - b.Property("AccessFailedCount") - .HasColumnType("int"); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnType("nvarchar(max)"); - - b.Property("Email") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("EmailConfirmed") - .HasColumnType("bit"); - - b.Property("LockoutEnabled") - .HasColumnType("bit"); - - b.Property("LockoutEnd") - .HasColumnType("datetimeoffset"); - - b.Property("NormalizedEmail") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("NormalizedUserName") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("PasswordHash") - .HasColumnType("nvarchar(max)"); - - b.Property("PhoneNumber") - .HasColumnType("nvarchar(max)"); - - b.Property("PhoneNumberConfirmed") - .HasColumnType("bit"); - - b.Property("SecurityStamp") - .HasColumnType("nvarchar(max)"); - - b.Property("TwoFactorEnabled") - .HasColumnType("bit"); - - b.Property("UserName") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.HasKey("Id"); - - b.HasIndex("NormalizedEmail") - .HasDatabaseName("EmailIndex"); - - b.HasIndex("NormalizedUserName") - .IsUnique() - .HasDatabaseName("UserNameIndex") - .HasFilter("[NormalizedUserName] IS NOT NULL"); - - b.ToTable("AspNetUsers", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => - { - b.Property("Id") - .HasColumnType("nvarchar(450)"); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnType("nvarchar(max)"); - - b.Property("Name") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("NormalizedName") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.HasKey("Id"); - - b.HasIndex("NormalizedName") - .IsUnique() - .HasDatabaseName("RoleNameIndex") - .HasFilter("[NormalizedName] IS NOT NULL"); - - b.ToTable("AspNetRoles", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ClaimType") - .HasColumnType("nvarchar(max)"); - - b.Property("ClaimValue") - .HasColumnType("nvarchar(max)"); - - b.Property("RoleId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("Id"); - - b.HasIndex("RoleId"); - - b.ToTable("AspNetRoleClaims", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ClaimType") - .HasColumnType("nvarchar(max)"); - - b.Property("ClaimValue") - .HasColumnType("nvarchar(max)"); - - b.Property("UserId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("AspNetUserClaims", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => - { - b.Property("LoginProvider") - .HasColumnType("nvarchar(450)"); - - b.Property("ProviderKey") - .HasColumnType("nvarchar(450)"); - - b.Property("ProviderDisplayName") - .HasColumnType("nvarchar(max)"); - - b.Property("UserId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("LoginProvider", "ProviderKey"); - - b.HasIndex("UserId"); - - b.ToTable("AspNetUserLogins", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => - { - b.Property("UserId") - .HasColumnType("nvarchar(450)"); - - b.Property("RoleId") - .HasColumnType("nvarchar(450)"); - - b.HasKey("UserId", "RoleId"); - - b.HasIndex("RoleId"); - - b.ToTable("AspNetUserRoles", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => - { - b.Property("UserId") - .HasColumnType("nvarchar(450)"); - - b.Property("LoginProvider") - .HasColumnType("nvarchar(450)"); - - b.Property("Name") - .HasColumnType("nvarchar(450)"); - - b.Property("Value") - .HasColumnType("nvarchar(max)"); - - b.HasKey("UserId", "LoginProvider", "Name"); - - b.ToTable("AspNetUserTokens", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) - .WithMany() - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => - { - b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => - { - b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) - .WithMany() - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => - { - b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Infrastructure/Data/Migrations/20240404023737_ChangeIdsToGuidsAndRemoveTodos.cs b/src/Infrastructure/Data/Migrations/20240404023737_ChangeIdsToGuidsAndRemoveTodos.cs deleted file mode 100644 index 6ef89a3..0000000 --- a/src/Infrastructure/Data/Migrations/20240404023737_ChangeIdsToGuidsAndRemoveTodos.cs +++ /dev/null @@ -1,149 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace Hutopy.Infrastructure.Data.Migrations -{ - /// - public partial class ChangeIdsToGuidsAndRemoveTodos : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "TodoItems"); - - migrationBuilder.DropTable( - name: "TodoLists"); - - migrationBuilder.DropPrimaryKey( - name: "PK_FuturCreators", - table: "FutureCreators"); - - migrationBuilder.DropPrimaryKey( - name: "PK_DomainUsers", - table: "DomainUsers"); - - migrationBuilder.DropColumn( - name: "Id", - table: "FutureCreators"); - - migrationBuilder.DropColumn( - name: "Id", - table: "DomainUsers"); - - migrationBuilder.AddColumn( - name: "Id", - table: "FutureCreators", - type: "uniqueidentifier", - nullable: false, - defaultValueSql: "NEWID()" - ); - - migrationBuilder.AddColumn( - name: "Id", - table: "DomainUsers", - type: "uniqueidentifier", - nullable: false, - defaultValueSql: "NEWID()" - ); - - migrationBuilder.AddPrimaryKey( - name: "PK_FutureCreators", - table: "FutureCreators", - column: "Id"); - - migrationBuilder.AddPrimaryKey( - name: "PK_DomainUsers", - table: "DomainUsers", - column: "Id"); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropPrimaryKey( - name: "PK_FutureCreators", - table: "FutureCreators"); - - migrationBuilder.RenameTable( - name: "FutureCreators", - newName: "FutureCreator"); - - migrationBuilder.AlterColumn( - name: "Id", - table: "DomainUsers", - type: "int", - nullable: false, - oldClrType: typeof(Guid), - oldType: "uniqueidentifier") - .Annotation("SqlServer:Identity", "1, 1"); - - migrationBuilder.AlterColumn( - name: "Id", - table: "FutureCreator", - type: "int", - nullable: false, - oldClrType: typeof(Guid), - oldType: "uniqueidentifier") - .Annotation("SqlServer:Identity", "1, 1"); - - migrationBuilder.AddPrimaryKey( - name: "PK_FutureCreator", - table: "FutureCreator", - column: "Id"); - - migrationBuilder.CreateTable( - name: "TodoLists", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - Created = table.Column(type: "datetimeoffset", nullable: false), - CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), - LastModified = table.Column(type: "datetimeoffset", nullable: false), - LastModifiedBy = table.Column(type: "nvarchar(max)", nullable: true), - Title = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: false), - Colour_Code = table.Column(type: "nvarchar(max)", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_TodoLists", x => x.Id); - }); - - migrationBuilder.CreateTable( - name: "TodoItems", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - ListId = table.Column(type: "int", nullable: false), - Created = table.Column(type: "datetimeoffset", nullable: false), - CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), - Done = table.Column(type: "bit", nullable: false), - LastModified = table.Column(type: "datetimeoffset", nullable: false), - LastModifiedBy = table.Column(type: "nvarchar(max)", nullable: true), - Note = table.Column(type: "nvarchar(max)", nullable: true), - Priority = table.Column(type: "int", nullable: false), - Reminder = table.Column(type: "datetime2", nullable: true), - Title = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_TodoItems", x => x.Id); - table.ForeignKey( - name: "FK_TodoItems_TodoLists_ListId", - column: x => x.ListId, - principalTable: "TodoLists", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateIndex( - name: "IX_TodoItems_ListId", - table: "TodoItems", - column: "ListId"); - } - } -} diff --git a/src/Infrastructure/Data/Migrations/20240404030232_RemovePasswordFromDomainUser.Designer.cs b/src/Infrastructure/Data/Migrations/20240404030232_RemovePasswordFromDomainUser.Designer.cs deleted file mode 100644 index a58545e..0000000 --- a/src/Infrastructure/Data/Migrations/20240404030232_RemovePasswordFromDomainUser.Designer.cs +++ /dev/null @@ -1,368 +0,0 @@ -// -using System; -using Hutopy.Infrastructure.Data; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -#nullable disable - -namespace Hutopy.Infrastructure.Data.Migrations -{ - [DbContext(typeof(ApplicationDbContext))] - [Migration("20240404030232_RemovePasswordFromDomainUser")] - partial class RemovePasswordFromDomainUser - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "8.0.3") - .HasAnnotation("Relational:MaxIdentifierLength", 128); - - SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); - - modelBuilder.Entity("Hutopy.Domain.Entities.FutureCreator", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uniqueidentifier"); - - b.Property("Created") - .HasColumnType("datetimeoffset"); - - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("EmailAddress") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("FirstName") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("LastModified") - .HasColumnType("datetimeoffset"); - - b.Property("LastModifiedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("LastName") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("PhoneNumber") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("ReasonToJoin") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("SocialNetworkAccount") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.ToTable("FutureCreators"); - }); - - modelBuilder.Entity("Hutopy.Domain.Entities.User", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uniqueidentifier"); - - b.Property("Created") - .HasColumnType("datetimeoffset"); - - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("EmailAddress") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("FirstName") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("IdentityUserId") - .HasColumnType("uniqueidentifier"); - - b.Property("LastModified") - .HasColumnType("datetimeoffset"); - - b.Property("LastModifiedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("LastName") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("UserName") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.ToTable("DomainUsers"); - }); - - modelBuilder.Entity("Hutopy.Infrastructure.Identity.ApplicationUser", b => - { - b.Property("Id") - .HasColumnType("nvarchar(450)"); - - b.Property("AccessFailedCount") - .HasColumnType("int"); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnType("nvarchar(max)"); - - b.Property("Email") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("EmailConfirmed") - .HasColumnType("bit"); - - b.Property("LockoutEnabled") - .HasColumnType("bit"); - - b.Property("LockoutEnd") - .HasColumnType("datetimeoffset"); - - b.Property("NormalizedEmail") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("NormalizedUserName") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("PasswordHash") - .HasColumnType("nvarchar(max)"); - - b.Property("PhoneNumber") - .HasColumnType("nvarchar(max)"); - - b.Property("PhoneNumberConfirmed") - .HasColumnType("bit"); - - b.Property("SecurityStamp") - .HasColumnType("nvarchar(max)"); - - b.Property("TwoFactorEnabled") - .HasColumnType("bit"); - - b.Property("UserName") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.HasKey("Id"); - - b.HasIndex("NormalizedEmail") - .HasDatabaseName("EmailIndex"); - - b.HasIndex("NormalizedUserName") - .IsUnique() - .HasDatabaseName("UserNameIndex") - .HasFilter("[NormalizedUserName] IS NOT NULL"); - - b.ToTable("AspNetUsers", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => - { - b.Property("Id") - .HasColumnType("nvarchar(450)"); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnType("nvarchar(max)"); - - b.Property("Name") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("NormalizedName") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.HasKey("Id"); - - b.HasIndex("NormalizedName") - .IsUnique() - .HasDatabaseName("RoleNameIndex") - .HasFilter("[NormalizedName] IS NOT NULL"); - - b.ToTable("AspNetRoles", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ClaimType") - .HasColumnType("nvarchar(max)"); - - b.Property("ClaimValue") - .HasColumnType("nvarchar(max)"); - - b.Property("RoleId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("Id"); - - b.HasIndex("RoleId"); - - b.ToTable("AspNetRoleClaims", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ClaimType") - .HasColumnType("nvarchar(max)"); - - b.Property("ClaimValue") - .HasColumnType("nvarchar(max)"); - - b.Property("UserId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("AspNetUserClaims", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => - { - b.Property("LoginProvider") - .HasColumnType("nvarchar(450)"); - - b.Property("ProviderKey") - .HasColumnType("nvarchar(450)"); - - b.Property("ProviderDisplayName") - .HasColumnType("nvarchar(max)"); - - b.Property("UserId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("LoginProvider", "ProviderKey"); - - b.HasIndex("UserId"); - - b.ToTable("AspNetUserLogins", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => - { - b.Property("UserId") - .HasColumnType("nvarchar(450)"); - - b.Property("RoleId") - .HasColumnType("nvarchar(450)"); - - b.HasKey("UserId", "RoleId"); - - b.HasIndex("RoleId"); - - b.ToTable("AspNetUserRoles", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => - { - b.Property("UserId") - .HasColumnType("nvarchar(450)"); - - b.Property("LoginProvider") - .HasColumnType("nvarchar(450)"); - - b.Property("Name") - .HasColumnType("nvarchar(450)"); - - b.Property("Value") - .HasColumnType("nvarchar(max)"); - - b.HasKey("UserId", "LoginProvider", "Name"); - - b.ToTable("AspNetUserTokens", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) - .WithMany() - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => - { - b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => - { - b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) - .WithMany() - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => - { - b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Infrastructure/Data/Migrations/20240404030232_RemovePasswordFromDomainUser.cs b/src/Infrastructure/Data/Migrations/20240404030232_RemovePasswordFromDomainUser.cs deleted file mode 100644 index 66d0ef3..0000000 --- a/src/Infrastructure/Data/Migrations/20240404030232_RemovePasswordFromDomainUser.cs +++ /dev/null @@ -1,29 +0,0 @@ -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace Hutopy.Infrastructure.Data.Migrations -{ - /// - public partial class RemovePasswordFromDomainUser : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropColumn( - name: "Password", - table: "DomainUsers"); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.AddColumn( - name: "Password", - table: "DomainUsers", - type: "nvarchar(max)", - nullable: false, - defaultValue: ""); - } - } -} diff --git a/src/Infrastructure/Data/Migrations/20240410023815_RemovedDomainUserAddFirstNameLastNameToApplicationUser.cs b/src/Infrastructure/Data/Migrations/20240410023815_RemovedDomainUserAddFirstNameLastNameToApplicationUser.cs deleted file mode 100644 index 1fc9b4c..0000000 --- a/src/Infrastructure/Data/Migrations/20240410023815_RemovedDomainUserAddFirstNameLastNameToApplicationUser.cs +++ /dev/null @@ -1,64 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace Hutopy.Infrastructure.Data.Migrations -{ - /// - public partial class RemovedDomainUserAddFirstNameLastNameToApplicationUser : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "DomainUsers"); - - migrationBuilder.AddColumn( - name: "FirstName", - table: "AspNetUsers", - type: "nvarchar(max)", - nullable: false, - defaultValue: ""); - - migrationBuilder.AddColumn( - name: "LastName", - table: "AspNetUsers", - type: "nvarchar(max)", - nullable: false, - defaultValue: ""); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropColumn( - name: "FirstName", - table: "AspNetUsers"); - - migrationBuilder.DropColumn( - name: "LastName", - table: "AspNetUsers"); - - migrationBuilder.CreateTable( - name: "DomainUsers", - columns: table => new - { - Id = table.Column(type: "uniqueidentifier", nullable: false), - Created = table.Column(type: "datetimeoffset", nullable: false), - CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), - EmailAddress = table.Column(type: "nvarchar(max)", nullable: false), - FirstName = table.Column(type: "nvarchar(max)", nullable: false), - IdentityUserId = table.Column(type: "uniqueidentifier", nullable: false), - LastModified = table.Column(type: "datetimeoffset", nullable: false), - LastModifiedBy = table.Column(type: "nvarchar(max)", nullable: true), - LastName = table.Column(type: "nvarchar(max)", nullable: false), - UserName = table.Column(type: "nvarchar(max)", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_DomainUsers", x => x.Id); - }); - } - } -} diff --git a/src/Infrastructure/DependencyInjection.cs b/src/Infrastructure/DependencyInjection.cs index 3aabf8c..715bce6 100644 --- a/src/Infrastructure/DependencyInjection.cs +++ b/src/Infrastructure/DependencyInjection.cs @@ -1,4 +1,5 @@ -using Hutopy.Application.Common.Interfaces; +using System; +using Hutopy.Application.Common.Interfaces; using Hutopy.Domain.Constants; using Hutopy.Domain.Interfaces; using Hutopy.Infrastructure.Data; @@ -18,11 +19,18 @@ public static class DependencyInjection { public static IServiceCollection AddInfrastructureServices(this IServiceCollection services, IConfiguration configuration) { - // Replace password in the connection string with env var. + // 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 = Environment.GetEnvironmentVariable("DB_PASSWORD"); + + var dbPassword = Environment.GetEnvironmentVariable("DB_PASSWORD") ?? ""; + var dbHost = Environment.GetEnvironmentVariable("DB_HOST") ?? "localhost"; - connectionString = connectionString.Replace("{DB_PASSWORD}", dbPassword); + if (dbHost == "localhost" && 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."); diff --git a/src/Infrastructure/Infrastructure.csproj b/src/Infrastructure/Infrastructure.csproj index 2958bd6..2a665da 100644 --- a/src/Infrastructure/Infrastructure.csproj +++ b/src/Infrastructure/Infrastructure.csproj @@ -19,4 +19,7 @@ + + + diff --git a/src/Infrastructure/Data/Migrations/20240410023815_RemovedDomainUserAddFirstNameLastNameToApplicationUser.Designer.cs b/src/Infrastructure/Migrations/20240418221249_InitialMigration.Designer.cs similarity index 98% rename from src/Infrastructure/Data/Migrations/20240410023815_RemovedDomainUserAddFirstNameLastNameToApplicationUser.Designer.cs rename to src/Infrastructure/Migrations/20240418221249_InitialMigration.Designer.cs index 6df4b5a..e1c834e 100644 --- a/src/Infrastructure/Data/Migrations/20240410023815_RemovedDomainUserAddFirstNameLastNameToApplicationUser.Designer.cs +++ b/src/Infrastructure/Migrations/20240418221249_InitialMigration.Designer.cs @@ -9,11 +9,11 @@ using Microsoft.EntityFrameworkCore.Storage.ValueConversion; #nullable disable -namespace Hutopy.Infrastructure.Data.Migrations +namespace Hutopy.Infrastructure.Migrations { [DbContext(typeof(ApplicationDbContext))] - [Migration("20240410023815_RemovedDomainUserAddFirstNameLastNameToApplicationUser")] - partial class RemovedDomainUserAddFirstNameLastNameToApplicationUser + [Migration("20240418221249_InitialMigration")] + partial class InitialMigration { /// protected override void BuildTargetModel(ModelBuilder modelBuilder) diff --git a/src/Infrastructure/Data/Migrations/00000000000000_InitialCreate.cs b/src/Infrastructure/Migrations/20240418221249_InitialMigration.cs similarity index 80% rename from src/Infrastructure/Data/Migrations/00000000000000_InitialCreate.cs rename to src/Infrastructure/Migrations/20240418221249_InitialMigration.cs index 3335275..ae91d8e 100644 --- a/src/Infrastructure/Data/Migrations/00000000000000_InitialCreate.cs +++ b/src/Infrastructure/Migrations/20240418221249_InitialMigration.cs @@ -3,10 +3,10 @@ using Microsoft.EntityFrameworkCore.Migrations; #nullable disable -namespace Hutopy.Infrastructure.Data.Migrations +namespace Hutopy.Infrastructure.Migrations { /// - public partial class InitialCreate : Migration + public partial class InitialMigration : Migration { /// protected override void Up(MigrationBuilder migrationBuilder) @@ -30,6 +30,8 @@ namespace Hutopy.Infrastructure.Data.Migrations columns: table => new { Id = table.Column(type: "nvarchar(450)", nullable: false), + FirstName = table.Column(type: "nvarchar(max)", nullable: false), + LastName = table.Column(type: "nvarchar(max)", nullable: false), UserName = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), NormalizedUserName = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), Email = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), @@ -51,13 +53,16 @@ namespace Hutopy.Infrastructure.Data.Migrations }); migrationBuilder.CreateTable( - name: "TodoLists", + name: "FutureCreators", columns: table => new { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - Title = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: false), - Colour_Code = table.Column(type: "nvarchar(max)", nullable: false), + Id = table.Column(type: "uniqueidentifier", nullable: false), + FirstName = table.Column(type: "nvarchar(max)", nullable: false), + LastName = table.Column(type: "nvarchar(max)", nullable: false), + EmailAddress = table.Column(type: "nvarchar(max)", nullable: false), + PhoneNumber = table.Column(type: "nvarchar(max)", nullable: false), + SocialNetworkAccount = table.Column(type: "nvarchar(max)", nullable: false), + ReasonToJoin = table.Column(type: "nvarchar(max)", nullable: false), Created = table.Column(type: "datetimeoffset", nullable: false), CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), LastModified = table.Column(type: "datetimeoffset", nullable: false), @@ -65,7 +70,7 @@ namespace Hutopy.Infrastructure.Data.Migrations }, constraints: table => { - table.PrimaryKey("PK_TodoLists", x => x.Id); + table.PrimaryKey("PK_FutureCreators", x => x.Id); }); migrationBuilder.CreateTable( @@ -114,8 +119,8 @@ namespace Hutopy.Infrastructure.Data.Migrations name: "AspNetUserLogins", columns: table => new { - LoginProvider = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: false), - ProviderKey = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: false), + LoginProvider = table.Column(type: "nvarchar(450)", nullable: false), + ProviderKey = table.Column(type: "nvarchar(450)", nullable: false), ProviderDisplayName = table.Column(type: "nvarchar(max)", nullable: true), UserId = table.Column(type: "nvarchar(450)", nullable: false) }, @@ -159,8 +164,8 @@ namespace Hutopy.Infrastructure.Data.Migrations columns: table => new { UserId = table.Column(type: "nvarchar(450)", nullable: false), - LoginProvider = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: false), - Name = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: false), + LoginProvider = table.Column(type: "nvarchar(450)", nullable: false), + Name = table.Column(type: "nvarchar(450)", nullable: false), Value = table.Column(type: "nvarchar(max)", nullable: true) }, constraints: table => @@ -174,34 +179,6 @@ namespace Hutopy.Infrastructure.Data.Migrations onDelete: ReferentialAction.Cascade); }); - migrationBuilder.CreateTable( - name: "TodoItems", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - ListId = table.Column(type: "int", nullable: false), - Title = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: false), - Note = table.Column(type: "nvarchar(max)", nullable: true), - Priority = table.Column(type: "int", nullable: false), - Reminder = table.Column(type: "datetime2", nullable: true), - Done = table.Column(type: "bit", nullable: false), - Created = table.Column(type: "datetimeoffset", nullable: false), - CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), - LastModified = table.Column(type: "datetimeoffset", nullable: false), - LastModifiedBy = table.Column(type: "nvarchar(max)", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_TodoItems", x => x.Id); - table.ForeignKey( - name: "FK_TodoItems_TodoLists_ListId", - column: x => x.ListId, - principalTable: "TodoLists", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - migrationBuilder.CreateIndex( name: "IX_AspNetRoleClaims_RoleId", table: "AspNetRoleClaims", @@ -240,11 +217,6 @@ namespace Hutopy.Infrastructure.Data.Migrations column: "NormalizedUserName", unique: true, filter: "[NormalizedUserName] IS NOT NULL"); - - migrationBuilder.CreateIndex( - name: "IX_TodoItems_ListId", - table: "TodoItems", - column: "ListId"); } /// @@ -266,16 +238,13 @@ namespace Hutopy.Infrastructure.Data.Migrations name: "AspNetUserTokens"); migrationBuilder.DropTable( - name: "TodoItems"); + name: "FutureCreators"); migrationBuilder.DropTable( name: "AspNetRoles"); migrationBuilder.DropTable( name: "AspNetUsers"); - - migrationBuilder.DropTable( - name: "TodoLists"); } } } diff --git a/src/Infrastructure/Data/Migrations/ApplicationDbContextModelSnapshot.cs b/src/Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs similarity index 99% rename from src/Infrastructure/Data/Migrations/ApplicationDbContextModelSnapshot.cs rename to src/Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs index 3065590..33d2e9d 100644 --- a/src/Infrastructure/Data/Migrations/ApplicationDbContextModelSnapshot.cs +++ b/src/Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs @@ -8,7 +8,7 @@ using Microsoft.EntityFrameworkCore.Storage.ValueConversion; #nullable disable -namespace Hutopy.Infrastructure.Data.Migrations +namespace Hutopy.Infrastructure.Migrations { [DbContext(typeof(ApplicationDbContext))] partial class ApplicationDbContextModelSnapshot : ModelSnapshot diff --git a/src/Web/Program.cs b/src/Web/Program.cs index 803e8f0..9490c81 100644 --- a/src/Web/Program.cs +++ b/src/Web/Program.cs @@ -4,9 +4,16 @@ using Hutopy.Infrastructure; using Hutopy.Infrastructure.Data; using Hutopy.Infrastructure.Services; using Hutopy.Web; +using Azure.Identity; var builder = WebApplication.CreateBuilder(args); +if (!builder.Environment.IsDevelopment()) +{ + var keyVaultEndpoint = new Uri(Environment.GetEnvironmentVariable("VaultUri") ?? ""); + builder.Configuration.AddAzureKeyVault(keyVaultEndpoint, new DefaultAzureCredential()); +} + builder.Services.AddCors(options => { options.AddPolicy("AllowAll", builder => @@ -30,12 +37,11 @@ var app = builder.Build(); app.UseCors("AllowAll"); +// Initialize and seed the db. +await app.InitialiseDatabaseAsync(); + // Configure the HTTP request pipeline. -if (app.Environment.IsDevelopment()) -{ - await app.InitialiseDatabaseAsync(); -} -else +if (!app.Environment.IsDevelopment()) { // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. app.UseHsts(); diff --git a/src/Web/Properties/ServiceDependencies/Hutopy - Zip Deploy/profile.arm.json b/src/Web/Properties/ServiceDependencies/Hutopy - Zip Deploy/profile.arm.json new file mode 100644 index 0000000..277eb06 --- /dev/null +++ b/src/Web/Properties/ServiceDependencies/Hutopy - Zip Deploy/profile.arm.json @@ -0,0 +1,173 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_dependencyType": "compute.function.linux.appService" + }, + "parameters": { + "resourceGroupName": { + "type": "string", + "defaultValue": "Hutopy", + "metadata": { + "description": "Name of the resource group for the resource. It is recommended to put resources under same resource group for better tracking." + } + }, + "resourceGroupLocation": { + "type": "string", + "defaultValue": "canadaeast", + "metadata": { + "description": "Location of the resource group. Resource groups could have different location than resources, however by default we use API versions from latest hybrid profile which support all locations for resource types we support." + } + }, + "resourceName": { + "type": "string", + "defaultValue": "Hutopy", + "metadata": { + "description": "Name of the main resource to be created by this template." + } + }, + "resourceLocation": { + "type": "string", + "defaultValue": "[parameters('resourceGroupLocation')]", + "metadata": { + "description": "Location of the resource. By default use resource group's location, unless the resource provider is not supported there." + } + } + }, + "resources": [ + { + "type": "Microsoft.Resources/resourceGroups", + "name": "[parameters('resourceGroupName')]", + "location": "[parameters('resourceGroupLocation')]", + "apiVersion": "2019-10-01" + }, + { + "type": "Microsoft.Resources/deployments", + "name": "[concat(parameters('resourceGroupName'), 'Deployment', uniqueString(concat(parameters('resourceName'), subscription().subscriptionId)))]", + "resourceGroup": "[parameters('resourceGroupName')]", + "apiVersion": "2019-10-01", + "dependsOn": [ + "[parameters('resourceGroupName')]" + ], + "properties": { + "mode": "Incremental", + "expressionEvaluationOptions": { + "scope": "inner" + }, + "parameters": { + "resourceGroupName": { + "value": "[parameters('resourceGroupName')]" + }, + "resourceGroupLocation": { + "value": "[parameters('resourceGroupLocation')]" + }, + "resourceName": { + "value": "[parameters('resourceName')]" + }, + "resourceLocation": { + "value": "[parameters('resourceLocation')]" + } + }, + "template": { + "$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "resourceGroupName": { + "type": "string" + }, + "resourceGroupLocation": { + "type": "string" + }, + "resourceName": { + "type": "string" + }, + "resourceLocation": { + "type": "string" + } + }, + "variables": { + "storage_name": "[toLower(concat('storage', uniqueString(concat(parameters('resourceName'), subscription().subscriptionId))))]", + "appServicePlan_name": "[concat('Plan', uniqueString(concat(parameters('resourceName'), subscription().subscriptionId)))]", + "storage_ResourceId": "[concat('/subscriptions/', subscription().subscriptionId, '/resourceGroups/', parameters('resourceGroupName'), '/providers/Microsoft.Storage/storageAccounts/', variables('storage_name'))]", + "appServicePlan_ResourceId": "[concat('/subscriptions/', subscription().subscriptionId, '/resourceGroups/', parameters('resourceGroupName'), '/providers/Microsoft.Web/serverFarms/', variables('appServicePlan_name'))]", + "function_ResourceId": "[concat('/subscriptions/', subscription().subscriptionId, '/resourceGroups/', parameters('resourceGroupName'), '/providers/Microsoft.Web/sites/', parameters('resourceName'))]" + }, + "resources": [ + { + "location": "[parameters('resourceLocation')]", + "name": "[parameters('resourceName')]", + "type": "Microsoft.Web/sites", + "apiVersion": "2015-08-01", + "tags": { + "[concat('hidden-related:', variables('appServicePlan_ResourceId'))]": "empty" + }, + "dependsOn": [ + "[variables('appServicePlan_ResourceId')]", + "[variables('storage_ResourceId')]" + ], + "kind": "functionapp", + "properties": { + "name": "[parameters('resourceName')]", + "kind": "functionapp", + "httpsOnly": true, + "reserved": false, + "serverFarmId": "[variables('appServicePlan_ResourceId')]", + "siteConfig": { + "alwaysOn": true, + "linuxFxVersion": "dotnet|3.1" + } + }, + "identity": { + "type": "SystemAssigned" + }, + "resources": [ + { + "name": "appsettings", + "type": "config", + "apiVersion": "2015-08-01", + "dependsOn": [ + "[variables('function_ResourceId')]" + ], + "properties": { + "AzureWebJobsStorage": "[concat('DefaultEndpointsProtocol=https;AccountName=', variables('storage_name'), ';AccountKey=', listKeys(variables('storage_ResourceId'), '2017-10-01').keys[0].value, ';EndpointSuffix=', 'core.windows.net')]", + "FUNCTIONS_EXTENSION_VERSION": "~3", + "FUNCTIONS_WORKER_RUNTIME": "dotnet" + } + } + ] + }, + { + "location": "[parameters('resourceGroupLocation')]", + "name": "[variables('storage_name')]", + "type": "Microsoft.Storage/storageAccounts", + "apiVersion": "2017-10-01", + "tags": { + "[concat('hidden-related:', concat('/providers/Microsoft.Web/sites/', parameters('resourceName')))]": "empty" + }, + "properties": { + "supportsHttpsTrafficOnly": true + }, + "sku": { + "name": "Standard_LRS" + }, + "kind": "Storage" + }, + { + "location": "[parameters('resourceGroupLocation')]", + "name": "[variables('appServicePlan_name')]", + "type": "Microsoft.Web/serverFarms", + "apiVersion": "2015-02-01", + "kind": "linux", + "properties": { + "name": "[variables('appServicePlan_name')]", + "sku": "Standard", + "workerSizeId": "0", + "reserved": true + } + } + ] + } + } + } + ] +} \ No newline at end of file diff --git a/src/Web/Properties/ServiceDependencies/Hutopy - Zip Deploy/secrets1.arm.json b/src/Web/Properties/ServiceDependencies/Hutopy - Zip Deploy/secrets1.arm.json new file mode 100644 index 0000000..3776ec4 --- /dev/null +++ b/src/Web/Properties/ServiceDependencies/Hutopy - Zip Deploy/secrets1.arm.json @@ -0,0 +1,76 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "resourceGroupName": { + "type": "string", + "defaultValue": "Hutopy", + "metadata": { + "_parameterType": "resourceGroup", + "description": "Name of the resource group for the resource. It is recommended to put resources under same resource group for better tracking." + } + }, + "resourceGroupLocation": { + "type": "string", + "defaultValue": "canadaeast", + "metadata": { + "_parameterType": "location", + "description": "Location of the resource group. Resource groups could have different location than resources." + } + }, + "resourceLocation": { + "type": "string", + "defaultValue": "[parameters('resourceGroupLocation')]", + "metadata": { + "_parameterType": "location", + "description": "Location of the resource. By default use resource group's location, unless the resource provider is not supported there." + } + } + }, + "resources": [ + { + "type": "Microsoft.Resources/resourceGroups", + "name": "[parameters('resourceGroupName')]", + "location": "[parameters('resourceGroupLocation')]", + "apiVersion": "2019-10-01" + }, + { + "type": "Microsoft.Resources/deployments", + "name": "[concat(parameters('resourceGroupName'), 'Deployment', uniqueString(concat('Hutopyvault', subscription().subscriptionId)))]", + "resourceGroup": "[parameters('resourceGroupName')]", + "apiVersion": "2019-10-01", + "dependsOn": [ + "[parameters('resourceGroupName')]" + ], + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [ + { + "name": "Hutopyvault", + "type": "Microsoft.KeyVault/vaults", + "location": "[parameters('resourceLocation')]", + "properties": { + "sku": { + "family": "A", + "name": "Standard" + }, + "tenantId": "5f2d8eae-fe77-483e-883b-0eac5059186a", + "accessPolicies": [], + "enabledForDeployment": true, + "enabledForDiskEncryption": true, + "enabledForTemplateDeployment": true + }, + "apiVersion": "2016-10-01" + } + ] + } + } + } + ], + "metadata": { + "_dependencyType": "secrets.keyVault" + } +} \ No newline at end of file diff --git a/src/Web/Properties/launchSettings.json b/src/Web/Properties/launchSettings.json.dist similarity index 83% rename from src/Web/Properties/launchSettings.json rename to src/Web/Properties/launchSettings.json.dist index 6ef4f83..85845fa 100644 --- a/src/Web/Properties/launchSettings.json +++ b/src/Web/Properties/launchSettings.json.dist @@ -13,7 +13,10 @@ "launchBrowser": true, "applicationUrl": "https://localhost:5001;http://localhost:5000", "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" + "ASPNETCORE_ENVIRONMENT": "Development", + "VaultUri": "", + "DB_PASSWORD": "", + "DB_HOST": "" } }, "IIS Express": { diff --git a/src/Web/Properties/serviceDependencies.Hutopy - Zip Deploy.json b/src/Web/Properties/serviceDependencies.Hutopy - Zip Deploy.json new file mode 100644 index 0000000..346631c --- /dev/null +++ b/src/Web/Properties/serviceDependencies.Hutopy - Zip Deploy.json @@ -0,0 +1,12 @@ +{ + "dependencies": { + "secrets1": { + "serviceConnectorResourceId": "/subscriptions/[parameters('subscriptionId')]/resourceGroups/[parameters('resourceGroupName')]/providers/Microsoft.Web/sites/Hutopy/providers/Microsoft.ServiceLinker/linkers/VaultUri_8A210A7503", + "secretStore": "AzureAppSettings", + "resourceId": "/subscriptions/[parameters('subscriptionId')]/resourceGroups/[parameters('resourceGroupName')]/providers/Microsoft.KeyVault/vaults/Hutopyvault", + "type": "secrets.keyVault", + "connectionId": "VaultUri", + "dynamicId": null + } + } +} \ No newline at end of file diff --git a/src/Web/Properties/serviceDependencies.json b/src/Web/Properties/serviceDependencies.json new file mode 100644 index 0000000..4f5d819 --- /dev/null +++ b/src/Web/Properties/serviceDependencies.json @@ -0,0 +1,9 @@ +{ + "dependencies": { + "secrets1": { + "type": "secrets", + "connectionId": "VaultUri", + "dynamicId": null + } + } +} \ No newline at end of file diff --git a/src/Web/appsettings.json b/src/Web/appsettings.json index 84c0835..76a510b 100644 --- a/src/Web/appsettings.json +++ b/src/Web/appsettings.json @@ -1,6 +1,6 @@ { "ConnectionStrings": { - "DefaultConnection": "Server=localhost,1433;Database=HutopyLocal;User Id=sa;Password={DB_PASSWORD};MultipleActiveResultSets=true;TrustServerCertificate=True" + "DefaultConnection": "Server={DB_HOST},1433;Database=Hutopy;User Id=sa;Password={DB_PASSWORD};MultipleActiveResultSets=true;TrustServerCertificate=True" }, "Logging": { "LogLevel": { From a0a6e7deb4b27f9208f5ef4c6820ad19051cc67d Mon Sep 17 00:00:00 2001 From: Dominic Villemure Date: Sun, 21 Apr 2024 11:07:34 -0400 Subject: [PATCH 025/229] # added userSecret to store .. secrets --- README.md | 21 ++++++++++++++++--- src/Infrastructure/DependencyInjection.cs | 6 +++--- ...Settings.json.dist => launchSettings.json} | 5 +---- src/Web/Web.csproj | 1 + 4 files changed, 23 insertions(+), 10 deletions(-) rename src/Web/Properties/{launchSettings.json.dist => launchSettings.json} (83%) diff --git a/README.md b/README.md index e923dc0..fb5f274 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,6 @@ - Clean Architecture ( with Infrastructure, Domain, Application and Web layers ) - Minimal API endpoints. - Guards ( Fail fast ) : https://github.com/ardalis/GuardClauses -- ## Tools - Install Docker : https://www.docker.com/get-started/ @@ -20,8 +19,6 @@ Or with a mounted volume to persist data on the computer instead ( persist data docker run -e 'ACCEPT_EULA=Y' -e 'MSSQL_SA_PASSWORD=' -p 1433:1433 -v C:\dev\DockerVolumes\SqlServer-Utopy-1\data:/var/opt/mssql/data -v C:\dev\DockerVolumes\SqlServer-Utopy-1\log:/var/opt/mssql/log -v C:\dev\DockerVolumes\SqlServer-Utopy-1\secrets:/var/opt/mssql/secrets -d mcr.microsoft.com/mssql/server:2022-latest ``` -Set your password in an env var for the connection string. Windows : $Env:DB_PASSWORD = "YourPassword" - ## Entity Framework Create a new migration : @@ -34,6 +31,24 @@ Update database : ./Ef.ps1 database update ``` +## Secret Manager tool +Go to Web project: cd src/Web + +Add a user secret for local development : +``` +dotnet user-secrets set "DB_PASSWORD" "12345" +``` + +list your stored secrets : +``` +dotnet user-secrets list +``` + +Delete a secret : +``` +dotnet user-secrets remove "DB_PASSWORD" +``` + ## Build Run `dotnet build -tl` to build the solution. diff --git a/src/Infrastructure/DependencyInjection.cs b/src/Infrastructure/DependencyInjection.cs index 715bce6..e0bf63d 100644 --- a/src/Infrastructure/DependencyInjection.cs +++ b/src/Infrastructure/DependencyInjection.cs @@ -22,9 +22,9 @@ public static class DependencyInjection // 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 = Environment.GetEnvironmentVariable("DB_PASSWORD") ?? ""; - var dbHost = Environment.GetEnvironmentVariable("DB_HOST") ?? "localhost"; + + var dbPassword = configuration["DB_PASSWORD"] ?? ""; + var dbHost = configuration["DB_HOST"] ?? "localhost"; if (dbHost == "localhost" && dbPassword != string.Empty) { diff --git a/src/Web/Properties/launchSettings.json.dist b/src/Web/Properties/launchSettings.json similarity index 83% rename from src/Web/Properties/launchSettings.json.dist rename to src/Web/Properties/launchSettings.json index 85845fa..6ef4f83 100644 --- a/src/Web/Properties/launchSettings.json.dist +++ b/src/Web/Properties/launchSettings.json @@ -13,10 +13,7 @@ "launchBrowser": true, "applicationUrl": "https://localhost:5001;http://localhost:5000", "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development", - "VaultUri": "", - "DB_PASSWORD": "", - "DB_HOST": "" + "ASPNETCORE_ENVIRONMENT": "Development" } }, "IIS Express": { diff --git a/src/Web/Web.csproj b/src/Web/Web.csproj index 14b1052..a5444e7 100644 --- a/src/Web/Web.csproj +++ b/src/Web/Web.csproj @@ -3,6 +3,7 @@ Hutopy.Web Hutopy.Web + de6d03c4-8b1c-49e2-a8ca-c38cd4dc7d85 From 27819566f9afd32245d328e1a79277cfaaf2656a Mon Sep 17 00:00:00 2001 From: Dominic Villemure Date: Sun, 21 Apr 2024 13:49:13 -0400 Subject: [PATCH 026/229] #26 added cors policy to allows credentials on our UI origins --- src/Web/Program.cs | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/src/Web/Program.cs b/src/Web/Program.cs index 9490c81..b2b34db 100644 --- a/src/Web/Program.cs +++ b/src/Web/Program.cs @@ -19,8 +19,24 @@ builder.Services.AddCors(options => options.AddPolicy("AllowAll", builder => { builder.AllowAnyOrigin() - .AllowAnyMethod() - .AllowAnyHeader(); + .AllowAnyMethod() + .AllowAnyHeader(); + }); + + options.AddPolicy("AllowHutopyUi", builder => + { + builder.WithOrigins("https://zealous-bay-08204590f.5.azurestaticapps.net") + .AllowAnyMethod() + .AllowAnyHeader() + .AllowCredentials(); + }); + + options.AddPolicy("AllowHutopyUiPreview", builder => + { + builder.WithOrigins("https://zealous-bay-08204590f-preview.eastus2.5.azurestaticapps.net") + .AllowAnyMethod() + .AllowAnyHeader() + .AllowCredentials(); }); }); @@ -36,6 +52,8 @@ builder.Services.AddScoped(); var app = builder.Build(); app.UseCors("AllowAll"); +app.UseCors("AllowHutopyUi"); +app.UseCors("AllowHutopyUiPreview"); // Initialize and seed the db. await app.InitialiseDatabaseAsync(); From b63d53f109ddbf431309b2818ebf6e166bd0102d Mon Sep 17 00:00:00 2001 From: Dominic Villemure Date: Mon, 22 Apr 2024 15:55:49 -0400 Subject: [PATCH 027/229] #27 added userTransactions --- .../Interfaces/IApplicationDbContext.cs | 1 + .../Commands/CreateSessionCheckoutCommand.cs | 24 +- .../Users/Queries/GetCurrentUser.cs | 37 ++ src/Application/Users/Queries/UserDto.cs | 12 + .../Users/Queries/UserTransactionDto.cs | 20 + src/Domain/Entities/UserTransaction.cs | 11 + src/Domain/Interfaces/IUserService.cs | 1 + .../Data/ApplicationDbContext.cs | 9 + src/Infrastructure/Infrastructure.csproj | 3 - ...0422173330_AddUserTransactions.Designer.cs | 383 ++++++++++++++++++ .../20240422173330_AddUserTransactions.cs | 52 +++ .../ApplicationDbContextModelSnapshot.cs | 49 +++ src/Infrastructure/Services/UserService.cs | 26 +- src/Infrastructure/Stripe/StripeService.cs | 12 +- src/Web/Endpoints/GetMyUser.cs | 17 + src/Web/Endpoints/Users.cs | 2 +- src/Web/wwwroot/api/specification.json | 65 ++- 17 files changed, 696 insertions(+), 28 deletions(-) create mode 100644 src/Application/Users/Queries/GetCurrentUser.cs create mode 100644 src/Application/Users/Queries/UserDto.cs create mode 100644 src/Application/Users/Queries/UserTransactionDto.cs create mode 100644 src/Domain/Entities/UserTransaction.cs create mode 100644 src/Infrastructure/Migrations/20240422173330_AddUserTransactions.Designer.cs create mode 100644 src/Infrastructure/Migrations/20240422173330_AddUserTransactions.cs create mode 100644 src/Web/Endpoints/GetMyUser.cs diff --git a/src/Application/Common/Interfaces/IApplicationDbContext.cs b/src/Application/Common/Interfaces/IApplicationDbContext.cs index 3615321..75eabb6 100644 --- a/src/Application/Common/Interfaces/IApplicationDbContext.cs +++ b/src/Application/Common/Interfaces/IApplicationDbContext.cs @@ -5,5 +5,6 @@ namespace Hutopy.Application.Common.Interfaces; public interface IApplicationDbContext { DbSet FutureCreators { get; } + DbSet UserTransactions { get; } Task SaveChangesAsync(CancellationToken cancellationToken); } diff --git a/src/Application/Stripe/Commands/CreateSessionCheckoutCommand.cs b/src/Application/Stripe/Commands/CreateSessionCheckoutCommand.cs index 878a2d1..e627bf1 100644 --- a/src/Application/Stripe/Commands/CreateSessionCheckoutCommand.cs +++ b/src/Application/Stripe/Commands/CreateSessionCheckoutCommand.cs @@ -1,25 +1,31 @@ using Hutopy.Application.Common.Interfaces; - +using Hutopy.Domain.Entities; namespace Hutopy.Application.Stripe.Commands; -public abstract record CreateSessionCheckoutCommand : IRequest +public record CreateSessionCheckoutCommand : IRequest { + public required string CreatorId { get; init; } public required int Price { get; init; } - - public string Currency { get; init; } = "cad"; + public string Currency { get; init; } = "CAD"; + public string TipMessage { get; init; } = string.Empty; } - public class CreateSessionCheckoutCommandHandler( - IApplicationDbContext context, - IStripeService stripeService) + IApplicationDbContext dbContext, + IStripeService stripeService + ) : IRequestHandler { - private readonly IApplicationDbContext _context = context; - public async Task Handle(CreateSessionCheckoutCommand request, CancellationToken cancellationToken) { var stripeSecret = await stripeService.CreateCheckoutSession(request.Price, request.Currency); + + var userTransaction = new UserTransaction + { + Currency = request.Currency, Amount = request.Price, TipMessage = request.TipMessage, ApplicationUserId = request.CreatorId + }; + + await dbContext.UserTransactions.AddAsync(userTransaction, cancellationToken); return stripeSecret; } diff --git a/src/Application/Users/Queries/GetCurrentUser.cs b/src/Application/Users/Queries/GetCurrentUser.cs new file mode 100644 index 0000000..a087cf8 --- /dev/null +++ b/src/Application/Users/Queries/GetCurrentUser.cs @@ -0,0 +1,37 @@ +using Hutopy.Application.Common.Interfaces; +using Hutopy.Domain.Interfaces; + +namespace Hutopy.Application.Users.Queries; + +public record GetCurrentUserQuery : IRequest; + +public class GetCurrentUserQueryHandler( + IApplicationDbContext context, + IMapper mapper, + IUserService userService + ) + : IRequestHandler +{ + public async Task Handle(GetCurrentUserQuery request, CancellationToken cancellationToken) + { + var identityUser = await userService.GetCurrentUserAsync(); + var currentUserId = new Guid(identityUser?.Id ?? ""); + + var transactions = await context.UserTransactions + .Where(x => x.Id == currentUserId) + .OrderBy(x => x.LastModified) + .ProjectTo(mapper.ConfigurationProvider) + .ToListAsync(cancellationToken); + + + var user = new UserDto() + { + Id = currentUserId, + FirstName = identityUser?.FirstName ?? "", + LastName = identityUser?.LastName ?? "", + UserTransactions = transactions + }; + + return user; + } +} diff --git a/src/Application/Users/Queries/UserDto.cs b/src/Application/Users/Queries/UserDto.cs new file mode 100644 index 0000000..da62e26 --- /dev/null +++ b/src/Application/Users/Queries/UserDto.cs @@ -0,0 +1,12 @@ +namespace Hutopy.Application.Users.Queries; + +public class UserDto +{ + public Guid Id { get; init; } + + public required string FirstName { get; init; } + + public required string LastName { get; init; } + + public List UserTransactions { get; init; } = []; +} diff --git a/src/Application/Users/Queries/UserTransactionDto.cs b/src/Application/Users/Queries/UserTransactionDto.cs new file mode 100644 index 0000000..e6103c7 --- /dev/null +++ b/src/Application/Users/Queries/UserTransactionDto.cs @@ -0,0 +1,20 @@ +using Hutopy.Domain.Entities; + +namespace Hutopy.Application.Users.Queries; + +public class UserTransactionDto +{ + public required decimal Amount { get; init; } + + public string Currency { get; init; } = "cad"; + + public string TipMessage { get; init; } = string.Empty; + + private class Mapping : Profile + { + public Mapping() + { + CreateMap(); + } + } +} diff --git a/src/Domain/Entities/UserTransaction.cs b/src/Domain/Entities/UserTransaction.cs new file mode 100644 index 0000000..4617c46 --- /dev/null +++ b/src/Domain/Entities/UserTransaction.cs @@ -0,0 +1,11 @@ +namespace Hutopy.Domain.Entities; + +public class UserTransaction : BaseAuditableEntity +{ + public decimal Amount { get; set; } + public string Currency { get; set; } = "CAD"; + public string TipMessage { get; set; } = string.Empty; + + // Foreign key to ApplicationUser + public string ApplicationUserId { get; set; } = string.Empty; +} diff --git a/src/Domain/Interfaces/IUserService.cs b/src/Domain/Interfaces/IUserService.cs index c3bd5ac..efe46bb 100644 --- a/src/Domain/Interfaces/IUserService.cs +++ b/src/Domain/Interfaces/IUserService.cs @@ -7,6 +7,7 @@ public interface IUserService Task CreateUserAsync(string email, string userName, string firstName, string lastName, string password); Task FindUserByIdAsync(string id); + Task GetCurrentUserAsync(); Task FindUserByEmailAsync(string id); } diff --git a/src/Infrastructure/Data/ApplicationDbContext.cs b/src/Infrastructure/Data/ApplicationDbContext.cs index 1dd4d94..8ae973e 100644 --- a/src/Infrastructure/Data/ApplicationDbContext.cs +++ b/src/Infrastructure/Data/ApplicationDbContext.cs @@ -12,10 +12,19 @@ public class ApplicationDbContext( : IdentityDbContext(options), IApplicationDbContext { public DbSet FutureCreators => Set(); + public DbSet UserTransactions => Set(); protected override void OnModelCreating(ModelBuilder builder) { base.OnModelCreating(builder); + + // Relationship between ApplicationUser and UserTransaction + builder.Entity() + .HasOne() + .WithMany() + .HasForeignKey(ut => ut.ApplicationUserId) + .IsRequired(); + builder.ApplyConfigurationsFromAssembly(Assembly.GetExecutingAssembly()); } } diff --git a/src/Infrastructure/Infrastructure.csproj b/src/Infrastructure/Infrastructure.csproj index 2a665da..2958bd6 100644 --- a/src/Infrastructure/Infrastructure.csproj +++ b/src/Infrastructure/Infrastructure.csproj @@ -19,7 +19,4 @@ - - - diff --git a/src/Infrastructure/Migrations/20240422173330_AddUserTransactions.Designer.cs b/src/Infrastructure/Migrations/20240422173330_AddUserTransactions.Designer.cs new file mode 100644 index 0000000..cc634ad --- /dev/null +++ b/src/Infrastructure/Migrations/20240422173330_AddUserTransactions.Designer.cs @@ -0,0 +1,383 @@ +// +using System; +using Hutopy.Infrastructure.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Hutopy.Infrastructure.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + [Migration("20240422173330_AddUserTransactions")] + partial class AddUserTransactions + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.3") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("Hutopy.Domain.Entities.FutureCreator", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Created") + .HasColumnType("datetimeoffset"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("EmailAddress") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("FirstName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("LastModified") + .HasColumnType("datetimeoffset"); + + b.Property("LastModifiedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("LastName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumber") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("ReasonToJoin") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("SocialNetworkAccount") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("FutureCreators"); + }); + + modelBuilder.Entity("Hutopy.Domain.Entities.UserTransaction", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Amount") + .HasColumnType("decimal(18,2)"); + + b.Property("ApplicationUserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.Property("Created") + .HasColumnType("datetimeoffset"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("Currency") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("LastModified") + .HasColumnType("datetimeoffset"); + + b.Property("LastModifiedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("TipMessage") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationUserId"); + + b.ToTable("UserTransactions"); + }); + + modelBuilder.Entity("Hutopy.Infrastructure.Identity.ApplicationUser", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("AccessFailedCount") + .HasColumnType("int"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("nvarchar(max)"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("EmailConfirmed") + .HasColumnType("bit"); + + b.Property("FirstName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("LastName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("LockoutEnabled") + .HasColumnType("bit"); + + b.Property("LockoutEnd") + .HasColumnType("datetimeoffset"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("PasswordHash") + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumber") + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("bit"); + + b.Property("SecurityStamp") + .HasColumnType("nvarchar(max)"); + + b.Property("TwoFactorEnabled") + .HasColumnType("bit"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex") + .HasFilter("[NormalizedUserName] IS NOT NULL"); + + b.ToTable("AspNetUsers", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("nvarchar(max)"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex") + .HasFilter("[NormalizedName] IS NOT NULL"); + + b.ToTable("AspNetRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("nvarchar(max)"); + + b.Property("ClaimValue") + .HasColumnType("nvarchar(max)"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("nvarchar(max)"); + + b.Property("ClaimValue") + .HasColumnType("nvarchar(max)"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("nvarchar(450)"); + + b.Property("ProviderKey") + .HasColumnType("nvarchar(450)"); + + b.Property("ProviderDisplayName") + .HasColumnType("nvarchar(max)"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("nvarchar(450)"); + + b.Property("RoleId") + .HasColumnType("nvarchar(450)"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("nvarchar(450)"); + + b.Property("LoginProvider") + .HasColumnType("nvarchar(450)"); + + b.Property("Name") + .HasColumnType("nvarchar(450)"); + + b.Property("Value") + .HasColumnType("nvarchar(max)"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens", (string)null); + }); + + modelBuilder.Entity("Hutopy.Domain.Entities.UserTransaction", b => + { + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("ApplicationUserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Infrastructure/Migrations/20240422173330_AddUserTransactions.cs b/src/Infrastructure/Migrations/20240422173330_AddUserTransactions.cs new file mode 100644 index 0000000..f60e3fc --- /dev/null +++ b/src/Infrastructure/Migrations/20240422173330_AddUserTransactions.cs @@ -0,0 +1,52 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Hutopy.Infrastructure.Migrations +{ + /// + public partial class AddUserTransactions : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "UserTransactions", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + Amount = table.Column(type: "decimal(18,2)", nullable: false), + Currency = table.Column(type: "nvarchar(max)", nullable: false), + TipMessage = table.Column(type: "nvarchar(max)", nullable: false), + ApplicationUserId = table.Column(type: "nvarchar(450)", nullable: false), + Created = table.Column(type: "datetimeoffset", nullable: false), + CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), + LastModified = table.Column(type: "datetimeoffset", nullable: false), + LastModifiedBy = table.Column(type: "nvarchar(max)", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_UserTransactions", x => x.Id); + table.ForeignKey( + name: "FK_UserTransactions_AspNetUsers_ApplicationUserId", + column: x => x.ApplicationUserId, + principalTable: "AspNetUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "IX_UserTransactions_ApplicationUserId", + table: "UserTransactions", + column: "ApplicationUserId"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "UserTransactions"); + } + } +} diff --git a/src/Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs b/src/Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs index 33d2e9d..157cea1 100644 --- a/src/Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs +++ b/src/Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs @@ -69,6 +69,46 @@ namespace Hutopy.Infrastructure.Migrations b.ToTable("FutureCreators"); }); + modelBuilder.Entity("Hutopy.Domain.Entities.UserTransaction", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Amount") + .HasColumnType("decimal(18,2)"); + + b.Property("ApplicationUserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.Property("Created") + .HasColumnType("datetimeoffset"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("Currency") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("LastModified") + .HasColumnType("datetimeoffset"); + + b.Property("LastModifiedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("TipMessage") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationUserId"); + + b.ToTable("UserTransactions"); + }); + modelBuilder.Entity("Hutopy.Infrastructure.Identity.ApplicationUser", b => { b.Property("Id") @@ -275,6 +315,15 @@ namespace Hutopy.Infrastructure.Migrations b.ToTable("AspNetUserTokens", (string)null); }); + modelBuilder.Entity("Hutopy.Domain.Entities.UserTransaction", b => + { + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("ApplicationUserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => { b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) diff --git a/src/Infrastructure/Services/UserService.cs b/src/Infrastructure/Services/UserService.cs index 98c0c7c..7fae66c 100644 --- a/src/Infrastructure/Services/UserService.cs +++ b/src/Infrastructure/Services/UserService.cs @@ -1,15 +1,14 @@ -using Hutopy.Domain.Interfaces; +using System.Security.Claims; +using Hutopy.Domain.Interfaces; using Hutopy.Domain.Models; using Hutopy.Infrastructure.Identity; -using Microsoft.AspNetCore.Http.HttpResults; +using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Identity; namespace Hutopy.Infrastructure.Services; -public class UserService(UserManager userManager) : IUserService +public class UserService(UserManager userManager, IHttpContextAccessor httpContextAccessor) : IUserService { - private readonly UserManager _userManager = userManager; - public async Task CreateUserAsync(string email, string userName, string firstName, string lastName, string password) { var applicationUser = new ApplicationUser @@ -21,7 +20,7 @@ public class UserService(UserManager userManager) : IUserServic }; //todo: Need to handle errors better for the user. - var response = await _userManager.CreateAsync(applicationUser, password); + var response = await userManager.CreateAsync(applicationUser, password); if (response.Errors.Any()) { @@ -31,7 +30,7 @@ public class UserService(UserManager userManager) : IUserServic public async Task FindUserByIdAsync(string id) { - var response = await _userManager.FindByIdAsync(id); + var response = await userManager.FindByIdAsync(id); if (response == null) return null; @@ -46,10 +45,21 @@ public class UserService(UserManager userManager) : IUserServic return userModel; } + + public async Task GetCurrentUserAsync() + { + var userId = httpContextAccessor.HttpContext?.User.FindFirstValue(ClaimTypes.NameIdentifier); + if (string.IsNullOrEmpty(userId)) + { + return null; + } + + return await FindUserByIdAsync(userId); + } public async Task FindUserByEmailAsync(string email) { - var response = await _userManager.FindByEmailAsync(email); + var response = await userManager.FindByEmailAsync(email); if (response == null) return null; diff --git a/src/Infrastructure/Stripe/StripeService.cs b/src/Infrastructure/Stripe/StripeService.cs index f54fda4..154c541 100644 --- a/src/Infrastructure/Stripe/StripeService.cs +++ b/src/Infrastructure/Stripe/StripeService.cs @@ -1,16 +1,16 @@ using Stripe; using Stripe.Checkout; using Hutopy.Application.Common.Interfaces; +using Microsoft.Extensions.Configuration; namespace Hutopy.Infrastructure.Stripe; public class StripeService : IStripeService { - public StripeService() - { - // I removed the key to push. Will need to be in config. - StripeConfiguration.ApiKey = ""; - } + public StripeService(IConfiguration configuration) + { + StripeConfiguration.ApiKey = configuration["STRIPE_API_KEY"]; + } public async Task CreateCheckoutSession(int price, string currency = "cad") { @@ -32,7 +32,7 @@ public class StripeService : IStripeService ], Mode = "payment", UiMode = "embedded", - ReturnUrl = $"http://localhost:5173/creatorfolio", + ReturnUrl = $"https://zealous-bay-08204590f.5.azurestaticapps.net/paymentcompleted", }; var service = new SessionService(); diff --git a/src/Web/Endpoints/GetMyUser.cs b/src/Web/Endpoints/GetMyUser.cs new file mode 100644 index 0000000..5fe1c79 --- /dev/null +++ b/src/Web/Endpoints/GetMyUser.cs @@ -0,0 +1,17 @@ +using Hutopy.Application.Users.Queries; + +namespace Hutopy.Web.Endpoints; + +public class GetMyUser : EndpointGroupBase +{ + public override void Map(WebApplication app) + { + app.MapGroup(this) + .MapGet(GetCurrentUser); + } + + private static async Task GetCurrentUser(ISender sender, [AsParameters] GetCurrentUserQuery query) + { + return await sender.Send(query); + } +} diff --git a/src/Web/Endpoints/Users.cs b/src/Web/Endpoints/Users.cs index 38ccb1e..0492fb5 100644 --- a/src/Web/Endpoints/Users.cs +++ b/src/Web/Endpoints/Users.cs @@ -13,7 +13,7 @@ public class Users : EndpointGroupBase .MapIdentityApi(); } - public async Task CreateUser(ISender sender, CreateUserCommand command, IUserService userService) + private static async Task CreateUser(ISender sender, CreateUserCommand command, IUserService userService) { await userService.CreateUserAsync(command.EmailAddress, command.UserName, command.FirstName, command.LastName, command.Password); return await sender.Send(command); diff --git a/src/Web/wwwroot/api/specification.json b/src/Web/wwwroot/api/specification.json index 944608b..5e5b6e3 100644 --- a/src/Web/wwwroot/api/specification.json +++ b/src/Web/wwwroot/api/specification.json @@ -6,6 +6,26 @@ "version": "1.0.0" }, "paths": { + "/api/GetMyUser": { + "get": { + "tags": [ + "GetMyUser" + ], + "operationId": "GetCurrentUser", + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UserDto" + } + } + } + } + } + } + }, "/api/JoinUs": { "get": { "tags": [ @@ -559,6 +579,44 @@ }, "components": { "schemas": { + "UserDto": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "string", + "format": "guid" + }, + "firstName": { + "type": "string" + }, + "lastName": { + "type": "string" + }, + "userTransactions": { + "type": "array", + "items": { + "$ref": "#/components/schemas/UserTransactionDto" + } + } + } + }, + "UserTransactionDto": { + "type": "object", + "additionalProperties": false, + "properties": { + "amount": { + "type": "number", + "format": "decimal" + }, + "currency": { + "type": "string" + }, + "tipMessage": { + "type": "string" + } + } + }, "PaginatedListOfFutureCreatorListDto": { "type": "object", "additionalProperties": false, @@ -631,15 +689,20 @@ }, "CreateSessionCheckoutCommand": { "type": "object", - "x-abstract": true, "additionalProperties": false, "properties": { + "creatorId": { + "type": "string" + }, "price": { "type": "integer", "format": "int32" }, "currency": { "type": "string" + }, + "tipMessage": { + "type": "string" } } }, From bd6028c524913d9ca988efdc9c8a0e72b557711e Mon Sep 17 00:00:00 2001 From: Dominic Villemure Date: Mon, 22 Apr 2024 16:34:17 -0400 Subject: [PATCH 028/229] #27 saveChanges --- .../Stripe/Commands/CreateSessionCheckoutCommand.cs | 2 ++ src/Infrastructure/Services/UserService.cs | 9 ++++----- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/Application/Stripe/Commands/CreateSessionCheckoutCommand.cs b/src/Application/Stripe/Commands/CreateSessionCheckoutCommand.cs index e627bf1..9014f97 100644 --- a/src/Application/Stripe/Commands/CreateSessionCheckoutCommand.cs +++ b/src/Application/Stripe/Commands/CreateSessionCheckoutCommand.cs @@ -27,6 +27,8 @@ public class CreateSessionCheckoutCommandHandler( await dbContext.UserTransactions.AddAsync(userTransaction, cancellationToken); + await dbContext.SaveChangesAsync(cancellationToken); + return stripeSecret; } } diff --git a/src/Infrastructure/Services/UserService.cs b/src/Infrastructure/Services/UserService.cs index 7fae66c..b0704c2 100644 --- a/src/Infrastructure/Services/UserService.cs +++ b/src/Infrastructure/Services/UserService.cs @@ -1,13 +1,11 @@ -using System.Security.Claims; -using Hutopy.Domain.Interfaces; +using Hutopy.Domain.Interfaces; using Hutopy.Domain.Models; using Hutopy.Infrastructure.Identity; -using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Identity; namespace Hutopy.Infrastructure.Services; -public class UserService(UserManager userManager, IHttpContextAccessor httpContextAccessor) : IUserService +public class UserService(UserManager userManager) : IUserService { public async Task CreateUserAsync(string email, string userName, string firstName, string lastName, string password) { @@ -48,7 +46,8 @@ public class UserService(UserManager userManager, IHttpContextA public async Task GetCurrentUserAsync() { - var userId = httpContextAccessor.HttpContext?.User.FindFirstValue(ClaimTypes.NameIdentifier); + // todo: Get the id of the user doing the request. + var userId = ""; if (string.IsNullOrEmpty(userId)) { return null; From 5f92998663b6cb325758160c2647d345ec8b837b Mon Sep 17 00:00:00 2001 From: Kamigen <46357922+Edouard127@users.noreply.github.com> Date: Mon, 22 Apr 2024 16:43:20 -0400 Subject: [PATCH 029/229] Feature: Google OAuth2 --- src/Application/Users/Commands/CreateUser.cs | 2 - src/Infrastructure/Services/UserService.cs | 45 ++++++++++++-------- src/Web/Program.cs | 2 + src/Web/wwwroot/api/specification.json | 42 ++++++++++++++++++ 4 files changed, 71 insertions(+), 20 deletions(-) diff --git a/src/Application/Users/Commands/CreateUser.cs b/src/Application/Users/Commands/CreateUser.cs index 8992f01..e15cc1b 100644 --- a/src/Application/Users/Commands/CreateUser.cs +++ b/src/Application/Users/Commands/CreateUser.cs @@ -1,8 +1,6 @@ using System.Dynamic; using Hutopy.Application.Common.Interfaces; -using Hutopy.Domain.Entities; using Hutopy.Domain.Interfaces; -using Microsoft.EntityFrameworkCore; namespace Hutopy.Application.Users.Commands; public record CreateUserCommand : IRequest diff --git a/src/Infrastructure/Services/UserService.cs b/src/Infrastructure/Services/UserService.cs index 169c5f3..767a1c4 100644 --- a/src/Infrastructure/Services/UserService.cs +++ b/src/Infrastructure/Services/UserService.cs @@ -1,4 +1,6 @@ -using Google.Apis.Oauth2.v2.Data; +using System.Security.Cryptography; +using System.Text; +using Google.Apis.Oauth2.v2.Data; using Hutopy.Domain.Interfaces; using Hutopy.Domain.Models; using Hutopy.Infrastructure.Identity; @@ -8,6 +10,8 @@ namespace Hutopy.Infrastructure.Services; public class UserService(UserManager userManager) : IUserService { + private readonly Random _random = new(DateTime.Now.Millisecond); + public async Task CreateUserAsync(string email, string userName, string firstName, string lastName, string password) { var applicationUser = new ApplicationUser @@ -22,26 +26,13 @@ public class UserService(UserManager userManager) : IUserServic if (!response.Succeeded) { - throw new Exception("Failed to create user"); + throw new Exception("Failed to create user", new AggregateException(response.Errors.Select(e => new Exception(e.Description)))); } } public async Task CreateUserAsync(Userinfo userInfo) { - var applicationUser = new ApplicationUser - { - UserName = userInfo.Name, - Email = userInfo.Email, - FirstName = userInfo.GivenName, - LastName = userInfo.FamilyName - }; - - var response = await userManager.CreateAsync(applicationUser, Guid.NewGuid().ToString("N")[..32]); - - if (!response.Succeeded) - { - throw new Exception("Failed to create user"); - } + await CreateUserAsync(userInfo.Email, userInfo.GivenName, userInfo.GivenName, userInfo.FamilyName, GeneratePassword(24)); } public async Task FindUserByIdAsync(string id) @@ -50,7 +41,7 @@ public class UserService(UserManager userManager) : IUserServic if (response == null) return null; - var userModel = new UserModel() + var userModel = new UserModel { Id = response.Id, UserName = response.UserName, @@ -68,7 +59,7 @@ public class UserService(UserManager userManager) : IUserServic if (response == null) return null; - var userModel = new UserModel() + var userModel = new UserModel { Id = response.Id, UserName = response.UserName, @@ -79,5 +70,23 @@ public class UserService(UserManager userManager) : IUserServic return userModel; } + + private const string Characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; + private const string SpecialCharacters = "!@#$%^&*()_+"; + + private String GeneratePassword(int length) + { + // Using a string builder has additional overhead, maybe we can find something else + var password = new StringBuilder(); + + for (var i = 0; i < length; i++) + { + password.Append(Characters[_random.Next(Characters.Length)]); + } + + password.Append(SpecialCharacters[_random.Next(SpecialCharacters.Length)]); + + return password.ToString(); + } } diff --git a/src/Web/Program.cs b/src/Web/Program.cs index b2b34db..76fb1d8 100644 --- a/src/Web/Program.cs +++ b/src/Web/Program.cs @@ -1,4 +1,5 @@ using Hutopy.Application; +using Hutopy.Application.Common.Interfaces; using Hutopy.Domain.Interfaces; using Hutopy.Infrastructure; using Hutopy.Infrastructure.Data; @@ -48,6 +49,7 @@ builder.Services.AddInfrastructureServices(builder.Configuration); builder.Services.AddWebServices(); builder.Services.AddScoped(); +builder.Services.AddScoped(); var app = builder.Build(); diff --git a/src/Web/wwwroot/api/specification.json b/src/Web/wwwroot/api/specification.json index 944608b..fc53d77 100644 --- a/src/Web/wwwroot/api/specification.json +++ b/src/Web/wwwroot/api/specification.json @@ -6,6 +6,39 @@ "version": "1.0.0" }, "paths": { + "/api/Google": { + "post": { + "tags": [ + "Google" + ], + "operationId": "CreateGoogleUser", + "requestBody": { + "x-name": "command", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateGoogleUserCommand" + } + } + }, + "required": true, + "x-position": 1 + }, + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "string", + "format": "guid" + } + } + } + } + } + } + }, "/api/JoinUs": { "get": { "tags": [ @@ -559,6 +592,15 @@ }, "components": { "schemas": { + "CreateGoogleUserCommand": { + "type": "object", + "additionalProperties": false, + "properties": { + "accessToken": { + "type": "string" + } + } + }, "PaginatedListOfFutureCreatorListDto": { "type": "object", "additionalProperties": false, From 6883855ecbd491f29f233839593a0e7adb9e5a3b Mon Sep 17 00:00:00 2001 From: Dominic Villemure Date: Wed, 24 Apr 2024 19:37:35 -0400 Subject: [PATCH 030/229] #27 small changes for the userTransaction --- src/Application/Common/Interfaces/IStripeService.cs | 2 +- .../Stripe/Commands/CreateSessionCheckoutCommand.cs | 11 ++++++++--- src/Infrastructure/Stripe/StripeService.cs | 11 +++++------ src/Web/wwwroot/api/specification.json | 2 +- 4 files changed, 15 insertions(+), 11 deletions(-) diff --git a/src/Application/Common/Interfaces/IStripeService.cs b/src/Application/Common/Interfaces/IStripeService.cs index 1231a8e..75edbe9 100644 --- a/src/Application/Common/Interfaces/IStripeService.cs +++ b/src/Application/Common/Interfaces/IStripeService.cs @@ -3,5 +3,5 @@ namespace Hutopy.Application.Common.Interfaces; public interface IStripeService { - public Task CreateCheckoutSession(int price, string currency); + public Task CreateCheckoutSession(int amount, string currency); } diff --git a/src/Application/Stripe/Commands/CreateSessionCheckoutCommand.cs b/src/Application/Stripe/Commands/CreateSessionCheckoutCommand.cs index 9014f97..b428733 100644 --- a/src/Application/Stripe/Commands/CreateSessionCheckoutCommand.cs +++ b/src/Application/Stripe/Commands/CreateSessionCheckoutCommand.cs @@ -5,7 +5,7 @@ namespace Hutopy.Application.Stripe.Commands; public record CreateSessionCheckoutCommand : IRequest { public required string CreatorId { get; init; } - public required int Price { get; init; } + public required int Amount { get; init; } public string Currency { get; init; } = "CAD"; public string TipMessage { get; init; } = string.Empty; } @@ -18,11 +18,16 @@ public class CreateSessionCheckoutCommandHandler( { public async Task Handle(CreateSessionCheckoutCommand request, CancellationToken cancellationToken) { - var stripeSecret = await stripeService.CreateCheckoutSession(request.Price, request.Currency); + var stripeSecret = await stripeService.CreateCheckoutSession(request.Amount, request.Currency); + + // ReSharper disable once PossibleLossOfFraction + decimal priceInDollars = (request.Amount / 100); + + //todo: Need to add this transaction after the confirmation from stripe in the frontEnd ( redirect, re-call backend ) var userTransaction = new UserTransaction { - Currency = request.Currency, Amount = request.Price, TipMessage = request.TipMessage, ApplicationUserId = request.CreatorId + Currency = request.Currency, Amount = priceInDollars, TipMessage = request.TipMessage, ApplicationUserId = request.CreatorId }; await dbContext.UserTransactions.AddAsync(userTransaction, cancellationToken); diff --git a/src/Infrastructure/Stripe/StripeService.cs b/src/Infrastructure/Stripe/StripeService.cs index 154c541..881b6c4 100644 --- a/src/Infrastructure/Stripe/StripeService.cs +++ b/src/Infrastructure/Stripe/StripeService.cs @@ -1,18 +1,17 @@ using Stripe; using Stripe.Checkout; using Hutopy.Application.Common.Interfaces; -using Microsoft.Extensions.Configuration; namespace Hutopy.Infrastructure.Stripe; public class StripeService : IStripeService { - public StripeService(IConfiguration configuration) + public StripeService() { - StripeConfiguration.ApiKey = configuration["STRIPE_API_KEY"]; + StripeConfiguration.ApiKey = ""; } - public async Task CreateCheckoutSession(int price, string currency = "cad") + public async Task CreateCheckoutSession(int amount, string currency = "cad") { var options = new SessionCreateOptions { @@ -22,7 +21,7 @@ public class StripeService : IStripeService { PriceData = new SessionLineItemPriceDataOptions { - UnitAmount = price, + UnitAmount = amount, Currency = currency, ProductData = new SessionLineItemPriceDataProductDataOptions { Name = "Tip", }, }, @@ -32,7 +31,7 @@ public class StripeService : IStripeService ], Mode = "payment", UiMode = "embedded", - ReturnUrl = $"https://zealous-bay-08204590f.5.azurestaticapps.net/paymentcompleted", + ReturnUrl = "https://zealous-bay-08204590f.5.azurestaticapps.net/paymentcompleted", }; var service = new SessionService(); diff --git a/src/Web/wwwroot/api/specification.json b/src/Web/wwwroot/api/specification.json index 5e5b6e3..1bdd8f1 100644 --- a/src/Web/wwwroot/api/specification.json +++ b/src/Web/wwwroot/api/specification.json @@ -694,7 +694,7 @@ "creatorId": { "type": "string" }, - "price": { + "amount": { "type": "integer", "format": "int32" }, From cba08b04642d8611eab055958b8493a891d44622 Mon Sep 17 00:00:00 2001 From: Dominic Villemure Date: Wed, 24 Apr 2024 22:14:14 -0400 Subject: [PATCH 031/229] #27 added confirm endpoint for stripe --- .../Commands/ConfirmStripeTransaction.cs | 24 ++ src/Domain/Entities/UserTransaction.cs | 1 + .../Data/ApplicationDbContext.cs | 2 + ...ddIsConfirmedToUserTransaction.Designer.cs | 387 ++++++++++++++++++ ...5020920_AddIsConfirmedToUserTransaction.cs | 29 ++ .../ApplicationDbContextModelSnapshot.cs | 4 + src/Web/Endpoints/Stripe.cs | 6 + src/Web/wwwroot/api/specification.json | 45 ++ 8 files changed, 498 insertions(+) create mode 100644 src/Application/Stripe/Commands/ConfirmStripeTransaction.cs create mode 100644 src/Infrastructure/Migrations/20240425020920_AddIsConfirmedToUserTransaction.Designer.cs create mode 100644 src/Infrastructure/Migrations/20240425020920_AddIsConfirmedToUserTransaction.cs diff --git a/src/Application/Stripe/Commands/ConfirmStripeTransaction.cs b/src/Application/Stripe/Commands/ConfirmStripeTransaction.cs new file mode 100644 index 0000000..7aa8a3e --- /dev/null +++ b/src/Application/Stripe/Commands/ConfirmStripeTransaction.cs @@ -0,0 +1,24 @@ +using Hutopy.Application.Common.Interfaces; + +namespace Hutopy.Application.Stripe.Commands; +public record ConfirmStripeTransactionCommand : IRequest +{ + public required Guid UserTransactionId { get; init; } + public required bool IsConfirmed { get; init; } +} + +public class ConfirmStripeTransactionCommandHandler( + IApplicationDbContext dbContext + ) + : IRequestHandler +{ + public async Task Handle(ConfirmStripeTransactionCommand request, CancellationToken cancellationToken) + { + var transaction = await dbContext.UserTransactions.FirstOrDefaultAsync(x => x.Id == request.UserTransactionId, cancellationToken); + if (transaction is null) return ""; + transaction.IsConfirmed = request.IsConfirmed; + dbContext.UserTransactions.Update(transaction); + + return transaction.Id.ToString(); + } +} diff --git a/src/Domain/Entities/UserTransaction.cs b/src/Domain/Entities/UserTransaction.cs index 4617c46..b879fd2 100644 --- a/src/Domain/Entities/UserTransaction.cs +++ b/src/Domain/Entities/UserTransaction.cs @@ -8,4 +8,5 @@ public class UserTransaction : BaseAuditableEntity // Foreign key to ApplicationUser public string ApplicationUserId { get; set; } = string.Empty; + public bool IsConfirmed { get; set; } = false; } diff --git a/src/Infrastructure/Data/ApplicationDbContext.cs b/src/Infrastructure/Data/ApplicationDbContext.cs index 8ae973e..cb3a247 100644 --- a/src/Infrastructure/Data/ApplicationDbContext.cs +++ b/src/Infrastructure/Data/ApplicationDbContext.cs @@ -24,6 +24,8 @@ public class ApplicationDbContext( .WithMany() .HasForeignKey(ut => ut.ApplicationUserId) .IsRequired(); + + builder.Entity().Property(x => x.Amount).HasPrecision(18, 2); builder.ApplyConfigurationsFromAssembly(Assembly.GetExecutingAssembly()); } diff --git a/src/Infrastructure/Migrations/20240425020920_AddIsConfirmedToUserTransaction.Designer.cs b/src/Infrastructure/Migrations/20240425020920_AddIsConfirmedToUserTransaction.Designer.cs new file mode 100644 index 0000000..80ac05b --- /dev/null +++ b/src/Infrastructure/Migrations/20240425020920_AddIsConfirmedToUserTransaction.Designer.cs @@ -0,0 +1,387 @@ +// +using System; +using Hutopy.Infrastructure.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Hutopy.Infrastructure.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + [Migration("20240425020920_AddIsConfirmedToUserTransaction")] + partial class AddIsConfirmedToUserTransaction + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.3") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("Hutopy.Domain.Entities.FutureCreator", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Created") + .HasColumnType("datetimeoffset"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("EmailAddress") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("FirstName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("LastModified") + .HasColumnType("datetimeoffset"); + + b.Property("LastModifiedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("LastName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumber") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("ReasonToJoin") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("SocialNetworkAccount") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("FutureCreators"); + }); + + modelBuilder.Entity("Hutopy.Domain.Entities.UserTransaction", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Amount") + .HasPrecision(18, 2) + .HasColumnType("decimal(18,2)"); + + b.Property("ApplicationUserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.Property("Created") + .HasColumnType("datetimeoffset"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("Currency") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("IsConfirmed") + .HasColumnType("bit"); + + b.Property("LastModified") + .HasColumnType("datetimeoffset"); + + b.Property("LastModifiedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("TipMessage") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationUserId"); + + b.ToTable("UserTransactions"); + }); + + modelBuilder.Entity("Hutopy.Infrastructure.Identity.ApplicationUser", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("AccessFailedCount") + .HasColumnType("int"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("nvarchar(max)"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("EmailConfirmed") + .HasColumnType("bit"); + + b.Property("FirstName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("LastName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("LockoutEnabled") + .HasColumnType("bit"); + + b.Property("LockoutEnd") + .HasColumnType("datetimeoffset"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("PasswordHash") + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumber") + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("bit"); + + b.Property("SecurityStamp") + .HasColumnType("nvarchar(max)"); + + b.Property("TwoFactorEnabled") + .HasColumnType("bit"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex") + .HasFilter("[NormalizedUserName] IS NOT NULL"); + + b.ToTable("AspNetUsers", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("nvarchar(max)"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex") + .HasFilter("[NormalizedName] IS NOT NULL"); + + b.ToTable("AspNetRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("nvarchar(max)"); + + b.Property("ClaimValue") + .HasColumnType("nvarchar(max)"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("nvarchar(max)"); + + b.Property("ClaimValue") + .HasColumnType("nvarchar(max)"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("nvarchar(450)"); + + b.Property("ProviderKey") + .HasColumnType("nvarchar(450)"); + + b.Property("ProviderDisplayName") + .HasColumnType("nvarchar(max)"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("nvarchar(450)"); + + b.Property("RoleId") + .HasColumnType("nvarchar(450)"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("nvarchar(450)"); + + b.Property("LoginProvider") + .HasColumnType("nvarchar(450)"); + + b.Property("Name") + .HasColumnType("nvarchar(450)"); + + b.Property("Value") + .HasColumnType("nvarchar(max)"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens", (string)null); + }); + + modelBuilder.Entity("Hutopy.Domain.Entities.UserTransaction", b => + { + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("ApplicationUserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Infrastructure/Migrations/20240425020920_AddIsConfirmedToUserTransaction.cs b/src/Infrastructure/Migrations/20240425020920_AddIsConfirmedToUserTransaction.cs new file mode 100644 index 0000000..39ded1c --- /dev/null +++ b/src/Infrastructure/Migrations/20240425020920_AddIsConfirmedToUserTransaction.cs @@ -0,0 +1,29 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Hutopy.Infrastructure.Migrations +{ + /// + public partial class AddIsConfirmedToUserTransaction : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "IsConfirmed", + table: "UserTransactions", + type: "bit", + nullable: false, + defaultValue: false); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "IsConfirmed", + table: "UserTransactions"); + } + } +} diff --git a/src/Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs b/src/Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs index 157cea1..dedb234 100644 --- a/src/Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs +++ b/src/Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs @@ -76,6 +76,7 @@ namespace Hutopy.Infrastructure.Migrations .HasColumnType("uniqueidentifier"); b.Property("Amount") + .HasPrecision(18, 2) .HasColumnType("decimal(18,2)"); b.Property("ApplicationUserId") @@ -92,6 +93,9 @@ namespace Hutopy.Infrastructure.Migrations .IsRequired() .HasColumnType("nvarchar(max)"); + b.Property("IsConfirmed") + .HasColumnType("bit"); + b.Property("LastModified") .HasColumnType("datetimeoffset"); diff --git a/src/Web/Endpoints/Stripe.cs b/src/Web/Endpoints/Stripe.cs index b5c4a6a..b944419 100644 --- a/src/Web/Endpoints/Stripe.cs +++ b/src/Web/Endpoints/Stripe.cs @@ -7,6 +7,7 @@ public class Stripe : EndpointGroupBase public override void Map(WebApplication app) { app.MapGroup(this) + .MapPost(ConfirmTransaction, "/confirmTransaction") .MapPost(CreateSessionCheckout); } @@ -14,4 +15,9 @@ public class Stripe : EndpointGroupBase { return sender.Send(command); } + + private static Task ConfirmTransaction(ISender sender, ConfirmStripeTransactionCommand command) + { + return sender.Send(command); + } } diff --git a/src/Web/wwwroot/api/specification.json b/src/Web/wwwroot/api/specification.json index 1bdd8f1..5a1838c 100644 --- a/src/Web/wwwroot/api/specification.json +++ b/src/Web/wwwroot/api/specification.json @@ -99,6 +99,38 @@ } } }, + "/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": { "post": { "tags": [ @@ -687,6 +719,19 @@ } } }, + "ConfirmStripeTransactionCommand": { + "type": "object", + "additionalProperties": false, + "properties": { + "userTransactionId": { + "type": "string", + "format": "guid" + }, + "isConfirmed": { + "type": "boolean" + } + } + }, "CreateSessionCheckoutCommand": { "type": "object", "additionalProperties": false, From 5980eb7f0f542d2d3310583c3356769076fd89e4 Mon Sep 17 00:00:00 2001 From: Kamigen <46357922+Edouard127@users.noreply.github.com> Date: Sun, 28 Apr 2024 19:16:40 -0400 Subject: [PATCH 032/229] Fix: String not edited if host is local --- src/Infrastructure/DependencyInjection.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Infrastructure/DependencyInjection.cs b/src/Infrastructure/DependencyInjection.cs index e0bf63d..ae83424 100644 --- a/src/Infrastructure/DependencyInjection.cs +++ b/src/Infrastructure/DependencyInjection.cs @@ -26,7 +26,7 @@ public static class DependencyInjection var dbPassword = configuration["DB_PASSWORD"] ?? ""; var dbHost = configuration["DB_HOST"] ?? "localhost"; - if (dbHost == "localhost" && dbPassword != string.Empty) + if (dbPassword != string.Empty) { connectionString = connectionString.Replace("{DB_PASSWORD}", dbPassword); connectionString = connectionString.Replace("{DB_HOST}", dbHost); From 3a9dbf42a133c3dca7106b398677ae9fcf371a5a Mon Sep 17 00:00:00 2001 From: Kamigen <46357922+Edouard127@users.noreply.github.com> Date: Sun, 28 Apr 2024 19:27:16 -0400 Subject: [PATCH 033/229] Update specification.json --- src/Web/wwwroot/api/specification.json | 42 ++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/src/Web/wwwroot/api/specification.json b/src/Web/wwwroot/api/specification.json index 5a1838c..f5515cb 100644 --- a/src/Web/wwwroot/api/specification.json +++ b/src/Web/wwwroot/api/specification.json @@ -26,6 +26,39 @@ } } }, + "/api/Google": { + "post": { + "tags": [ + "Google" + ], + "operationId": "CreateGoogleUser", + "requestBody": { + "x-name": "command", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateGoogleUserCommand" + } + } + }, + "required": true, + "x-position": 1 + }, + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "string", + "format": "guid" + } + } + } + } + } + } + }, "/api/JoinUs": { "get": { "tags": [ @@ -649,6 +682,15 @@ } } }, + "CreateGoogleUserCommand": { + "type": "object", + "additionalProperties": false, + "properties": { + "accessToken": { + "type": "string" + } + } + }, "PaginatedListOfFutureCreatorListDto": { "type": "object", "additionalProperties": false, From be1d4cb3b61a1921775a19568b2cb734bd31b1d9 Mon Sep 17 00:00:00 2001 From: Kamigen <46357922+Edouard127@users.noreply.github.com> Date: Sun, 28 Apr 2024 19:52:31 -0400 Subject: [PATCH 034/229] TODO: Login user when account already exists --- src/Web/Endpoints/Google.cs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/Web/Endpoints/Google.cs b/src/Web/Endpoints/Google.cs index 8f3e323..cd75695 100644 --- a/src/Web/Endpoints/Google.cs +++ b/src/Web/Endpoints/Google.cs @@ -14,9 +14,18 @@ public class Google : EndpointGroupBase public static async Task CreateGoogleUser(ISender sender, CreateGoogleUserCommand command, IUserService userService, IGoogleService googleService) { - var user = await googleService.GetUserInfoAsync(command.AccessToken) ?? throw new Exception("Failed to get user info from Google"); + var googleUser = await googleService.GetUserInfoAsync(command.AccessToken) ?? throw new Exception("Failed to get user info from Google"); - await userService.CreateUserAsync(user); + + + var user = await userService.FindUserByEmailAsync(googleUser.Email); + if (user != null) + { + // TODO: Return login information + return await sender.Send(command); + } + + await userService.CreateUserAsync(googleUser); return await sender.Send(command); } From 025195627c0faf30dbde05b0dcde616663186c3b Mon Sep 17 00:00:00 2001 From: Kamigen <46357922+Edouard127@users.noreply.github.com> Date: Mon, 29 Apr 2024 18:30:04 -0400 Subject: [PATCH 035/229] Test: Integrated google auth --- Directory.Packages.props | 2 + .../Common/Interfaces/IGoogleService.cs | 8 ---- .../Google/Commands/CreateGoogleUser.cs | 20 --------- src/Infrastructure/Infrastructure.csproj | 1 + src/Infrastructure/Services/GoogleService.cs | 24 ----------- src/Web/Endpoints/Google.cs | 32 -------------- src/Web/Program.cs | 18 +++++++- src/Web/Web.csproj | 2 + src/Web/wwwroot/api/specification.json | 42 ------------------- 9 files changed, 22 insertions(+), 127 deletions(-) delete mode 100644 src/Application/Common/Interfaces/IGoogleService.cs delete mode 100644 src/Application/Google/Commands/CreateGoogleUser.cs delete mode 100644 src/Infrastructure/Services/GoogleService.cs delete mode 100644 src/Web/Endpoints/Google.cs diff --git a/Directory.Packages.props b/Directory.Packages.props index 758ff65..d3ae35d 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -14,6 +14,8 @@ + + diff --git a/src/Application/Common/Interfaces/IGoogleService.cs b/src/Application/Common/Interfaces/IGoogleService.cs deleted file mode 100644 index aba62f7..0000000 --- a/src/Application/Common/Interfaces/IGoogleService.cs +++ /dev/null @@ -1,8 +0,0 @@ -using Google.Apis.Oauth2.v2.Data; - -namespace Hutopy.Application.Common.Interfaces; - -public interface IGoogleService -{ - Task GetUserInfoAsync(string accessToken); -} diff --git a/src/Application/Google/Commands/CreateGoogleUser.cs b/src/Application/Google/Commands/CreateGoogleUser.cs deleted file mode 100644 index a5f2bca..0000000 --- a/src/Application/Google/Commands/CreateGoogleUser.cs +++ /dev/null @@ -1,20 +0,0 @@ -using Hutopy.Application.Common.Interfaces; - -namespace Hutopy.Application.Google.Commands; - -public record CreateGoogleUserCommand : IRequest -{ - public required string AccessToken { get; init; } -} - -public class CreateGoogleUser( - IApplicationDbContext context - ) : IRequestHandler -{ - public async Task Handle(CreateGoogleUserCommand request, CancellationToken cancellationToken) - { - await context.SaveChangesAsync(cancellationToken); - - return Guid.NewGuid(); - } -} diff --git a/src/Infrastructure/Infrastructure.csproj b/src/Infrastructure/Infrastructure.csproj index 2958bd6..108c958 100644 --- a/src/Infrastructure/Infrastructure.csproj +++ b/src/Infrastructure/Infrastructure.csproj @@ -4,6 +4,7 @@ Hutopy.Infrastructure + diff --git a/src/Infrastructure/Services/GoogleService.cs b/src/Infrastructure/Services/GoogleService.cs deleted file mode 100644 index b8abdf2..0000000 --- a/src/Infrastructure/Services/GoogleService.cs +++ /dev/null @@ -1,24 +0,0 @@ -using Google.Apis.Auth.OAuth2; -using Google.Apis.Services; -using Google.Apis.Oauth2.v2; -using Google.Apis.Oauth2.v2.Data; -using Hutopy.Application.Common.Interfaces; - -namespace Hutopy.Infrastructure.Services; - -public class GoogleService : IGoogleService -{ - public async Task GetUserInfoAsync(string accessToken) - { - var user = GoogleCredential.FromAccessToken(accessToken); - - var service = new Oauth2Service( - new BaseClientService.Initializer - { - HttpClientInitializer = user, - ApplicationName = "Hutopy" - }); - - return await service.Userinfo.Get().ExecuteAsync(); - } -} diff --git a/src/Web/Endpoints/Google.cs b/src/Web/Endpoints/Google.cs deleted file mode 100644 index cd75695..0000000 --- a/src/Web/Endpoints/Google.cs +++ /dev/null @@ -1,32 +0,0 @@ -using Hutopy.Application.Common.Interfaces; -using Hutopy.Application.Google.Commands; -using Hutopy.Domain.Interfaces; - -namespace Hutopy.Web.Endpoints; - -public class Google : EndpointGroupBase -{ - public override void Map(WebApplication app) - { - app.MapGroup(this) - .MapPost(CreateGoogleUser); - } - - public static async Task CreateGoogleUser(ISender sender, CreateGoogleUserCommand command, IUserService userService, IGoogleService googleService) - { - var googleUser = await googleService.GetUserInfoAsync(command.AccessToken) ?? throw new Exception("Failed to get user info from Google"); - - - - var user = await userService.FindUserByEmailAsync(googleUser.Email); - if (user != null) - { - // TODO: Return login information - return await sender.Send(command); - } - - await userService.CreateUserAsync(googleUser); - - return await sender.Send(command); - } -} diff --git a/src/Web/Program.cs b/src/Web/Program.cs index 76fb1d8..0e3863c 100644 --- a/src/Web/Program.cs +++ b/src/Web/Program.cs @@ -6,6 +6,9 @@ using Hutopy.Infrastructure.Data; using Hutopy.Infrastructure.Services; using Hutopy.Web; using Azure.Identity; +using Microsoft.AspNetCore.Authentication.Cookies; +using Microsoft.AspNetCore.Authentication.Google; +using Microsoft.AspNetCore.Identity; var builder = WebApplication.CreateBuilder(args); @@ -48,8 +51,21 @@ builder.Services.AddApplicationServices(); builder.Services.AddInfrastructureServices(builder.Configuration); builder.Services.AddWebServices(); +// OAuth +builder.Services.AddAuthentication() + .AddGoogle(options => + { + options.ClientId = builder.Configuration["Google:ClientId"] ?? throw new ArgumentNullException("The Google ClientId is missing."); + options.ClientSecret = builder.Configuration["Google:ClientSecret"] ?? throw new ArgumentNullException("The Google ClientSecret is missing."); + options.CallbackPath = "/api/google/o/signin-callback"; + }); + /*.AddFacebook(options => + { + options.AppId = ""; // TODO + options.AppSecret = ""; // TODO + });*/ // We can add a lot more if needed, microsoft, twitter, etc. + builder.Services.AddScoped(); -builder.Services.AddScoped(); var app = builder.Build(); diff --git a/src/Web/Web.csproj b/src/Web/Web.csproj index a5444e7..d5e0c62 100644 --- a/src/Web/Web.csproj +++ b/src/Web/Web.csproj @@ -14,6 +14,8 @@ + + diff --git a/src/Web/wwwroot/api/specification.json b/src/Web/wwwroot/api/specification.json index f5515cb..5a1838c 100644 --- a/src/Web/wwwroot/api/specification.json +++ b/src/Web/wwwroot/api/specification.json @@ -26,39 +26,6 @@ } } }, - "/api/Google": { - "post": { - "tags": [ - "Google" - ], - "operationId": "CreateGoogleUser", - "requestBody": { - "x-name": "command", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateGoogleUserCommand" - } - } - }, - "required": true, - "x-position": 1 - }, - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "type": "string", - "format": "guid" - } - } - } - } - } - } - }, "/api/JoinUs": { "get": { "tags": [ @@ -682,15 +649,6 @@ } } }, - "CreateGoogleUserCommand": { - "type": "object", - "additionalProperties": false, - "properties": { - "accessToken": { - "type": "string" - } - } - }, "PaginatedListOfFutureCreatorListDto": { "type": "object", "additionalProperties": false, From f9a661c8d2be3cd33a5200a77ca25606318cc0ee Mon Sep 17 00:00:00 2001 From: Kamigen <46357922+Edouard127@users.noreply.github.com> Date: Wed, 1 May 2024 17:54:21 -0400 Subject: [PATCH 036/229] Test: ASP Google login --- src/Web/Endpoints/Google.cs | 23 +++++++++++++++++++++++ src/Web/Program.cs | 24 +++++++++++++++++++++--- src/Web/wwwroot/api/specification.json | 13 +++++++++++++ 3 files changed, 57 insertions(+), 3 deletions(-) create mode 100644 src/Web/Endpoints/Google.cs diff --git a/src/Web/Endpoints/Google.cs b/src/Web/Endpoints/Google.cs new file mode 100644 index 0000000..274426c --- /dev/null +++ b/src/Web/Endpoints/Google.cs @@ -0,0 +1,23 @@ +using Microsoft.AspNetCore.Authentication; +using Microsoft.AspNetCore.Authentication.Google; + +namespace Hutopy.Web.Endpoints; + +public class Google : EndpointGroupBase +{ + public override void Map(WebApplication app) + { + app.MapGroup(this) + .MapGet("/o/sign-in", Callback); + } + + private static async Task Callback(ISender sender, HttpContext context) + { + await context.ChallengeAsync(GoogleDefaults.AuthenticationScheme, + new AuthenticationProperties + { + RedirectUri = "/o/google/callback", + ExpiresUtc = DateTimeOffset.UtcNow.AddDays(30), + }); + } +} diff --git a/src/Web/Program.cs b/src/Web/Program.cs index 0e3863c..1b712f9 100644 --- a/src/Web/Program.cs +++ b/src/Web/Program.cs @@ -1,11 +1,11 @@ using Hutopy.Application; -using Hutopy.Application.Common.Interfaces; using Hutopy.Domain.Interfaces; using Hutopy.Infrastructure; using Hutopy.Infrastructure.Data; using Hutopy.Infrastructure.Services; using Hutopy.Web; using Azure.Identity; +using Hutopy.Infrastructure.Identity; using Microsoft.AspNetCore.Authentication.Cookies; using Microsoft.AspNetCore.Authentication.Google; using Microsoft.AspNetCore.Identity; @@ -52,12 +52,30 @@ builder.Services.AddInfrastructureServices(builder.Configuration); builder.Services.AddWebServices(); // OAuth -builder.Services.AddAuthentication() +builder.Services.AddAuthentication(options => + { + options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme; + options.DefaultChallengeScheme = GoogleDefaults.AuthenticationScheme; + }) + .AddCookie(options => + { + options.Cookie.Name = "Hutopy"; + options.Cookie.SecurePolicy = builder.Environment.IsDevelopment() ? CookieSecurePolicy.None : CookieSecurePolicy.Always; + options.Cookie.SameSite = SameSiteMode.Strict; + options.Cookie.HttpOnly = true; + options.Cookie.IsEssential = true; + options.Cookie.MaxAge = TimeSpan.FromDays(30); + }) .AddGoogle(options => { options.ClientId = builder.Configuration["Google:ClientId"] ?? throw new ArgumentNullException("The Google ClientId is missing."); options.ClientSecret = builder.Configuration["Google:ClientSecret"] ?? throw new ArgumentNullException("The Google ClientSecret is missing."); - options.CallbackPath = "/api/google/o/signin-callback"; + options.CallbackPath = "/o/google/callback"; + options.Events.OnRedirectToAuthorizationEndpoint = context => + { + context.Response.Redirect(context.RedirectUri + "&prompt=consent"); + return Task.CompletedTask; + }; }); /*.AddFacebook(options => { diff --git a/src/Web/wwwroot/api/specification.json b/src/Web/wwwroot/api/specification.json index 5a1838c..c080bf3 100644 --- a/src/Web/wwwroot/api/specification.json +++ b/src/Web/wwwroot/api/specification.json @@ -26,6 +26,19 @@ } } }, + "/api/Google/o/sign-in": { + "get": { + "tags": [ + "Google" + ], + "operationId": "GetApiGoogleOSignIn", + "responses": { + "200": { + "description": "" + } + } + } + }, "/api/JoinUs": { "get": { "tags": [ From b966e28d9a278565042d372e7277b401442836ce Mon Sep 17 00:00:00 2001 From: Kamigen <46357922+Edouard127@users.noreply.github.com> Date: Wed, 1 May 2024 18:15:52 -0400 Subject: [PATCH 037/229] Moved back to default redirect uri --- src/Web/Endpoints/Google.cs | 2 +- src/Web/Program.cs | 10 +++------- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/src/Web/Endpoints/Google.cs b/src/Web/Endpoints/Google.cs index 274426c..640ac44 100644 --- a/src/Web/Endpoints/Google.cs +++ b/src/Web/Endpoints/Google.cs @@ -16,7 +16,7 @@ public class Google : EndpointGroupBase await context.ChallengeAsync(GoogleDefaults.AuthenticationScheme, new AuthenticationProperties { - RedirectUri = "/o/google/callback", + RedirectUri = "/signin-google", ExpiresUtc = DateTimeOffset.UtcNow.AddDays(30), }); } diff --git a/src/Web/Program.cs b/src/Web/Program.cs index 1b712f9..0c0b449 100644 --- a/src/Web/Program.cs +++ b/src/Web/Program.cs @@ -52,12 +52,8 @@ builder.Services.AddInfrastructureServices(builder.Configuration); builder.Services.AddWebServices(); // OAuth -builder.Services.AddAuthentication(options => - { - options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme; - options.DefaultChallengeScheme = GoogleDefaults.AuthenticationScheme; - }) - .AddCookie(options => +builder.Services.AddAuthentication() + .AddCookie(CookieAuthenticationDefaults.AuthenticationScheme,options => { options.Cookie.Name = "Hutopy"; options.Cookie.SecurePolicy = builder.Environment.IsDevelopment() ? CookieSecurePolicy.None : CookieSecurePolicy.Always; @@ -70,7 +66,7 @@ builder.Services.AddAuthentication(options => { options.ClientId = builder.Configuration["Google:ClientId"] ?? throw new ArgumentNullException("The Google ClientId is missing."); options.ClientSecret = builder.Configuration["Google:ClientSecret"] ?? throw new ArgumentNullException("The Google ClientSecret is missing."); - options.CallbackPath = "/o/google/callback"; + options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme; options.Events.OnRedirectToAuthorizationEndpoint = context => { context.Response.Redirect(context.RedirectUri + "&prompt=consent"); From cd2bf64af59b4591cfb78b1d2d3f522322821045 Mon Sep 17 00:00:00 2001 From: Kamigen <46357922+Edouard127@users.noreply.github.com> Date: Wed, 1 May 2024 18:43:20 -0400 Subject: [PATCH 038/229] Added challenge result --- src/Web/Endpoints/Google.cs | 17 ++++++++------ src/Web/Program.cs | 31 +++++++++++++------------- src/Web/wwwroot/api/specification.json | 10 ++++++++- 3 files changed, 35 insertions(+), 23 deletions(-) diff --git a/src/Web/Endpoints/Google.cs b/src/Web/Endpoints/Google.cs index 640ac44..0a9a92d 100644 --- a/src/Web/Endpoints/Google.cs +++ b/src/Web/Endpoints/Google.cs @@ -1,5 +1,6 @@ using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authentication.Google; +using Microsoft.AspNetCore.Mvc; namespace Hutopy.Web.Endpoints; @@ -11,13 +12,15 @@ public class Google : EndpointGroupBase .MapGet("/o/sign-in", Callback); } - private static async Task Callback(ISender sender, HttpContext context) + private static async Task Callback(ISender sender, HttpContext context) { - await context.ChallengeAsync(GoogleDefaults.AuthenticationScheme, - new AuthenticationProperties - { - RedirectUri = "/signin-google", - ExpiresUtc = DateTimeOffset.UtcNow.AddDays(30), - }); + var properties = new AuthenticationProperties + { + RedirectUri = "/signin-google", ExpiresUtc = DateTimeOffset.UtcNow.AddDays(30), + }; + + await context.ChallengeAsync(GoogleDefaults.AuthenticationScheme, properties); + + return new ChallengeResult(GoogleDefaults.AuthenticationScheme, properties); } } diff --git a/src/Web/Program.cs b/src/Web/Program.cs index 0c0b449..b6c6745 100644 --- a/src/Web/Program.cs +++ b/src/Web/Program.cs @@ -5,10 +5,7 @@ using Hutopy.Infrastructure.Data; using Hutopy.Infrastructure.Services; using Hutopy.Web; using Azure.Identity; -using Hutopy.Infrastructure.Identity; using Microsoft.AspNetCore.Authentication.Cookies; -using Microsoft.AspNetCore.Authentication.Google; -using Microsoft.AspNetCore.Identity; var builder = WebApplication.CreateBuilder(args); @@ -52,11 +49,16 @@ builder.Services.AddInfrastructureServices(builder.Configuration); builder.Services.AddWebServices(); // OAuth -builder.Services.AddAuthentication() - .AddCookie(CookieAuthenticationDefaults.AuthenticationScheme,options => +builder.Services.AddAuthorization(); +builder.Services.AddAuthentication(options => + { + options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme; + }) + .AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, options => { options.Cookie.Name = "Hutopy"; - options.Cookie.SecurePolicy = builder.Environment.IsDevelopment() ? CookieSecurePolicy.None : CookieSecurePolicy.Always; + options.Cookie.SecurePolicy = + builder.Environment.IsDevelopment() ? CookieSecurePolicy.None : CookieSecurePolicy.Always; options.Cookie.SameSite = SameSiteMode.Strict; options.Cookie.HttpOnly = true; options.Cookie.IsEssential = true; @@ -64,8 +66,10 @@ builder.Services.AddAuthentication() }) .AddGoogle(options => { - options.ClientId = builder.Configuration["Google:ClientId"] ?? throw new ArgumentNullException("The Google ClientId is missing."); - options.ClientSecret = builder.Configuration["Google:ClientSecret"] ?? throw new ArgumentNullException("The Google ClientSecret is missing."); + options.ClientId = builder.Configuration["Google:ClientId"] ?? + throw new ArgumentNullException("The Google ClientId is missing."); + options.ClientSecret = builder.Configuration["Google:ClientSecret"] ?? + throw new ArgumentNullException("The Google ClientSecret is missing."); options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme; options.Events.OnRedirectToAuthorizationEndpoint = context => { @@ -73,16 +77,15 @@ builder.Services.AddAuthentication() return Task.CompletedTask; }; }); - /*.AddFacebook(options => - { - options.AppId = ""; // TODO - options.AppSecret = ""; // TODO - });*/ // We can add a lot more if needed, microsoft, twitter, etc. +builder.Services.AddControllers(); builder.Services.AddScoped(); var app = builder.Build(); +app.UseAuthentication(); +app.UseAuthorization(); + app.UseCors("AllowAll"); app.UseCors("AllowHutopyUi"); app.UseCors("AllowHutopyUiPreview"); @@ -111,8 +114,6 @@ app.MapControllerRoute( name: "default", pattern: "{controller}/{action=Index}/{id?}"); -app.MapRazorPages(); - app.MapFallbackToFile("index.html"); app.UseExceptionHandler(options => { }); diff --git a/src/Web/wwwroot/api/specification.json b/src/Web/wwwroot/api/specification.json index c080bf3..79be20e 100644 --- a/src/Web/wwwroot/api/specification.json +++ b/src/Web/wwwroot/api/specification.json @@ -34,7 +34,15 @@ "operationId": "GetApiGoogleOSignIn", "responses": { "200": { - "description": "" + "description": "", + "content": { + "application/octet-stream": { + "schema": { + "type": "string", + "format": "binary" + } + } + } } } } From bbbfddd6cbd09616aa3336480f0601744832f698 Mon Sep 17 00:00:00 2001 From: Kamigen <46357922+Edouard127@users.noreply.github.com> Date: Wed, 8 May 2024 19:04:25 -0400 Subject: [PATCH 039/229] Feature: Google oauth --- src/Infrastructure/Services/UserService.cs | 70 ++++++++++++++++------ src/Web/Controllers/GoogleController.cs | 54 +++++++++++++++++ src/Web/Endpoints/Google.cs | 26 -------- src/Web/Program.cs | 43 +++++++------ src/Web/wwwroot/api/specification.json | 34 ++++------- 5 files changed, 143 insertions(+), 84 deletions(-) create mode 100644 src/Web/Controllers/GoogleController.cs delete mode 100644 src/Web/Endpoints/Google.cs diff --git a/src/Infrastructure/Services/UserService.cs b/src/Infrastructure/Services/UserService.cs index b45e3b3..12910a4 100644 --- a/src/Infrastructure/Services/UserService.cs +++ b/src/Infrastructure/Services/UserService.cs @@ -32,7 +32,7 @@ public class UserService(UserManager userManager) : IUserServic public async Task CreateUserAsync(Userinfo userInfo) { - await CreateUserAsync(userInfo.Email, userInfo.GivenName, userInfo.GivenName, userInfo.FamilyName, GeneratePassword(24)); + await CreateUserAsync(userInfo.Email, userInfo.GivenName, userInfo.GivenName, userInfo.FamilyName, RandomGenerator.RandomString(24)); } public async Task FindUserByIdAsync(string id) @@ -82,23 +82,55 @@ public class UserService(UserManager userManager) : IUserServic return userModel; } - - private const string Characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; - private const string SpecialCharacters = "!@#$%^&*()_+"; - - private String GeneratePassword(int length) - { - // Using a string builder has additional overhead, maybe we can find something else - var password = new StringBuilder(); - - for (var i = 0; i < length; i++) - { - password.Append(Characters[_random.Next(Characters.Length)]); - } - - password.Append(SpecialCharacters[_random.Next(SpecialCharacters.Length)]); - - return password.ToString(); - } } +public class RandomGenerator +{ + private const string LetterBytes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" + + "0123456789" + + "!@#$%^&*()_+" + + "-=[];',./`~{}|:\"<>?"; + private const int LetterIdxBits = 6; + private const int LetterIdxMask = 1 << LetterIdxBits; + private const int LetterIdxMax = 64 / LetterIdxBits; + + private static readonly Random Src = new(); + + public static byte[] RandBytesMaskSrc(int n) + { + var b = new byte[n]; + + for (var i = n - 1; i >= 0;) + { + long cache = Src.NextInt64(); + int remain = LetterIdxMax; + + while (remain != 0) + { + if (i < 0) + break; + + if (cache == 0) + cache = Src.NextInt64(); + + var idx = (int)(cache & LetterIdxMask); + if (idx < LetterBytes.Length) + { + b[i] = (byte)LetterBytes[idx]; + i--; + } + + cache >>= LetterIdxBits; + remain--; + } + } + + return b; + } + + public static string RandomString(int length) + { + var bytes = RandBytesMaskSrc(length); + return Encoding.UTF8.GetString(bytes); // Equivalent for *(string*)(&bytes[0]) + } +} diff --git a/src/Web/Controllers/GoogleController.cs b/src/Web/Controllers/GoogleController.cs new file mode 100644 index 0000000..173413a --- /dev/null +++ b/src/Web/Controllers/GoogleController.cs @@ -0,0 +1,54 @@ +using System.Security.Claims; +using Google.Apis.Oauth2.v2.Data; +using Hutopy.Domain.Interfaces; +using Microsoft.AspNetCore.Authentication; +using Microsoft.AspNetCore.Authentication.Cookies; +using Microsoft.AspNetCore.Authentication.Google; +using Microsoft.AspNetCore.Mvc; + +namespace Hutopy.Web.Controllers; + +public class GoogleController( + IUserService userService) : Controller +{ + [HttpGet("/api/google/sign-in")] + public async Task SignIn() + { + await HttpContext.ChallengeAsync(GoogleDefaults.AuthenticationScheme, new AuthenticationProperties + { + RedirectUri = Url.Action("Callback"), + }); + } + + public async Task Callback() + { + var authenticateResult = await HttpContext.AuthenticateAsync(CookieAuthenticationDefaults.AuthenticationScheme); + + if (!authenticateResult.Succeeded) + { + return BadRequest(); + } + + var claims = authenticateResult.Principal.Claims.ToList(); + + var userInfo = new Userinfo + { + Name = claims.FirstOrDefault(c => c.Type == ClaimTypes.Name)?.Value, + Email = claims.FirstOrDefault(c => c.Type == ClaimTypes.Email)?.Value, + GivenName = claims.FirstOrDefault(c => c.Type == ClaimTypes.GivenName)?.Value, + FamilyName = claims.FirstOrDefault(c => c.Type == ClaimTypes.Surname)?.Value + }; + + await userService.CreateUserAsync(userInfo); // TODO: Don't create user if already exists + + await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, new ClaimsPrincipal(new ClaimsIdentity(new List + { + new(ClaimTypes.Name, userInfo.Name), + new(ClaimTypes.Email, userInfo.Email), + new(ClaimTypes.GivenName, userInfo.GivenName), + new(ClaimTypes.Surname, userInfo.FamilyName) + }, CookieAuthenticationDefaults.AuthenticationScheme))); + + return Redirect("/"); + } +} diff --git a/src/Web/Endpoints/Google.cs b/src/Web/Endpoints/Google.cs deleted file mode 100644 index 0a9a92d..0000000 --- a/src/Web/Endpoints/Google.cs +++ /dev/null @@ -1,26 +0,0 @@ -using Microsoft.AspNetCore.Authentication; -using Microsoft.AspNetCore.Authentication.Google; -using Microsoft.AspNetCore.Mvc; - -namespace Hutopy.Web.Endpoints; - -public class Google : EndpointGroupBase -{ - public override void Map(WebApplication app) - { - app.MapGroup(this) - .MapGet("/o/sign-in", Callback); - } - - private static async Task Callback(ISender sender, HttpContext context) - { - var properties = new AuthenticationProperties - { - RedirectUri = "/signin-google", ExpiresUtc = DateTimeOffset.UtcNow.AddDays(30), - }; - - await context.ChallengeAsync(GoogleDefaults.AuthenticationScheme, properties); - - return new ChallengeResult(GoogleDefaults.AuthenticationScheme, properties); - } -} diff --git a/src/Web/Program.cs b/src/Web/Program.cs index b6c6745..5407839 100644 --- a/src/Web/Program.cs +++ b/src/Web/Program.cs @@ -5,7 +5,11 @@ using Hutopy.Infrastructure.Data; using Hutopy.Infrastructure.Services; using Hutopy.Web; using Azure.Identity; +using Hutopy.Infrastructure.Identity; using Microsoft.AspNetCore.Authentication.Cookies; +using Microsoft.AspNetCore.Authentication.Google; +using Microsoft.AspNetCore.HttpOverrides; +using Microsoft.AspNetCore.Identity; var builder = WebApplication.CreateBuilder(args); @@ -49,40 +53,43 @@ builder.Services.AddInfrastructureServices(builder.Configuration); builder.Services.AddWebServices(); // OAuth -builder.Services.AddAuthorization(); builder.Services.AddAuthentication(options => { options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme; + options.DefaultChallengeScheme = GoogleDefaults.AuthenticationScheme; }) - .AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, options => - { - options.Cookie.Name = "Hutopy"; - options.Cookie.SecurePolicy = - builder.Environment.IsDevelopment() ? CookieSecurePolicy.None : CookieSecurePolicy.Always; - options.Cookie.SameSite = SameSiteMode.Strict; - options.Cookie.HttpOnly = true; - options.Cookie.IsEssential = true; - options.Cookie.MaxAge = TimeSpan.FromDays(30); - }) - .AddGoogle(options => + .AddCookie() + .AddGoogle( + GoogleDefaults.AuthenticationScheme, + options => { options.ClientId = builder.Configuration["Google:ClientId"] ?? throw new ArgumentNullException("The Google ClientId is missing."); options.ClientSecret = builder.Configuration["Google:ClientSecret"] ?? throw new ArgumentNullException("The Google ClientSecret is missing."); - options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme; - options.Events.OnRedirectToAuthorizationEndpoint = context => - { - context.Response.Redirect(context.RedirectUri + "&prompt=consent"); - return Task.CompletedTask; - }; }); +// Password hashing +builder.Services.AddIdentity(options => + { + options.Password.RequireDigit = true; + options.Password.RequireLowercase = false; + options.Password.RequireUppercase = true; + options.Password.RequireNonAlphanumeric = true; + options.Password.RequiredLength = 8; + }) + .AddEntityFrameworkStores() + .AddDefaultTokenProviders(); + builder.Services.AddControllers(); builder.Services.AddScoped(); var app = builder.Build(); +app.UseForwardedHeaders( + new ForwardedHeadersOptions { ForwardedHeaders = ForwardedHeaders.XForwardedProto } +); + app.UseAuthentication(); app.UseAuthorization(); diff --git a/src/Web/wwwroot/api/specification.json b/src/Web/wwwroot/api/specification.json index 79be20e..fcb4d9f 100644 --- a/src/Web/wwwroot/api/specification.json +++ b/src/Web/wwwroot/api/specification.json @@ -26,27 +26,6 @@ } } }, - "/api/Google/o/sign-in": { - "get": { - "tags": [ - "Google" - ], - "operationId": "GetApiGoogleOSignIn", - "responses": { - "200": { - "description": "", - "content": { - "application/octet-stream": { - "schema": { - "type": "string", - "format": "binary" - } - } - } - } - } - } - }, "/api/JoinUs": { "get": { "tags": [ @@ -628,6 +607,19 @@ } ] } + }, + "/api/google/sign-in": { + "get": { + "tags": [ + "Google" + ], + "operationId": "Google_SignIn", + "responses": { + "200": { + "description": "" + } + } + } } }, "components": { From 4f97f8ad25669d88589214db2a47a925fdf5968d Mon Sep 17 00:00:00 2001 From: Dominic Villemure Date: Thu, 9 May 2024 18:00:42 -0400 Subject: [PATCH 040/229] #27 added more info to transaction + callback from stripe --- Directory.Packages.props | 2 +- src/Application/Application.csproj | 1 + .../Common/Interfaces/IStripeService.cs | 4 + .../Commands/ConfirmStripeTransaction.cs | 69 ++- .../Commands/CreateSessionCheckoutCommand.cs | 2 - src/Domain/Entities/UserTransaction.cs | 10 +- ...ddMoreInformationToTransaction.Designer.cs | 418 ++++++++++++++++++ ...9215538_AddMoreInformationToTransaction.cs | 106 +++++ .../ApplicationDbContextModelSnapshot.cs | 31 ++ src/Infrastructure/Stripe/StripeService.cs | 34 +- src/Web/Endpoints/Stripe.cs | 4 +- src/Web/appsettings.Development.json | 21 +- src/Web/wwwroot/api/specification.json | 90 +++- 13 files changed, 770 insertions(+), 22 deletions(-) create mode 100644 src/Infrastructure/Migrations/20240509215538_AddMoreInformationToTransaction.Designer.cs create mode 100644 src/Infrastructure/Migrations/20240509215538_AddMoreInformationToTransaction.cs diff --git a/Directory.Packages.props b/Directory.Packages.props index 74620e0..90a35bf 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -37,7 +37,7 @@ - + \ No newline at end of file diff --git a/src/Application/Application.csproj b/src/Application/Application.csproj index 8544947..e01512a 100644 --- a/src/Application/Application.csproj +++ b/src/Application/Application.csproj @@ -10,6 +10,7 @@ + diff --git a/src/Application/Common/Interfaces/IStripeService.cs b/src/Application/Common/Interfaces/IStripeService.cs index 75edbe9..ca32184 100644 --- a/src/Application/Common/Interfaces/IStripeService.cs +++ b/src/Application/Common/Interfaces/IStripeService.cs @@ -1,7 +1,11 @@ +using Hutopy.Application.Common.Models; +using Hutopy.Application.Stripe.Commands; + namespace Hutopy.Application.Common.Interfaces; public interface IStripeService { public Task CreateCheckoutSession(int amount, string currency); + public Result ValidateTransaction(ConfirmStripeTransactionCommand request); } diff --git a/src/Application/Stripe/Commands/ConfirmStripeTransaction.cs b/src/Application/Stripe/Commands/ConfirmStripeTransaction.cs index 7aa8a3e..ea5a61c 100644 --- a/src/Application/Stripe/Commands/ConfirmStripeTransaction.cs +++ b/src/Application/Stripe/Commands/ConfirmStripeTransaction.cs @@ -1,24 +1,75 @@ using Hutopy.Application.Common.Interfaces; +using Stripe; + namespace Hutopy.Application.Stripe.Commands; -public record ConfirmStripeTransactionCommand : IRequest +public class ConfirmStripeTransactionCommand : IRequest { - public required Guid UserTransactionId { get; init; } - public required bool IsConfirmed { get; init; } + public string Id { get; set; } + public string Object { get; set; } + public int Created { get; set; } + public Data Data { get; set; } + public Request Request { get; set; } +} + +public class Data +{ + public Object Object { get; set; } +} + +public class Object +{ + public string Id { get; set; } = String.Empty; + public int Amount { get; set; } + public BillingDetails Billing_details { get; set; } = new(); + public string Calculated_statement_descriptor { get; set; } = String.Empty; + public string Currency { get; set; } = String.Empty; + public bool Paid { get; set; } + public string Payment_intent { get; set; } = String.Empty; + public string Payment_method { get; set; } = String.Empty; + public string Receipt_url { get; set; } = String.Empty; + public string Status { get; set; } = String.Empty; + public string Failure_message { get; set; } = String.Empty; +} + +public class BillingDetails +{ + public string Email { get; set; } = String.Empty; + public string Name { get; set; } = String.Empty; + public string Phone { get; set; } = String.Empty; +} + +public class Request +{ + public string Id { get; set; } = String.Empty; } public class ConfirmStripeTransactionCommandHandler( - IApplicationDbContext dbContext + IApplicationDbContext dbContext, + IStripeService stripeService ) : IRequestHandler { public async Task Handle(ConfirmStripeTransactionCommand request, CancellationToken cancellationToken) { - var transaction = await dbContext.UserTransactions.FirstOrDefaultAsync(x => x.Id == request.UserTransactionId, cancellationToken); - if (transaction is null) return ""; - transaction.IsConfirmed = request.IsConfirmed; - dbContext.UserTransactions.Update(transaction); + var lastTransaction = await dbContext.UserTransactions.OrderBy(x => x.Created).LastAsync(cancellationToken); + var stripeConfirmation = stripeService.ValidateTransaction(request); - return transaction.Id.ToString(); + if (stripeConfirmation.Succeeded) + { + lastTransaction.IsConfirmed = true; + lastTransaction.Paid = request.Data.Object.Paid; + lastTransaction.StripeChargeId = request.Data.Object.Id; + lastTransaction.StripeEventId = request.Id; + lastTransaction.StripeReceiptUrl = request.Data.Object.Receipt_url; + lastTransaction.StripePaymentIntent = request.Data.Object.Payment_intent; + lastTransaction.StripePaymentMethod = request.Data.Object.Payment_method; + lastTransaction.StripeBillingDetailEmail = request.Data.Object.Billing_details.Email; + lastTransaction.StripeBillingDetailName = request.Data.Object.Billing_details.Name; + } + + await dbContext.SaveChangesAsync(cancellationToken); + + return ""; } } diff --git a/src/Application/Stripe/Commands/CreateSessionCheckoutCommand.cs b/src/Application/Stripe/Commands/CreateSessionCheckoutCommand.cs index b428733..28e9d72 100644 --- a/src/Application/Stripe/Commands/CreateSessionCheckoutCommand.cs +++ b/src/Application/Stripe/Commands/CreateSessionCheckoutCommand.cs @@ -22,9 +22,7 @@ public class CreateSessionCheckoutCommandHandler( // ReSharper disable once PossibleLossOfFraction decimal priceInDollars = (request.Amount / 100); - - //todo: Need to add this transaction after the confirmation from stripe in the frontEnd ( redirect, re-call backend ) var userTransaction = new UserTransaction { Currency = request.Currency, Amount = priceInDollars, TipMessage = request.TipMessage, ApplicationUserId = request.CreatorId diff --git a/src/Domain/Entities/UserTransaction.cs b/src/Domain/Entities/UserTransaction.cs index b879fd2..5ab7314 100644 --- a/src/Domain/Entities/UserTransaction.cs +++ b/src/Domain/Entities/UserTransaction.cs @@ -8,5 +8,13 @@ public class UserTransaction : BaseAuditableEntity // Foreign key to ApplicationUser public string ApplicationUserId { get; set; } = string.Empty; - public bool IsConfirmed { get; set; } = false; + public bool IsConfirmed { get; set; } + public string StripeEventId { get; set; } = string.Empty; + public string StripeChargeId { get; set; } = string.Empty; + public string StripePaymentIntent { get; set; } = string.Empty; + public string StripePaymentMethod { get; set; } = string.Empty; + public string StripeReceiptUrl { get; set; } = string.Empty; + public string StripeBillingDetailEmail { get; set; } = string.Empty; + public string StripeBillingDetailName { get; set; } = string.Empty; + public bool Paid { get; set; } } diff --git a/src/Infrastructure/Migrations/20240509215538_AddMoreInformationToTransaction.Designer.cs b/src/Infrastructure/Migrations/20240509215538_AddMoreInformationToTransaction.Designer.cs new file mode 100644 index 0000000..f8c9e81 --- /dev/null +++ b/src/Infrastructure/Migrations/20240509215538_AddMoreInformationToTransaction.Designer.cs @@ -0,0 +1,418 @@ +// +using System; +using Hutopy.Infrastructure.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Hutopy.Infrastructure.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + [Migration("20240509215538_AddMoreInformationToTransaction")] + partial class AddMoreInformationToTransaction + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.3") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("Hutopy.Domain.Entities.FutureCreator", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Created") + .HasColumnType("datetimeoffset"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("EmailAddress") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("FirstName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("LastModified") + .HasColumnType("datetimeoffset"); + + b.Property("LastModifiedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("LastName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumber") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("ReasonToJoin") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("SocialNetworkAccount") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("FutureCreators"); + }); + + modelBuilder.Entity("Hutopy.Domain.Entities.UserTransaction", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Amount") + .HasPrecision(18, 2) + .HasColumnType("decimal(18,2)"); + + b.Property("ApplicationUserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.Property("Created") + .HasColumnType("datetimeoffset"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("Currency") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("IsConfirmed") + .HasColumnType("bit"); + + b.Property("LastModified") + .HasColumnType("datetimeoffset"); + + b.Property("LastModifiedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("Paid") + .HasColumnType("bit"); + + b.Property("StripeBillingDetailEmail") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("StripeBillingDetailName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("StripeChargeId") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("StripeEventId") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("StripePaymentIntent") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("StripePaymentMethod") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("StripeReceiptUrl") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("TipMessage") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationUserId"); + + b.ToTable("UserTransactions"); + }); + + modelBuilder.Entity("Hutopy.Infrastructure.Identity.ApplicationUser", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("AccessFailedCount") + .HasColumnType("int"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("nvarchar(max)"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("EmailConfirmed") + .HasColumnType("bit"); + + b.Property("FirstName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("LastName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("LockoutEnabled") + .HasColumnType("bit"); + + b.Property("LockoutEnd") + .HasColumnType("datetimeoffset"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("PasswordHash") + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumber") + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("bit"); + + b.Property("SecurityStamp") + .HasColumnType("nvarchar(max)"); + + b.Property("TwoFactorEnabled") + .HasColumnType("bit"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex") + .HasFilter("[NormalizedUserName] IS NOT NULL"); + + b.ToTable("AspNetUsers", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("nvarchar(max)"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex") + .HasFilter("[NormalizedName] IS NOT NULL"); + + b.ToTable("AspNetRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("nvarchar(max)"); + + b.Property("ClaimValue") + .HasColumnType("nvarchar(max)"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("nvarchar(max)"); + + b.Property("ClaimValue") + .HasColumnType("nvarchar(max)"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("nvarchar(450)"); + + b.Property("ProviderKey") + .HasColumnType("nvarchar(450)"); + + b.Property("ProviderDisplayName") + .HasColumnType("nvarchar(max)"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("nvarchar(450)"); + + b.Property("RoleId") + .HasColumnType("nvarchar(450)"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("nvarchar(450)"); + + b.Property("LoginProvider") + .HasColumnType("nvarchar(450)"); + + b.Property("Name") + .HasColumnType("nvarchar(450)"); + + b.Property("Value") + .HasColumnType("nvarchar(max)"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens", (string)null); + }); + + modelBuilder.Entity("Hutopy.Domain.Entities.UserTransaction", b => + { + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("ApplicationUserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Infrastructure/Migrations/20240509215538_AddMoreInformationToTransaction.cs b/src/Infrastructure/Migrations/20240509215538_AddMoreInformationToTransaction.cs new file mode 100644 index 0000000..d91d3cf --- /dev/null +++ b/src/Infrastructure/Migrations/20240509215538_AddMoreInformationToTransaction.cs @@ -0,0 +1,106 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Hutopy.Infrastructure.Migrations +{ + /// + public partial class AddMoreInformationToTransaction : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "Paid", + table: "UserTransactions", + type: "bit", + nullable: false, + defaultValue: false); + + migrationBuilder.AddColumn( + name: "StripeBillingDetailEmail", + table: "UserTransactions", + type: "nvarchar(max)", + nullable: false, + defaultValue: ""); + + migrationBuilder.AddColumn( + name: "StripeBillingDetailName", + table: "UserTransactions", + type: "nvarchar(max)", + nullable: false, + defaultValue: ""); + + migrationBuilder.AddColumn( + name: "StripeChargeId", + table: "UserTransactions", + type: "nvarchar(max)", + nullable: false, + defaultValue: ""); + + migrationBuilder.AddColumn( + name: "StripeEventId", + table: "UserTransactions", + type: "nvarchar(max)", + nullable: false, + defaultValue: ""); + + migrationBuilder.AddColumn( + name: "StripePaymentIntent", + table: "UserTransactions", + type: "nvarchar(max)", + nullable: false, + defaultValue: ""); + + migrationBuilder.AddColumn( + name: "StripePaymentMethod", + table: "UserTransactions", + type: "nvarchar(max)", + nullable: false, + defaultValue: ""); + + migrationBuilder.AddColumn( + name: "StripeReceiptUrl", + table: "UserTransactions", + type: "nvarchar(max)", + nullable: false, + defaultValue: ""); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "Paid", + table: "UserTransactions"); + + migrationBuilder.DropColumn( + name: "StripeBillingDetailEmail", + table: "UserTransactions"); + + migrationBuilder.DropColumn( + name: "StripeBillingDetailName", + table: "UserTransactions"); + + migrationBuilder.DropColumn( + name: "StripeChargeId", + table: "UserTransactions"); + + migrationBuilder.DropColumn( + name: "StripeEventId", + table: "UserTransactions"); + + migrationBuilder.DropColumn( + name: "StripePaymentIntent", + table: "UserTransactions"); + + migrationBuilder.DropColumn( + name: "StripePaymentMethod", + table: "UserTransactions"); + + migrationBuilder.DropColumn( + name: "StripeReceiptUrl", + table: "UserTransactions"); + } + } +} diff --git a/src/Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs b/src/Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs index dedb234..cb3b55f 100644 --- a/src/Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs +++ b/src/Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs @@ -102,6 +102,37 @@ namespace Hutopy.Infrastructure.Migrations b.Property("LastModifiedBy") .HasColumnType("nvarchar(max)"); + b.Property("Paid") + .HasColumnType("bit"); + + b.Property("StripeBillingDetailEmail") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("StripeBillingDetailName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("StripeChargeId") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("StripeEventId") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("StripePaymentIntent") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("StripePaymentMethod") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("StripeReceiptUrl") + .IsRequired() + .HasColumnType("nvarchar(max)"); + b.Property("TipMessage") .IsRequired() .HasColumnType("nvarchar(max)"); diff --git a/src/Infrastructure/Stripe/StripeService.cs b/src/Infrastructure/Stripe/StripeService.cs index 881b6c4..dc84e34 100644 --- a/src/Infrastructure/Stripe/StripeService.cs +++ b/src/Infrastructure/Stripe/StripeService.cs @@ -1,13 +1,20 @@ using Stripe; using Stripe.Checkout; using Hutopy.Application.Common.Interfaces; +using Microsoft.AspNetCore.Http; +using Hutopy.Application.Common.Models; +using Hutopy.Application.Stripe.Commands; namespace Hutopy.Infrastructure.Stripe; public class StripeService : IStripeService { - public StripeService() + const string EndpointSecret = ""; + private readonly IHttpContextAccessor _httpContextAccessor; + + public StripeService(IHttpContextAccessor httpContextAccessor) { + _httpContextAccessor = httpContextAccessor; StripeConfiguration.ApiKey = ""; } @@ -31,7 +38,7 @@ public class StripeService : IStripeService ], Mode = "payment", UiMode = "embedded", - ReturnUrl = "https://zealous-bay-08204590f.5.azurestaticapps.net/paymentcompleted", + ReturnUrl = "https://hutopy.ca/paymentcompleted", }; var service = new SessionService(); @@ -39,4 +46,27 @@ public class StripeService : IStripeService return session.ClientSecret; } + + public Result ValidateTransaction(ConfirmStripeTransactionCommand request) + { + try + { + if (request.Data.Object.Status is "succeeded") + { + return new Result(true, new List()); + } + + return new Result(false, new List()); + + } + catch (StripeException e) + { + Console.WriteLine("Error: {0}", e.Message); + return new Result(false, new List{e.Message}); + } + catch (Exception e) + { + return new Result(false, new List{e.Message}); + } + } } diff --git a/src/Web/Endpoints/Stripe.cs b/src/Web/Endpoints/Stripe.cs index b944419..264f4c8 100644 --- a/src/Web/Endpoints/Stripe.cs +++ b/src/Web/Endpoints/Stripe.cs @@ -16,8 +16,8 @@ public class Stripe : EndpointGroupBase return sender.Send(command); } - private static Task ConfirmTransaction(ISender sender, ConfirmStripeTransactionCommand command) + private async static Task ConfirmTransaction(ISender sender, ConfirmStripeTransactionCommand command) { - return sender.Send(command); + return await sender.Send(command); } } diff --git a/src/Web/appsettings.Development.json b/src/Web/appsettings.Development.json index 84308c9..b98033c 100644 --- a/src/Web/appsettings.Development.json +++ b/src/Web/appsettings.Development.json @@ -2,9 +2,28 @@ "Logging": { "LogLevel": { "Default": "Information", - "Microsoft": "Warning", + "Microsoft": "Information", "Microsoft.AspNetCore.SpaProxy": "Information", "Microsoft.Hosting.Lifetime": "Information" } + }, + "Google": { + "ClientId": "468391910875-78sfopq1t12ulrv4f5vj227j45guuj66.apps.googleusercontent.com", + "ClientSecret": "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", + "ProjectId": "hutopy-420016", + "AuthUri": "https://accounts.google.com/o/oauth2/auth", + "TokenUri": "https://oauth2.googleapis.com/token", + "AuthProviderX509CertUrl": "https://www.googleapis.com/oauth2/v1/certs", + "RedirectUris": [ + "https://hutopy.ca", + "https://hutopy.com", + "http://localhost" + ], + "JavascriptOrigins": [ + "https://hutopy.ca", + "https://hutopy.com", + "http://localhost" + ] } } + diff --git a/src/Web/wwwroot/api/specification.json b/src/Web/wwwroot/api/specification.json index 5a1838c..9c7a80c 100644 --- a/src/Web/wwwroot/api/specification.json +++ b/src/Web/wwwroot/api/specification.json @@ -723,12 +723,94 @@ "type": "object", "additionalProperties": false, "properties": { - "userTransactionId": { - "type": "string", - "format": "guid" + "id": { + "type": "string" }, - "isConfirmed": { + "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" } } }, From c06c3039e8f9d1e34839659684f77be912f70e9f Mon Sep 17 00:00:00 2001 From: Dominic Villemure Date: Thu, 9 May 2024 21:58:21 -0400 Subject: [PATCH 041/229] #27 not needed stripe in application --- src/Application/Application.csproj | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Application/Application.csproj b/src/Application/Application.csproj index e01512a..8544947 100644 --- a/src/Application/Application.csproj +++ b/src/Application/Application.csproj @@ -10,7 +10,6 @@ - From e3eed8adebd1d3af1f405dab88f1d82b4c55a1f8 Mon Sep 17 00:00:00 2001 From: Dominic Villemure Date: Thu, 9 May 2024 21:59:01 -0400 Subject: [PATCH 042/229] #27 remove using --- src/Application/Stripe/Commands/ConfirmStripeTransaction.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Application/Stripe/Commands/ConfirmStripeTransaction.cs b/src/Application/Stripe/Commands/ConfirmStripeTransaction.cs index ea5a61c..eb074a0 100644 --- a/src/Application/Stripe/Commands/ConfirmStripeTransaction.cs +++ b/src/Application/Stripe/Commands/ConfirmStripeTransaction.cs @@ -1,6 +1,4 @@ using Hutopy.Application.Common.Interfaces; -using Stripe; - namespace Hutopy.Application.Stripe.Commands; public class ConfirmStripeTransactionCommand : IRequest From 59b6dc265da577b93240f028ee32f1fc9ce6d63c Mon Sep 17 00:00:00 2001 From: Dominic Villemure Date: Thu, 9 May 2024 22:00:00 -0400 Subject: [PATCH 043/229] #27 remove secrets --- src/Web/appsettings.Development.json | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/src/Web/appsettings.Development.json b/src/Web/appsettings.Development.json index b98033c..be4dfad 100644 --- a/src/Web/appsettings.Development.json +++ b/src/Web/appsettings.Development.json @@ -6,24 +6,6 @@ "Microsoft.AspNetCore.SpaProxy": "Information", "Microsoft.Hosting.Lifetime": "Information" } - }, - "Google": { - "ClientId": "468391910875-78sfopq1t12ulrv4f5vj227j45guuj66.apps.googleusercontent.com", - "ClientSecret": "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", - "ProjectId": "hutopy-420016", - "AuthUri": "https://accounts.google.com/o/oauth2/auth", - "TokenUri": "https://oauth2.googleapis.com/token", - "AuthProviderX509CertUrl": "https://www.googleapis.com/oauth2/v1/certs", - "RedirectUris": [ - "https://hutopy.ca", - "https://hutopy.com", - "http://localhost" - ], - "JavascriptOrigins": [ - "https://hutopy.ca", - "https://hutopy.com", - "http://localhost" - ] } } From 8789001babfb1e3e9df339f00e5693e0d8d1c263 Mon Sep 17 00:00:00 2001 From: Dominic Villemure Date: Thu, 9 May 2024 22:02:21 -0400 Subject: [PATCH 044/229] #27 remove appsettings.Development.json from tracked files --- .gitignore | 4 ++++ src/Web/appsettings.Development.json | 11 ----------- 2 files changed, 4 insertions(+), 11 deletions(-) delete mode 100644 src/Web/appsettings.Development.json diff --git a/.gitignore b/.gitignore index 87e0e84..6614a0b 100644 --- a/.gitignore +++ b/.gitignore @@ -485,3 +485,7 @@ $RECYCLE.BIN/ # Other IDE files .vscode/ .idea/ + + +#AppSettings dev +*/appsettings.Development.json diff --git a/src/Web/appsettings.Development.json b/src/Web/appsettings.Development.json deleted file mode 100644 index be4dfad..0000000 --- a/src/Web/appsettings.Development.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "Logging": { - "LogLevel": { - "Default": "Information", - "Microsoft": "Information", - "Microsoft.AspNetCore.SpaProxy": "Information", - "Microsoft.Hosting.Lifetime": "Information" - } - } -} - From 0bcbd9fc0ea7ac16619d550198d6e1322af1a264 Mon Sep 17 00:00:00 2001 From: Dominic Villemure Date: Thu, 9 May 2024 22:03:05 -0400 Subject: [PATCH 045/229] #26 specific ignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 6614a0b..d6fda7d 100644 --- a/.gitignore +++ b/.gitignore @@ -489,3 +489,4 @@ $RECYCLE.BIN/ #AppSettings dev */appsettings.Development.json +/src/Web/appsettings.Development.json From 3f2056385001cbf992e6eec382c879f0ec3ea836 Mon Sep 17 00:00:00 2001 From: Dominic Villemure Date: Thu, 9 May 2024 22:03:55 -0400 Subject: [PATCH 046/229] #27 dist file for devs --- src/Web/appsettings.Development.dist | 29 ++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 src/Web/appsettings.Development.dist diff --git a/src/Web/appsettings.Development.dist b/src/Web/appsettings.Development.dist new file mode 100644 index 0000000..58d6716 --- /dev/null +++ b/src/Web/appsettings.Development.dist @@ -0,0 +1,29 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft": "Information", + "Microsoft.AspNetCore.SpaProxy": "Information", + "Microsoft.Hosting.Lifetime": "Information" + } + }, + "Google": { + "ClientId": "", + "ClientSecret": "", + "ProjectId": "", + "AuthUri": "", + "TokenUri": "", + "AuthProviderX509CertUrl": "", + "RedirectUris": [ + "https://hutopy.ca", + "https://hutopy.com", + "http://localhost" + ], + "JavascriptOrigins": [ + "https://hutopy.ca", + "https://hutopy.com", + "http://localhost" + ] + } +} + From 5161e3a91ac592b2ffe787bb6d30c32582ad2be2 Mon Sep 17 00:00:00 2001 From: Dominic Villemure Date: Sun, 12 May 2024 16:40:24 -0400 Subject: [PATCH 047/229] #27 get last receipt, get minimalUser, get my user --- .../Common/Interfaces/IStripeService.cs | 2 +- .../Commands/ConfirmStripeTransaction.cs | 16 +-- .../Commands/CreateSessionCheckoutCommand.cs | 2 +- .../Stripe/Queries/GetMyLastReceipt.cs | 29 +++++ .../Stripe/Queries/MyLastReceiptDto.cs | 6 + .../{ => GetCurrentUser}/GetCurrentUser.cs | 3 +- .../Queries/{ => GetCurrentUser}/UserDto.cs | 1 + .../UserTransactionDto.cs | 0 .../Queries/GetMinimalUser/GetMinimalUser.cs | 28 +++++ .../Queries/GetMinimalUser/MinimalUserDto.cs | 8 ++ src/Domain/Entities/UserTransaction.cs | 2 +- src/Infrastructure/Services/UserService.cs | 14 ++- src/Infrastructure/Stripe/StripeService.cs | 8 +- src/Web/Endpoints/GetMyUser.cs | 1 + src/Web/Endpoints/Stripe.cs | 7 ++ src/Web/Endpoints/Users.cs | 7 ++ src/Web/wwwroot/api/specification.json | 106 +++++++++++++++++- 17 files changed, 216 insertions(+), 24 deletions(-) create mode 100644 src/Application/Stripe/Queries/GetMyLastReceipt.cs create mode 100644 src/Application/Stripe/Queries/MyLastReceiptDto.cs rename src/Application/Users/Queries/{ => GetCurrentUser}/GetCurrentUser.cs (93%) rename src/Application/Users/Queries/{ => GetCurrentUser}/UserDto.cs (83%) rename src/Application/Users/Queries/{ => GetCurrentUser}/UserTransactionDto.cs (100%) create mode 100644 src/Application/Users/Queries/GetMinimalUser/GetMinimalUser.cs create mode 100644 src/Application/Users/Queries/GetMinimalUser/MinimalUserDto.cs diff --git a/src/Application/Common/Interfaces/IStripeService.cs b/src/Application/Common/Interfaces/IStripeService.cs index ca32184..6737a3d 100644 --- a/src/Application/Common/Interfaces/IStripeService.cs +++ b/src/Application/Common/Interfaces/IStripeService.cs @@ -6,6 +6,6 @@ namespace Hutopy.Application.Common.Interfaces; public interface IStripeService { - public Task CreateCheckoutSession(int amount, string currency); + public Task CreateCheckoutSession(int amount, string creatorId, string currency); public Result ValidateTransaction(ConfirmStripeTransactionCommand request); } diff --git a/src/Application/Stripe/Commands/ConfirmStripeTransaction.cs b/src/Application/Stripe/Commands/ConfirmStripeTransaction.cs index eb074a0..0ddd17e 100644 --- a/src/Application/Stripe/Commands/ConfirmStripeTransaction.cs +++ b/src/Application/Stripe/Commands/ConfirmStripeTransaction.cs @@ -56,15 +56,15 @@ public class ConfirmStripeTransactionCommandHandler( if (stripeConfirmation.Succeeded) { lastTransaction.IsConfirmed = true; - lastTransaction.Paid = request.Data.Object.Paid; - lastTransaction.StripeChargeId = request.Data.Object.Id; - lastTransaction.StripeEventId = request.Id; - lastTransaction.StripeReceiptUrl = request.Data.Object.Receipt_url; - lastTransaction.StripePaymentIntent = request.Data.Object.Payment_intent; - lastTransaction.StripePaymentMethod = request.Data.Object.Payment_method; - lastTransaction.StripeBillingDetailEmail = request.Data.Object.Billing_details.Email; - lastTransaction.StripeBillingDetailName = request.Data.Object.Billing_details.Name; } + lastTransaction.Paid = request.Data.Object.Paid; + lastTransaction.StripeChargeId = request.Data.Object.Id; + lastTransaction.StripeEventId = request.Id; + lastTransaction.StripeReceiptUrl = request.Data.Object.Receipt_url; + lastTransaction.StripePaymentIntent = request.Data.Object.Payment_intent; + lastTransaction.StripePaymentMethod = request.Data.Object.Payment_method; + lastTransaction.StripeBillingDetailEmail = request.Data.Object.Billing_details.Email; + lastTransaction.StripeBillingDetailName = request.Data.Object.Billing_details.Name; await dbContext.SaveChangesAsync(cancellationToken); diff --git a/src/Application/Stripe/Commands/CreateSessionCheckoutCommand.cs b/src/Application/Stripe/Commands/CreateSessionCheckoutCommand.cs index 28e9d72..681c4d8 100644 --- a/src/Application/Stripe/Commands/CreateSessionCheckoutCommand.cs +++ b/src/Application/Stripe/Commands/CreateSessionCheckoutCommand.cs @@ -18,7 +18,7 @@ public class CreateSessionCheckoutCommandHandler( { public async Task Handle(CreateSessionCheckoutCommand request, CancellationToken cancellationToken) { - var stripeSecret = await stripeService.CreateCheckoutSession(request.Amount, request.Currency); + var stripeSecret = await stripeService.CreateCheckoutSession(request.Amount, request.CreatorId, request.Currency); // ReSharper disable once PossibleLossOfFraction decimal priceInDollars = (request.Amount / 100); diff --git a/src/Application/Stripe/Queries/GetMyLastReceipt.cs b/src/Application/Stripe/Queries/GetMyLastReceipt.cs new file mode 100644 index 0000000..b8a0602 --- /dev/null +++ b/src/Application/Stripe/Queries/GetMyLastReceipt.cs @@ -0,0 +1,29 @@ +using Hutopy.Application.Common.Interfaces; + +namespace Hutopy.Application.Stripe.Queries; + +public record GetMyLastReceiptQuery : IRequest +{ + public string Email { get; set; } = string.Empty; + public string CreatorId { get; set; } = string.Empty; +}; + +public class GetMyLastReceiptQueryHandler( + IApplicationDbContext dbContext + ) + : IRequestHandler +{ + public async Task Handle(GetMyLastReceiptQuery request, CancellationToken cancellationToken) + { + var lastTransaction = await dbContext.UserTransactions.OrderBy(x => x.Created) + .LastOrDefaultAsync(x => x.ApplicationUserId == request.CreatorId && x.StripeBillingDetailEmail == request.Email, + cancellationToken); + + var receiptUrl = new MyLastReceiptDto + { + ReceiptUrl = lastTransaction?.StripeReceiptUrl ?? "", + }; + + return receiptUrl; + } +} diff --git a/src/Application/Stripe/Queries/MyLastReceiptDto.cs b/src/Application/Stripe/Queries/MyLastReceiptDto.cs new file mode 100644 index 0000000..5ce1645 --- /dev/null +++ b/src/Application/Stripe/Queries/MyLastReceiptDto.cs @@ -0,0 +1,6 @@ +namespace Hutopy.Application.Stripe.Queries; + +public class MyLastReceiptDto +{ + public string ReceiptUrl { get; set; } +} diff --git a/src/Application/Users/Queries/GetCurrentUser.cs b/src/Application/Users/Queries/GetCurrentUser/GetCurrentUser.cs similarity index 93% rename from src/Application/Users/Queries/GetCurrentUser.cs rename to src/Application/Users/Queries/GetCurrentUser/GetCurrentUser.cs index a087cf8..82dc2f8 100644 --- a/src/Application/Users/Queries/GetCurrentUser.cs +++ b/src/Application/Users/Queries/GetCurrentUser/GetCurrentUser.cs @@ -18,12 +18,11 @@ public class GetCurrentUserQueryHandler( var currentUserId = new Guid(identityUser?.Id ?? ""); var transactions = await context.UserTransactions - .Where(x => x.Id == currentUserId) + .Where(x => x.ApplicationUserId == currentUserId.ToString()) .OrderBy(x => x.LastModified) .ProjectTo(mapper.ConfigurationProvider) .ToListAsync(cancellationToken); - var user = new UserDto() { Id = currentUserId, diff --git a/src/Application/Users/Queries/UserDto.cs b/src/Application/Users/Queries/GetCurrentUser/UserDto.cs similarity index 83% rename from src/Application/Users/Queries/UserDto.cs rename to src/Application/Users/Queries/GetCurrentUser/UserDto.cs index da62e26..acece9c 100644 --- a/src/Application/Users/Queries/UserDto.cs +++ b/src/Application/Users/Queries/GetCurrentUser/UserDto.cs @@ -7,6 +7,7 @@ public class UserDto public required string FirstName { get; init; } public required string LastName { get; init; } + public string UserName { get; init; } = String.Empty; public List UserTransactions { get; init; } = []; } diff --git a/src/Application/Users/Queries/UserTransactionDto.cs b/src/Application/Users/Queries/GetCurrentUser/UserTransactionDto.cs similarity index 100% rename from src/Application/Users/Queries/UserTransactionDto.cs rename to src/Application/Users/Queries/GetCurrentUser/UserTransactionDto.cs diff --git a/src/Application/Users/Queries/GetMinimalUser/GetMinimalUser.cs b/src/Application/Users/Queries/GetMinimalUser/GetMinimalUser.cs new file mode 100644 index 0000000..4206c79 --- /dev/null +++ b/src/Application/Users/Queries/GetMinimalUser/GetMinimalUser.cs @@ -0,0 +1,28 @@ +using Hutopy.Domain.Interfaces; + +namespace Hutopy.Application.Users.Queries.GetMinimalUser; + +public record GetMinimalUserQuery : IRequest +{ + public string UserId { get; set; } = string.Empty; +}; + +public class GetMinimalUserQueryHandler( + IUserService userService + ) + : IRequestHandler +{ + public async Task Handle(GetMinimalUserQuery request, CancellationToken cancellationToken) + { + var identityUser = await userService.FindUserByIdAsync(request.UserId); + + var user = new MinimalUserDto() + { + FirstName = identityUser?.FirstName ?? "", + LastName = identityUser?.LastName ?? "", + UserName = identityUser?.UserName ?? "" + }; + + return user; + } +} diff --git a/src/Application/Users/Queries/GetMinimalUser/MinimalUserDto.cs b/src/Application/Users/Queries/GetMinimalUser/MinimalUserDto.cs new file mode 100644 index 0000000..0b01fba --- /dev/null +++ b/src/Application/Users/Queries/GetMinimalUser/MinimalUserDto.cs @@ -0,0 +1,8 @@ +namespace Hutopy.Application.Users.Queries.GetMinimalUser; + +public class MinimalUserDto +{ + public required string FirstName { get; init; } + public required string LastName { get; init; } + public string UserName { get; init; } = String.Empty; +} diff --git a/src/Domain/Entities/UserTransaction.cs b/src/Domain/Entities/UserTransaction.cs index 5ab7314..78e32d4 100644 --- a/src/Domain/Entities/UserTransaction.cs +++ b/src/Domain/Entities/UserTransaction.cs @@ -7,7 +7,7 @@ public class UserTransaction : BaseAuditableEntity public string TipMessage { get; set; } = string.Empty; // Foreign key to ApplicationUser - public string ApplicationUserId { get; set; } = string.Empty; + public required string ApplicationUserId { get; set; } public bool IsConfirmed { get; set; } public string StripeEventId { get; set; } = string.Empty; public string StripeChargeId { get; set; } = string.Empty; diff --git a/src/Infrastructure/Services/UserService.cs b/src/Infrastructure/Services/UserService.cs index b0704c2..66dca70 100644 --- a/src/Infrastructure/Services/UserService.cs +++ b/src/Infrastructure/Services/UserService.cs @@ -1,11 +1,13 @@ -using Hutopy.Domain.Interfaces; +using System.Security.Claims; +using Hutopy.Domain.Interfaces; using Hutopy.Domain.Models; using Hutopy.Infrastructure.Identity; +using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Identity; namespace Hutopy.Infrastructure.Services; -public class UserService(UserManager userManager) : IUserService +public class UserService(UserManager userManager, IHttpContextAccessor contextAccessor) : IUserService { public async Task CreateUserAsync(string email, string userName, string firstName, string lastName, string password) { @@ -38,7 +40,7 @@ public class UserService(UserManager userManager) : IUserServic UserName = response.UserName, FirstName = response.FirstName, LastName = response.LastName, - Email = response.Email + Email = response.Email, }; return userModel; @@ -47,13 +49,13 @@ public class UserService(UserManager userManager) : IUserServic public async Task GetCurrentUserAsync() { // todo: Get the id of the user doing the request. - var userId = ""; - if (string.IsNullOrEmpty(userId)) + var currentUserId = contextAccessor.HttpContext?.User?.FindFirst(ClaimTypes.NameIdentifier)?.Value; + if (string.IsNullOrEmpty(currentUserId)) { return null; } - return await FindUserByIdAsync(userId); + return await FindUserByIdAsync(currentUserId); } public async Task FindUserByEmailAsync(string email) diff --git a/src/Infrastructure/Stripe/StripeService.cs b/src/Infrastructure/Stripe/StripeService.cs index dc84e34..061f9e2 100644 --- a/src/Infrastructure/Stripe/StripeService.cs +++ b/src/Infrastructure/Stripe/StripeService.cs @@ -9,7 +9,6 @@ namespace Hutopy.Infrastructure.Stripe; public class StripeService : IStripeService { - const string EndpointSecret = ""; private readonly IHttpContextAccessor _httpContextAccessor; public StripeService(IHttpContextAccessor httpContextAccessor) @@ -18,7 +17,7 @@ public class StripeService : IStripeService StripeConfiguration.ApiKey = ""; } - public async Task CreateCheckoutSession(int amount, string currency = "cad") + public async Task CreateCheckoutSession(int amount, string creatorId, string currency = "cad") { var options = new SessionCreateOptions { @@ -38,7 +37,9 @@ public class StripeService : IStripeService ], Mode = "payment", UiMode = "embedded", - ReturnUrl = "https://hutopy.ca/paymentcompleted", + ReturnUrl = $"https://hutopy.ca/paymentcompleted?creatorId={creatorId}", + InvoiceCreation = new SessionInvoiceCreationOptions(){ Enabled = true}, + ClientReferenceId = creatorId }; var service = new SessionService(); @@ -57,7 +58,6 @@ public class StripeService : IStripeService } return new Result(false, new List()); - } catch (StripeException e) { diff --git a/src/Web/Endpoints/GetMyUser.cs b/src/Web/Endpoints/GetMyUser.cs index 5fe1c79..d7c78a6 100644 --- a/src/Web/Endpoints/GetMyUser.cs +++ b/src/Web/Endpoints/GetMyUser.cs @@ -7,6 +7,7 @@ public class GetMyUser : EndpointGroupBase public override void Map(WebApplication app) { app.MapGroup(this) + .RequireAuthorization() .MapGet(GetCurrentUser); } diff --git a/src/Web/Endpoints/Stripe.cs b/src/Web/Endpoints/Stripe.cs index 264f4c8..2eb01dc 100644 --- a/src/Web/Endpoints/Stripe.cs +++ b/src/Web/Endpoints/Stripe.cs @@ -1,4 +1,5 @@ using Hutopy.Application.Stripe.Commands; +using Hutopy.Application.Stripe.Queries; namespace Hutopy.Web.Endpoints; @@ -8,6 +9,7 @@ public class Stripe : EndpointGroupBase { app.MapGroup(this) .MapPost(ConfirmTransaction, "/confirmTransaction") + .MapGet(GetMyLastReceipt, "/getMyLastReceipt") .MapPost(CreateSessionCheckout); } @@ -20,4 +22,9 @@ public class Stripe : EndpointGroupBase { return await sender.Send(command); } + + private static async Task GetMyLastReceipt(ISender sender, [AsParameters] GetMyLastReceiptQuery query) + { + return await sender.Send(query); + } } diff --git a/src/Web/Endpoints/Users.cs b/src/Web/Endpoints/Users.cs index 0492fb5..1cbd880 100644 --- a/src/Web/Endpoints/Users.cs +++ b/src/Web/Endpoints/Users.cs @@ -1,4 +1,5 @@ using Hutopy.Application.Users.Commands; +using Hutopy.Application.Users.Queries.GetMinimalUser; using Hutopy.Domain.Interfaces; using Hutopy.Infrastructure.Identity; @@ -10,6 +11,7 @@ public class Users : EndpointGroupBase { app.MapGroup(this) .MapPost(CreateUser) + .MapGet(GetMinimalUser) .MapIdentityApi(); } @@ -18,4 +20,9 @@ public class Users : EndpointGroupBase await userService.CreateUserAsync(command.EmailAddress, command.UserName, command.FirstName, command.LastName, command.Password); return await sender.Send(command); } + + private static async Task GetMinimalUser(ISender sender, [AsParameters] GetMinimalUserQuery query) + { + return await sender.Send(query); + } } diff --git a/src/Web/wwwroot/api/specification.json b/src/Web/wwwroot/api/specification.json index 9c7a80c..d0680de 100644 --- a/src/Web/wwwroot/api/specification.json +++ b/src/Web/wwwroot/api/specification.json @@ -23,7 +23,12 @@ } } } - } + }, + "security": [ + { + "JWT": [] + } + ] } }, "/api/JoinUs": { @@ -131,6 +136,48 @@ } } }, + "/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": [ @@ -194,6 +241,36 @@ } } } + }, + "get": { + "tags": [ + "Users" + ], + "operationId": "GetMinimalUser", + "parameters": [ + { + "name": "UserId", + "in": "query", + "required": true, + "schema": { + "type": "string", + "nullable": true + }, + "x-position": 1 + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MinimalUserDto" + } + } + } + } + } } }, "/api/Users/register": { @@ -625,6 +702,9 @@ "lastName": { "type": "string" }, + "userName": { + "type": "string" + }, "userTransactions": { "type": "array", "items": { @@ -814,6 +894,15 @@ } } }, + "MyLastReceiptDto": { + "type": "object", + "additionalProperties": false, + "properties": { + "receiptUrl": { + "type": "string" + } + } + }, "CreateSessionCheckoutCommand": { "type": "object", "additionalProperties": false, @@ -854,6 +943,21 @@ } } }, + "MinimalUserDto": { + "type": "object", + "additionalProperties": false, + "properties": { + "firstName": { + "type": "string" + }, + "lastName": { + "type": "string" + }, + "userName": { + "type": "string" + } + } + }, "HttpValidationProblemDetails": { "allOf": [ { From 5cdfd9c63984ccd3f4518e2461ffe5761c2ffba1 Mon Sep 17 00:00:00 2001 From: Dominic Villemure Date: Sat, 18 May 2024 00:04:10 -0400 Subject: [PATCH 048/229] #27 more info to myUser and userTransactions --- .../Users/Queries/GetCurrentUser/GetCurrentUser.cs | 7 +++++-- .../Users/Queries/GetCurrentUser/UserDto.cs | 8 ++++---- .../Queries/GetCurrentUser/UserTransactionDto.cs | 7 +++++-- src/Infrastructure/Services/UserService.cs | 3 +-- src/Web/Endpoints/GetMyUser.cs | 1 + src/Web/wwwroot/api/specification.json | 11 +++++++++++ 6 files changed, 27 insertions(+), 10 deletions(-) diff --git a/src/Application/Users/Queries/GetCurrentUser/GetCurrentUser.cs b/src/Application/Users/Queries/GetCurrentUser/GetCurrentUser.cs index 82dc2f8..cada50a 100644 --- a/src/Application/Users/Queries/GetCurrentUser/GetCurrentUser.cs +++ b/src/Application/Users/Queries/GetCurrentUser/GetCurrentUser.cs @@ -1,7 +1,7 @@ using Hutopy.Application.Common.Interfaces; using Hutopy.Domain.Interfaces; -namespace Hutopy.Application.Users.Queries; +namespace Hutopy.Application.Users.Queries.GetCurrentUser; public record GetCurrentUserQuery : IRequest; @@ -21,6 +21,7 @@ public class GetCurrentUserQueryHandler( .Where(x => x.ApplicationUserId == currentUserId.ToString()) .OrderBy(x => x.LastModified) .ProjectTo(mapper.ConfigurationProvider) + .Where(x => x.IsConfirmed == true) .ToListAsync(cancellationToken); var user = new UserDto() @@ -28,7 +29,9 @@ public class GetCurrentUserQueryHandler( Id = currentUserId, FirstName = identityUser?.FirstName ?? "", LastName = identityUser?.LastName ?? "", - UserTransactions = transactions + UserName =identityUser?.UserName ?? "", + UserTransactions = transactions, + TotalBalance = transactions.Sum(x => x.Amount) }; return user; diff --git a/src/Application/Users/Queries/GetCurrentUser/UserDto.cs b/src/Application/Users/Queries/GetCurrentUser/UserDto.cs index acece9c..a5e1b49 100644 --- a/src/Application/Users/Queries/GetCurrentUser/UserDto.cs +++ b/src/Application/Users/Queries/GetCurrentUser/UserDto.cs @@ -1,13 +1,13 @@ -namespace Hutopy.Application.Users.Queries; +namespace Hutopy.Application.Users.Queries.GetCurrentUser; public class UserDto { public Guid Id { get; init; } - public required string FirstName { get; init; } - public required string LastName { get; init; } public string UserName { get; init; } = String.Empty; - public List UserTransactions { get; init; } = []; + + public required decimal TotalBalance { get; init; } + } diff --git a/src/Application/Users/Queries/GetCurrentUser/UserTransactionDto.cs b/src/Application/Users/Queries/GetCurrentUser/UserTransactionDto.cs index e6103c7..f682df4 100644 --- a/src/Application/Users/Queries/GetCurrentUser/UserTransactionDto.cs +++ b/src/Application/Users/Queries/GetCurrentUser/UserTransactionDto.cs @@ -1,15 +1,18 @@ using Hutopy.Domain.Entities; -namespace Hutopy.Application.Users.Queries; +namespace Hutopy.Application.Users.Queries.GetCurrentUser; public class UserTransactionDto { public required decimal Amount { get; init; } - + public string Currency { get; init; } = "cad"; public string TipMessage { get; init; } = string.Empty; + public DateTimeOffset Created { get; init; } + + public bool IsConfirmed { get; init; } private class Mapping : Profile { public Mapping() diff --git a/src/Infrastructure/Services/UserService.cs b/src/Infrastructure/Services/UserService.cs index 66dca70..8546a36 100644 --- a/src/Infrastructure/Services/UserService.cs +++ b/src/Infrastructure/Services/UserService.cs @@ -48,8 +48,7 @@ public class UserService(UserManager userManager, IHttpContextA public async Task GetCurrentUserAsync() { - // todo: Get the id of the user doing the request. - var currentUserId = contextAccessor.HttpContext?.User?.FindFirst(ClaimTypes.NameIdentifier)?.Value; + var currentUserId = contextAccessor.HttpContext?.User.FindFirst(ClaimTypes.NameIdentifier)?.Value; if (string.IsNullOrEmpty(currentUserId)) { return null; diff --git a/src/Web/Endpoints/GetMyUser.cs b/src/Web/Endpoints/GetMyUser.cs index d7c78a6..feb5b50 100644 --- a/src/Web/Endpoints/GetMyUser.cs +++ b/src/Web/Endpoints/GetMyUser.cs @@ -1,4 +1,5 @@ using Hutopy.Application.Users.Queries; +using Hutopy.Application.Users.Queries.GetCurrentUser; namespace Hutopy.Web.Endpoints; diff --git a/src/Web/wwwroot/api/specification.json b/src/Web/wwwroot/api/specification.json index d0680de..1b42f2f 100644 --- a/src/Web/wwwroot/api/specification.json +++ b/src/Web/wwwroot/api/specification.json @@ -710,6 +710,10 @@ "items": { "$ref": "#/components/schemas/UserTransactionDto" } + }, + "totalBalance": { + "type": "number", + "format": "decimal" } } }, @@ -726,6 +730,13 @@ }, "tipMessage": { "type": "string" + }, + "created": { + "type": "string", + "format": "date-time" + }, + "isConfirmed": { + "type": "boolean" } } }, From fc0c94306b2a4bb591125865688e6fc301697a28 Mon Sep 17 00:00:00 2001 From: Kamigen <46357922+Edouard127@users.noreply.github.com> Date: Fri, 24 May 2024 17:00:25 -0400 Subject: [PATCH 049/229] Fix: Sign-in user if exists --- src/Infrastructure/Services/UserService.cs | 4 ++++ src/Web/Controllers/GoogleController.cs | 14 ++++++++++---- src/Web/Program.cs | 8 ++++---- 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/src/Infrastructure/Services/UserService.cs b/src/Infrastructure/Services/UserService.cs index ebb5695..8610844 100644 --- a/src/Infrastructure/Services/UserService.cs +++ b/src/Infrastructure/Services/UserService.cs @@ -84,8 +84,12 @@ public class UserService(UserManager userManager, IHttpContextA } } +// If we need to add special characters we can alternate between 2 pools. public class RandomGenerator { + // For the moment, numbers and special characters don't work because + // the random generator is designed to handle a single integer. + // We can modify this in the future. private const string LetterBytes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" + "0123456789" + "!@#$%^&*()_+" diff --git a/src/Web/Controllers/GoogleController.cs b/src/Web/Controllers/GoogleController.cs index 173413a..236f130 100644 --- a/src/Web/Controllers/GoogleController.cs +++ b/src/Web/Controllers/GoogleController.cs @@ -39,16 +39,22 @@ public class GoogleController( FamilyName = claims.FirstOrDefault(c => c.Type == ClaimTypes.Surname)?.Value }; - await userService.CreateUserAsync(userInfo); // TODO: Don't create user if already exists - - await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, new ClaimsPrincipal(new ClaimsIdentity(new List + var claimsIdentity = new ClaimsIdentity(new List { new(ClaimTypes.Name, userInfo.Name), new(ClaimTypes.Email, userInfo.Email), new(ClaimTypes.GivenName, userInfo.GivenName), new(ClaimTypes.Surname, userInfo.FamilyName) - }, CookieAuthenticationDefaults.AuthenticationScheme))); + }, CookieAuthenticationDefaults.AuthenticationScheme); + if (await userService.FindUserByEmailAsync(userInfo.Email) != null) // TODO: Do we need to check for null ? + { + await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, new ClaimsPrincipal(claimsIdentity)); + return Redirect("/"); + } + + await userService.CreateUserAsync(userInfo); + await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, new ClaimsPrincipal(claimsIdentity)); return Redirect("/"); } } diff --git a/src/Web/Program.cs b/src/Web/Program.cs index 5407839..c49790c 100644 --- a/src/Web/Program.cs +++ b/src/Web/Program.cs @@ -72,11 +72,11 @@ builder.Services.AddAuthentication(options => // Password hashing builder.Services.AddIdentity(options => { - options.Password.RequireDigit = true; + options.Password.RequireDigit = false; options.Password.RequireLowercase = false; - options.Password.RequireUppercase = true; - options.Password.RequireNonAlphanumeric = true; - options.Password.RequiredLength = 8; + options.Password.RequireUppercase = false; + options.Password.RequireNonAlphanumeric = false; + options.Password.RequiredLength = 16; }) .AddEntityFrameworkStores() .AddDefaultTokenProviders(); From d5048d3a0652201584b2c57237f1d5e750c49b7c Mon Sep 17 00:00:00 2001 From: Dominic Villemure Date: Sun, 2 Jun 2024 14:45:28 -0400 Subject: [PATCH 050/229] #48 cleaned userService. We will use IdentityService only --- .../Common/Interfaces/IIdentityService.cs | 9 ++- src/Application/Users/Commands/CreateUser.cs | 20 ++--- .../Queries/GetCurrentUser/GetCurrentUser.cs | 5 +- .../Queries/GetMinimalUser/GetMinimalUser.cs | 8 +- src/Domain/Interfaces/IUserService.cs | 13 ---- src/Infrastructure/DependencyInjection.cs | 9 +-- .../Identity/IdentityService.cs | 73 ++++++++++++++++- src/Infrastructure/Services/UserService.cs | 78 ------------------- src/Web/DependencyInjection.cs | 4 - src/Web/Endpoints/Users.cs | 8 +- src/Web/Program.cs | 4 - 11 files changed, 97 insertions(+), 134 deletions(-) delete mode 100644 src/Domain/Interfaces/IUserService.cs delete mode 100644 src/Infrastructure/Services/UserService.cs diff --git a/src/Application/Common/Interfaces/IIdentityService.cs b/src/Application/Common/Interfaces/IIdentityService.cs index 5dbcb4c..9686bbc 100644 --- a/src/Application/Common/Interfaces/IIdentityService.cs +++ b/src/Application/Common/Interfaces/IIdentityService.cs @@ -1,16 +1,21 @@ using Hutopy.Application.Common.Models; +using Hutopy.Domain.Models; namespace Hutopy.Application.Common.Interfaces; public interface IIdentityService { Task GetUserNameAsync(string userId); + + Task CreateUserAsync(string email, string userName, string firstName, string lastName, string password); + + Task FindUserByIdAsync(string id); + Task GetCurrentUserAsync(); + Task FindUserByEmailAsync(string id); Task IsInRoleAsync(string userId, string role); Task AuthorizeAsync(string userId, string policyName); - Task<(Result Result, string UserId)> CreateUserAsync(string userName, string password); - Task DeleteUserAsync(string userId); } diff --git a/src/Application/Users/Commands/CreateUser.cs b/src/Application/Users/Commands/CreateUser.cs index 8992f01..38cc962 100644 --- a/src/Application/Users/Commands/CreateUser.cs +++ b/src/Application/Users/Commands/CreateUser.cs @@ -1,8 +1,4 @@ -using System.Dynamic; -using Hutopy.Application.Common.Interfaces; -using Hutopy.Domain.Entities; -using Hutopy.Domain.Interfaces; -using Microsoft.EntityFrameworkCore; +using Hutopy.Application.Common.Interfaces; namespace Hutopy.Application.Users.Commands; public record CreateUserCommand : IRequest @@ -17,24 +13,20 @@ public record CreateUserCommand : IRequest public class CreateUserCommandHandler : IRequestHandler { private readonly IApplicationDbContext _context; - private readonly IUserService _userService; + private readonly IIdentityService _identityService; - public CreateUserCommandHandler(IApplicationDbContext context, IUserService userService) + public CreateUserCommandHandler(IApplicationDbContext context, IIdentityService identityService) { _context = context; - _userService = userService; + _identityService = identityService; } public async Task Handle(CreateUserCommand request, CancellationToken cancellationToken) { - // Dont really need the handler for the create. The get will work like this : - var user = await _userService.FindUserByIdAsync("072ae7d5-8c4a-4a0f-b250-7d39941125cb"); - // var user2 = await _userService.FindUserByEmailAsync("test10@hotmail.com"); - - var tt = user?.FirstName; + var user = await _identityService.FindUserByEmailAsync(request.EmailAddress); await _context.SaveChangesAsync(cancellationToken); - return Guid.NewGuid(); + return new Guid(user?.Id ?? string.Empty); } } diff --git a/src/Application/Users/Queries/GetCurrentUser/GetCurrentUser.cs b/src/Application/Users/Queries/GetCurrentUser/GetCurrentUser.cs index cada50a..d621ab5 100644 --- a/src/Application/Users/Queries/GetCurrentUser/GetCurrentUser.cs +++ b/src/Application/Users/Queries/GetCurrentUser/GetCurrentUser.cs @@ -1,5 +1,4 @@ using Hutopy.Application.Common.Interfaces; -using Hutopy.Domain.Interfaces; namespace Hutopy.Application.Users.Queries.GetCurrentUser; @@ -8,13 +7,13 @@ public record GetCurrentUserQuery : IRequest; public class GetCurrentUserQueryHandler( IApplicationDbContext context, IMapper mapper, - IUserService userService + IIdentityService identityService ) : IRequestHandler { public async Task Handle(GetCurrentUserQuery request, CancellationToken cancellationToken) { - var identityUser = await userService.GetCurrentUserAsync(); + var identityUser = await identityService.GetCurrentUserAsync(); var currentUserId = new Guid(identityUser?.Id ?? ""); var transactions = await context.UserTransactions diff --git a/src/Application/Users/Queries/GetMinimalUser/GetMinimalUser.cs b/src/Application/Users/Queries/GetMinimalUser/GetMinimalUser.cs index 4206c79..5fd288d 100644 --- a/src/Application/Users/Queries/GetMinimalUser/GetMinimalUser.cs +++ b/src/Application/Users/Queries/GetMinimalUser/GetMinimalUser.cs @@ -1,4 +1,4 @@ -using Hutopy.Domain.Interfaces; +using Hutopy.Application.Common.Interfaces; namespace Hutopy.Application.Users.Queries.GetMinimalUser; @@ -8,15 +8,15 @@ public record GetMinimalUserQuery : IRequest }; public class GetMinimalUserQueryHandler( - IUserService userService + IIdentityService identityService ) : IRequestHandler { public async Task Handle(GetMinimalUserQuery request, CancellationToken cancellationToken) { - var identityUser = await userService.FindUserByIdAsync(request.UserId); + var identityUser = await identityService.FindUserByIdAsync(request.UserId); - var user = new MinimalUserDto() + var user = new MinimalUserDto { FirstName = identityUser?.FirstName ?? "", LastName = identityUser?.LastName ?? "", diff --git a/src/Domain/Interfaces/IUserService.cs b/src/Domain/Interfaces/IUserService.cs deleted file mode 100644 index efe46bb..0000000 --- a/src/Domain/Interfaces/IUserService.cs +++ /dev/null @@ -1,13 +0,0 @@ -using Hutopy.Domain.Models; - -namespace Hutopy.Domain.Interfaces; - -public interface IUserService -{ - Task CreateUserAsync(string email, string userName, string firstName, string lastName, string password); - - Task FindUserByIdAsync(string id); - Task GetCurrentUserAsync(); - - Task FindUserByEmailAsync(string id); -} diff --git a/src/Infrastructure/DependencyInjection.cs b/src/Infrastructure/DependencyInjection.cs index ae83424..31b0b30 100644 --- a/src/Infrastructure/DependencyInjection.cs +++ b/src/Infrastructure/DependencyInjection.cs @@ -1,11 +1,8 @@ -using System; -using Hutopy.Application.Common.Interfaces; +using Hutopy.Application.Common.Interfaces; using Hutopy.Domain.Constants; -using Hutopy.Domain.Interfaces; using Hutopy.Infrastructure.Data; using Hutopy.Infrastructure.Data.Interceptors; using Hutopy.Infrastructure.Identity; -using Hutopy.Infrastructure.Services; using Hutopy.Infrastructure.Stripe; using Microsoft.AspNetCore.Identity; using Microsoft.EntityFrameworkCore; @@ -51,8 +48,6 @@ public static class DependencyInjection .AddBearerToken(IdentityConstants.BearerScheme); services.AddAuthorizationBuilder(); - services.AddScoped(); - // Might need to change and use AddIdentity() when we need to integrate connection via third party ( facebook, google ) services @@ -62,7 +57,7 @@ public static class DependencyInjection .AddApiEndpoints(); services.AddSingleton(TimeProvider.System); - services.AddTransient(); + services.AddScoped(); services.AddTransient(); services.AddAuthorization(options => diff --git a/src/Infrastructure/Identity/IdentityService.cs b/src/Infrastructure/Identity/IdentityService.cs index 71a3886..c9cc75a 100644 --- a/src/Infrastructure/Identity/IdentityService.cs +++ b/src/Infrastructure/Identity/IdentityService.cs @@ -1,6 +1,9 @@ +using System.Security.Claims; using Hutopy.Application.Common.Interfaces; using Hutopy.Application.Common.Models; +using Hutopy.Domain.Models; using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Identity; namespace Hutopy.Infrastructure.Identity; @@ -8,7 +11,9 @@ namespace Hutopy.Infrastructure.Identity; public class IdentityService( UserManager userManager, IUserClaimsPrincipalFactory userClaimsPrincipalFactory, - IAuthorizationService authorizationService) + IAuthorizationService authorizationService, + IHttpContextAccessor contextAccessor + ) : IIdentityService { public async Task GetUserNameAsync(string userId) @@ -30,6 +35,72 @@ public class IdentityService( return (result.ToApplicationResult(), user.Id); } + + public async Task CreateUserAsync(string email, string userName, string firstName, string lastName, string password) + { + var applicationUser = new ApplicationUser + { + UserName = userName, + Email = email, + FirstName = firstName, + LastName = lastName + }; + + //todo: Need to handle errors better for the user. + var response = await userManager.CreateAsync(applicationUser, password); + + if (response.Errors.Any()) + { + throw new InvalidOperationException(response.Errors.First().Description); + } + } + + public async Task FindUserByIdAsync(string id) + { + var response = await userManager.FindByIdAsync(id); + + if (response == null) return null; + + var userModel = new UserModel() + { + Id = response.Id, + UserName = response.UserName, + FirstName = response.FirstName, + LastName = response.LastName, + Email = response.Email, + }; + + return userModel; + } + + public async Task GetCurrentUserAsync() + { + var currentUserId = contextAccessor.HttpContext?.User.FindFirst(ClaimTypes.NameIdentifier)?.Value; + if (string.IsNullOrEmpty(currentUserId)) + { + return null; + } + + return await FindUserByIdAsync(currentUserId); + } + + public async Task FindUserByEmailAsync(string email) + { + var response = await userManager.FindByEmailAsync(email); + + if (response == null) return null; + + var userModel = new UserModel + { + Id = response.Id, + UserName = response.UserName, + FirstName = response.FirstName, + LastName = response.LastName, + Email = response.Email + }; + + return userModel; + } public async Task IsInRoleAsync(string userId, string role) { diff --git a/src/Infrastructure/Services/UserService.cs b/src/Infrastructure/Services/UserService.cs deleted file mode 100644 index 8546a36..0000000 --- a/src/Infrastructure/Services/UserService.cs +++ /dev/null @@ -1,78 +0,0 @@ -using System.Security.Claims; -using Hutopy.Domain.Interfaces; -using Hutopy.Domain.Models; -using Hutopy.Infrastructure.Identity; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Identity; - -namespace Hutopy.Infrastructure.Services; - -public class UserService(UserManager userManager, IHttpContextAccessor contextAccessor) : IUserService -{ - public async Task CreateUserAsync(string email, string userName, string firstName, string lastName, string password) - { - var applicationUser = new ApplicationUser - { - UserName = userName, - Email = email, - FirstName = firstName, - LastName = lastName - }; - - //todo: Need to handle errors better for the user. - var response = await userManager.CreateAsync(applicationUser, password); - - if (response.Errors.Any()) - { - throw new InvalidOperationException(response.Errors.First().Description); - } - } - - public async Task FindUserByIdAsync(string id) - { - var response = await userManager.FindByIdAsync(id); - - if (response == null) return null; - - var userModel = new UserModel() - { - Id = response.Id, - UserName = response.UserName, - FirstName = response.FirstName, - LastName = response.LastName, - Email = response.Email, - }; - - return userModel; - } - - public async Task GetCurrentUserAsync() - { - var currentUserId = contextAccessor.HttpContext?.User.FindFirst(ClaimTypes.NameIdentifier)?.Value; - if (string.IsNullOrEmpty(currentUserId)) - { - return null; - } - - return await FindUserByIdAsync(currentUserId); - } - - public async Task FindUserByEmailAsync(string email) - { - var response = await userManager.FindByEmailAsync(email); - - if (response == null) return null; - - var userModel = new UserModel() - { - Id = response.Id, - UserName = response.UserName, - FirstName = response.FirstName, - LastName = response.LastName, - Email = response.Email - }; - - return userModel; - } -} - diff --git a/src/Web/DependencyInjection.cs b/src/Web/DependencyInjection.cs index fe6aab9..f8ede38 100644 --- a/src/Web/DependencyInjection.cs +++ b/src/Web/DependencyInjection.cs @@ -1,8 +1,6 @@ using Azure.Identity; using Hutopy.Application.Common.Interfaces; -using Hutopy.Domain.Interfaces; using Hutopy.Infrastructure.Data; -using Hutopy.Infrastructure.Services; using Hutopy.Web.Services; using Microsoft.AspNetCore.Mvc; using NSwag; @@ -17,8 +15,6 @@ public static class DependencyInjection services.AddDatabaseDeveloperPageExceptionFilter(); services.AddScoped(); - services.AddScoped(); - services.AddHttpContextAccessor(); diff --git a/src/Web/Endpoints/Users.cs b/src/Web/Endpoints/Users.cs index 1cbd880..f58b366 100644 --- a/src/Web/Endpoints/Users.cs +++ b/src/Web/Endpoints/Users.cs @@ -1,6 +1,6 @@ -using Hutopy.Application.Users.Commands; +using Hutopy.Application.Common.Interfaces; +using Hutopy.Application.Users.Commands; using Hutopy.Application.Users.Queries.GetMinimalUser; -using Hutopy.Domain.Interfaces; using Hutopy.Infrastructure.Identity; namespace Hutopy.Web.Endpoints; @@ -15,9 +15,9 @@ public class Users : EndpointGroupBase .MapIdentityApi(); } - private static async Task CreateUser(ISender sender, CreateUserCommand command, IUserService userService) + private static async Task CreateUser(ISender sender, CreateUserCommand command, IIdentityService identityService) { - await userService.CreateUserAsync(command.EmailAddress, command.UserName, command.FirstName, command.LastName, command.Password); + await identityService.CreateUserAsync(command.EmailAddress, command.UserName, command.FirstName, command.LastName, command.Password); return await sender.Send(command); } diff --git a/src/Web/Program.cs b/src/Web/Program.cs index b2b34db..646e478 100644 --- a/src/Web/Program.cs +++ b/src/Web/Program.cs @@ -1,8 +1,6 @@ using Hutopy.Application; -using Hutopy.Domain.Interfaces; using Hutopy.Infrastructure; using Hutopy.Infrastructure.Data; -using Hutopy.Infrastructure.Services; using Hutopy.Web; using Azure.Identity; @@ -47,8 +45,6 @@ builder.Services.AddApplicationServices(); builder.Services.AddInfrastructureServices(builder.Configuration); builder.Services.AddWebServices(); -builder.Services.AddScoped(); - var app = builder.Build(); app.UseCors("AllowAll"); From c31b3a2e71391cb582747f56d90de27108358b94 Mon Sep 17 00:00:00 2001 From: Dominic Villemure Date: Sun, 2 Jun 2024 15:59:17 -0400 Subject: [PATCH 051/229] #48 added basic role features and some cleanUp --- .../Common/Interfaces/IIdentityService.cs | 10 ++-- .../Common/Interfaces/IRoleService.cs | 10 ++++ src/Application/Common/Models/RoleModel.cs | 7 +++ .../Common}/Models/UserModel.cs | 2 +- src/Application/DependencyInjection.cs | 3 +- .../Queries/GetFutureCreatorList.cs | 2 + src/Application/Users/Commands/CreateUser.cs | 2 + .../Queries/GetCurrentUser/GetCurrentUser.cs | 7 ++- .../Users/Queries/GetCurrentUser/UserDto.cs | 1 + .../Identity/ApplicationRole.cs | 7 +++ .../Identity/IdentityService.cs | 47 +++++++++++++++--- src/Infrastructure/Identity/RoleService.cs | 49 +++++++++++++++++++ src/Web/Endpoints/Users.cs | 6 +-- src/Web/wwwroot/api/specification.json | 6 +++ 14 files changed, 136 insertions(+), 23 deletions(-) create mode 100644 src/Application/Common/Interfaces/IRoleService.cs create mode 100644 src/Application/Common/Models/RoleModel.cs rename src/{Domain => Application/Common}/Models/UserModel.cs (83%) create mode 100644 src/Infrastructure/Identity/ApplicationRole.cs create mode 100644 src/Infrastructure/Identity/RoleService.cs diff --git a/src/Application/Common/Interfaces/IIdentityService.cs b/src/Application/Common/Interfaces/IIdentityService.cs index 9686bbc..b816ad7 100644 --- a/src/Application/Common/Interfaces/IIdentityService.cs +++ b/src/Application/Common/Interfaces/IIdentityService.cs @@ -1,21 +1,17 @@ using Hutopy.Application.Common.Models; -using Hutopy.Domain.Models; namespace Hutopy.Application.Common.Interfaces; public interface IIdentityService { Task GetUserNameAsync(string userId); - - Task CreateUserAsync(string email, string userName, string firstName, string lastName, string password); - + Task CreateUserAsync(string email, string userName, string firstName, string lastName, string password); Task FindUserByIdAsync(string id); Task GetCurrentUserAsync(); Task FindUserByEmailAsync(string id); - Task IsInRoleAsync(string userId, string role); - Task AuthorizeAsync(string userId, string policyName); - + Task AddRoleAsync(string userId, string role); + Task> GetCurrentUserRolesAsync(); Task DeleteUserAsync(string userId); } diff --git a/src/Application/Common/Interfaces/IRoleService.cs b/src/Application/Common/Interfaces/IRoleService.cs new file mode 100644 index 0000000..96ed4d2 --- /dev/null +++ b/src/Application/Common/Interfaces/IRoleService.cs @@ -0,0 +1,10 @@ +using Hutopy.Application.Common.Models; + +namespace Hutopy.Application.Common.Interfaces; + +public interface IRoleService +{ + public Task CreateRoleAsync(string roleName); + public Task DeleteRoleAsync(string roleName); + public Task FindRoleByIdAsync(string roleId); +} diff --git a/src/Application/Common/Models/RoleModel.cs b/src/Application/Common/Models/RoleModel.cs new file mode 100644 index 0000000..ed49feb --- /dev/null +++ b/src/Application/Common/Models/RoleModel.cs @@ -0,0 +1,7 @@ +namespace Hutopy.Application.Common.Models; + +public class RoleModel +{ + public string? Id { get; set; } + public string? Name { get; set; } +} diff --git a/src/Domain/Models/UserModel.cs b/src/Application/Common/Models/UserModel.cs similarity index 83% rename from src/Domain/Models/UserModel.cs rename to src/Application/Common/Models/UserModel.cs index a3c9eb2..5c4358b 100644 --- a/src/Domain/Models/UserModel.cs +++ b/src/Application/Common/Models/UserModel.cs @@ -1,4 +1,4 @@ -namespace Hutopy.Domain.Models; +namespace Hutopy.Application.Common.Models; public class UserModel { diff --git a/src/Application/DependencyInjection.cs b/src/Application/DependencyInjection.cs index d65e206..41c71da 100644 --- a/src/Application/DependencyInjection.cs +++ b/src/Application/DependencyInjection.cs @@ -1,4 +1,5 @@ using System.Reflection; +using Hutopy.Application.Common.Behaviours; using Microsoft.Extensions.DependencyInjection; namespace Hutopy.Application; @@ -15,7 +16,7 @@ public static class DependencyInjection { cfg.RegisterServicesFromAssembly(Assembly.GetExecutingAssembly()); //cfg.AddBehavior(typeof(IPipelineBehavior<,>), typeof(UnhandledExceptionBehaviour<,>)); - //cfg.AddBehavior(typeof(IPipelineBehavior<,>), typeof(AuthorizationBehaviour<,>)); + cfg.AddBehavior(typeof(IPipelineBehavior<,>), typeof(AuthorizationBehaviour<,>)); //cfg.AddBehavior(typeof(IPipelineBehavior<,>), typeof(ValidationBehaviour<,>)); //cfg.AddBehavior(typeof(IPipelineBehavior<,>), typeof(PerformanceBehaviour<,>)); }); diff --git a/src/Application/FutureCreators/Queries/GetFutureCreatorList.cs b/src/Application/FutureCreators/Queries/GetFutureCreatorList.cs index 1b5fb23..0281518 100644 --- a/src/Application/FutureCreators/Queries/GetFutureCreatorList.cs +++ b/src/Application/FutureCreators/Queries/GetFutureCreatorList.cs @@ -2,9 +2,11 @@ using Hutopy.Application.Common.Interfaces; using Hutopy.Application.Common.Mappings; using Hutopy.Application.Common.Models; +using Hutopy.Application.Common.Security; namespace Hutopy.Application.FutureCreators.Queries; +[Authorize(Roles = "Administrator")] public record GetFutureCreatorListQuery : IRequest> { public int PageNumber { get; init; } = 1; diff --git a/src/Application/Users/Commands/CreateUser.cs b/src/Application/Users/Commands/CreateUser.cs index 38cc962..54077eb 100644 --- a/src/Application/Users/Commands/CreateUser.cs +++ b/src/Application/Users/Commands/CreateUser.cs @@ -23,6 +23,8 @@ public class CreateUserCommandHandler : IRequestHandler public async Task Handle(CreateUserCommand request, CancellationToken cancellationToken) { + await _identityService.CreateUserAsync(request.EmailAddress, request.UserName, request.FirstName, request.LastName, request.Password); + var user = await _identityService.FindUserByEmailAsync(request.EmailAddress); await _context.SaveChangesAsync(cancellationToken); diff --git a/src/Application/Users/Queries/GetCurrentUser/GetCurrentUser.cs b/src/Application/Users/Queries/GetCurrentUser/GetCurrentUser.cs index d621ab5..49f1152 100644 --- a/src/Application/Users/Queries/GetCurrentUser/GetCurrentUser.cs +++ b/src/Application/Users/Queries/GetCurrentUser/GetCurrentUser.cs @@ -23,14 +23,17 @@ public class GetCurrentUserQueryHandler( .Where(x => x.IsConfirmed == true) .ToListAsync(cancellationToken); - var user = new UserDto() + var roles = await identityService.GetCurrentUserRolesAsync(); + + var user = new UserDto { Id = currentUserId, FirstName = identityUser?.FirstName ?? "", LastName = identityUser?.LastName ?? "", UserName =identityUser?.UserName ?? "", UserTransactions = transactions, - TotalBalance = transactions.Sum(x => x.Amount) + TotalBalance = transactions.Sum(x => x.Amount), + UserRoles = roles }; return user; diff --git a/src/Application/Users/Queries/GetCurrentUser/UserDto.cs b/src/Application/Users/Queries/GetCurrentUser/UserDto.cs index a5e1b49..0e2af25 100644 --- a/src/Application/Users/Queries/GetCurrentUser/UserDto.cs +++ b/src/Application/Users/Queries/GetCurrentUser/UserDto.cs @@ -7,6 +7,7 @@ public class UserDto public required string LastName { get; init; } public string UserName { get; init; } = String.Empty; public List UserTransactions { get; init; } = []; + public IList UserRoles { get; init; } = []; public required decimal TotalBalance { get; init; } diff --git a/src/Infrastructure/Identity/ApplicationRole.cs b/src/Infrastructure/Identity/ApplicationRole.cs new file mode 100644 index 0000000..eba9904 --- /dev/null +++ b/src/Infrastructure/Identity/ApplicationRole.cs @@ -0,0 +1,7 @@ +using Microsoft.AspNetCore.Identity; + +namespace Hutopy.Infrastructure.Identity; + +public class ApplicationRole : IdentityRole +{ +} diff --git a/src/Infrastructure/Identity/IdentityService.cs b/src/Infrastructure/Identity/IdentityService.cs index c9cc75a..618b647 100644 --- a/src/Infrastructure/Identity/IdentityService.cs +++ b/src/Infrastructure/Identity/IdentityService.cs @@ -1,7 +1,6 @@ using System.Security.Claims; using Hutopy.Application.Common.Interfaces; using Hutopy.Application.Common.Models; -using Hutopy.Domain.Models; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Identity; @@ -36,7 +35,7 @@ public class IdentityService( return (result.ToApplicationResult(), user.Id); } - public async Task CreateUserAsync(string email, string userName, string firstName, string lastName, string password) + public async Task CreateUserAsync(string email, string userName, string firstName, string lastName, string password) { var applicationUser = new ApplicationUser { @@ -46,13 +45,9 @@ public class IdentityService( LastName = lastName }; - //todo: Need to handle errors better for the user. var response = await userManager.CreateAsync(applicationUser, password); - - if (response.Errors.Any()) - { - throw new InvalidOperationException(response.Errors.First().Description); - } + + return response.ToApplicationResult(); } public async Task FindUserByIdAsync(string id) @@ -108,6 +103,14 @@ public class IdentityService( return user != null && await userManager.IsInRoleAsync(user, role); } + + public async Task CurrentUserIsInRoleAsync(string role) + { + var currentUserModel = await GetCurrentUserAsync(); + var currentUser = await userManager.FindByIdAsync(currentUserModel?.Id ?? ""); + + return currentUser != null && await userManager.IsInRoleAsync(currentUser, role); + } public async Task AuthorizeAsync(string userId, string policyName) { @@ -138,4 +141,32 @@ public class IdentityService( return result.ToApplicationResult(); } + + public async Task AddRoleAsync(string userId, string role) + { + var hasAdminAccess = await CurrentUserIsInRoleAsync("Administrator"); + + if (!hasAdminAccess) return Result.Failure(new []{"Only administrator can assign new roles to a user."}); + + var user = await userManager.FindByIdAsync(userId); + + if (user is null) return Result.Failure(new []{"User not found."}); + + var result = await userManager.AddToRoleAsync(user, role); + + return result.ToApplicationResult(); + } + + public async Task> GetCurrentUserRolesAsync() + { + var currentUserModel = await GetCurrentUserAsync(); + + var currentUser = await userManager.FindByIdAsync(currentUserModel?.Id ?? ""); + + if (currentUser is null) return []; + + var userRoles = await userManager.GetRolesAsync(currentUser); + + return userRoles; + } } diff --git a/src/Infrastructure/Identity/RoleService.cs b/src/Infrastructure/Identity/RoleService.cs new file mode 100644 index 0000000..71f0ed0 --- /dev/null +++ b/src/Infrastructure/Identity/RoleService.cs @@ -0,0 +1,49 @@ +using Hutopy.Application.Common.Interfaces; +using Hutopy.Application.Common.Models; +using Microsoft.AspNetCore.Identity; + +namespace Hutopy.Infrastructure.Identity; + +public class RoleService( + RoleManager roleManager + ) + : IRoleService +{ + public async Task CreateRoleAsync(string roleName) + { + var role = new ApplicationRole { Name = roleName, Id = Guid.NewGuid().ToString()}; + var result = await roleManager.CreateAsync(role); + + return result.ToApplicationResult(); + } + + public async Task DeleteRoleAsync(string roleName) + { + var role = new ApplicationRole { Name = roleName }; + var result = await roleManager.DeleteAsync(role); + + return result.ToApplicationResult(); + } + + public async Task FindRoleByIdAsync(string roleId) + { + var result = await roleManager.FindByIdAsync(roleId); + + if (result is null) return null; + + var roleModel = new RoleModel { Id = result.Id, Name = result.Name }; + + return roleModel; + } + + public async Task FindRoleByNameAsync(string roleName) + { + var result = await roleManager.FindByNameAsync(roleName); + + if (result is null) return null; + + var roleModel = new RoleModel { Id = result.Id, Name = result.Name }; + + return roleModel; + } +} diff --git a/src/Web/Endpoints/Users.cs b/src/Web/Endpoints/Users.cs index f58b366..32b8acc 100644 --- a/src/Web/Endpoints/Users.cs +++ b/src/Web/Endpoints/Users.cs @@ -1,5 +1,4 @@ -using Hutopy.Application.Common.Interfaces; -using Hutopy.Application.Users.Commands; +using Hutopy.Application.Users.Commands; using Hutopy.Application.Users.Queries.GetMinimalUser; using Hutopy.Infrastructure.Identity; @@ -15,9 +14,8 @@ public class Users : EndpointGroupBase .MapIdentityApi(); } - private static async Task CreateUser(ISender sender, CreateUserCommand command, IIdentityService identityService) + private static async Task CreateUser(ISender sender, CreateUserCommand command) { - await identityService.CreateUserAsync(command.EmailAddress, command.UserName, command.FirstName, command.LastName, command.Password); return await sender.Send(command); } diff --git a/src/Web/wwwroot/api/specification.json b/src/Web/wwwroot/api/specification.json index 1b42f2f..e9729d9 100644 --- a/src/Web/wwwroot/api/specification.json +++ b/src/Web/wwwroot/api/specification.json @@ -711,6 +711,12 @@ "$ref": "#/components/schemas/UserTransactionDto" } }, + "userRoles": { + "type": "array", + "items": { + "type": "string" + } + }, "totalBalance": { "type": "number", "format": "decimal" From aa8a5ad93d52295b3a318ae40f1fe1c4d117100a Mon Sep 17 00:00:00 2001 From: Kamigen <46357922+Edouard127@users.noreply.github.com> Date: Wed, 5 Jun 2024 16:01:44 -0400 Subject: [PATCH 052/229] Feature: Google and Facebook sign-in --- src/Domain/Interfaces/IUserService.cs | 5 +- src/Infrastructure/Services/UserService.cs | 6 --- src/Web/Controllers/FacebookController.cs | 53 ++++++++++++++++++++++ src/Web/Controllers/GoogleController.cs | 39 +++++++--------- src/Web/Program.cs | 14 +++++- src/Web/wwwroot/api/specification.json | 13 ++++++ 6 files changed, 96 insertions(+), 34 deletions(-) create mode 100644 src/Web/Controllers/FacebookController.cs diff --git a/src/Domain/Interfaces/IUserService.cs b/src/Domain/Interfaces/IUserService.cs index 2af0f97..efe46bb 100644 --- a/src/Domain/Interfaces/IUserService.cs +++ b/src/Domain/Interfaces/IUserService.cs @@ -1,5 +1,4 @@ -using Google.Apis.Oauth2.v2.Data; -using Hutopy.Domain.Models; +using Hutopy.Domain.Models; namespace Hutopy.Domain.Interfaces; @@ -7,8 +6,6 @@ public interface IUserService { Task CreateUserAsync(string email, string userName, string firstName, string lastName, string password); - Task CreateUserAsync(Userinfo userInfo); - Task FindUserByIdAsync(string id); Task GetCurrentUserAsync(); diff --git a/src/Infrastructure/Services/UserService.cs b/src/Infrastructure/Services/UserService.cs index 8610844..4e52033 100644 --- a/src/Infrastructure/Services/UserService.cs +++ b/src/Infrastructure/Services/UserService.cs @@ -1,5 +1,4 @@ using System.Text; -using Google.Apis.Oauth2.v2.Data; using System.Security.Claims; using Hutopy.Domain.Interfaces; using Hutopy.Domain.Models; @@ -30,11 +29,6 @@ public class UserService(UserManager userManager, IHttpContextA } } - public async Task CreateUserAsync(Userinfo userInfo) - { - await CreateUserAsync(userInfo.Email, userInfo.GivenName, userInfo.GivenName, userInfo.FamilyName, RandomGenerator.RandomString(24)); - } - public async Task FindUserByIdAsync(string id) { var response = await userManager.FindByIdAsync(id); diff --git a/src/Web/Controllers/FacebookController.cs b/src/Web/Controllers/FacebookController.cs new file mode 100644 index 0000000..394eea1 --- /dev/null +++ b/src/Web/Controllers/FacebookController.cs @@ -0,0 +1,53 @@ +using System.Security.Claims; +using Hutopy.Domain.Interfaces; +using Hutopy.Infrastructure.Services; +using Microsoft.AspNetCore.Authentication; +using Microsoft.AspNetCore.Authentication.Cookies; +using Microsoft.AspNetCore.Authentication.Facebook; +using Microsoft.AspNetCore.Mvc; + +namespace Hutopy.Web.Controllers; + +public class FacebookController(IUserService userService) : Controller +{ + [HttpGet("/api/facebook/sign-in")] + public async Task SignIn() + { + await HttpContext.ChallengeAsync(FacebookDefaults.AuthenticationScheme, new AuthenticationProperties + { + RedirectUri = Url.Action("Authorize") + }); + } + + public async Task Authorize() + { + var authenticateResult = await HttpContext.AuthenticateAsync(FacebookDefaults.AuthenticationScheme); + + if (!authenticateResult.Succeeded) return BadRequest(); + + var claims = authenticateResult.Principal.Claims.ToList(); + + var name = claims.FirstOrDefault(c => c.Type == ClaimTypes.Name)?.Value; + var email = claims.FirstOrDefault(c => c.Type == ClaimTypes.Email)?.Value; + var givenName = claims.FirstOrDefault(c => c.Type == ClaimTypes.GivenName)?.Value; + var familyName = claims.FirstOrDefault(c => c.Type == ClaimTypes.Surname)?.Value; + + var claimsIdentity = new ClaimsIdentity(new List + { + new(ClaimTypes.Name, name), + new(ClaimTypes.Email, email), + new(ClaimTypes.GivenName, givenName), + new(ClaimTypes.Surname, familyName) + }, CookieAuthenticationDefaults.AuthenticationScheme); + + if (await userService.FindUserByEmailAsync(email) != null) + { + await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, new ClaimsPrincipal(claimsIdentity)); + return Redirect("/"); + } + + await userService.CreateUserAsync(email, givenName, givenName, familyName, RandomGenerator.RandomString(24)); + await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, new ClaimsPrincipal(claimsIdentity)); + return Redirect("/"); + } +} diff --git a/src/Web/Controllers/GoogleController.cs b/src/Web/Controllers/GoogleController.cs index 236f130..0780277 100644 --- a/src/Web/Controllers/GoogleController.cs +++ b/src/Web/Controllers/GoogleController.cs @@ -1,6 +1,6 @@ using System.Security.Claims; -using Google.Apis.Oauth2.v2.Data; using Hutopy.Domain.Interfaces; +using Hutopy.Infrastructure.Services; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authentication.Cookies; using Microsoft.AspNetCore.Authentication.Google; @@ -8,52 +8,45 @@ using Microsoft.AspNetCore.Mvc; namespace Hutopy.Web.Controllers; -public class GoogleController( - IUserService userService) : Controller +public class GoogleController(IUserService userService) : Controller { [HttpGet("/api/google/sign-in")] public async Task SignIn() { await HttpContext.ChallengeAsync(GoogleDefaults.AuthenticationScheme, new AuthenticationProperties { - RedirectUri = Url.Action("Callback"), + RedirectUri = Url.Action("Authorize") }); } - public async Task Callback() + public async Task Authorize() { - var authenticateResult = await HttpContext.AuthenticateAsync(CookieAuthenticationDefaults.AuthenticationScheme); + var authenticateResult = await HttpContext.AuthenticateAsync(GoogleDefaults.AuthenticationScheme); - if (!authenticateResult.Succeeded) - { - return BadRequest(); - } + if (!authenticateResult.Succeeded) return BadRequest(); var claims = authenticateResult.Principal.Claims.ToList(); - var userInfo = new Userinfo - { - Name = claims.FirstOrDefault(c => c.Type == ClaimTypes.Name)?.Value, - Email = claims.FirstOrDefault(c => c.Type == ClaimTypes.Email)?.Value, - GivenName = claims.FirstOrDefault(c => c.Type == ClaimTypes.GivenName)?.Value, - FamilyName = claims.FirstOrDefault(c => c.Type == ClaimTypes.Surname)?.Value - }; + var name = claims.FirstOrDefault(c => c.Type == ClaimTypes.Name)?.Value; + var email = claims.FirstOrDefault(c => c.Type == ClaimTypes.Email)?.Value; + var givenName = claims.FirstOrDefault(c => c.Type == ClaimTypes.GivenName)?.Value; + var familyName = claims.FirstOrDefault(c => c.Type == ClaimTypes.Surname)?.Value; var claimsIdentity = new ClaimsIdentity(new List { - new(ClaimTypes.Name, userInfo.Name), - new(ClaimTypes.Email, userInfo.Email), - new(ClaimTypes.GivenName, userInfo.GivenName), - new(ClaimTypes.Surname, userInfo.FamilyName) + new(ClaimTypes.Name, name), + new(ClaimTypes.Email, email), + new(ClaimTypes.GivenName, givenName), + new(ClaimTypes.Surname, familyName) }, CookieAuthenticationDefaults.AuthenticationScheme); - if (await userService.FindUserByEmailAsync(userInfo.Email) != null) // TODO: Do we need to check for null ? + if (await userService.FindUserByEmailAsync(email) != null) { await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, new ClaimsPrincipal(claimsIdentity)); return Redirect("/"); } - await userService.CreateUserAsync(userInfo); + await userService.CreateUserAsync(email, givenName, givenName, familyName, RandomGenerator.RandomString(24)); await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, new ClaimsPrincipal(claimsIdentity)); return Redirect("/"); } diff --git a/src/Web/Program.cs b/src/Web/Program.cs index c49790c..45dfcf2 100644 --- a/src/Web/Program.cs +++ b/src/Web/Program.cs @@ -7,6 +7,7 @@ using Hutopy.Web; using Azure.Identity; using Hutopy.Infrastructure.Identity; using Microsoft.AspNetCore.Authentication.Cookies; +using Microsoft.AspNetCore.Authentication.Facebook; using Microsoft.AspNetCore.Authentication.Google; using Microsoft.AspNetCore.HttpOverrides; using Microsoft.AspNetCore.Identity; @@ -56,7 +57,7 @@ builder.Services.AddWebServices(); builder.Services.AddAuthentication(options => { options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme; - options.DefaultChallengeScheme = GoogleDefaults.AuthenticationScheme; + options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme; }) .AddCookie() .AddGoogle( @@ -67,6 +68,17 @@ builder.Services.AddAuthentication(options => throw new ArgumentNullException("The Google ClientId is missing."); options.ClientSecret = builder.Configuration["Google:ClientSecret"] ?? throw new ArgumentNullException("The Google ClientSecret is missing."); + //options.AccessDeniedPath = "/AccessDeniedPathInfo"; + }) + .AddFacebook( + FacebookDefaults.AuthenticationScheme, + options => + { + options.ClientId = builder.Configuration["Facebook:ClientId"] ?? + throw new ArgumentNullException("The Facebook ClientId is missing."); + options.ClientSecret = builder.Configuration["Facebook:ClientSecret"] ?? + throw new ArgumentNullException("The Facebook ClientSecret is missing."); + //options.AccessDeniedPath = "/AccessDeniedPathInfo"; }); // Password hashing diff --git a/src/Web/wwwroot/api/specification.json b/src/Web/wwwroot/api/specification.json index b5a4c09..a6129af 100644 --- a/src/Web/wwwroot/api/specification.json +++ b/src/Web/wwwroot/api/specification.json @@ -685,6 +685,19 @@ ] } }, + "/api/facebook/sign-in": { + "get": { + "tags": [ + "Facebook" + ], + "operationId": "Facebook_SignIn", + "responses": { + "200": { + "description": "" + } + } + } + }, "/api/google/sign-in": { "get": { "tags": [ From 4a5abf59eba7f726e24447bdbb7be7d10ac84ba6 Mon Sep 17 00:00:00 2001 From: Dominic Villemure Date: Thu, 6 Jun 2024 18:04:42 -0400 Subject: [PATCH 053/229] added findByUserNameAsync to the interface and service --- .../Common/Interfaces/IIdentityService.cs | 1 + src/Infrastructure/Identity/IdentityService.cs | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/src/Application/Common/Interfaces/IIdentityService.cs b/src/Application/Common/Interfaces/IIdentityService.cs index b816ad7..0af5c4a 100644 --- a/src/Application/Common/Interfaces/IIdentityService.cs +++ b/src/Application/Common/Interfaces/IIdentityService.cs @@ -9,6 +9,7 @@ public interface IIdentityService Task FindUserByIdAsync(string id); Task GetCurrentUserAsync(); Task FindUserByEmailAsync(string id); + Task GetUserByUserNameAsync(string userName); Task IsInRoleAsync(string userId, string role); Task AuthorizeAsync(string userId, string policyName); Task AddRoleAsync(string userId, string role); diff --git a/src/Infrastructure/Identity/IdentityService.cs b/src/Infrastructure/Identity/IdentityService.cs index 618b647..3326217 100644 --- a/src/Infrastructure/Identity/IdentityService.cs +++ b/src/Infrastructure/Identity/IdentityService.cs @@ -21,6 +21,24 @@ public class IdentityService( return user?.UserName; } + + public async Task GetUserByUserNameAsync(string userName) + { + var response = await userManager.FindByNameAsync(userName); + + if (response == null) return null; + + var userModel = new UserModel() + { + Id = response.Id, + UserName = response.UserName, + FirstName = response.FirstName, + LastName = response.LastName, + Email = response.Email, + }; + + return userModel; + } public async Task<(Result Result, string UserId)> CreateUserAsync(string userName, string password) { From 1c277f530d1f00368fb59eed1078cab1819fbd3a Mon Sep 17 00:00:00 2001 From: PascalMarchesseault <97350299+PascalMarchesseault@users.noreply.github.com> Date: Sat, 8 Jun 2024 12:03:20 -0400 Subject: [PATCH 054/229] Ajout de PublicCreatorInfo --- .../Queries/GetCreatorInfo/CreatorInfoDto.cs | 9 ++++ .../Queries/GetCreatorInfo/GetCreatorInfo.cs | 32 +++++++++++++ src/Web/Endpoints/GetCreatorInfo.cs | 19 ++++++++ src/Web/wwwroot/api/specification.json | 47 +++++++++++++++++++ 4 files changed, 107 insertions(+) create mode 100644 src/Application/Users/Queries/GetCreatorInfo/CreatorInfoDto.cs create mode 100644 src/Application/Users/Queries/GetCreatorInfo/GetCreatorInfo.cs create mode 100644 src/Web/Endpoints/GetCreatorInfo.cs diff --git a/src/Application/Users/Queries/GetCreatorInfo/CreatorInfoDto.cs b/src/Application/Users/Queries/GetCreatorInfo/CreatorInfoDto.cs new file mode 100644 index 0000000..e03d762 --- /dev/null +++ b/src/Application/Users/Queries/GetCreatorInfo/CreatorInfoDto.cs @@ -0,0 +1,9 @@ +namespace Hutopy.Application.Users.Queries.GetCreatorInfo; + +public class CreatorInfoDto +{ + public required string FirstName { get; init; } + public required string LastName { get; init; } + public string UserName { get; init; } = String.Empty; + +} diff --git a/src/Application/Users/Queries/GetCreatorInfo/GetCreatorInfo.cs b/src/Application/Users/Queries/GetCreatorInfo/GetCreatorInfo.cs new file mode 100644 index 0000000..2f2e7d9 --- /dev/null +++ b/src/Application/Users/Queries/GetCreatorInfo/GetCreatorInfo.cs @@ -0,0 +1,32 @@ +using Hutopy.Application.Common.Interfaces; + +namespace Hutopy.Application.Users.Queries.GetCreatorInfo; + +public record GetCreatorInfoQuery : IRequest +{ + public string UserName { get; set; } = string.Empty; +}; + + +public class GetCreatorInfoHandler( + IIdentityService identityService + ) + : IRequestHandler +{ + public async Task Handle(GetCreatorInfoQuery request, CancellationToken cancellationToken) + { + + var userName = await identityService.GetUserByUserNameAsync(request.UserName); + var creatorInfo = new CreatorInfoDto + { + + FirstName = userName?.FirstName ?? "", + LastName = userName?.LastName ?? "", + UserName = userName?.UserName ?? "", + + }; + return creatorInfo; + } + + +} diff --git a/src/Web/Endpoints/GetCreatorInfo.cs b/src/Web/Endpoints/GetCreatorInfo.cs new file mode 100644 index 0000000..e31263f --- /dev/null +++ b/src/Web/Endpoints/GetCreatorInfo.cs @@ -0,0 +1,19 @@ +using Hutopy.Application.Users.Queries; +using Hutopy.Application.Users.Queries.GetCreatorInfo; + + +namespace Hutopy.Web.Endpoints; + +public class GetCreatorInfo : EndpointGroupBase +{ + public override void Map(WebApplication app) + { + app.MapGroup(this) + .MapGet(GetSelectedCreatorInfo); + } + + private static async Task GetSelectedCreatorInfo(ISender sender, [AsParameters] GetCreatorInfoQuery query) + { + return await sender.Send(query); + } +} diff --git a/src/Web/wwwroot/api/specification.json b/src/Web/wwwroot/api/specification.json index e9729d9..670f3b3 100644 --- a/src/Web/wwwroot/api/specification.json +++ b/src/Web/wwwroot/api/specification.json @@ -6,6 +6,38 @@ "version": "1.0.0" }, "paths": { + "/api/GetCreatorInfo": { + "get": { + "tags": [ + "GetCreatorInfo" + ], + "operationId": "GetSelectedCreatorInfo", + "parameters": [ + { + "name": "UserName", + "in": "query", + "required": true, + "schema": { + "type": "string", + "nullable": true + }, + "x-position": 1 + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreatorInfoDto" + } + } + } + } + } + } + }, "/api/GetMyUser": { "get": { "tags": [ @@ -688,6 +720,21 @@ }, "components": { "schemas": { + "CreatorInfoDto": { + "type": "object", + "additionalProperties": false, + "properties": { + "firstName": { + "type": "string" + }, + "lastName": { + "type": "string" + }, + "userName": { + "type": "string" + } + } + }, "UserDto": { "type": "object", "additionalProperties": false, From 48dcae22a3cfd60f678f678b8b929a0c0363d3b6 Mon Sep 17 00:00:00 2001 From: PascalMarchesseault <97350299+PascalMarchesseault@users.noreply.github.com> Date: Sun, 9 Jun 2024 23:03:33 -0400 Subject: [PATCH 055/229] Merge - Geminimal & CreatorInfo --- .../Queries/GetCreatorInfo/CreatorInfoDto.cs | 9 --- .../Queries/GetCreatorInfo/GetCreatorInfo.cs | 32 ----------- .../Queries/GetMinimalUser/GetMinimalUser.cs | 28 ++++++--- .../Queries/GetMinimalUser/MinimalUserDto.cs | 2 +- src/Web/Endpoints/GetCreatorInfo.cs | 19 ------- src/Web/Endpoints/Users.cs | 4 +- src/Web/wwwroot/api/specification.json | 57 +++---------------- 7 files changed, 34 insertions(+), 117 deletions(-) delete mode 100644 src/Application/Users/Queries/GetCreatorInfo/CreatorInfoDto.cs delete mode 100644 src/Application/Users/Queries/GetCreatorInfo/GetCreatorInfo.cs delete mode 100644 src/Web/Endpoints/GetCreatorInfo.cs diff --git a/src/Application/Users/Queries/GetCreatorInfo/CreatorInfoDto.cs b/src/Application/Users/Queries/GetCreatorInfo/CreatorInfoDto.cs deleted file mode 100644 index e03d762..0000000 --- a/src/Application/Users/Queries/GetCreatorInfo/CreatorInfoDto.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace Hutopy.Application.Users.Queries.GetCreatorInfo; - -public class CreatorInfoDto -{ - public required string FirstName { get; init; } - public required string LastName { get; init; } - public string UserName { get; init; } = String.Empty; - -} diff --git a/src/Application/Users/Queries/GetCreatorInfo/GetCreatorInfo.cs b/src/Application/Users/Queries/GetCreatorInfo/GetCreatorInfo.cs deleted file mode 100644 index 2f2e7d9..0000000 --- a/src/Application/Users/Queries/GetCreatorInfo/GetCreatorInfo.cs +++ /dev/null @@ -1,32 +0,0 @@ -using Hutopy.Application.Common.Interfaces; - -namespace Hutopy.Application.Users.Queries.GetCreatorInfo; - -public record GetCreatorInfoQuery : IRequest -{ - public string UserName { get; set; } = string.Empty; -}; - - -public class GetCreatorInfoHandler( - IIdentityService identityService - ) - : IRequestHandler -{ - public async Task Handle(GetCreatorInfoQuery request, CancellationToken cancellationToken) - { - - var userName = await identityService.GetUserByUserNameAsync(request.UserName); - var creatorInfo = new CreatorInfoDto - { - - FirstName = userName?.FirstName ?? "", - LastName = userName?.LastName ?? "", - UserName = userName?.UserName ?? "", - - }; - return creatorInfo; - } - - -} diff --git a/src/Application/Users/Queries/GetMinimalUser/GetMinimalUser.cs b/src/Application/Users/Queries/GetMinimalUser/GetMinimalUser.cs index 5fd288d..e7e5940 100644 --- a/src/Application/Users/Queries/GetMinimalUser/GetMinimalUser.cs +++ b/src/Application/Users/Queries/GetMinimalUser/GetMinimalUser.cs @@ -1,10 +1,12 @@ using Hutopy.Application.Common.Interfaces; +using Hutopy.Application.Common.Models; namespace Hutopy.Application.Users.Queries.GetMinimalUser; public record GetMinimalUserQuery : IRequest { - public string UserId { get; set; } = string.Empty; + public string? UserId { get; set; } = string.Empty; + public string? UserName { get; set; } = string.Empty; }; public class GetMinimalUserQueryHandler( @@ -14,15 +16,27 @@ public class GetMinimalUserQueryHandler( { public async Task Handle(GetMinimalUserQuery request, CancellationToken cancellationToken) { - var identityUser = await identityService.FindUserByIdAsync(request.UserId); - + UserModel? identityUser = null; + + if (request.UserId != string.Empty) + { + identityUser = await identityService.FindUserByIdAsync(request.UserId); + + } + + if (request.UserName != string.Empty) + { + identityUser = await identityService.GetUserByUserNameAsync(request.UserName); + } + + var user = new MinimalUserDto { - FirstName = identityUser?.FirstName ?? "", - LastName = identityUser?.LastName ?? "", - UserName = identityUser?.UserName ?? "" + FirstName = identityUser?.FirstName ?? string.Empty, + LastName = identityUser?.LastName ?? string.Empty, + UserName = identityUser?.UserName ?? string.Empty }; return user; } -} +} \ No newline at end of file diff --git a/src/Application/Users/Queries/GetMinimalUser/MinimalUserDto.cs b/src/Application/Users/Queries/GetMinimalUser/MinimalUserDto.cs index 0b01fba..97fa6a1 100644 --- a/src/Application/Users/Queries/GetMinimalUser/MinimalUserDto.cs +++ b/src/Application/Users/Queries/GetMinimalUser/MinimalUserDto.cs @@ -4,5 +4,5 @@ public class MinimalUserDto { public required string FirstName { get; init; } public required string LastName { get; init; } - public string UserName { get; init; } = String.Empty; + public required string UserName { get; init; } = String.Empty; } diff --git a/src/Web/Endpoints/GetCreatorInfo.cs b/src/Web/Endpoints/GetCreatorInfo.cs deleted file mode 100644 index e31263f..0000000 --- a/src/Web/Endpoints/GetCreatorInfo.cs +++ /dev/null @@ -1,19 +0,0 @@ -using Hutopy.Application.Users.Queries; -using Hutopy.Application.Users.Queries.GetCreatorInfo; - - -namespace Hutopy.Web.Endpoints; - -public class GetCreatorInfo : EndpointGroupBase -{ - public override void Map(WebApplication app) - { - app.MapGroup(this) - .MapGet(GetSelectedCreatorInfo); - } - - private static async Task GetSelectedCreatorInfo(ISender sender, [AsParameters] GetCreatorInfoQuery query) - { - return await sender.Send(query); - } -} diff --git a/src/Web/Endpoints/Users.cs b/src/Web/Endpoints/Users.cs index 32b8acc..b0b9c59 100644 --- a/src/Web/Endpoints/Users.cs +++ b/src/Web/Endpoints/Users.cs @@ -12,15 +12,17 @@ public class Users : EndpointGroupBase .MapPost(CreateUser) .MapGet(GetMinimalUser) .MapIdentityApi(); + } private static async Task CreateUser(ISender sender, CreateUserCommand command) { return await sender.Send(command); } - + private static async Task GetMinimalUser(ISender sender, [AsParameters] GetMinimalUserQuery query) { return await sender.Send(query); } + } diff --git a/src/Web/wwwroot/api/specification.json b/src/Web/wwwroot/api/specification.json index 670f3b3..ece282e 100644 --- a/src/Web/wwwroot/api/specification.json +++ b/src/Web/wwwroot/api/specification.json @@ -6,38 +6,6 @@ "version": "1.0.0" }, "paths": { - "/api/GetCreatorInfo": { - "get": { - "tags": [ - "GetCreatorInfo" - ], - "operationId": "GetSelectedCreatorInfo", - "parameters": [ - { - "name": "UserName", - "in": "query", - "required": true, - "schema": { - "type": "string", - "nullable": true - }, - "x-position": 1 - } - ], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreatorInfoDto" - } - } - } - } - } - } - }, "/api/GetMyUser": { "get": { "tags": [ @@ -283,12 +251,20 @@ { "name": "UserId", "in": "query", - "required": true, "schema": { "type": "string", "nullable": true }, "x-position": 1 + }, + { + "name": "UserName", + "in": "query", + "schema": { + "type": "string", + "nullable": true + }, + "x-position": 2 } ], "responses": { @@ -720,21 +696,6 @@ }, "components": { "schemas": { - "CreatorInfoDto": { - "type": "object", - "additionalProperties": false, - "properties": { - "firstName": { - "type": "string" - }, - "lastName": { - "type": "string" - }, - "userName": { - "type": "string" - } - } - }, "UserDto": { "type": "object", "additionalProperties": false, From 6f76cb208474b8a6deebf4698e19d17a9f5daac3 Mon Sep 17 00:00:00 2001 From: Dominic Villemure Date: Sun, 9 Jun 2024 23:44:37 -0400 Subject: [PATCH 056/229] #oauth changed GoogleController for the jwt flow ( using a common token if we connect from our app or from google ) --- Directory.Packages.props | 1 + .../Common/Interfaces/IIdentityService.cs | 5 +- src/Application/Users/Commands/Login.cs | 27 + src/Infrastructure/DependencyInjection.cs | 17 +- .../Identity/IdentityService.cs | 25 +- src/Infrastructure/Services/UserService.cs | 134 ---- src/Infrastructure/Utils/GenerateJwtToken.cs | 31 + src/Infrastructure/Utils/RandomGenerator.cs | 58 ++ src/Web/Controllers/FacebookController.cs | 18 +- src/Web/Controllers/GoogleController.cs | 85 ++- src/Web/DependencyInjection.cs | 51 +- src/Web/Endpoints/Users.cs | 9 +- src/Web/Program.cs | 56 +- src/Web/Web.csproj | 1 + src/Web/appsettings.Development.dist | 30 +- src/Web/wwwroot/api/specification.json | 632 ++---------------- 16 files changed, 338 insertions(+), 842 deletions(-) create mode 100644 src/Application/Users/Commands/Login.cs delete mode 100644 src/Infrastructure/Services/UserService.cs create mode 100644 src/Infrastructure/Utils/GenerateJwtToken.cs create mode 100644 src/Infrastructure/Utils/RandomGenerator.cs diff --git a/Directory.Packages.props b/Directory.Packages.props index b8593ab..f4732ee 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -16,6 +16,7 @@ + diff --git a/src/Application/Common/Interfaces/IIdentityService.cs b/src/Application/Common/Interfaces/IIdentityService.cs index 5451d37..cd97117 100644 --- a/src/Application/Common/Interfaces/IIdentityService.cs +++ b/src/Application/Common/Interfaces/IIdentityService.cs @@ -10,15 +10,12 @@ public interface IIdentityService Task FindUserByIdAsync(string id); Task GetCurrentUserAsync(); Task FindUserByEmailAsync(string id); + Task LoginAsync(string email, string password); Task GetUserByUserNameAsync(string userName); Task IsInRoleAsync(string userId, string role); Task AuthorizeAsync(string userId, string policyName); Task AddRoleAsync(string userId, string role); Task> GetCurrentUserRolesAsync(); - - Task<(Result Result, string UserId)> CreateUserAsync(string userName, string password); - Task<(Result Result, string UserId)> CreateUserAsync(Userinfo userInfo); - Task DeleteUserAsync(string userId); } diff --git a/src/Application/Users/Commands/Login.cs b/src/Application/Users/Commands/Login.cs new file mode 100644 index 0000000..f61f810 --- /dev/null +++ b/src/Application/Users/Commands/Login.cs @@ -0,0 +1,27 @@ +using Hutopy.Application.Common.Interfaces; + +namespace Hutopy.Application.Users.Commands; +public record LoginCommand : IRequest +{ + public required string EmailAddress { get; init; } + public required string Password { get; init; } +} + +public class LoginCommandHandler : IRequestHandler +{ + private readonly IApplicationDbContext _context; + private readonly IIdentityService _identityService; + + public LoginCommandHandler(IApplicationDbContext context, IIdentityService identityService) + { + _context = context; + _identityService = identityService; + } + + public async Task Handle(LoginCommand request, CancellationToken cancellationToken) + { + var jwt = await _identityService.LoginAsync(request.EmailAddress, request.Password); + + return jwt ?? "Invalid login credentials"; + } +} diff --git a/src/Infrastructure/DependencyInjection.cs b/src/Infrastructure/DependencyInjection.cs index 31b0b30..42ca0c3 100644 --- a/src/Infrastructure/DependencyInjection.cs +++ b/src/Infrastructure/DependencyInjection.cs @@ -48,13 +48,20 @@ public static class DependencyInjection .AddBearerToken(IdentityConstants.BearerScheme); services.AddAuthorizationBuilder(); - - // Might need to change and use AddIdentity() when we need to integrate connection via third party ( facebook, google ) - services - .AddIdentityCore() + + services.AddIdentityCore(options => + { + options.Password.RequireDigit = false; + options.Password.RequireLowercase = false; + options.Password.RequireUppercase = false; + options.Password.RequireNonAlphanumeric = false; + options.Password.RequiredLength = 8; + }) .AddRoles() .AddEntityFrameworkStores() - .AddApiEndpoints(); + .AddApiEndpoints() + .AddSignInManager>() + .AddDefaultTokenProviders(); services.AddSingleton(TimeProvider.System); services.AddScoped(); diff --git a/src/Infrastructure/Identity/IdentityService.cs b/src/Infrastructure/Identity/IdentityService.cs index b7f7d77..0a25594 100644 --- a/src/Infrastructure/Identity/IdentityService.cs +++ b/src/Infrastructure/Identity/IdentityService.cs @@ -2,17 +2,21 @@ using Google.Apis.Oauth2.v2.Data; using System.Security.Claims; using Hutopy.Application.Common.Interfaces; using Hutopy.Application.Common.Models; +using Hutopy.Infrastructure.Utils; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Identity; +using Microsoft.Extensions.Configuration; namespace Hutopy.Infrastructure.Identity; public class IdentityService( UserManager userManager, + SignInManager signInManager, IUserClaimsPrincipalFactory userClaimsPrincipalFactory, IAuthorizationService authorizationService, - IHttpContextAccessor contextAccessor + IHttpContextAccessor contextAccessor, + IConfiguration configuration ) : IIdentityService { @@ -205,4 +209,23 @@ public class IdentityService( return userRoles; } + + public async Task LoginAsync(string userName, string password) + { + var result = await signInManager.PasswordSignInAsync(userName, password, isPersistent: false, lockoutOnFailure: false); + + if (!result.Succeeded) + { + return null; + } + + var user = await GetUserByUserNameAsync(userName); + var token = JwtTokenHelper.GenerateJwtToken( + issuer: configuration["Jwt:Issuer"] ?? "", + audience: configuration["Jwt:Audience"] ?? "", + key: configuration["Jwt:Key"] ?? "", + userId: user?.Id ?? ""); + + return token; + } } diff --git a/src/Infrastructure/Services/UserService.cs b/src/Infrastructure/Services/UserService.cs deleted file mode 100644 index 4e52033..0000000 --- a/src/Infrastructure/Services/UserService.cs +++ /dev/null @@ -1,134 +0,0 @@ -using System.Text; -using System.Security.Claims; -using Hutopy.Domain.Interfaces; -using Hutopy.Domain.Models; -using Hutopy.Infrastructure.Identity; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Identity; - -namespace Hutopy.Infrastructure.Services; - -public class UserService(UserManager userManager, IHttpContextAccessor contextAccessor) : IUserService -{ - public async Task CreateUserAsync(string email, string userName, string firstName, string lastName, string password) - { - var applicationUser = new ApplicationUser - { - UserName = userName, - Email = email, - FirstName = firstName, - LastName = lastName - }; - - //todo: Need to handle errors better for the user. - var response = await userManager.CreateAsync(applicationUser, password); - - if (response.Errors.Any()) - { - throw new Exception("Failed to create user", new AggregateException(response.Errors.Select(e => new Exception(e.Description)))); - } - } - - public async Task FindUserByIdAsync(string id) - { - var response = await userManager.FindByIdAsync(id); - - if (response == null) return null; - - var userModel = new UserModel - { - Id = response.Id, - UserName = response.UserName, - FirstName = response.FirstName, - LastName = response.LastName, - Email = response.Email, - }; - - return userModel; - } - - public async Task GetCurrentUserAsync() - { - // todo: Get the id of the user doing the request. - var currentUserId = contextAccessor.HttpContext?.User?.FindFirst(ClaimTypes.NameIdentifier)?.Value; - if (string.IsNullOrEmpty(currentUserId)) - { - return null; - } - - return await FindUserByIdAsync(currentUserId); - } - - public async Task FindUserByEmailAsync(string email) - { - var response = await userManager.FindByEmailAsync(email); - - if (response == null) return null; - - var userModel = new UserModel - { - Id = response.Id, - UserName = response.UserName, - FirstName = response.FirstName, - LastName = response.LastName, - Email = response.Email - }; - - return userModel; - } -} - -// If we need to add special characters we can alternate between 2 pools. -public class RandomGenerator -{ - // For the moment, numbers and special characters don't work because - // the random generator is designed to handle a single integer. - // We can modify this in the future. - private const string LetterBytes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" - + "0123456789" - + "!@#$%^&*()_+" - + "-=[];',./`~{}|:\"<>?"; - private const int LetterIdxBits = 6; - private const int LetterIdxMask = 1 << LetterIdxBits; - private const int LetterIdxMax = 64 / LetterIdxBits; - - private static readonly Random Src = new(); - - public static byte[] RandBytesMaskSrc(int n) - { - var b = new byte[n]; - - for (var i = n - 1; i >= 0;) - { - long cache = Src.NextInt64(); - int remain = LetterIdxMax; - - while (remain != 0) - { - if (i < 0) - break; - - if (cache == 0) - cache = Src.NextInt64(); - - var idx = (int)(cache & LetterIdxMask); - if (idx < LetterBytes.Length) - { - b[i] = (byte)LetterBytes[idx]; - i--; - } - - cache >>= LetterIdxBits; - remain--; - } - } - - return b; - } - - public static string RandomString(int length) - { - var bytes = RandBytesMaskSrc(length); - return Encoding.UTF8.GetString(bytes); // Equivalent for *(string*)(&bytes[0]) - } -} diff --git a/src/Infrastructure/Utils/GenerateJwtToken.cs b/src/Infrastructure/Utils/GenerateJwtToken.cs new file mode 100644 index 0000000..9f01d6a --- /dev/null +++ b/src/Infrastructure/Utils/GenerateJwtToken.cs @@ -0,0 +1,31 @@ +using System.IdentityModel.Tokens.Jwt; +using System.Security.Claims; +using System.Text; +using Microsoft.IdentityModel.Tokens; + +namespace Hutopy.Infrastructure.Utils; + +public static class JwtTokenHelper +{ + public static string GenerateJwtToken(string issuer, string audience, string key, string userId) + { + var claims = new[] + { + new Claim(JwtRegisteredClaimNames.Sub, userId), + new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()), + new Claim(ClaimTypes.NameIdentifier, userId) + }; + + var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(key)); + var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256); + + var token = new JwtSecurityToken( + issuer: issuer, + audience: audience, + claims: claims, + expires: DateTime.Now.AddMinutes(30), + signingCredentials: credentials); + + return new JwtSecurityTokenHandler().WriteToken(token); + } +} diff --git a/src/Infrastructure/Utils/RandomGenerator.cs b/src/Infrastructure/Utils/RandomGenerator.cs new file mode 100644 index 0000000..1e5a9a2 --- /dev/null +++ b/src/Infrastructure/Utils/RandomGenerator.cs @@ -0,0 +1,58 @@ +using System.Text; + +namespace Hutopy.Infrastructure.Utils; + +// If we need to add special characters we can alternate between 2 pools. +public class RandomGenerator +{ + // For the moment, numbers and special characters don't work because + // the random generator is designed to handle a single integer. + // We can modify this in the future. + private const string LetterBytes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" + + "0123456789" + + "!@#$%^&*()_+" + + "-=[];',./`~{}|:\"<>?"; + private const int LetterIdxBits = 6; + private const int LetterIdxMask = 1 << LetterIdxBits; + private const int LetterIdxMax = 64 / LetterIdxBits; + + private static readonly Random Src = new(); + + public static byte[] RandBytesMaskSrc(int n) + { + var b = new byte[n]; + + for (var i = n - 1; i >= 0;) + { + long cache = Src.NextInt64(); + int remain = LetterIdxMax; + + while (remain != 0) + { + if (i < 0) + break; + + if (cache == 0) + cache = Src.NextInt64(); + + var idx = (int)(cache & LetterIdxMask); + if (idx < LetterBytes.Length) + { + b[i] = (byte)LetterBytes[idx]; + i--; + } + + cache >>= LetterIdxBits; + remain--; + } + } + + return b; + } + + public static string RandomString(int length) + { + var bytes = RandBytesMaskSrc(length); + return Encoding.UTF8.GetString(bytes); // Equivalent for *(string*)(&bytes[0]) + } +} diff --git a/src/Web/Controllers/FacebookController.cs b/src/Web/Controllers/FacebookController.cs index 394eea1..679502e 100644 --- a/src/Web/Controllers/FacebookController.cs +++ b/src/Web/Controllers/FacebookController.cs @@ -1,6 +1,6 @@ using System.Security.Claims; -using Hutopy.Domain.Interfaces; -using Hutopy.Infrastructure.Services; +using Hutopy.Application.Common.Interfaces; +using Hutopy.Infrastructure.Utils; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authentication.Cookies; using Microsoft.AspNetCore.Authentication.Facebook; @@ -8,7 +8,7 @@ using Microsoft.AspNetCore.Mvc; namespace Hutopy.Web.Controllers; -public class FacebookController(IUserService userService) : Controller +public class FacebookController(IIdentityService identityService) : Controller { [HttpGet("/api/facebook/sign-in")] public async Task SignIn() @@ -27,10 +27,10 @@ public class FacebookController(IUserService userService) : Controller var claims = authenticateResult.Principal.Claims.ToList(); - var name = claims.FirstOrDefault(c => c.Type == ClaimTypes.Name)?.Value; - var email = claims.FirstOrDefault(c => c.Type == ClaimTypes.Email)?.Value; - var givenName = claims.FirstOrDefault(c => c.Type == ClaimTypes.GivenName)?.Value; - var familyName = claims.FirstOrDefault(c => c.Type == ClaimTypes.Surname)?.Value; + var name = claims.FirstOrDefault(c => c.Type == ClaimTypes.Name)?.Value ?? ""; + var email = claims.FirstOrDefault(c => c.Type == ClaimTypes.Email)?.Value ?? ""; + var givenName = claims.FirstOrDefault(c => c.Type == ClaimTypes.GivenName)?.Value ?? ""; + var familyName = claims.FirstOrDefault(c => c.Type == ClaimTypes.Surname)?.Value ?? ""; var claimsIdentity = new ClaimsIdentity(new List { @@ -40,13 +40,13 @@ public class FacebookController(IUserService userService) : Controller new(ClaimTypes.Surname, familyName) }, CookieAuthenticationDefaults.AuthenticationScheme); - if (await userService.FindUserByEmailAsync(email) != null) + if (await identityService.FindUserByEmailAsync(email) != null) { await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, new ClaimsPrincipal(claimsIdentity)); return Redirect("/"); } - await userService.CreateUserAsync(email, givenName, givenName, familyName, RandomGenerator.RandomString(24)); + await identityService.CreateUserAsync(email, givenName, givenName, familyName, RandomGenerator.RandomString(24)); await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, new ClaimsPrincipal(claimsIdentity)); return Redirect("/"); } diff --git a/src/Web/Controllers/GoogleController.cs b/src/Web/Controllers/GoogleController.cs index 0780277..1f5228e 100644 --- a/src/Web/Controllers/GoogleController.cs +++ b/src/Web/Controllers/GoogleController.cs @@ -1,53 +1,70 @@ using System.Security.Claims; -using Hutopy.Domain.Interfaces; -using Hutopy.Infrastructure.Services; +using Hutopy.Application.Common.Interfaces; +using Hutopy.Infrastructure.Utils; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authentication.Cookies; -using Microsoft.AspNetCore.Authentication.Google; using Microsoft.AspNetCore.Mvc; +using Newtonsoft.Json.Linq; namespace Hutopy.Web.Controllers; -public class GoogleController(IUserService userService) : Controller +public class GoogleController(IIdentityService identityService, IHttpClientFactory httpClientFactory) : Controller { - [HttpGet("/api/google/sign-in")] - public async Task SignIn() + [HttpPost("/api/google/sign-in")] + public async Task SignIn([FromBody] GoogleSignInRequest request) { - await HttpContext.ChallengeAsync(GoogleDefaults.AuthenticationScheme, new AuthenticationProperties + var httpClient = httpClientFactory.CreateClient(); + // Verify the token with Google + var response = await httpClient.GetAsync($"https://www.googleapis.com/oauth2/v1/userinfo?access_token={request.AccessToken}"); + if (!response.IsSuccessStatusCode) { - RedirectUri = Url.Action("Authorize") - }); - } - - public async Task Authorize() - { - var authenticateResult = await HttpContext.AuthenticateAsync(GoogleDefaults.AuthenticationScheme); + return BadRequest("Invalid Google token."); + } + + var payload = JObject.Parse(await response.Content.ReadAsStringAsync()); + + var email = payload["email"]?.ToString() ?? ""; + var name = payload["name"]?.ToString() ?? ""; + var givenName = payload["given_name"]?.ToString() ?? ""; + var familyName = payload["family_name"]?.ToString() ?? ""; + + if (string.IsNullOrEmpty(email)) + { + return BadRequest("Google token did not contain an email."); + } + + // Check if user exists or create a new one + var user = await identityService.FindUserByEmailAsync(email); + if (user == null) + { + await identityService.CreateUserAsync(email, email, givenName, familyName, RandomGenerator.RandomString(24)); + user = await identityService.FindUserByEmailAsync(email); + } - if (!authenticateResult.Succeeded) return BadRequest(); - - var claims = authenticateResult.Principal.Claims.ToList(); - - var name = claims.FirstOrDefault(c => c.Type == ClaimTypes.Name)?.Value; - var email = claims.FirstOrDefault(c => c.Type == ClaimTypes.Email)?.Value; - var givenName = claims.FirstOrDefault(c => c.Type == ClaimTypes.GivenName)?.Value; - var familyName = claims.FirstOrDefault(c => c.Type == ClaimTypes.Surname)?.Value; - - var claimsIdentity = new ClaimsIdentity(new List + if (user is null) + { + return BadRequest("Unable to find or create the user."); + } + + // Sign in the user + var claims = new List { new(ClaimTypes.Name, name), new(ClaimTypes.Email, email), new(ClaimTypes.GivenName, givenName), new(ClaimTypes.Surname, familyName) - }, CookieAuthenticationDefaults.AuthenticationScheme); - - if (await userService.FindUserByEmailAsync(email) != null) - { - await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, new ClaimsPrincipal(claimsIdentity)); - return Redirect("/"); - } - - await userService.CreateUserAsync(email, givenName, givenName, familyName, RandomGenerator.RandomString(24)); + }; + + var claimsIdentity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme); await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, new ClaimsPrincipal(claimsIdentity)); - return Redirect("/"); + + var jwtToken = JwtTokenHelper.GenerateJwtToken("https://hutopy.com", "Hutopy", "V3J3bWFuUml3ZVpQbmxlWmZhWEo3ZkJSZ01YbHBwS24=", user.Id!); + + return Ok(new { accessToken = jwtToken, email }); + } + + public class GoogleSignInRequest + { + public required string AccessToken { get; set; } } } diff --git a/src/Web/DependencyInjection.cs b/src/Web/DependencyInjection.cs index f8ede38..a921805 100644 --- a/src/Web/DependencyInjection.cs +++ b/src/Web/DependencyInjection.cs @@ -1,8 +1,14 @@ -using Azure.Identity; +using System.Text; +using Azure.Identity; using Hutopy.Application.Common.Interfaces; using Hutopy.Infrastructure.Data; using Hutopy.Web.Services; +using Microsoft.AspNetCore.Authentication.Cookies; +using Microsoft.AspNetCore.Authentication.Facebook; +using Microsoft.AspNetCore.Authentication.Google; +using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Mvc; +using Microsoft.IdentityModel.Tokens; using NSwag; using NSwag.Generation.Processors.Security; @@ -24,6 +30,8 @@ public static class DependencyInjection services.AddExceptionHandler(); services.AddRazorPages(); + + services.AddHttpClient(); // Customise default API behaviour services.Configure(options => @@ -62,4 +70,45 @@ public static class DependencyInjection return services; } + + public static IServiceCollection AddAuthorizationAndAuthentication(this IServiceCollection services, ConfigurationManager configuration) + { + services.AddAuthentication(options => + { + options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme; + options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme; + }) + .AddCookie("Identity.Application", options => + { + options.LoginPath = "/api/Users/login"; + }) + .AddCookie() + .AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, jwtBearerOptions => + { + jwtBearerOptions.Authority = "https://hutopy.com"; + jwtBearerOptions.TokenValidationParameters = new TokenValidationParameters + { + ValidateIssuer = true, + ValidIssuer = configuration["Jwt:Issuer"], + ValidateAudience = true, + ValidAudience = configuration["Jwt:Audience"], + ValidateLifetime = true, + IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(configuration["Jwt:Key"] ?? "")) + }; + }) + .AddGoogle(GoogleDefaults.AuthenticationScheme, options => + { + options.ClientId = configuration["Google:ClientId"] ?? ""; + options.ClientSecret = configuration["Google:ClientSecret"] ?? ""; + }) + .AddFacebook(FacebookDefaults.AuthenticationScheme, options => + { + options.ClientId = configuration["Facebook:ClientId"] ?? + throw new ArgumentNullException("The Facebook ClientId is missing."); + options.ClientSecret = configuration["Facebook:ClientSecret"] ?? + throw new ArgumentNullException("The Facebook ClientSecret is missing."); + }); + + return services; + } } diff --git a/src/Web/Endpoints/Users.cs b/src/Web/Endpoints/Users.cs index 32b8acc..41b558d 100644 --- a/src/Web/Endpoints/Users.cs +++ b/src/Web/Endpoints/Users.cs @@ -10,8 +10,8 @@ public class Users : EndpointGroupBase { app.MapGroup(this) .MapPost(CreateUser) - .MapGet(GetMinimalUser) - .MapIdentityApi(); + .MapPost(Login, "/login") + .MapGet(GetMinimalUser); } private static async Task CreateUser(ISender sender, CreateUserCommand command) @@ -23,4 +23,9 @@ public class Users : EndpointGroupBase { return await sender.Send(query); } + + private static async Task Login(ISender sender, LoginCommand command) + { + return await sender.Send(command); + } } diff --git a/src/Web/Program.cs b/src/Web/Program.cs index 14bda9f..1246d0d 100644 --- a/src/Web/Program.cs +++ b/src/Web/Program.cs @@ -3,12 +3,7 @@ using Hutopy.Infrastructure; using Hutopy.Infrastructure.Data; using Hutopy.Web; using Azure.Identity; -using Hutopy.Infrastructure.Identity; -using Microsoft.AspNetCore.Authentication.Cookies; -using Microsoft.AspNetCore.Authentication.Facebook; -using Microsoft.AspNetCore.Authentication.Google; using Microsoft.AspNetCore.HttpOverrides; -using Microsoft.AspNetCore.Identity; var builder = WebApplication.CreateBuilder(args); @@ -50,49 +45,8 @@ builder.Services.AddKeyVaultIfConfigured(builder.Configuration); builder.Services.AddApplicationServices(); builder.Services.AddInfrastructureServices(builder.Configuration); builder.Services.AddWebServices(); - -// OAuth -builder.Services.AddAuthentication(options => - { - options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme; - options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme; - }) - .AddCookie() - .AddGoogle( - GoogleDefaults.AuthenticationScheme, - options => - { - options.ClientId = builder.Configuration["Google:ClientId"] ?? - throw new ArgumentNullException("The Google ClientId is missing."); - options.ClientSecret = builder.Configuration["Google:ClientSecret"] ?? - throw new ArgumentNullException("The Google ClientSecret is missing."); - //options.AccessDeniedPath = "/AccessDeniedPathInfo"; - }) - .AddFacebook( - FacebookDefaults.AuthenticationScheme, - options => - { - options.ClientId = builder.Configuration["Facebook:ClientId"] ?? - throw new ArgumentNullException("The Facebook ClientId is missing."); - options.ClientSecret = builder.Configuration["Facebook:ClientSecret"] ?? - throw new ArgumentNullException("The Facebook ClientSecret is missing."); - //options.AccessDeniedPath = "/AccessDeniedPathInfo"; - }); - -// Password hashing -builder.Services.AddIdentity(options => - { - options.Password.RequireDigit = false; - options.Password.RequireLowercase = false; - options.Password.RequireUppercase = false; - options.Password.RequireNonAlphanumeric = false; - options.Password.RequiredLength = 16; - }) - .AddEntityFrameworkStores() - .AddDefaultTokenProviders(); - +builder.Services.AddAuthorizationAndAuthentication(builder.Configuration); builder.Services.AddControllers(); -builder.Services.AddScoped(); var app = builder.Build(); @@ -100,13 +54,15 @@ app.UseForwardedHeaders( new ForwardedHeadersOptions { ForwardedHeaders = ForwardedHeaders.XForwardedProto } ); -app.UseAuthentication(); -app.UseAuthorization(); - app.UseCors("AllowAll"); app.UseCors("AllowHutopyUi"); app.UseCors("AllowHutopyUiPreview"); +app.UseAuthentication(); +app.UseAuthorization(); + + + // Initialize and seed the db. await app.InitialiseDatabaseAsync(); diff --git a/src/Web/Web.csproj b/src/Web/Web.csproj index d5e0c62..9193242 100644 --- a/src/Web/Web.csproj +++ b/src/Web/Web.csproj @@ -16,6 +16,7 @@ + diff --git a/src/Web/appsettings.Development.dist b/src/Web/appsettings.Development.dist index 58d6716..d25bfda 100644 --- a/src/Web/appsettings.Development.dist +++ b/src/Web/appsettings.Development.dist @@ -9,21 +9,15 @@ }, "Google": { "ClientId": "", - "ClientSecret": "", - "ProjectId": "", - "AuthUri": "", - "TokenUri": "", - "AuthProviderX509CertUrl": "", - "RedirectUris": [ - "https://hutopy.ca", - "https://hutopy.com", - "http://localhost" - ], - "JavascriptOrigins": [ - "https://hutopy.ca", - "https://hutopy.com", - "http://localhost" - ] - } -} - + "ClientSecret": "" + }, + "Facebook": { + "ClientId": "", + "ClientSecret": "" + }, + "Jwt": { + "Issuer": "", + "Audience": "", + "Key": "" + } +} \ No newline at end of file diff --git a/src/Web/wwwroot/api/specification.json b/src/Web/wwwroot/api/specification.json index 2a98d65..5b73a58 100644 --- a/src/Web/wwwroot/api/specification.json +++ b/src/Web/wwwroot/api/specification.json @@ -273,75 +273,22 @@ } } }, - "/api/Users/register": { - "post": { - "tags": [ - "Users" - ], - "operationId": "PostApiUsersRegister", - "requestBody": { - "x-name": "registration", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/RegisterRequest" - } - } - }, - "x-position": 1 - }, - "responses": { - "200": { - "description": "" - }, - "400": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HttpValidationProblemDetails" - } - } - } - } - } - } - }, "/api/Users/login": { "post": { "tags": [ "Users" ], - "operationId": "PostApiUsersLogin", - "parameters": [ - { - "name": "useCookies", - "in": "query", - "schema": { - "type": "boolean", - "nullable": true - }, - "x-position": 2 - }, - { - "name": "useSessionCookies", - "in": "query", - "schema": { - "type": "boolean", - "nullable": true - }, - "x-position": 3 - } - ], + "operationId": "Login", "requestBody": { - "x-name": "login", + "x-name": "command", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/LoginRequest" + "$ref": "#/components/schemas/LoginCommand" } } }, + "required": true, "x-position": 1 }, "responses": { @@ -350,7 +297,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/AccessTokenResponse" + "type": "string" } } } @@ -358,305 +305,6 @@ } } }, - "/api/Users/refresh": { - "post": { - "tags": [ - "Users" - ], - "operationId": "PostApiUsersRefresh", - "requestBody": { - "x-name": "refreshRequest", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/RefreshRequest" - } - } - }, - "x-position": 1 - }, - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AccessTokenResponse" - } - } - } - } - } - } - }, - "/api/Users/confirmEmail": { - "get": { - "tags": [ - "Users" - ], - "operationId": "GetApiUsersConfirmEmail", - "parameters": [ - { - "name": "userId", - "in": "query", - "schema": { - "type": "string", - "nullable": true - }, - "x-position": 1 - }, - { - "name": "code", - "in": "query", - "schema": { - "type": "string", - "nullable": true - }, - "x-position": 2 - }, - { - "name": "changedEmail", - "in": "query", - "schema": { - "type": "string", - "nullable": true - }, - "x-position": 3 - } - ], - "responses": { - "200": { - "description": "" - } - } - } - }, - "/api/Users/resendConfirmationEmail": { - "post": { - "tags": [ - "Users" - ], - "operationId": "PostApiUsersResendConfirmationEmail", - "requestBody": { - "x-name": "resendRequest", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ResendConfirmationEmailRequest" - } - } - }, - "x-position": 1 - }, - "responses": { - "200": { - "description": "" - } - } - } - }, - "/api/Users/forgotPassword": { - "post": { - "tags": [ - "Users" - ], - "operationId": "PostApiUsersForgotPassword", - "requestBody": { - "x-name": "resetRequest", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ForgotPasswordRequest" - } - } - }, - "x-position": 1 - }, - "responses": { - "200": { - "description": "" - }, - "400": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HttpValidationProblemDetails" - } - } - } - } - } - } - }, - "/api/Users/resetPassword": { - "post": { - "tags": [ - "Users" - ], - "operationId": "PostApiUsersResetPassword", - "requestBody": { - "x-name": "resetRequest", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ResetPasswordRequest" - } - } - }, - "x-position": 1 - }, - "responses": { - "200": { - "description": "" - }, - "400": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HttpValidationProblemDetails" - } - } - } - } - } - } - }, - "/api/Users/manage/2fa": { - "post": { - "tags": [ - "Users" - ], - "operationId": "PostApiUsersManage2fa", - "requestBody": { - "x-name": "tfaRequest", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/TwoFactorRequest" - } - } - }, - "x-position": 1 - }, - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/TwoFactorResponse" - } - } - } - }, - "400": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HttpValidationProblemDetails" - } - } - } - }, - "404": { - "description": "" - } - }, - "security": [ - { - "JWT": [] - } - ] - } - }, - "/api/Users/manage/info": { - "get": { - "tags": [ - "Users" - ], - "operationId": "GetApiUsersManageInfo", - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/InfoResponse" - } - } - } - }, - "400": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HttpValidationProblemDetails" - } - } - } - }, - "404": { - "description": "" - } - }, - "security": [ - { - "JWT": [] - } - ] - }, - "post": { - "tags": [ - "Users" - ], - "operationId": "PostApiUsersManageInfo", - "requestBody": { - "x-name": "infoRequest", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/InfoRequest" - } - } - }, - "x-position": 1 - }, - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/InfoResponse" - } - } - } - }, - "400": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HttpValidationProblemDetails" - } - } - } - }, - "404": { - "description": "" - } - }, - "security": [ - { - "JWT": [] - } - ] - } - }, "/api/WeatherForecasts": { "get": { "tags": [ @@ -699,14 +347,34 @@ } }, "/api/google/sign-in": { - "get": { + "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": "" + "description": "", + "content": { + "application/octet-stream": { + "schema": { + "type": "string", + "format": "binary" + } + } + } } } } @@ -986,6 +654,18 @@ } } }, + "LoginCommand": { + "type": "object", + "additionalProperties": false, + "properties": { + "emailAddress": { + "type": "string" + }, + "password": { + "type": "string" + } + } + }, "MinimalUserDto": { "type": "object", "additionalProperties": false, @@ -1001,231 +681,6 @@ } } }, - "HttpValidationProblemDetails": { - "allOf": [ - { - "$ref": "#/components/schemas/ProblemDetails" - }, - { - "type": "object", - "additionalProperties": { - "nullable": true - }, - "properties": { - "errors": { - "type": "object", - "additionalProperties": { - "type": "array", - "items": { - "type": "string" - } - } - } - } - } - ] - }, - "ProblemDetails": { - "type": "object", - "additionalProperties": { - "nullable": true - }, - "properties": { - "type": { - "type": "string", - "nullable": true - }, - "title": { - "type": "string", - "nullable": true - }, - "status": { - "type": "integer", - "format": "int32", - "nullable": true - }, - "detail": { - "type": "string", - "nullable": true - }, - "instance": { - "type": "string", - "nullable": true - } - } - }, - "RegisterRequest": { - "type": "object", - "additionalProperties": false, - "properties": { - "email": { - "type": "string" - }, - "password": { - "type": "string" - } - } - }, - "AccessTokenResponse": { - "type": "object", - "additionalProperties": false, - "properties": { - "tokenType": { - "type": "string" - }, - "accessToken": { - "type": "string" - }, - "expiresIn": { - "type": "integer", - "format": "int64" - }, - "refreshToken": { - "type": "string" - } - } - }, - "LoginRequest": { - "type": "object", - "additionalProperties": false, - "properties": { - "email": { - "type": "string" - }, - "password": { - "type": "string" - }, - "twoFactorCode": { - "type": "string", - "nullable": true - }, - "twoFactorRecoveryCode": { - "type": "string", - "nullable": true - } - } - }, - "RefreshRequest": { - "type": "object", - "additionalProperties": false, - "properties": { - "refreshToken": { - "type": "string" - } - } - }, - "ResendConfirmationEmailRequest": { - "type": "object", - "additionalProperties": false, - "properties": { - "email": { - "type": "string" - } - } - }, - "ForgotPasswordRequest": { - "type": "object", - "additionalProperties": false, - "properties": { - "email": { - "type": "string" - } - } - }, - "ResetPasswordRequest": { - "type": "object", - "additionalProperties": false, - "properties": { - "email": { - "type": "string" - }, - "resetCode": { - "type": "string" - }, - "newPassword": { - "type": "string" - } - } - }, - "TwoFactorResponse": { - "type": "object", - "additionalProperties": false, - "properties": { - "sharedKey": { - "type": "string" - }, - "recoveryCodesLeft": { - "type": "integer", - "format": "int32" - }, - "recoveryCodes": { - "type": "array", - "nullable": true, - "items": { - "type": "string" - } - }, - "isTwoFactorEnabled": { - "type": "boolean" - }, - "isMachineRemembered": { - "type": "boolean" - } - } - }, - "TwoFactorRequest": { - "type": "object", - "additionalProperties": false, - "properties": { - "enable": { - "type": "boolean", - "nullable": true - }, - "twoFactorCode": { - "type": "string", - "nullable": true - }, - "resetSharedKey": { - "type": "boolean" - }, - "resetRecoveryCodes": { - "type": "boolean" - }, - "forgetMachine": { - "type": "boolean" - } - } - }, - "InfoResponse": { - "type": "object", - "additionalProperties": false, - "properties": { - "email": { - "type": "string" - }, - "isEmailConfirmed": { - "type": "boolean" - } - } - }, - "InfoRequest": { - "type": "object", - "additionalProperties": false, - "properties": { - "newEmail": { - "type": "string", - "nullable": true - }, - "newPassword": { - "type": "string", - "nullable": true - }, - "oldPassword": { - "type": "string", - "nullable": true - } - } - }, "WeatherForecast": { "type": "object", "additionalProperties": false, @@ -1247,6 +702,15 @@ "nullable": true } } + }, + "GoogleSignInRequest": { + "type": "object", + "additionalProperties": false, + "properties": { + "accessToken": { + "type": "string" + } + } } }, "securitySchemes": { From 66bfeea3eec2677e6ab39c9abfb0bd4f79b7ec8f Mon Sep 17 00:00:00 2001 From: Dominic Villemure Date: Sun, 9 Jun 2024 23:53:43 -0400 Subject: [PATCH 057/229] #oauth cleanup --- src/Infrastructure/Identity/ApplicationUser.cs | 1 - src/Web/Controllers/GoogleController.cs | 13 ++++++++++--- src/Web/DependencyInjection.cs | 9 ++++++--- src/Web/Program.cs | 2 -- 4 files changed, 16 insertions(+), 9 deletions(-) diff --git a/src/Infrastructure/Identity/ApplicationUser.cs b/src/Infrastructure/Identity/ApplicationUser.cs index 39cb433..0462aff 100644 --- a/src/Infrastructure/Identity/ApplicationUser.cs +++ b/src/Infrastructure/Identity/ApplicationUser.cs @@ -6,5 +6,4 @@ public class ApplicationUser : IdentityUser { public string FirstName { get; set; } = string.Empty; public string LastName { get; set; } = string.Empty; - //public string Gender { get; set; } = string.Empty; } diff --git a/src/Web/Controllers/GoogleController.cs b/src/Web/Controllers/GoogleController.cs index 1f5228e..49c57e2 100644 --- a/src/Web/Controllers/GoogleController.cs +++ b/src/Web/Controllers/GoogleController.cs @@ -8,7 +8,7 @@ using Newtonsoft.Json.Linq; namespace Hutopy.Web.Controllers; -public class GoogleController(IIdentityService identityService, IHttpClientFactory httpClientFactory) : Controller +public class GoogleController(IIdentityService identityService, IHttpClientFactory httpClientFactory, IConfiguration configuration) : Controller { [HttpPost("/api/google/sign-in")] public async Task SignIn([FromBody] GoogleSignInRequest request) @@ -41,7 +41,7 @@ public class GoogleController(IIdentityService identityService, IHttpClientFacto user = await identityService.FindUserByEmailAsync(email); } - if (user is null) + if (user?.Id is null) { return BadRequest("Unable to find or create the user."); } @@ -58,7 +58,14 @@ public class GoogleController(IIdentityService identityService, IHttpClientFacto var claimsIdentity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme); await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, new ClaimsPrincipal(claimsIdentity)); - var jwtToken = JwtTokenHelper.GenerateJwtToken("https://hutopy.com", "Hutopy", "V3J3bWFuUml3ZVpQbmxlWmZhWEo3ZkJSZ01YbHBwS24=", user.Id!); + var issuer = configuration["Jwt:Issuer"] ?? + throw new ArgumentNullException("The Jwt issuer is missing."); + var audience = configuration["Jwt:Audience"] ?? + throw new ArgumentNullException("The Jwt audience is missing."); + var key = configuration["Jwt:Key"] ?? + throw new ArgumentNullException("The Jwt key is missing."); + + var jwtToken = JwtTokenHelper.GenerateJwtToken(issuer, audience, key, user.Id); return Ok(new { accessToken = jwtToken, email }); } diff --git a/src/Web/DependencyInjection.cs b/src/Web/DependencyInjection.cs index a921805..402b870 100644 --- a/src/Web/DependencyInjection.cs +++ b/src/Web/DependencyInjection.cs @@ -93,13 +93,16 @@ public static class DependencyInjection ValidateAudience = true, ValidAudience = configuration["Jwt:Audience"], ValidateLifetime = true, - IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(configuration["Jwt:Key"] ?? "")) + IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(configuration["Jwt:Key"] ?? + throw new ArgumentNullException("The Jwt Key is missing."))) }; }) .AddGoogle(GoogleDefaults.AuthenticationScheme, options => { - options.ClientId = configuration["Google:ClientId"] ?? ""; - options.ClientSecret = configuration["Google:ClientSecret"] ?? ""; + options.ClientId = configuration["Google:ClientId"] ?? + throw new ArgumentNullException("The Google ClientId is missing.");; + options.ClientSecret = configuration["Google:ClientSecret"] ?? + throw new ArgumentNullException("The Google ClientSecret is missing.");; }) .AddFacebook(FacebookDefaults.AuthenticationScheme, options => { diff --git a/src/Web/Program.cs b/src/Web/Program.cs index 1246d0d..781bdc2 100644 --- a/src/Web/Program.cs +++ b/src/Web/Program.cs @@ -61,8 +61,6 @@ app.UseCors("AllowHutopyUiPreview"); app.UseAuthentication(); app.UseAuthorization(); - - // Initialize and seed the db. await app.InitialiseDatabaseAsync(); From 47fb3caa0df62843195f17f7852d83f825cd019e Mon Sep 17 00:00:00 2001 From: Dominic Villemure Date: Tue, 11 Jun 2024 20:14:36 -0400 Subject: [PATCH 058/229] #58 added owned entity for SocialNetworks that belongs to an ApplicationUser --- .../Data/ApplicationDbContext.cs | 39 +- .../ApplicationUserConfiguration.cs | 16 + .../UserTransactionConfiguration.cs | 21 + .../Identity/ApplicationUser.cs | 4 +- .../Identity/OwnedEntities/SocialNetworks.cs | 13 + ...000806_AddSocialNetworksToUser.Designer.cs | 469 ++++++++++++++++++ .../20240612000806_AddSocialNetworksToUser.cs | 52 ++ .../ApplicationDbContextModelSnapshot.cs | 51 ++ 8 files changed, 643 insertions(+), 22 deletions(-) create mode 100644 src/Infrastructure/Data/Configurations/ApplicationUserConfiguration.cs create mode 100644 src/Infrastructure/Data/Configurations/UserTransactionConfiguration.cs create mode 100644 src/Infrastructure/Identity/OwnedEntities/SocialNetworks.cs create mode 100644 src/Infrastructure/Migrations/20240612000806_AddSocialNetworksToUser.Designer.cs create mode 100644 src/Infrastructure/Migrations/20240612000806_AddSocialNetworksToUser.cs diff --git a/src/Infrastructure/Data/ApplicationDbContext.cs b/src/Infrastructure/Data/ApplicationDbContext.cs index cb3a247..8b4676e 100644 --- a/src/Infrastructure/Data/ApplicationDbContext.cs +++ b/src/Infrastructure/Data/ApplicationDbContext.cs @@ -1,32 +1,29 @@ -using System.Reflection; -using Hutopy.Application.Common.Interfaces; +using Hutopy.Application.Common.Interfaces; using Hutopy.Domain.Entities; +using Hutopy.Infrastructure.Data.Configurations; using Hutopy.Infrastructure.Identity; using Microsoft.AspNetCore.Identity.EntityFrameworkCore; using Microsoft.EntityFrameworkCore; -namespace Hutopy.Infrastructure.Data; - -public class ApplicationDbContext( - DbContextOptions options) - : IdentityDbContext(options), IApplicationDbContext +namespace Hutopy.Infrastructure.Data { - public DbSet FutureCreators => Set(); - public DbSet UserTransactions => Set(); - - protected override void OnModelCreating(ModelBuilder builder) + public class ApplicationDbContext : IdentityDbContext, IApplicationDbContext { - base.OnModelCreating(builder); + public ApplicationDbContext(DbContextOptions options) + : base(options) + { + } - // Relationship between ApplicationUser and UserTransaction - builder.Entity() - .HasOne() - .WithMany() - .HasForeignKey(ut => ut.ApplicationUserId) - .IsRequired(); + public DbSet FutureCreators => Set(); + public DbSet UserTransactions => Set(); - builder.Entity().Property(x => x.Amount).HasPrecision(18, 2); - - builder.ApplyConfigurationsFromAssembly(Assembly.GetExecutingAssembly()); + protected override void OnModelCreating(ModelBuilder builder) + { + base.OnModelCreating(builder); + + // Apply configurations + builder.ApplyConfiguration(new UserTransactionConfiguration()); + builder.ApplyConfiguration(new ApplicationUserConfiguration()); + } } } diff --git a/src/Infrastructure/Data/Configurations/ApplicationUserConfiguration.cs b/src/Infrastructure/Data/Configurations/ApplicationUserConfiguration.cs new file mode 100644 index 0000000..0624b7a --- /dev/null +++ b/src/Infrastructure/Data/Configurations/ApplicationUserConfiguration.cs @@ -0,0 +1,16 @@ +using Hutopy.Infrastructure.Identity; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; + +namespace Hutopy.Infrastructure.Data.Configurations; + +public class ApplicationUserConfiguration : IEntityTypeConfiguration +{ + public void Configure(EntityTypeBuilder builder) + { + // Relationship between ApplicationUser and SocialNetworks + builder + .OwnsOne(u => u.SocialNetworks) + .ToTable($"{nameof(ApplicationUser)}_SocialNetworks"); + } +} diff --git a/src/Infrastructure/Data/Configurations/UserTransactionConfiguration.cs b/src/Infrastructure/Data/Configurations/UserTransactionConfiguration.cs new file mode 100644 index 0000000..f659e55 --- /dev/null +++ b/src/Infrastructure/Data/Configurations/UserTransactionConfiguration.cs @@ -0,0 +1,21 @@ +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; +using Hutopy.Domain.Entities; +using Hutopy.Infrastructure.Identity; + +namespace Hutopy.Infrastructure.Data.Configurations +{ + public class UserTransactionConfiguration : IEntityTypeConfiguration + { + public void Configure(EntityTypeBuilder builder) + { + // Relationship between ApplicationUser and UserTransaction + builder.HasOne() + .WithMany() + .HasForeignKey(ut => ut.ApplicationUserId) + .IsRequired(); + + builder.Property(x => x.Amount).HasPrecision(18, 2); + } + } +} diff --git a/src/Infrastructure/Identity/ApplicationUser.cs b/src/Infrastructure/Identity/ApplicationUser.cs index 0462aff..700a074 100644 --- a/src/Infrastructure/Identity/ApplicationUser.cs +++ b/src/Infrastructure/Identity/ApplicationUser.cs @@ -1,4 +1,5 @@ -using Microsoft.AspNetCore.Identity; +using Hutopy.Infrastructure.Identity.OwnedEntities; +using Microsoft.AspNetCore.Identity; namespace Hutopy.Infrastructure.Identity; @@ -6,4 +7,5 @@ public class ApplicationUser : IdentityUser { public string FirstName { get; set; } = string.Empty; public string LastName { get; set; } = string.Empty; + public SocialNetworks SocialNetworks { get; set; } = new(); } diff --git a/src/Infrastructure/Identity/OwnedEntities/SocialNetworks.cs b/src/Infrastructure/Identity/OwnedEntities/SocialNetworks.cs new file mode 100644 index 0000000..1e0d30e --- /dev/null +++ b/src/Infrastructure/Identity/OwnedEntities/SocialNetworks.cs @@ -0,0 +1,13 @@ +namespace Hutopy.Infrastructure.Identity.OwnedEntities; + +public class SocialNetworks +{ + public string FacebookUrl { get; init; } = String.Empty; + public string InstagramUrl { get; init; } = String.Empty; + public string XUrl { get; init; } = String.Empty; + public string LinkedInUrl { get; init; } = String.Empty; + public string TikTokUrl { get; init; } = String.Empty; + public string YoutubeUrl { get; init; } = String.Empty; + public string RedditUrl { get; init; } = String.Empty; + public string YourWebsiteUrl { get; init; } = String.Empty; +} diff --git a/src/Infrastructure/Migrations/20240612000806_AddSocialNetworksToUser.Designer.cs b/src/Infrastructure/Migrations/20240612000806_AddSocialNetworksToUser.Designer.cs new file mode 100644 index 0000000..2c074bc --- /dev/null +++ b/src/Infrastructure/Migrations/20240612000806_AddSocialNetworksToUser.Designer.cs @@ -0,0 +1,469 @@ +// +using System; +using Hutopy.Infrastructure.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Hutopy.Infrastructure.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + [Migration("20240612000806_AddSocialNetworksToUser")] + partial class AddSocialNetworksToUser + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.3") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("Hutopy.Domain.Entities.FutureCreator", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Created") + .HasColumnType("datetimeoffset"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("EmailAddress") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("FirstName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("LastModified") + .HasColumnType("datetimeoffset"); + + b.Property("LastModifiedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("LastName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumber") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("ReasonToJoin") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("SocialNetworkAccount") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("FutureCreators"); + }); + + modelBuilder.Entity("Hutopy.Domain.Entities.UserTransaction", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Amount") + .HasPrecision(18, 2) + .HasColumnType("decimal(18,2)"); + + b.Property("ApplicationUserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.Property("Created") + .HasColumnType("datetimeoffset"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("Currency") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("IsConfirmed") + .HasColumnType("bit"); + + b.Property("LastModified") + .HasColumnType("datetimeoffset"); + + b.Property("LastModifiedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("Paid") + .HasColumnType("bit"); + + b.Property("StripeBillingDetailEmail") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("StripeBillingDetailName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("StripeChargeId") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("StripeEventId") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("StripePaymentIntent") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("StripePaymentMethod") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("StripeReceiptUrl") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("TipMessage") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationUserId"); + + b.ToTable("UserTransactions"); + }); + + modelBuilder.Entity("Hutopy.Infrastructure.Identity.ApplicationUser", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("AccessFailedCount") + .HasColumnType("int"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("nvarchar(max)"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("EmailConfirmed") + .HasColumnType("bit"); + + b.Property("FirstName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("LastName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("LockoutEnabled") + .HasColumnType("bit"); + + b.Property("LockoutEnd") + .HasColumnType("datetimeoffset"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("PasswordHash") + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumber") + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("bit"); + + b.Property("SecurityStamp") + .HasColumnType("nvarchar(max)"); + + b.Property("TwoFactorEnabled") + .HasColumnType("bit"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex") + .HasFilter("[NormalizedUserName] IS NOT NULL"); + + b.ToTable("AspNetUsers", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("nvarchar(max)"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex") + .HasFilter("[NormalizedName] IS NOT NULL"); + + b.ToTable("AspNetRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("nvarchar(max)"); + + b.Property("ClaimValue") + .HasColumnType("nvarchar(max)"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("nvarchar(max)"); + + b.Property("ClaimValue") + .HasColumnType("nvarchar(max)"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("nvarchar(450)"); + + b.Property("ProviderKey") + .HasColumnType("nvarchar(450)"); + + b.Property("ProviderDisplayName") + .HasColumnType("nvarchar(max)"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("nvarchar(450)"); + + b.Property("RoleId") + .HasColumnType("nvarchar(450)"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("nvarchar(450)"); + + b.Property("LoginProvider") + .HasColumnType("nvarchar(450)"); + + b.Property("Name") + .HasColumnType("nvarchar(450)"); + + b.Property("Value") + .HasColumnType("nvarchar(max)"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens", (string)null); + }); + + modelBuilder.Entity("Hutopy.Domain.Entities.UserTransaction", b => + { + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("ApplicationUserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Hutopy.Infrastructure.Identity.ApplicationUser", b => + { + b.OwnsOne("Hutopy.Infrastructure.Identity.OwnedEntities.SocialNetworks", "SocialNetworks", b1 => + { + b1.Property("ApplicationUserId") + .HasColumnType("nvarchar(450)"); + + b1.Property("FacebookUrl") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.Property("InstagramUrl") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.Property("LinkedInUrl") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.Property("RedditUrl") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.Property("TikTokUrl") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.Property("XUrl") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.Property("YourWebsiteUrl") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.Property("YoutubeUrl") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.HasKey("ApplicationUserId"); + + b1.ToTable("ApplicationUser_SocialNetworks", (string)null); + + b1.WithOwner() + .HasForeignKey("ApplicationUserId"); + }); + + b.Navigation("SocialNetworks") + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Infrastructure/Migrations/20240612000806_AddSocialNetworksToUser.cs b/src/Infrastructure/Migrations/20240612000806_AddSocialNetworksToUser.cs new file mode 100644 index 0000000..14dfa81 --- /dev/null +++ b/src/Infrastructure/Migrations/20240612000806_AddSocialNetworksToUser.cs @@ -0,0 +1,52 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Hutopy.Infrastructure.Migrations +{ + /// + public partial class AddSocialNetworksToUser : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "ApplicationUser_SocialNetworks", + columns: table => new + { + ApplicationUserId = table.Column(type: "nvarchar(450)", nullable: false), + FacebookUrl = table.Column(type: "nvarchar(max)", nullable: false), + InstagramUrl = table.Column(type: "nvarchar(max)", nullable: false), + XUrl = table.Column(type: "nvarchar(max)", nullable: false), + LinkedInUrl = table.Column(type: "nvarchar(max)", nullable: false), + TikTokUrl = table.Column(type: "nvarchar(max)", nullable: false), + YoutubeUrl = table.Column(type: "nvarchar(max)", nullable: false), + RedditUrl = table.Column(type: "nvarchar(max)", nullable: false), + YourWebsiteUrl = table.Column(type: "nvarchar(max)", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_ApplicationUser_SocialNetworks", x => x.ApplicationUserId); + table.ForeignKey( + name: "FK_ApplicationUser_SocialNetworks_AspNetUsers_ApplicationUserId", + column: x => x.ApplicationUserId, + principalTable: "AspNetUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.Sql(@" + INSERT INTO ApplicationUser_SocialNetworks (ApplicationUserId, FacebookUrl, InstagramUrl, XUrl, LinkedInUrl, TikTokUrl, YoutubeUrl, RedditUrl, YourWebsiteUrl) + SELECT Id, '', '', '', '', '', '', '', '' + FROM AspNetUsers + "); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "ApplicationUser_SocialNetworks"); + } + } +} diff --git a/src/Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs b/src/Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs index cb3b55f..fcb6687 100644 --- a/src/Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs +++ b/src/Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs @@ -359,6 +359,57 @@ namespace Hutopy.Infrastructure.Migrations .IsRequired(); }); + modelBuilder.Entity("Hutopy.Infrastructure.Identity.ApplicationUser", b => + { + b.OwnsOne("Hutopy.Infrastructure.Identity.OwnedEntities.SocialNetworks", "SocialNetworks", b1 => + { + b1.Property("ApplicationUserId") + .HasColumnType("nvarchar(450)"); + + b1.Property("FacebookUrl") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.Property("InstagramUrl") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.Property("LinkedInUrl") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.Property("RedditUrl") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.Property("TikTokUrl") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.Property("XUrl") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.Property("YourWebsiteUrl") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.Property("YoutubeUrl") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.HasKey("ApplicationUserId"); + + b1.ToTable("ApplicationUser_SocialNetworks", (string)null); + + b1.WithOwner() + .HasForeignKey("ApplicationUserId"); + }); + + b.Navigation("SocialNetworks") + .IsRequired(); + }); + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => { b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) From 108d5424a48fe6b0becb3b39a80ce866f9c368b6 Mon Sep 17 00:00:00 2001 From: Dominic Villemure Date: Tue, 11 Jun 2024 20:20:51 -0400 Subject: [PATCH 059/229] #58 continue using Reflection to get configurations --- src/Infrastructure/Data/ApplicationDbContext.cs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/Infrastructure/Data/ApplicationDbContext.cs b/src/Infrastructure/Data/ApplicationDbContext.cs index 8b4676e..21b06a4 100644 --- a/src/Infrastructure/Data/ApplicationDbContext.cs +++ b/src/Infrastructure/Data/ApplicationDbContext.cs @@ -1,6 +1,6 @@ -using Hutopy.Application.Common.Interfaces; +using System.Reflection; +using Hutopy.Application.Common.Interfaces; using Hutopy.Domain.Entities; -using Hutopy.Infrastructure.Data.Configurations; using Hutopy.Infrastructure.Identity; using Microsoft.AspNetCore.Identity.EntityFrameworkCore; using Microsoft.EntityFrameworkCore; @@ -22,8 +22,7 @@ namespace Hutopy.Infrastructure.Data base.OnModelCreating(builder); // Apply configurations - builder.ApplyConfiguration(new UserTransactionConfiguration()); - builder.ApplyConfiguration(new ApplicationUserConfiguration()); + builder.ApplyConfigurationsFromAssembly(Assembly.GetExecutingAssembly()); } } } From d4c88d2f15eaa0b0b3de8a4cd340a3d44e16f8e2 Mon Sep 17 00:00:00 2001 From: Dominic Villemure Date: Sun, 16 Jun 2024 10:00:15 -0400 Subject: [PATCH 060/229] config for stripe api key --- src/Infrastructure/Stripe/StripeService.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Infrastructure/Stripe/StripeService.cs b/src/Infrastructure/Stripe/StripeService.cs index 061f9e2..7b78fff 100644 --- a/src/Infrastructure/Stripe/StripeService.cs +++ b/src/Infrastructure/Stripe/StripeService.cs @@ -4,6 +4,7 @@ using Hutopy.Application.Common.Interfaces; using Microsoft.AspNetCore.Http; using Hutopy.Application.Common.Models; using Hutopy.Application.Stripe.Commands; +using Microsoft.Extensions.Configuration; namespace Hutopy.Infrastructure.Stripe; @@ -11,10 +12,11 @@ public class StripeService : IStripeService { private readonly IHttpContextAccessor _httpContextAccessor; - public StripeService(IHttpContextAccessor httpContextAccessor) + public StripeService(IHttpContextAccessor httpContextAccessor, IConfiguration configuration) { _httpContextAccessor = httpContextAccessor; - StripeConfiguration.ApiKey = ""; + var stripeKey = configuration["STRIPE-API-KEY"] ?? ""; + StripeConfiguration.ApiKey = stripeKey; } public async Task CreateCheckoutSession(int amount, string creatorId, string currency = "cad") From 568a5c99ca314b82b67bbb7e6ca7c375271101de Mon Sep 17 00:00:00 2001 From: Dominic Villemure Date: Sun, 16 Jun 2024 11:00:40 -0400 Subject: [PATCH 061/229] oauth fixes to be able to use vault for env vars --- .../Identity/IdentityService.cs | 6 +++--- src/Web/Controllers/GoogleController.cs | 6 +++--- src/Web/DependencyInjection.cs | 14 ++++++------- src/Web/Endpoints/Users.cs | 1 - src/Web/appsettings.Development.dist | 20 +++++++------------ 5 files changed, 20 insertions(+), 27 deletions(-) diff --git a/src/Infrastructure/Identity/IdentityService.cs b/src/Infrastructure/Identity/IdentityService.cs index 0a25594..02b5ce0 100644 --- a/src/Infrastructure/Identity/IdentityService.cs +++ b/src/Infrastructure/Identity/IdentityService.cs @@ -221,9 +221,9 @@ public class IdentityService( var user = await GetUserByUserNameAsync(userName); var token = JwtTokenHelper.GenerateJwtToken( - issuer: configuration["Jwt:Issuer"] ?? "", - audience: configuration["Jwt:Audience"] ?? "", - key: configuration["Jwt:Key"] ?? "", + issuer: configuration["Jwt-Issuer"] ?? "", + audience: configuration["Jwt-Audience"] ?? "", + key: configuration["Jwt-Key"] ?? "", userId: user?.Id ?? ""); return token; diff --git a/src/Web/Controllers/GoogleController.cs b/src/Web/Controllers/GoogleController.cs index 49c57e2..6df233a 100644 --- a/src/Web/Controllers/GoogleController.cs +++ b/src/Web/Controllers/GoogleController.cs @@ -58,11 +58,11 @@ public class GoogleController(IIdentityService identityService, IHttpClientFacto var claimsIdentity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme); await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, new ClaimsPrincipal(claimsIdentity)); - var issuer = configuration["Jwt:Issuer"] ?? + var issuer = configuration["Jwt-Issuer"] ?? throw new ArgumentNullException("The Jwt issuer is missing."); - var audience = configuration["Jwt:Audience"] ?? + var audience = configuration["Jwt-Audience"] ?? throw new ArgumentNullException("The Jwt audience is missing."); - var key = configuration["Jwt:Key"] ?? + var key = configuration["Jwt-Key"] ?? throw new ArgumentNullException("The Jwt key is missing."); var jwtToken = JwtTokenHelper.GenerateJwtToken(issuer, audience, key, user.Id); diff --git a/src/Web/DependencyInjection.cs b/src/Web/DependencyInjection.cs index 402b870..3a7eb61 100644 --- a/src/Web/DependencyInjection.cs +++ b/src/Web/DependencyInjection.cs @@ -89,26 +89,26 @@ public static class DependencyInjection jwtBearerOptions.TokenValidationParameters = new TokenValidationParameters { ValidateIssuer = true, - ValidIssuer = configuration["Jwt:Issuer"], + ValidIssuer = configuration["Jwt-Issuer"], ValidateAudience = true, - ValidAudience = configuration["Jwt:Audience"], + ValidAudience = configuration["Jwt-Audience"], ValidateLifetime = true, - IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(configuration["Jwt:Key"] ?? + IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(configuration["Jwt-Key"] ?? throw new ArgumentNullException("The Jwt Key is missing."))) }; }) .AddGoogle(GoogleDefaults.AuthenticationScheme, options => { - options.ClientId = configuration["Google:ClientId"] ?? + options.ClientId = configuration["Google-ClientId"] ?? throw new ArgumentNullException("The Google ClientId is missing.");; - options.ClientSecret = configuration["Google:ClientSecret"] ?? + options.ClientSecret = configuration["Google-ClientSecret"] ?? throw new ArgumentNullException("The Google ClientSecret is missing.");; }) .AddFacebook(FacebookDefaults.AuthenticationScheme, options => { - options.ClientId = configuration["Facebook:ClientId"] ?? + options.ClientId = configuration["Facebook-ClientId"] ?? throw new ArgumentNullException("The Facebook ClientId is missing."); - options.ClientSecret = configuration["Facebook:ClientSecret"] ?? + options.ClientSecret = configuration["Facebook-ClientSecret"] ?? throw new ArgumentNullException("The Facebook ClientSecret is missing."); }); diff --git a/src/Web/Endpoints/Users.cs b/src/Web/Endpoints/Users.cs index 2c4f403..39f784a 100644 --- a/src/Web/Endpoints/Users.cs +++ b/src/Web/Endpoints/Users.cs @@ -1,6 +1,5 @@ using Hutopy.Application.Users.Commands; using Hutopy.Application.Users.Queries.GetMinimalUser; -using Hutopy.Infrastructure.Identity; namespace Hutopy.Web.Endpoints; diff --git a/src/Web/appsettings.Development.dist b/src/Web/appsettings.Development.dist index d25bfda..25369fa 100644 --- a/src/Web/appsettings.Development.dist +++ b/src/Web/appsettings.Development.dist @@ -7,17 +7,11 @@ "Microsoft.Hosting.Lifetime": "Information" } }, - "Google": { - "ClientId": "", - "ClientSecret": "" - }, - "Facebook": { - "ClientId": "", - "ClientSecret": "" - }, - "Jwt": { - "Issuer": "", - "Audience": "", - "Key": "" - } + "Google-ClientId": "", + "Google-ClientSecret": "", + "Facebook-ClientId": "", + "Facebook-ClientSecret": "", + "Jwt-Audience": "", + "Jwt-Issuer": "", + "Jwt-Key": "", } \ No newline at end of file From ab88511f222a1d11c13351231842c67a7c115028 Mon Sep 17 00:00:00 2001 From: Dominic Villemure Date: Sun, 23 Jun 2024 20:24:15 -0400 Subject: [PATCH 062/229] #67 added blob storage service + endpoints for profile picture. WIP --- Directory.Packages.props | 1 + .../Constants/CommonFileNames.cs | 6 + .../Constants/ContainerNames.cs | 6 + .../Constants/SubDirectoryNames.cs | 7 + .../Interfaces/IAzureBlobStorageService.cs | 7 + .../Users/Commands/UploadProfilePicture.cs | 25 ++++ .../GetCurrentUserProfilePicture.cs | 23 +++ .../Users/Queries/GetCurrentUser/UserDto.cs | 1 - .../AzureBlob/AzureBlobStorageService.cs | 74 ++++++++++ .../AzureBlob/BlobStructure.txt | 33 +++++ src/Infrastructure/DependencyInjection.cs | 7 + src/Infrastructure/Infrastructure.csproj | 1 + src/Web/Endpoints/GetMyUser.cs | 8 +- src/Web/Endpoints/Users.cs | 10 ++ src/Web/wwwroot/api/specification.json | 131 ++++++++++++++++++ 15 files changed, 338 insertions(+), 2 deletions(-) create mode 100644 src/Application/AzureBlobStorage/Constants/CommonFileNames.cs create mode 100644 src/Application/AzureBlobStorage/Constants/ContainerNames.cs create mode 100644 src/Application/AzureBlobStorage/Constants/SubDirectoryNames.cs create mode 100644 src/Application/Common/Interfaces/IAzureBlobStorageService.cs create mode 100644 src/Application/Users/Commands/UploadProfilePicture.cs create mode 100644 src/Application/Users/Queries/GetCurrentUser/GetCurrentUserProfilePicture.cs create mode 100644 src/Infrastructure/AzureBlob/AzureBlobStorageService.cs create mode 100644 src/Infrastructure/AzureBlob/BlobStructure.txt diff --git a/Directory.Packages.props b/Directory.Packages.props index f4732ee..a2b4869 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -8,6 +8,7 @@ + diff --git a/src/Application/AzureBlobStorage/Constants/CommonFileNames.cs b/src/Application/AzureBlobStorage/Constants/CommonFileNames.cs new file mode 100644 index 0000000..7eabb9a --- /dev/null +++ b/src/Application/AzureBlobStorage/Constants/CommonFileNames.cs @@ -0,0 +1,6 @@ +namespace Hutopy.Application.AzureBlobStorage.Constants; + +public static class CommonFileNames +{ + public static string ProfilePicture = "profilePicture"; +} diff --git a/src/Application/AzureBlobStorage/Constants/ContainerNames.cs b/src/Application/AzureBlobStorage/Constants/ContainerNames.cs new file mode 100644 index 0000000..5bab776 --- /dev/null +++ b/src/Application/AzureBlobStorage/Constants/ContainerNames.cs @@ -0,0 +1,6 @@ +namespace Hutopy.Application.AzureBlobStorage.Constants; + +public static class ContainerNames +{ + public static string Users = "users"; +} diff --git a/src/Application/AzureBlobStorage/Constants/SubDirectoryNames.cs b/src/Application/AzureBlobStorage/Constants/SubDirectoryNames.cs new file mode 100644 index 0000000..6ee43ea --- /dev/null +++ b/src/Application/AzureBlobStorage/Constants/SubDirectoryNames.cs @@ -0,0 +1,7 @@ +namespace Hutopy.Application.AzureBlobStorage.Constants; + +public static class SubDirectoryNames +{ + public static string Profile = "profile"; + public static string Posts = "posts"; +} diff --git a/src/Application/Common/Interfaces/IAzureBlobStorageService.cs b/src/Application/Common/Interfaces/IAzureBlobStorageService.cs new file mode 100644 index 0000000..c8bdd20 --- /dev/null +++ b/src/Application/Common/Interfaces/IAzureBlobStorageService.cs @@ -0,0 +1,7 @@ +namespace Hutopy.Application.Common.Interfaces; + +public interface IAzureBlobStorageService +{ + Task UploadFileAsync(string containerName, string blobName, Stream fileStream); + Task DownloadFileAsync(string containerName, string blobName); +} diff --git a/src/Application/Users/Commands/UploadProfilePicture.cs b/src/Application/Users/Commands/UploadProfilePicture.cs new file mode 100644 index 0000000..08746d9 --- /dev/null +++ b/src/Application/Users/Commands/UploadProfilePicture.cs @@ -0,0 +1,25 @@ +using Hutopy.Application.AzureBlobStorage.Constants; +using Hutopy.Application.Common.Interfaces; + +namespace Hutopy.Application.Users.Commands; + +public class UploadProfilePictureCommand : IRequest +{ + public required Stream ProfilePicture { get; init; } +} + +public class UploadProfilePictureCommandHandler(IIdentityService identityService, IAzureBlobStorageService azureBlobStorageService) : IRequestHandler +{ + public async Task Handle(UploadProfilePictureCommand request, CancellationToken cancellationToken) + { + var identityUser = await identityService.GetCurrentUserAsync(); + var currentUserId = new Guid(identityUser?.Id ?? "").ToString(); + + var blobName = $"{currentUserId}/{SubDirectoryNames.Profile}/{CommonFileNames.ProfilePicture}"; + + var url = await azureBlobStorageService.UploadFileAsync(ContainerNames.Users, blobName, request.ProfilePicture); + + return url; + } +} + diff --git a/src/Application/Users/Queries/GetCurrentUser/GetCurrentUserProfilePicture.cs b/src/Application/Users/Queries/GetCurrentUser/GetCurrentUserProfilePicture.cs new file mode 100644 index 0000000..cb4e6b4 --- /dev/null +++ b/src/Application/Users/Queries/GetCurrentUser/GetCurrentUserProfilePicture.cs @@ -0,0 +1,23 @@ +using Hutopy.Application.AzureBlobStorage.Constants; +using Hutopy.Application.Common.Interfaces; + +namespace Hutopy.Application.Users.Queries.GetCurrentUser; + +public record GetCurrentUserProfilePictureQuery : IRequest; + +public class GetCurrentUserProfilePictureQueryHandler( + IIdentityService identityService, + IAzureBlobStorageService azureBlobStorageService + ) + : IRequestHandler +{ + public async Task Handle(GetCurrentUserProfilePictureQuery request, CancellationToken cancellationToken) + { + var identityUser = await identityService.GetCurrentUserAsync(); + var currentUserId = new Guid(identityUser?.Id ?? ""); + + var blobName = $"{currentUserId.ToString()}/{SubDirectoryNames.Profile}/{CommonFileNames.ProfilePicture}"; + + return await azureBlobStorageService.DownloadFileAsync(ContainerNames.Users, blobName); + } +} diff --git a/src/Application/Users/Queries/GetCurrentUser/UserDto.cs b/src/Application/Users/Queries/GetCurrentUser/UserDto.cs index 0e2af25..c7d121d 100644 --- a/src/Application/Users/Queries/GetCurrentUser/UserDto.cs +++ b/src/Application/Users/Queries/GetCurrentUser/UserDto.cs @@ -8,7 +8,6 @@ public class UserDto public string UserName { get; init; } = String.Empty; public List UserTransactions { get; init; } = []; public IList UserRoles { get; init; } = []; - public required decimal TotalBalance { get; init; } } diff --git a/src/Infrastructure/AzureBlob/AzureBlobStorageService.cs b/src/Infrastructure/AzureBlob/AzureBlobStorageService.cs new file mode 100644 index 0000000..f54f96b --- /dev/null +++ b/src/Infrastructure/AzureBlob/AzureBlobStorageService.cs @@ -0,0 +1,74 @@ +using Azure.Storage.Blobs; +using Azure.Storage.Blobs.Models; +using Hutopy.Application.Common.Interfaces; +using Microsoft.Extensions.Configuration; + +namespace Hutopy.Infrastructure.AzureBlob; + +public class AzureBlobStorageService : IAzureBlobStorageService +{ + private readonly BlobServiceClient _blobServiceClient; + + public AzureBlobStorageService(IConfiguration configuration) + { + var connectionString = configuration["Azure-Blob-Connection-String"] ?? ""; + _blobServiceClient = new BlobServiceClient(connectionString); + + } + + /// + /// Upload a file to microsoft azure blob storage. + /// + /// The blob name (path within the container, include the file name). + /// The name of the container where the file is stored. + /// The stream. + /// + public async Task UploadFileAsync(string containerName, string blobName, Stream fileStream) + { + // Get a reference to a container + var containerClient = _blobServiceClient.GetBlobContainerClient(containerName); + + // Create the container if it does not exist + await containerClient.CreateIfNotExistsAsync(); + + // Get a reference to a blob + var blobClient = containerClient.GetBlobClient(blobName); + + // Upload the file + await blobClient.UploadAsync(fileStream, true); + + // Return the URI of the uploaded blob + return blobClient.Uri.ToString(); + } + + /// + /// Download a file to microsoft azure blob storage. + /// + /// The blob name (path within the container). + /// The name of the container where the file is stored. (users) + /// + public async Task DownloadFileAsync(string containerName, string blobName) + { + // Get a reference to a container + var containerClient = _blobServiceClient.GetBlobContainerClient(containerName); + + // Get a reference to a blob + var blobClient = containerClient.GetBlobClient(blobName); + + try + { + // Download the blob to a stream + BlobDownloadInfo download = await blobClient.DownloadAsync(); + MemoryStream memoryStream = new(); + await download.Content.CopyToAsync(memoryStream); + memoryStream.Position = 0; // Ensure the stream is at the beginning + + return memoryStream; + } + catch (Exception ex) + { + // Log and handle the exception as needed + throw new ApplicationException("Error downloading file from Azure Blob Storage.", ex); + } + } +} diff --git a/src/Infrastructure/AzureBlob/BlobStructure.txt b/src/Infrastructure/AzureBlob/BlobStructure.txt new file mode 100644 index 0000000..5410c95 --- /dev/null +++ b/src/Infrastructure/AzureBlob/BlobStructure.txt @@ -0,0 +1,33 @@ +users/ +│ +├── userId1/ +│ ├── profile/ +│ │ └── profilePicture.jpg +│ │ └── data.json +│ │ +│ ├── posts/ +│ │ ├── post1/ +│ │ │ ├── image1.jpg +│ │ │ ├── video1.mp4 +│ │ │ └── audio1.mp3 +│ │ ├── post2/ +│ │ │ ├── image2.jpg +│ │ │ └── video2.mp4 +│ │ └── ... +│ +├── userId2/ +│ ├── profile/ +│ │ └── profilePicture.jpg +│ │ └── data.json +│ │ +│ ├── posts/ +│ │ ├── post1/ +│ │ │ ├── image1.jpg +│ │ │ ├── video1.mp4 +│ │ │ └── audio1.mp3 +│ │ ├── post2/ +│ │ │ ├── image2.jpg +│ │ │ └── video2.mp4 +│ │ └── ... +│ +└── ... diff --git a/src/Infrastructure/DependencyInjection.cs b/src/Infrastructure/DependencyInjection.cs index 42ca0c3..e03ce4c 100644 --- a/src/Infrastructure/DependencyInjection.cs +++ b/src/Infrastructure/DependencyInjection.cs @@ -1,5 +1,6 @@ using Hutopy.Application.Common.Interfaces; using Hutopy.Domain.Constants; +using Hutopy.Infrastructure.AzureBlob; using Hutopy.Infrastructure.Data; using Hutopy.Infrastructure.Data.Interceptors; using Hutopy.Infrastructure.Identity; @@ -63,8 +64,14 @@ public static class DependencyInjection .AddSignInManager>() .AddDefaultTokenProviders(); + // Singleton services services.AddSingleton(TimeProvider.System); + services.AddSingleton(); + + // Scoped services services.AddScoped(); + + // Transient services services.AddTransient(); services.AddAuthorization(options => diff --git a/src/Infrastructure/Infrastructure.csproj b/src/Infrastructure/Infrastructure.csproj index 108c958..dd3cb64 100644 --- a/src/Infrastructure/Infrastructure.csproj +++ b/src/Infrastructure/Infrastructure.csproj @@ -4,6 +4,7 @@ Hutopy.Infrastructure + diff --git a/src/Web/Endpoints/GetMyUser.cs b/src/Web/Endpoints/GetMyUser.cs index feb5b50..444cbe9 100644 --- a/src/Web/Endpoints/GetMyUser.cs +++ b/src/Web/Endpoints/GetMyUser.cs @@ -9,11 +9,17 @@ public class GetMyUser : EndpointGroupBase { app.MapGroup(this) .RequireAuthorization() - .MapGet(GetCurrentUser); + .MapGet(GetCurrentUser) + .MapGet(GetCurrentUserProfilePicture, "profile-picture"); } private static async Task GetCurrentUser(ISender sender, [AsParameters] GetCurrentUserQuery query) { return await sender.Send(query); } + + private static async Task GetCurrentUserProfilePicture(ISender sender, [AsParameters] GetCurrentUserProfilePictureQuery query) + { + return await sender.Send(query); + } } diff --git a/src/Web/Endpoints/Users.cs b/src/Web/Endpoints/Users.cs index 39f784a..b2a15c5 100644 --- a/src/Web/Endpoints/Users.cs +++ b/src/Web/Endpoints/Users.cs @@ -10,6 +10,7 @@ public class Users : EndpointGroupBase app.MapGroup(this) .MapPost(CreateUser) .MapPost(Login, "/login") + .MapPost(UploadProfilePicture, "/upload-profile-picture") .MapGet(GetMinimalUser); } @@ -27,4 +28,13 @@ public class Users : EndpointGroupBase { return await sender.Send(command); } + + private static async Task UploadProfilePicture(ISender sender, Stream stream) + { + var command = new UploadProfilePictureCommand + { + ProfilePicture = stream + }; + return await sender.Send(command); + } } diff --git a/src/Web/wwwroot/api/specification.json b/src/Web/wwwroot/api/specification.json index 93ac3dc..bf1f109 100644 --- a/src/Web/wwwroot/api/specification.json +++ b/src/Web/wwwroot/api/specification.json @@ -31,6 +31,56 @@ ] } }, + "/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": [ @@ -313,6 +363,40 @@ } } }, + "/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": [ @@ -448,6 +532,53 @@ } } }, + "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, From 73b43c80cb6699ef972f43988d2dcb6cbcb7d46b Mon Sep 17 00:00:00 2001 From: Jonathan Bourdon Date: Thu, 20 Jun 2024 13:40:27 -0400 Subject: [PATCH 063/229] Cleanup of appsettings files --- src/Web/appsettings.Development.dist | 17 ----------------- src/Web/appsettings.json | 3 --- 2 files changed, 20 deletions(-) delete mode 100644 src/Web/appsettings.Development.dist diff --git a/src/Web/appsettings.Development.dist b/src/Web/appsettings.Development.dist deleted file mode 100644 index 25369fa..0000000 --- a/src/Web/appsettings.Development.dist +++ /dev/null @@ -1,17 +0,0 @@ -{ - "Logging": { - "LogLevel": { - "Default": "Information", - "Microsoft": "Information", - "Microsoft.AspNetCore.SpaProxy": "Information", - "Microsoft.Hosting.Lifetime": "Information" - } - }, - "Google-ClientId": "", - "Google-ClientSecret": "", - "Facebook-ClientId": "", - "Facebook-ClientSecret": "", - "Jwt-Audience": "", - "Jwt-Issuer": "", - "Jwt-Key": "", -} \ No newline at end of file diff --git a/src/Web/appsettings.json b/src/Web/appsettings.json index 76a510b..222224e 100644 --- a/src/Web/appsettings.json +++ b/src/Web/appsettings.json @@ -1,7 +1,4 @@ { - "ConnectionStrings": { - "DefaultConnection": "Server={DB_HOST},1433;Database=Hutopy;User Id=sa;Password={DB_PASSWORD};MultipleActiveResultSets=true;TrustServerCertificate=True" - }, "Logging": { "LogLevel": { "Default": "Information", From 9a360dc407bc4fdb3e5e1b6c4baa980c940b2676 Mon Sep 17 00:00:00 2001 From: Jonathan Bourdon Date: Thu, 20 Jun 2024 13:40:55 -0400 Subject: [PATCH 064/229] Fix issue with missing configuration for Facebook or Google --- .../Identity/IdentityService.cs | 11 ++- src/Web/DependencyInjection.cs | 74 ++++++++++++------- 2 files changed, 54 insertions(+), 31 deletions(-) diff --git a/src/Infrastructure/Identity/IdentityService.cs b/src/Infrastructure/Identity/IdentityService.cs index 02b5ce0..9997316 100644 --- a/src/Infrastructure/Identity/IdentityService.cs +++ b/src/Infrastructure/Identity/IdentityService.cs @@ -218,12 +218,15 @@ public class IdentityService( { return null; } - + var user = await GetUserByUserNameAsync(userName); + + var jwtSection = configuration.GetRequiredSection("Authentication:Jwt"); + var token = JwtTokenHelper.GenerateJwtToken( - issuer: configuration["Jwt-Issuer"] ?? "", - audience: configuration["Jwt-Audience"] ?? "", - key: configuration["Jwt-Key"] ?? "", + issuer: jwtSection["Issuer"] ?? "", + audience: jwtSection["Audience"] ?? "", + key: jwtSection["Key"] ?? "", userId: user?.Id ?? ""); return token; diff --git a/src/Web/DependencyInjection.cs b/src/Web/DependencyInjection.cs index 3a7eb61..27f1ac1 100644 --- a/src/Web/DependencyInjection.cs +++ b/src/Web/DependencyInjection.cs @@ -30,7 +30,7 @@ public static class DependencyInjection services.AddExceptionHandler(); services.AddRazorPages(); - + services.AddHttpClient(); // Customise default API behaviour @@ -44,13 +44,16 @@ public static class DependencyInjection configure.Title = "Hutopy API"; // Add JWT - configure.AddSecurity("JWT", Enumerable.Empty(), new OpenApiSecurityScheme - { - Type = OpenApiSecuritySchemeType.ApiKey, - Name = "Authorization", - In = OpenApiSecurityApiKeyLocation.Header, - Description = "Type into the textbox: Bearer {your JWT token}." - }); + 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")); }); @@ -58,7 +61,8 @@ public static class DependencyInjection return services; } - public static IServiceCollection AddKeyVaultIfConfigured(this IServiceCollection services, ConfigurationManager configuration) + public static IServiceCollection AddKeyVaultIfConfigured(this IServiceCollection services, + ConfigurationManager configuration) { var keyVaultUri = configuration["KeyVaultUri"]; if (!string.IsNullOrWhiteSpace(keyVaultUri)) @@ -70,10 +74,11 @@ public static class DependencyInjection return services; } - - public static IServiceCollection AddAuthorizationAndAuthentication(this IServiceCollection services, ConfigurationManager configuration) + + public static IServiceCollection AddAuthorizationAndAuthentication(this IServiceCollection services, + ConfigurationManager configuration) { - services.AddAuthentication(options => + var authenticationBuilder = services.AddAuthentication(options => { options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme; options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme; @@ -82,35 +87,50 @@ public static class DependencyInjection { options.LoginPath = "/api/Users/login"; }) - .AddCookie() - .AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, jwtBearerOptions => + .AddCookie(); + + var authJwt = configuration.GetSection("Authentication:Jwt"); + if (authJwt.Exists()) + { + authenticationBuilder.AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, jwtBearerOptions => { jwtBearerOptions.Authority = "https://hutopy.com"; jwtBearerOptions.TokenValidationParameters = new TokenValidationParameters { ValidateIssuer = true, - ValidIssuer = configuration["Jwt-Issuer"], + ValidIssuer = authJwt["Issuer"], ValidateAudience = true, - ValidAudience = configuration["Jwt-Audience"], + ValidAudience = authJwt["Audience"], ValidateLifetime = true, - IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(configuration["Jwt-Key"] ?? + IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(authJwt["Key"] ?? throw new ArgumentNullException("The Jwt Key is missing."))) }; - }) - .AddGoogle(GoogleDefaults.AuthenticationScheme, options => + }); + } + + var authGoogle = configuration.GetSection("Authentication:Google"); + if (authGoogle.Exists()) + { + authenticationBuilder.AddGoogle(GoogleDefaults.AuthenticationScheme, options => { - options.ClientId = configuration["Google-ClientId"] ?? - throw new ArgumentNullException("The Google ClientId is missing.");; - options.ClientSecret = configuration["Google-ClientSecret"] ?? - throw new ArgumentNullException("The Google ClientSecret is missing.");; - }) - .AddFacebook(FacebookDefaults.AuthenticationScheme, options => + options.ClientId = authGoogle["ClientId"] ?? + throw new ArgumentNullException("The Google ClientId is missing."); + options.ClientSecret = authGoogle["ClientSecret"] ?? + throw new ArgumentNullException("The Google ClientSecret is missing."); + }); + } + + var authFacebook = configuration.GetSection("Authentication:Facebook"); + if (authFacebook.Exists()) + { + authenticationBuilder.AddFacebook(FacebookDefaults.AuthenticationScheme, options => { - options.ClientId = configuration["Facebook-ClientId"] ?? + options.ClientId = authFacebook["ClientId"] ?? throw new ArgumentNullException("The Facebook ClientId is missing."); - options.ClientSecret = configuration["Facebook-ClientSecret"] ?? + options.ClientSecret = authFacebook["ClientSecret"] ?? throw new ArgumentNullException("The Facebook ClientSecret is missing."); }); + } return services; } From 6307ea45e58195f3d8a86cf5daa17a01130ac487 Mon Sep 17 00:00:00 2001 From: Jonathan Bourdon Date: Thu, 20 Jun 2024 13:44:45 -0400 Subject: [PATCH 065/229] Just cleanup --- .../Queries/GetCurrentUser/GetCurrentUser.cs | 8 +-- src/Infrastructure/Utils/GenerateJwtToken.cs | 14 ++--- src/Web/Controllers/FacebookController.cs | 44 ++++++++------- src/Web/Controllers/GoogleController.cs | 56 ++++++++++--------- 4 files changed, 63 insertions(+), 59 deletions(-) diff --git a/src/Application/Users/Queries/GetCurrentUser/GetCurrentUser.cs b/src/Application/Users/Queries/GetCurrentUser/GetCurrentUser.cs index 49f1152..7cbabd6 100644 --- a/src/Application/Users/Queries/GetCurrentUser/GetCurrentUser.cs +++ b/src/Application/Users/Queries/GetCurrentUser/GetCurrentUser.cs @@ -8,14 +8,14 @@ public class GetCurrentUserQueryHandler( IApplicationDbContext context, IMapper mapper, IIdentityService identityService - ) +) : IRequestHandler { public async Task Handle(GetCurrentUserQuery request, CancellationToken cancellationToken) { var identityUser = await identityService.GetCurrentUserAsync(); - var currentUserId = new Guid(identityUser?.Id ?? ""); - + var currentUserId = Guid.Parse(identityUser!.Id!); + var transactions = await context.UserTransactions .Where(x => x.ApplicationUserId == currentUserId.ToString()) .OrderBy(x => x.LastModified) @@ -30,7 +30,7 @@ public class GetCurrentUserQueryHandler( Id = currentUserId, FirstName = identityUser?.FirstName ?? "", LastName = identityUser?.LastName ?? "", - UserName =identityUser?.UserName ?? "", + UserName = identityUser?.UserName ?? "", UserTransactions = transactions, TotalBalance = transactions.Sum(x => x.Amount), UserRoles = roles diff --git a/src/Infrastructure/Utils/GenerateJwtToken.cs b/src/Infrastructure/Utils/GenerateJwtToken.cs index 9f01d6a..00423f9 100644 --- a/src/Infrastructure/Utils/GenerateJwtToken.cs +++ b/src/Infrastructure/Utils/GenerateJwtToken.cs @@ -9,20 +9,18 @@ public static class JwtTokenHelper { public static string GenerateJwtToken(string issuer, string audience, string key, string userId) { - var claims = new[] - { - new Claim(JwtRegisteredClaimNames.Sub, userId), - new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()), - new Claim(ClaimTypes.NameIdentifier, userId) - }; - var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(key)); var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256); var token = new JwtSecurityToken( issuer: issuer, audience: audience, - claims: claims, + claims: new[] + { + new Claim(JwtRegisteredClaimNames.Sub, userId), + new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()), + new Claim(ClaimTypes.NameIdentifier, userId) + }, expires: DateTime.Now.AddMinutes(30), signingCredentials: credentials); diff --git a/src/Web/Controllers/FacebookController.cs b/src/Web/Controllers/FacebookController.cs index 679502e..3178b5f 100644 --- a/src/Web/Controllers/FacebookController.cs +++ b/src/Web/Controllers/FacebookController.cs @@ -13,41 +13,45 @@ public class FacebookController(IIdentityService identityService) : Controller [HttpGet("/api/facebook/sign-in")] public async Task SignIn() { - await HttpContext.ChallengeAsync(FacebookDefaults.AuthenticationScheme, new AuthenticationProperties - { - RedirectUri = Url.Action("Authorize") - }); + await HttpContext.ChallengeAsync(FacebookDefaults.AuthenticationScheme, + new AuthenticationProperties { RedirectUri = Url.Action("Authorize") }); } public async Task Authorize() { var authenticateResult = await HttpContext.AuthenticateAsync(FacebookDefaults.AuthenticationScheme); - + if (!authenticateResult.Succeeded) return BadRequest(); - + var claims = authenticateResult.Principal.Claims.ToList(); - + var name = claims.FirstOrDefault(c => c.Type == ClaimTypes.Name)?.Value ?? ""; var email = claims.FirstOrDefault(c => c.Type == ClaimTypes.Email)?.Value ?? ""; var givenName = claims.FirstOrDefault(c => c.Type == ClaimTypes.GivenName)?.Value ?? ""; var familyName = claims.FirstOrDefault(c => c.Type == ClaimTypes.Surname)?.Value ?? ""; - - var claimsIdentity = new ClaimsIdentity(new List - { - new(ClaimTypes.Name, name), - new(ClaimTypes.Email, email), - new(ClaimTypes.GivenName, givenName), - new(ClaimTypes.Surname, familyName) - }, CookieAuthenticationDefaults.AuthenticationScheme); - + + var claimsIdentity = new ClaimsIdentity( + new List + { + new(ClaimTypes.Name, name), + new(ClaimTypes.Email, email), + new(ClaimTypes.GivenName, givenName), + new(ClaimTypes.Surname, familyName) + }, + CookieAuthenticationDefaults.AuthenticationScheme); + if (await identityService.FindUserByEmailAsync(email) != null) { - await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, new ClaimsPrincipal(claimsIdentity)); + await HttpContext.SignInAsync( + CookieAuthenticationDefaults.AuthenticationScheme, + new ClaimsPrincipal(claimsIdentity)); return Redirect("/"); } - - await identityService.CreateUserAsync(email, givenName, givenName, familyName, RandomGenerator.RandomString(24)); - await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, new ClaimsPrincipal(claimsIdentity)); + + await identityService.CreateUserAsync(email, givenName, givenName, familyName, + RandomGenerator.RandomString(24)); + await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, + new ClaimsPrincipal(claimsIdentity)); return Redirect("/"); } } diff --git a/src/Web/Controllers/GoogleController.cs b/src/Web/Controllers/GoogleController.cs index 6df233a..40e8adc 100644 --- a/src/Web/Controllers/GoogleController.cs +++ b/src/Web/Controllers/GoogleController.cs @@ -13,7 +13,8 @@ public class GoogleController(IIdentityService identityService, IHttpClientFacto [HttpPost("/api/google/sign-in")] public async Task SignIn([FromBody] GoogleSignInRequest request) { - var httpClient = httpClientFactory.CreateClient(); + using var httpClient = httpClientFactory.CreateClient(); + // Verify the token with Google var response = await httpClient.GetAsync($"https://www.googleapis.com/oauth2/v1/userinfo?access_token={request.AccessToken}"); if (!response.IsSuccessStatusCode) @@ -21,12 +22,11 @@ public class GoogleController(IIdentityService identityService, IHttpClientFacto return BadRequest("Invalid Google token."); } - var payload = JObject.Parse(await response.Content.ReadAsStringAsync()); - - var email = payload["email"]?.ToString() ?? ""; - var name = payload["name"]?.ToString() ?? ""; - var givenName = payload["given_name"]?.ToString() ?? ""; - var familyName = payload["family_name"]?.ToString() ?? ""; + var userInfo = JObject.Parse(await response.Content.ReadAsStringAsync()); + var email = userInfo["email"]?.ToString() ?? ""; + var name = userInfo["name"]?.ToString() ?? ""; + var givenName = userInfo["given_name"]?.ToString() ?? ""; + var familyName = userInfo["family_name"]?.ToString() ?? ""; if (string.IsNullOrEmpty(email)) { @@ -47,27 +47,29 @@ public class GoogleController(IIdentityService identityService, IHttpClientFacto } // Sign in the user - var claims = new List - { - new(ClaimTypes.Name, name), - new(ClaimTypes.Email, email), - new(ClaimTypes.GivenName, givenName), - new(ClaimTypes.Surname, familyName) - }; - - var claimsIdentity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme); - await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, new ClaimsPrincipal(claimsIdentity)); - - var issuer = configuration["Jwt-Issuer"] ?? - throw new ArgumentNullException("The Jwt issuer is missing."); - var audience = configuration["Jwt-Audience"] ?? - throw new ArgumentNullException("The Jwt audience is missing."); - var key = configuration["Jwt-Key"] ?? - throw new ArgumentNullException("The Jwt key is missing."); - - var jwtToken = JwtTokenHelper.GenerateJwtToken(issuer, audience, key, user.Id); + var claimsIdentity = new ClaimsIdentity( + new List + { + new(ClaimTypes.Name, name), + new(ClaimTypes.Email, email), + new(ClaimTypes.GivenName, givenName), + new(ClaimTypes.Surname, familyName) + }, + CookieAuthenticationDefaults.AuthenticationScheme); - return Ok(new { accessToken = jwtToken, email }); + await HttpContext.SignInAsync( + CookieAuthenticationDefaults.AuthenticationScheme, + new ClaimsPrincipal(claimsIdentity)); + + var jwtSection = configuration.GetRequiredSection("Authentication:Jwt"); + + var token = JwtTokenHelper.GenerateJwtToken( + issuer: jwtSection["Issuer"] ?? throw new ArgumentNullException("The Jwt issuer is missing."), + audience: jwtSection["Audience"] ?? throw new ArgumentNullException("The Jwt audience is missing."), + key: jwtSection["Key"] ?? throw new ArgumentNullException("The Jwt key is missing."), + userId: user.Id); + + return Ok(new { accessToken = token, email }); } public class GoogleSignInRequest From 310cfdfeb991f0cea83867d581dab06704389dfd Mon Sep 17 00:00:00 2001 From: Jonathan Bourdon Date: Thu, 20 Jun 2024 13:46:00 -0400 Subject: [PATCH 066/229] Fix some endpoints in web.http --- src/Web/Web.http | 114 ++++------------------------------- src/Web/http-client.env.json | 5 ++ 2 files changed, 17 insertions(+), 102 deletions(-) create mode 100644 src/Web/http-client.env.json diff --git a/src/Web/Web.http b/src/Web/Web.http index 105a254..c0ac5aa 100644 --- a/src/Web/Web.http +++ b/src/Web/Web.http @@ -1,12 +1,10 @@ # For more info on HTTP files go to https://aka.ms/vs/httpfile -@Web_HostAddress = https://localhost:5001 - @Email=administrator@localhost @Password=Administrator1! -@BearerToken= +@auth_token= # POST Users Register -POST {{Web_HostAddress}}/api/Users/Register +POST {{base_url}}/api/Users/Register Content-Type: application/json { @@ -17,7 +15,7 @@ Content-Type: application/json ### # POST Users Login -POST {{Web_HostAddress}}/api/Users/Login +POST {{base_url}}/api/Users/login Content-Type: application/json { @@ -25,11 +23,13 @@ Content-Type: application/json "password": "{{Password}}" } +> {% client.global.set("auth_token", response.body); %} + ### # POST Users Refresh -POST {{Web_HostAddress}}/api/Users/Refresh -Authorization: Bearer {{BearerToken}} +POST {{base_url}}/api/Users/Refresh +Authorization: Bearer {{auth_token}} Content-Type: application/json { @@ -39,101 +39,11 @@ Content-Type: application/json ### # GET WeatherForecast -GET {{Web_HostAddress}}/api/WeatherForecasts -Authorization: Bearer {{BearerToken}} +GET {{base_url}}/api/WeatherForecasts +Authorization: Bearer {{auth_token}} ### -# GET TodoLists -GET {{Web_HostAddress}}/api/TodoLists -Authorization: Bearer {{BearerToken}} - -### - -# POST TodoLists -POST {{Web_HostAddress}}/api/TodoLists -Authorization: Bearer {{BearerToken}} -Content-Type: application/json - -// CreateTodoListCommand -{ - "Title": "Backlog" -} - -### - -# PUT TodoLists -PUT {{Web_HostAddress}}/api/TodoLists/1 -Authorization: Bearer {{BearerToken}} -Content-Type: application/json - -// UpdateTodoListCommand -{ - "Id": 1, - "Title": "Product Backlog" -} - -### - -# DELETE TodoLists -DELETE {{Web_HostAddress}}/api/TodoLists/1 -Authorization: Bearer {{BearerToken}} - -### - -# GET TodoItems -@PageNumber = 1 -@PageSize = 10 -GET {{Web_HostAddress}}/api/TodoItems?ListId=1&PageNumber={{PageNumber}}&PageSize={{PageSize}} - -Authorization: Bearer {{BearerToken}} - -### - -# POST TodoItems -POST {{Web_HostAddress}}/api/TodoItems -Authorization: Bearer {{BearerToken}} -Content-Type: application/json - -// CreateTodoItemCommand -{ - "ListId": 1, - "Title": "Eat a burrito 🌯" -} - -### - -#PUT TodoItems UpdateItemDetails -PUT {{Web_HostAddress}}/api/TodoItems/UpdateItemDetails?Id=1 -Authorization: Bearer {{BearerToken}} -Content-Type: application/json - -// UpdateTodoItemDetailCommand -{ - "Id": 1, - "ListId": 1, - "Priority": 3, - "Note": "This is a good idea!" -} - -### - -# PUT TodoItems -PUT {{Web_HostAddress}}/api/TodoItems/1 -Authorization: Bearer {{BearerToken}} -Content-Type: application/json - -// UpdateTodoItemCommand -{ - "Id": 1, - "Title": "Eat a yummy burrito 🌯", - "Done": true -} - -### - -# DELETE TodoItem -DELETE {{Web_HostAddress}}/api/TodoItems/1 -Authorization: Bearer {{BearerToken}} - -### \ No newline at end of file +# GET GetMyUser +GET {{base_url}}/api/GetMyUser +Authorization: Bearer {{auth_token}} \ No newline at end of file diff --git a/src/Web/http-client.env.json b/src/Web/http-client.env.json new file mode 100644 index 0000000..4af4838 --- /dev/null +++ b/src/Web/http-client.env.json @@ -0,0 +1,5 @@ +{ + "dev": { + "base_url": "https://localhost:5001" + } +} \ No newline at end of file From 499a9450369342c9c31cb530974b0f3e9257ae8c Mon Sep 17 00:00:00 2001 From: Jonathan Bourdon Date: Thu, 20 Jun 2024 13:46:53 -0400 Subject: [PATCH 067/229] Fix login --- src/Application/Users/Commands/Login.cs | 36 ++++++++++++------------- src/Web/Endpoints/Users.cs | 2 +- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/Application/Users/Commands/Login.cs b/src/Application/Users/Commands/Login.cs index f61f810..8f232b5 100644 --- a/src/Application/Users/Commands/Login.cs +++ b/src/Application/Users/Commands/Login.cs @@ -1,27 +1,27 @@ using Hutopy.Application.Common.Interfaces; namespace Hutopy.Application.Users.Commands; -public record LoginCommand : IRequest + +public record LoginCommand( + string Email, + string Password) + : IRequest; + +public record LoginResponse( + string AccessToken, + string RefreshToken); + +public class LoginCommandHandler( + IApplicationDbContext Context, + IIdentityService identityService) + : IRequestHandler { - public required string EmailAddress { get; init; } - public required string Password { get; init; } -} - -public class LoginCommandHandler : IRequestHandler -{ - private readonly IApplicationDbContext _context; - private readonly IIdentityService _identityService; - - public LoginCommandHandler(IApplicationDbContext context, IIdentityService identityService) + public async Task Handle(LoginCommand request, CancellationToken cancellationToken) { - _context = context; - _identityService = identityService; - } + var accessToken = await identityService.LoginAsync(request.Email, request.Password); - public async Task Handle(LoginCommand request, CancellationToken cancellationToken) - { - var jwt = await _identityService.LoginAsync(request.EmailAddress, request.Password); + if (string.IsNullOrWhiteSpace(accessToken)) throw new InvalidOperationException("Invalid login credentials"); - return jwt ?? "Invalid login credentials"; + return new LoginResponse(accessToken, string.Empty); } } diff --git a/src/Web/Endpoints/Users.cs b/src/Web/Endpoints/Users.cs index b2a15c5..c344509 100644 --- a/src/Web/Endpoints/Users.cs +++ b/src/Web/Endpoints/Users.cs @@ -24,7 +24,7 @@ public class Users : EndpointGroupBase return await sender.Send(query); } - private static async Task Login(ISender sender, LoginCommand command) + private static async Task Login(ISender sender, LoginCommand command) { return await sender.Send(command); } From 5231d44b132797c9bacadd53e7e4ec15b23806f5 Mon Sep 17 00:00:00 2001 From: Jonathan Bourdon Date: Thu, 20 Jun 2024 13:55:24 -0400 Subject: [PATCH 068/229] Add ignored appsettings.Development.json --- src/Web/appsettings.Development.json | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 src/Web/appsettings.Development.json diff --git a/src/Web/appsettings.Development.json b/src/Web/appsettings.Development.json new file mode 100644 index 0000000..9dad30e --- /dev/null +++ b/src/Web/appsettings.Development.json @@ -0,0 +1,20 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft": "Information", + "Microsoft.AspNetCore.SpaProxy": "Information", + "Microsoft.Hosting.Lifetime": "Information" + } + }, + "ConnectionStrings": { + "DefaultConnection": "Server=localhost,1433;Database=Hutopy;User Id=sa;Password=P@ssword123!;MultipleActiveResultSets=true;TrustServerCertificate=True" + }, + "Authentication": { + "Jwt": { + "Audience": "hutopy", + "Issuer": "https://auth.hutopy.com", + "Key": "b2df428b9929d3ace7c598bbf4e496b2f0b71ab3cd4f94540356cfc35b000000" + } + } +} \ No newline at end of file From ba35e3228eb7b42536c0bedbc646d1d52ae996dd Mon Sep 17 00:00:00 2001 From: Jonathan Bourdon Date: Thu, 20 Jun 2024 14:18:14 -0400 Subject: [PATCH 069/229] Add start-infrastructure script --- start-infrastructure.sh | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 start-infrastructure.sh diff --git a/start-infrastructure.sh b/start-infrastructure.sh new file mode 100644 index 0000000..d7a15c2 --- /dev/null +++ b/start-infrastructure.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +docker run \ + --cap-add SYS_PTRACE \ + -e 'ACCEPT_EULA=1' \ + -e 'MSSQL_SA_PASSWORD=P@ssword123!' \ + -p 1433:1433 \ + --name azuresqledge \ + -d mcr.microsoft.com/azure-sql-edge \ No newline at end of file From 81e92909890590f035ec5c4160c3cebd2916ef6b Mon Sep 17 00:00:00 2001 From: Jonathan Bourdon Date: Thu, 20 Jun 2024 16:27:44 -0400 Subject: [PATCH 070/229] Cleanup and more fixes --- Hutopy.sln | 1 + src/Infrastructure/DependencyInjection.cs | 29 +- src/Web/DependencyInjection.cs | 25 +- src/Web/Program.cs | 37 +- src/Web/Properties/launchSettings.json | 6 +- src/Web/Web.csproj | 46 +- src/Web/appsettings.Development.json | 2 +- src/Web/config.nswag | 63 -- src/Web/wwwroot/api/specification.json | 869 ------------------ .../TestcontainersTestDatabase.cs | 4 +- 10 files changed, 57 insertions(+), 1025 deletions(-) delete mode 100644 src/Web/config.nswag delete mode 100644 src/Web/wwwroot/api/specification.json diff --git a/Hutopy.sln b/Hutopy.sln index 5714f45..2fe5931 100644 --- a/Hutopy.sln +++ b/Hutopy.sln @@ -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}" diff --git a/src/Infrastructure/DependencyInjection.cs b/src/Infrastructure/DependencyInjection.cs index e03ce4c..b8f43d6 100644 --- a/src/Infrastructure/DependencyInjection.cs +++ b/src/Infrastructure/DependencyInjection.cs @@ -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(); services.AddScoped(); @@ -49,15 +40,9 @@ public static class DependencyInjection .AddBearerToken(IdentityConstants.BearerScheme); services.AddAuthorizationBuilder(); - - services.AddIdentityCore(options => - { - options.Password.RequireDigit = false; - options.Password.RequireLowercase = false; - options.Password.RequireUppercase = false; - options.Password.RequireNonAlphanumeric = false; - options.Password.RequiredLength = 8; - }) + + services + .AddIdentityCore() .AddRoles() .AddEntityFrameworkStores() .AddApiEndpoints() diff --git a/src/Web/DependencyInjection.cs b/src/Web/DependencyInjection.cs index 27f1ac1..2a76f33 100644 --- a/src/Web/DependencyInjection.cs +++ b/src/Web/DependencyInjection.cs @@ -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()) diff --git a/src/Web/Program.cs b/src/Web/Program.cs index 781bdc2..ea5b072 100644 --- a/src/Web/Program.cs +++ b/src/Web/Program.cs @@ -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(); diff --git a/src/Web/Properties/launchSettings.json b/src/Web/Properties/launchSettings.json index 6ef4f83..39a9650 100644 --- a/src/Web/Properties/launchSettings.json +++ b/src/Web/Properties/launchSettings.json @@ -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" } diff --git a/src/Web/Web.csproj b/src/Web/Web.csproj index 9193242..80a1ea9 100644 --- a/src/Web/Web.csproj +++ b/src/Web/Web.csproj @@ -7,46 +7,26 @@ - - + + - - - - - - - - - - + + + + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive - all - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - + - - - - OnBuildSuccess - - - - - - - - - - - - diff --git a/src/Web/appsettings.Development.json b/src/Web/appsettings.Development.json index 9dad30e..ec39dd6 100644 --- a/src/Web/appsettings.Development.json +++ b/src/Web/appsettings.Development.json @@ -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": { diff --git a/src/Web/config.nswag b/src/Web/config.nswag deleted file mode 100644 index 4af18f2..0000000 --- a/src/Web/config.nswag +++ /dev/null @@ -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 - } - } -} diff --git a/src/Web/wwwroot/api/specification.json b/src/Web/wwwroot/api/specification.json deleted file mode 100644 index bf1f109..0000000 --- a/src/Web/wwwroot/api/specification.json +++ /dev/null @@ -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": [] - } - ] -} \ No newline at end of file diff --git a/tests/Application.FunctionalTests/TestcontainersTestDatabase.cs b/tests/Application.FunctionalTests/TestcontainersTestDatabase.cs index eaf57f8..342336f 100644 --- a/tests/Application.FunctionalTests/TestcontainersTestDatabase.cs +++ b/tests/Application.FunctionalTests/TestcontainersTestDatabase.cs @@ -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"] }); } From 97a2c296f11706db320e85d64dea430be4ea4265 Mon Sep 17 00:00:00 2001 From: PascalMarchesseault <97350299+PascalMarchesseault@users.noreply.github.com> Date: Thu, 20 Jun 2024 16:35:04 -0400 Subject: [PATCH 071/229] add MultiSubnetFailover=True --- src/Web/appsettings.Development.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Web/appsettings.Development.json b/src/Web/appsettings.Development.json index ec39dd6..43ba880 100644 --- a/src/Web/appsettings.Development.json +++ b/src/Web/appsettings.Development.json @@ -8,7 +8,7 @@ } }, "ConnectionStrings": { - "DefaultConnection": "Server=localhost,1433;Initial Catalog=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;MultiSubnetFailover=True" }, "Authentication": { "Jwt": { From 623972bc36b855507cccb085d5ad3c15c372d909 Mon Sep 17 00:00:00 2001 From: Jonathan Bourdon Date: Thu, 27 Jun 2024 12:37:59 -0400 Subject: [PATCH 072/229] Adds messages api --- Directory.Packages.props | 1 + src/Application/Common/Models/UserModel.cs | 2 + .../Identity/IdentityService.cs | 11 ++- src/Infrastructure/Utils/GenerateJwtToken.cs | 25 +++++-- src/Web/Controllers/GoogleController.cs | 12 ++- src/Web/Endpoints/Users.cs | 10 +-- src/Web/Messages/Data/Message.cs | 13 ++++ src/Web/Messages/Data/MessagingDbContext.cs | 19 +++++ src/Web/Messages/Handlers/GetMessages.cs | 30 ++++++++ .../Messages/Handlers/GetMessagesByUser.cs | 33 ++++++++ src/Web/Messages/Handlers/PostMessage.cs | 34 +++++++++ src/Web/Messages/Handlers/PostReplyMessage.cs | 37 +++++++++ .../20240627081653_Initial.Designer.cs | 59 +++++++++++++++ .../Migrations/20240627081653_Initial.cs | 38 ++++++++++ .../MessagingDbContextModelSnapshot.cs | 56 ++++++++++++++ src/Web/Messages/Shared.cs | 42 +++++++++++ src/Web/Program.cs | 75 ++++++++++++------- src/Web/Web.csproj | 31 ++++---- src/Web/Web.http | 14 +++- src/Web/appsettings.Development.json | 3 +- .../CustomWebApplicationFactory.cs | 1 + 21 files changed, 485 insertions(+), 61 deletions(-) create mode 100644 src/Web/Messages/Data/Message.cs create mode 100644 src/Web/Messages/Data/MessagingDbContext.cs create mode 100644 src/Web/Messages/Handlers/GetMessages.cs create mode 100644 src/Web/Messages/Handlers/GetMessagesByUser.cs create mode 100644 src/Web/Messages/Handlers/PostMessage.cs create mode 100644 src/Web/Messages/Handlers/PostReplyMessage.cs create mode 100644 src/Web/Messages/Migrations/20240627081653_Initial.Designer.cs create mode 100644 src/Web/Messages/Migrations/20240627081653_Initial.cs create mode 100644 src/Web/Messages/Migrations/MessagingDbContextModelSnapshot.cs create mode 100644 src/Web/Messages/Shared.cs diff --git a/Directory.Packages.props b/Directory.Packages.props index a2b4869..3c60acd 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -10,6 +10,7 @@ + diff --git a/src/Application/Common/Models/UserModel.cs b/src/Application/Common/Models/UserModel.cs index 5c4358b..71a2680 100644 --- a/src/Application/Common/Models/UserModel.cs +++ b/src/Application/Common/Models/UserModel.cs @@ -1,5 +1,6 @@ namespace Hutopy.Application.Common.Models; +// TODO: Review nullable affectation here public class UserModel { public string? Id { get; set; } @@ -7,4 +8,5 @@ public class UserModel public string? FirstName { get; set; } public string? LastName { get; set; } public string? Email { get; set; } + public string? PortraitUrl { get; set; } } diff --git a/src/Infrastructure/Identity/IdentityService.cs b/src/Infrastructure/Identity/IdentityService.cs index 9997316..7cdf080 100644 --- a/src/Infrastructure/Identity/IdentityService.cs +++ b/src/Infrastructure/Identity/IdentityService.cs @@ -1,3 +1,4 @@ +using System.Diagnostics; using Google.Apis.Oauth2.v2.Data; using System.Security.Claims; using Hutopy.Application.Common.Interfaces; @@ -220,14 +221,20 @@ public class IdentityService( } var user = await GetUserByUserNameAsync(userName); + + if (user is null) throw new InvalidOperationException(); var jwtSection = configuration.GetRequiredSection("Authentication:Jwt"); - + var token = JwtTokenHelper.GenerateJwtToken( issuer: jwtSection["Issuer"] ?? "", audience: jwtSection["Audience"] ?? "", key: jwtSection["Key"] ?? "", - userId: user?.Id ?? ""); + userId: user.Id, + email: user.Email, + firstname: user.FirstName, + lastname: user.LastName, + portraitUrl: user.PortraitUrl); return token; } diff --git a/src/Infrastructure/Utils/GenerateJwtToken.cs b/src/Infrastructure/Utils/GenerateJwtToken.cs index 00423f9..19e6cbd 100644 --- a/src/Infrastructure/Utils/GenerateJwtToken.cs +++ b/src/Infrastructure/Utils/GenerateJwtToken.cs @@ -7,20 +7,31 @@ namespace Hutopy.Infrastructure.Utils; public static class JwtTokenHelper { - public static string GenerateJwtToken(string issuer, string audience, string key, string userId) + public static string GenerateJwtToken(string issuer, string audience, string key, string? userId, string? email, + string? firstname, string? lastname, string? portraitUrl) { var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(key)); var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256); + var claims = new List(new[] + { + new Claim(JwtRegisteredClaimNames.Sub, userId), + new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()), + new Claim(ClaimTypes.NameIdentifier, userId), + new Claim(ClaimTypes.Email, email), + new Claim(ClaimTypes.GivenName, firstname), + new Claim(ClaimTypes.Surname, lastname), + }); + + if (portraitUrl is not null) + { + claims.Add(new Claim("portrait-url", portraitUrl)); + } + var token = new JwtSecurityToken( issuer: issuer, audience: audience, - claims: new[] - { - new Claim(JwtRegisteredClaimNames.Sub, userId), - new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()), - new Claim(ClaimTypes.NameIdentifier, userId) - }, + claims: claims, expires: DateTime.Now.AddMinutes(30), signingCredentials: credentials); diff --git a/src/Web/Controllers/GoogleController.cs b/src/Web/Controllers/GoogleController.cs index 40e8adc..dfaa91e 100644 --- a/src/Web/Controllers/GoogleController.cs +++ b/src/Web/Controllers/GoogleController.cs @@ -64,10 +64,14 @@ public class GoogleController(IIdentityService identityService, IHttpClientFacto var jwtSection = configuration.GetRequiredSection("Authentication:Jwt"); var token = JwtTokenHelper.GenerateJwtToken( - issuer: jwtSection["Issuer"] ?? throw new ArgumentNullException("The Jwt issuer is missing."), - audience: jwtSection["Audience"] ?? throw new ArgumentNullException("The Jwt audience is missing."), - key: jwtSection["Key"] ?? throw new ArgumentNullException("The Jwt key is missing."), - userId: user.Id); + jwtSection["Issuer"] ?? throw new ArgumentNullException("The Jwt issuer is missing."), + jwtSection["Audience"] ?? throw new ArgumentNullException("The Jwt audience is missing."), + jwtSection["Key"] ?? throw new ArgumentNullException("The Jwt key is missing."), + user.Id, + user.Email, + user.FirstName, + user.LastName, + user.PortraitUrl); return Ok(new { accessToken = token, email }); } diff --git a/src/Web/Endpoints/Users.cs b/src/Web/Endpoints/Users.cs index c344509..bcfa964 100644 --- a/src/Web/Endpoints/Users.cs +++ b/src/Web/Endpoints/Users.cs @@ -23,18 +23,16 @@ public class Users : EndpointGroupBase { return await sender.Send(query); } - + private static async Task Login(ISender sender, LoginCommand command) { return await sender.Send(command); } - + private static async Task UploadProfilePicture(ISender sender, Stream stream) { - var command = new UploadProfilePictureCommand - { - ProfilePicture = stream - }; + var command = new UploadProfilePictureCommand { ProfilePicture = stream }; + return await sender.Send(command); } } diff --git a/src/Web/Messages/Data/Message.cs b/src/Web/Messages/Data/Message.cs new file mode 100644 index 0000000..df0fa50 --- /dev/null +++ b/src/Web/Messages/Data/Message.cs @@ -0,0 +1,13 @@ +namespace Hutopy.Web.Messages.Data; + +public class Message +{ + public Guid Id { get; init; } + public Guid ContentId { get; init; } // works for any - VideoId, ChatId, RoomId, xxxId, ForumId + public Guid CreatedBy { get; init; } + public DateTime CreatedAt { get; } + + public Guid ParentId { get; init; } + + public string Value { get; init; } = null!; +} diff --git a/src/Web/Messages/Data/MessagingDbContext.cs b/src/Web/Messages/Data/MessagingDbContext.cs new file mode 100644 index 0000000..28bb977 --- /dev/null +++ b/src/Web/Messages/Data/MessagingDbContext.cs @@ -0,0 +1,19 @@ +using Microsoft.EntityFrameworkCore; + +namespace Hutopy.Web.Messages.Data; + +public class MessagingDbContext( + DbContextOptions options) + : DbContext(options) +{ + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + modelBuilder + .Entity() + .Property(c => c.CreatedAt) + .ValueGeneratedOnAdd() + .HasDefaultValueSql("CURRENT_TIMESTAMP"); + } + + public DbSet Messages { get; set; } +} diff --git a/src/Web/Messages/Handlers/GetMessages.cs b/src/Web/Messages/Handlers/GetMessages.cs new file mode 100644 index 0000000..d7afb3f --- /dev/null +++ b/src/Web/Messages/Handlers/GetMessages.cs @@ -0,0 +1,30 @@ +using FastEndpoints; +using Hutopy.Web.Messages.Data; +using Microsoft.EntityFrameworkCore; + +namespace Hutopy.Web.Messages.Handlers; + +public class GetMessages( + MessagingDbContext context) + : EndpointWithoutRequest> +{ + public override void Configure() + { + Tags("Messages"); + Get("/api/messages/{ContentId:guid}"); + AllowAnonymous(); + } + + public override async Task HandleAsync( + CancellationToken ct) + { + var contentId = Route("ContentId"); + + var comments = await context + .Messages + .Where(c => c.ContentId == contentId) + .ToListAsync(cancellationToken: ct); + + await SendAsync(comments, cancellation: ct); + } +} diff --git a/src/Web/Messages/Handlers/GetMessagesByUser.cs b/src/Web/Messages/Handlers/GetMessagesByUser.cs new file mode 100644 index 0000000..d70cd11 --- /dev/null +++ b/src/Web/Messages/Handlers/GetMessagesByUser.cs @@ -0,0 +1,33 @@ +using FastEndpoints; +using Hutopy.Web.Messages.Data; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; + +namespace Hutopy.Web.Messages.Handlers; + +public record GetMessagesByUserRequest( + [FromRoute] Guid UserId); + +public class GetMessagesByUser( + MessagingDbContext context) + : EndpointWithoutRequest> +{ + public override void Configure() + { + Tags("Messages"); + Get("/api/messages/by-user/{UserId:guid}"); + } + + public override async Task HandleAsync( + CancellationToken ct) + { + var userId = Route("UserId"); + + var posts = await context + .Messages + .Where(c => c.CreatedBy == userId) + .ToListAsync(cancellationToken: ct); + + await SendAsync(posts, cancellation: ct); + } +} diff --git a/src/Web/Messages/Handlers/PostMessage.cs b/src/Web/Messages/Handlers/PostMessage.cs new file mode 100644 index 0000000..7460728 --- /dev/null +++ b/src/Web/Messages/Handlers/PostMessage.cs @@ -0,0 +1,34 @@ +using FastEndpoints; +using Hutopy.Web.Messages.Data; + +namespace Hutopy.Web.Messages.Handlers; + +public record PostMessageRequest( + Guid ContentId, + string Message); + +public class PostMessage( + MessagingDbContext context) + : Endpoint +{ + public override void Configure() + { + // TODO: Find how to specify the name we see in Swagger + Tags("Messages"); + Post("/api/messages"); + } + + public override async Task HandleAsync( + PostMessageRequest req, + CancellationToken ct) + { + await context.Messages.AddAsync( + new Message { + ContentId = req.ContentId, + CreatedBy = User.GetUserId(), + Value = req.Message }, + ct); + + await context.SaveChangesAsync(ct); + } +} diff --git a/src/Web/Messages/Handlers/PostReplyMessage.cs b/src/Web/Messages/Handlers/PostReplyMessage.cs new file mode 100644 index 0000000..2385765 --- /dev/null +++ b/src/Web/Messages/Handlers/PostReplyMessage.cs @@ -0,0 +1,37 @@ +using FastEndpoints; +using Hutopy.Web.Messages.Data; + +namespace Hutopy.Web.Messages.Handlers; + +public record PostReplyMessageRequest( + Guid ContentId, + Guid ParentId, + string Message); + +public sealed class PostReplyMessage( + MessagingDbContext context) + : Endpoint +{ + public override void Configure() + { + Tags("Messages"); + Post("/api/messages/reply"); + } + + public override async Task HandleAsync( + PostReplyMessageRequest req, + CancellationToken ct) + { + await context.Messages.AddAsync( + new Message + { + ContentId = req.ContentId, + ParentId = req.ParentId, + CreatedBy = User.GetUserId(), + Value = req.Message + }, + ct); + + await context.SaveChangesAsync(ct); + } +} diff --git a/src/Web/Messages/Migrations/20240627081653_Initial.Designer.cs b/src/Web/Messages/Migrations/20240627081653_Initial.Designer.cs new file mode 100644 index 0000000..72d8e1c --- /dev/null +++ b/src/Web/Messages/Migrations/20240627081653_Initial.Designer.cs @@ -0,0 +1,59 @@ +// +using System; +using Hutopy.Web.Messages.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Hutopy.Web.Messages.Migrations +{ + [DbContext(typeof(MessagingDbContext))] + [Migration("20240627081653_Initial")] + partial class Initial + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.3") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("Hutopy.Web.Messages.Data.Message", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("ContentId") + .HasColumnType("uniqueidentifier"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasDefaultValueSql("CURRENT_TIMESTAMP"); + + b.Property("CreatedBy") + .HasColumnType("uniqueidentifier"); + + b.Property("ParentId") + .HasColumnType("uniqueidentifier"); + + b.Property("Value") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("Messages"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Web/Messages/Migrations/20240627081653_Initial.cs b/src/Web/Messages/Migrations/20240627081653_Initial.cs new file mode 100644 index 0000000..bd5664e --- /dev/null +++ b/src/Web/Messages/Migrations/20240627081653_Initial.cs @@ -0,0 +1,38 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Hutopy.Web.Messages.Migrations +{ + /// + public partial class Initial : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "Messages", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + ContentId = table.Column(type: "uniqueidentifier", nullable: false), + CreatedBy = table.Column(type: "uniqueidentifier", nullable: false), + CreatedAt = table.Column(type: "datetime2", nullable: false, defaultValueSql: "CURRENT_TIMESTAMP"), + ParentId = table.Column(type: "uniqueidentifier", nullable: false), + Value = table.Column(type: "nvarchar(max)", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Messages", x => x.Id); + }); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "Messages"); + } + } +} diff --git a/src/Web/Messages/Migrations/MessagingDbContextModelSnapshot.cs b/src/Web/Messages/Migrations/MessagingDbContextModelSnapshot.cs new file mode 100644 index 0000000..be9a4b9 --- /dev/null +++ b/src/Web/Messages/Migrations/MessagingDbContextModelSnapshot.cs @@ -0,0 +1,56 @@ +// +using System; +using Hutopy.Web.Messages.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Hutopy.Web.Messages.Migrations +{ + [DbContext(typeof(MessagingDbContext))] + partial class MessagingDbContextModelSnapshot : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.3") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("Hutopy.Web.Messages.Data.Message", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("ContentId") + .HasColumnType("uniqueidentifier"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasDefaultValueSql("CURRENT_TIMESTAMP"); + + b.Property("CreatedBy") + .HasColumnType("uniqueidentifier"); + + b.Property("ParentId") + .HasColumnType("uniqueidentifier"); + + b.Property("Value") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("Messages"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Web/Messages/Shared.cs b/src/Web/Messages/Shared.cs new file mode 100644 index 0000000..eb48399 --- /dev/null +++ b/src/Web/Messages/Shared.cs @@ -0,0 +1,42 @@ +using System.Security.Claims; + +namespace Hutopy.Web.Messages; + +public class Shared(string claimName) : Exception; + +public static class ClaimsPrincipalExtensions +{ + public static Guid GetUserId(this ClaimsPrincipal claims) + { + return (Guid)claims.GetFirstValue(ClaimTypes.NameIdentifier); + } + + public static string GetFirstName(this ClaimsPrincipal claims) + { + return (string)claims.GetFirstValue(ClaimTypes.GivenName); + } + + public static string GetLastName(this ClaimsPrincipal claims) + { + return (string)claims.GetFirstValue(ClaimTypes.Surname); + } + + public static string GetEmail(this ClaimsPrincipal claims) + { + return (string)claims.GetFirstValue(ClaimTypes.Email); + } + + public static object GetFirstValue(this ClaimsPrincipal claims, string key) + { + var claim = claims.FindFirst(key); + + if (claim is null) throw new Shared(key); + + if (typeof(TValue) == typeof(Guid)) + { + return Guid.Parse(claim.Value); + } + + return Convert.ChangeType(claim.Value, typeof(TValue)); + } +} diff --git a/src/Web/Program.cs b/src/Web/Program.cs index ea5b072..78700bc 100644 --- a/src/Web/Program.cs +++ b/src/Web/Program.cs @@ -1,10 +1,14 @@ +using Azure.Identity; +using FastEndpoints; using Hutopy.Application; using Hutopy.Infrastructure; using Hutopy.Infrastructure.Data; using Hutopy.Web; -using Azure.Identity; +using Hutopy.Web.Messages.Data; using Microsoft.AspNetCore.HttpOverrides; +using Microsoft.EntityFrameworkCore; using NSwag; +using NSwag.Generation.AspNetCore.Processors; using NSwag.Generation.Processors.Security; var builder = WebApplication.CreateBuilder(args); @@ -16,31 +20,31 @@ if (!builder.Environment.IsDevelopment()) } builder.Services.AddCors(options => +{ + options.AddPolicy("AllowAll", builder => { - options.AddPolicy("AllowAll", builder => - { - builder.AllowAnyOrigin() - .AllowAnyMethod() - .AllowAnyHeader(); - }); - - options.AddPolicy("AllowHutopyUi", builder => - { - builder.WithOrigins("https://zealous-bay-08204590f.5.azurestaticapps.net") - .AllowAnyMethod() - .AllowAnyHeader() - .AllowCredentials(); - }); - - options.AddPolicy("AllowHutopyUiPreview", builder => - { - builder.WithOrigins("https://zealous-bay-08204590f-preview.eastus2.5.azurestaticapps.net") - .AllowAnyMethod() - .AllowAnyHeader() - .AllowCredentials(); - }); + builder.AllowAnyOrigin() + .AllowAnyMethod() + .AllowAnyHeader(); }); + options.AddPolicy("AllowHutopyUi", builder => + { + builder.WithOrigins("https://zealous-bay-08204590f.5.azurestaticapps.net") + .AllowAnyMethod() + .AllowAnyHeader() + .AllowCredentials(); + }); + + options.AddPolicy("AllowHutopyUiPreview", builder => + { + builder.WithOrigins("https://zealous-bay-08204590f-preview.eastus2.5.azurestaticapps.net") + .AllowAnyMethod() + .AllowAnyHeader() + .AllowCredentials(); + }); +}); + // Add services to the container. builder.Services.AddKeyVaultIfConfigured(builder.Configuration); @@ -48,6 +52,8 @@ builder.Services.AddApplicationServices(); builder.Services.AddInfrastructureServices(builder.Configuration); builder.Services.AddWebServices(); builder.Services.AddAuthorizationAndAuthentication(builder.Configuration); + +// TODO: This old tech should be remove - need to move Facebook / Google controllers to FastEndpoints builder.Services.AddControllers(); builder.Services.AddOpenApiDocument((configure, sp) => @@ -63,11 +69,19 @@ builder.Services.AddOpenApiDocument((configure, sp) => Type = OpenApiSecuritySchemeType.ApiKey, Name = "Authorization", In = OpenApiSecurityApiKeyLocation.Header, - Description = "Type into the textbox: Bearer {your JWT token}." + Description = "Type into the textbox: Bearer {your JWT token}.", }); - + + configure.OperationProcessors.Add(new AspNetCoreOperationTagsProcessor()); configure.OperationProcessors.Add(new AspNetCoreOperationSecurityScopeProcessor("JWT")); - }); +}); + +builder.Services.AddFastEndpoints(); + +builder.Services.AddDbContext((_, options) => +{ + options.UseSqlServer(builder.Configuration.GetConnectionString("CommentStore")); +}); var app = builder.Build(); @@ -110,6 +124,13 @@ app.MapControllerRoute( // app.UseExceptionHandler(); app.MapEndpoints(); +app.UseFastEndpoints(); + app.Run(); -public abstract partial class Program { } +namespace Hutopy.Web +{ + public abstract partial class Program + { + } +} diff --git a/src/Web/Web.csproj b/src/Web/Web.csproj index 80a1ea9..053126a 100644 --- a/src/Web/Web.csproj +++ b/src/Web/Web.csproj @@ -7,26 +7,31 @@ - - + + - - - - - - - - - - + + + + + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive all - + + + + + diff --git a/src/Web/Web.http b/src/Web/Web.http index c0ac5aa..054f4e4 100644 --- a/src/Web/Web.http +++ b/src/Web/Web.http @@ -23,7 +23,7 @@ Content-Type: application/json "password": "{{Password}}" } -> {% client.global.set("auth_token", response.body); %} +> {% client.global.set("auth_token", response.body.accessToken); %} ### @@ -46,4 +46,16 @@ Authorization: Bearer {{auth_token}} # GET GetMyUser GET {{base_url}}/api/GetMyUser +Authorization: Bearer {{auth_token}} + +### + +# GET /api/posts + +GET {{base_url}}/api/messages/00000001-0000-0000-0000-000000000001 + +### + +# GET /api/posts/by-user +GET {{base_url}}/api/messages/by-user/325C69E8-DBC4-4CEE-B56E-C3C90AEE7963 Authorization: Bearer {{auth_token}} \ No newline at end of file diff --git a/src/Web/appsettings.Development.json b/src/Web/appsettings.Development.json index 43ba880..9e2b285 100644 --- a/src/Web/appsettings.Development.json +++ b/src/Web/appsettings.Development.json @@ -8,7 +8,8 @@ } }, "ConnectionStrings": { - "DefaultConnection": "Server=localhost,1433;Initial Catalog=Hutopy;User Id=sa;Password=P@ssword123!;MultipleActiveResultSets=true;TrustServerCertificate=True;MultiSubnetFailover=True" + "DefaultConnection": "Server=localhost,1433;Initial Catalog=Hutopy;User Id=sa;Password=P@ssword123!;MultipleActiveResultSets=true;TrustServerCertificate=True;MultiSubnetFailover=True", + "CommentStore": "Server=localhost,1433;Initial Catalog=Hutopy;User Id=sa;Password=P@ssword123!;MultipleActiveResultSets=true;TrustServerCertificate=True;MultiSubnetFailover=True" }, "Authentication": { "Jwt": { diff --git a/tests/Application.FunctionalTests/CustomWebApplicationFactory.cs b/tests/Application.FunctionalTests/CustomWebApplicationFactory.cs index d99727f..c1d8a80 100644 --- a/tests/Application.FunctionalTests/CustomWebApplicationFactory.cs +++ b/tests/Application.FunctionalTests/CustomWebApplicationFactory.cs @@ -1,6 +1,7 @@ using System.Data.Common; using Hutopy.Application.Common.Interfaces; using Hutopy.Infrastructure.Data; +using Hutopy.Web; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Mvc.Testing; using Microsoft.AspNetCore.TestHost; From 0e318eae32c9a781847c00be3b5ac606a92d8ee8 Mon Sep 17 00:00:00 2001 From: Dominic Villemure Date: Sat, 29 Jun 2024 22:45:17 -0400 Subject: [PATCH 073/229] update-current-user WIP --- .../Common/Interfaces/IIdentityService.cs | 20 +- src/Application/Common/Models/Result.cs | 27 +- src/Application/Common/Models/UserModel.cs | 13 +- .../Commands/UpdateCurrentUserCommand.cs | 40 ++ .../Users/Models/SocialNetworksModel.cs | 13 + .../Queries/GetCurrentUser/GetCurrentUser.cs | 18 +- .../Users/Queries/GetCurrentUser/UserDto.cs | 12 + .../Identity/ApplicationUser.cs | 7 + .../Identity/IdentityService.cs | 99 +++- ...6_AddMissingInformationsToUser.Designer.cs | 497 ++++++++++++++++++ ...0630001806_AddMissingInformationsToUser.cs | 95 ++++ .../ApplicationDbContextModelSnapshot.cs | 28 + src/Web/Endpoints/UpdateMyUser.cs | 20 + 13 files changed, 855 insertions(+), 34 deletions(-) create mode 100644 src/Application/Users/Commands/UpdateCurrentUserCommand.cs create mode 100644 src/Application/Users/Models/SocialNetworksModel.cs create mode 100644 src/Infrastructure/Migrations/20240630001806_AddMissingInformationsToUser.Designer.cs create mode 100644 src/Infrastructure/Migrations/20240630001806_AddMissingInformationsToUser.cs create mode 100644 src/Web/Endpoints/UpdateMyUser.cs diff --git a/src/Application/Common/Interfaces/IIdentityService.cs b/src/Application/Common/Interfaces/IIdentityService.cs index cd97117..d92663e 100644 --- a/src/Application/Common/Interfaces/IIdentityService.cs +++ b/src/Application/Common/Interfaces/IIdentityService.cs @@ -1,21 +1,27 @@ using Google.Apis.Oauth2.v2.Data; using Hutopy.Application.Common.Models; +using Hutopy.Application.Users.Models; namespace Hutopy.Application.Common.Interfaces; public interface IIdentityService { - Task GetUserNameAsync(string userId); - Task CreateUserAsync(string email, string userName, string firstName, string lastName, string password); - Task FindUserByIdAsync(string id); + Task> CreateUserAsync(Userinfo userInfo); + Task> CreateUserAsync(string email, string userName, string firstName, string lastName, string password); Task GetCurrentUserAsync(); - Task FindUserByEmailAsync(string id); - Task LoginAsync(string email, string password); + Task> UpdateCurrentUserAsync(string id, string firstName, string lastName, string occupation, + string phoneNumber, string birthDate, string country, string city, string address, string about, + string description, + SocialNetworksModel socialNetworks); + Task> GetCurrentUserRolesAsync(); + Task FindUserByIdAsync(string id); + Task FindUserByEmailAsync(string email); Task GetUserByUserNameAsync(string userName); + Task LoginAsync(string email, string password); Task IsInRoleAsync(string userId, string role); Task AuthorizeAsync(string userId, string policyName); + Task GetUserNameAsync(string userId); + Task AddRoleAsync(string userId, string role); - Task> GetCurrentUserRolesAsync(); - Task<(Result Result, string UserId)> CreateUserAsync(Userinfo userInfo); Task DeleteUserAsync(string userId); } diff --git a/src/Application/Common/Models/Result.cs b/src/Application/Common/Models/Result.cs index f99bb27..9552531 100644 --- a/src/Application/Common/Models/Result.cs +++ b/src/Application/Common/Models/Result.cs @@ -5,9 +5,8 @@ public class Result( IEnumerable errors) { public bool Succeeded { get; init; } = succeeded; - public string[] Errors { get; init; } = errors.ToArray(); - + public static Result Success() { return new Result(true, Array.Empty()); @@ -18,3 +17,27 @@ public class Result( return new Result(false, errors); } } + +public class Result( + bool succeeded, + IEnumerable errors) +{ + public bool Succeeded { get; init; } = succeeded; + public string[] Errors { get; init; } = errors.ToArray(); + public T? Value { get; set; } + + public T GetValueOrDefault() + { + return Value ?? default(T)!; + } + + public static Result Success() + { + return new Result(true, Array.Empty()); + } + + public static Result Failure(IEnumerable errors) + { + return new Result(false, errors); + } +} diff --git a/src/Application/Common/Models/UserModel.cs b/src/Application/Common/Models/UserModel.cs index 71a2680..ac09db9 100644 --- a/src/Application/Common/Models/UserModel.cs +++ b/src/Application/Common/Models/UserModel.cs @@ -1,3 +1,5 @@ +using Hutopy.Application.Users.Models; + namespace Hutopy.Application.Common.Models; // TODO: Review nullable affectation here @@ -7,6 +9,15 @@ public class UserModel public string? UserName { get; set; } public string? FirstName { get; set; } public string? LastName { get; set; } - public string? Email { get; set; } + public string? Occupation { get; set; } + public string? Email { get; init; } = String.Empty; + public string? Phone { get; init; } = String.Empty; + public string? BirthDate { get; init; } = String.Empty; + public string? Country { get; init; } = String.Empty; + public string? City { get; init; } = String.Empty; + public string? Address { get; init; } = String.Empty; + public string? About { get; init; } = String.Empty; + public string? Description { get; init; } = String.Empty; + public SocialNetworksModel SocialNetworks { get; init; } = new(); public string? PortraitUrl { get; set; } } diff --git a/src/Application/Users/Commands/UpdateCurrentUserCommand.cs b/src/Application/Users/Commands/UpdateCurrentUserCommand.cs new file mode 100644 index 0000000..3a23915 --- /dev/null +++ b/src/Application/Users/Commands/UpdateCurrentUserCommand.cs @@ -0,0 +1,40 @@ +using Hutopy.Application.Common.Interfaces; +using Hutopy.Application.Users.Models; + +namespace Hutopy.Application.Users.Commands; + +public class UpdateCurrentUserCommand : IRequest +{ + public required string FirstName { get; init; } + public required string LastName { get; init; } + public required string Occupation { get; init; } + public required string PhoneNumber { get; init; } + public required string BirthDate { get; init; } + public required string Country { get; init; } + public required string City { get; init; } + public required string Address { get; init; } + public required string About { get; init; } + public required string Description { get; init; } + public required SocialNetworksModel SocialNetworks { get; init; } +} + +public class UpdateCurrentUserCommandHandler(IApplicationDbContext context, IIdentityService identityService) : + IRequestHandler +{ + public async Task Handle(UpdateCurrentUserCommand request, CancellationToken cancellationToken) + { + var identityUser = await identityService.GetCurrentUserAsync(); + + if (identityUser?.Id is null) return string.Empty; + + var result = await identityService.UpdateCurrentUserAsync(identityUser.Id, request.FirstName, request.LastName, + request.Occupation, request.PhoneNumber, request.BirthDate, + request.Country, request.City, request.Address, request.About, + request.Description, request.SocialNetworks); + + await context.SaveChangesAsync(cancellationToken); + + return result.GetValueOrDefault(); + } +} + diff --git a/src/Application/Users/Models/SocialNetworksModel.cs b/src/Application/Users/Models/SocialNetworksModel.cs new file mode 100644 index 0000000..edd3cce --- /dev/null +++ b/src/Application/Users/Models/SocialNetworksModel.cs @@ -0,0 +1,13 @@ +namespace Hutopy.Application.Users.Models; + +public class SocialNetworksModel +{ + public string FacebookUrl { get; init; } = String.Empty; + public string InstagramUrl { get; init; } = String.Empty; + public string XUrl { get; init; } = String.Empty; + public string LinkedInUrl { get; init; } = String.Empty; + public string TikTokUrl { get; init; } = String.Empty; + public string YoutubeUrl { get; init; } = String.Empty; + public string RedditUrl { get; init; } = String.Empty; + public string YourWebsiteUrl { get; init; } = String.Empty; +} diff --git a/src/Application/Users/Queries/GetCurrentUser/GetCurrentUser.cs b/src/Application/Users/Queries/GetCurrentUser/GetCurrentUser.cs index 7cbabd6..eeb9f7c 100644 --- a/src/Application/Users/Queries/GetCurrentUser/GetCurrentUser.cs +++ b/src/Application/Users/Queries/GetCurrentUser/GetCurrentUser.cs @@ -28,12 +28,22 @@ public class GetCurrentUserQueryHandler( var user = new UserDto { Id = currentUserId, - FirstName = identityUser?.FirstName ?? "", - LastName = identityUser?.LastName ?? "", - UserName = identityUser?.UserName ?? "", + FirstName = identityUser.FirstName ?? "", + LastName = identityUser.LastName ?? "", + UserName = identityUser.UserName ?? "", + Occupation = identityUser.Occupation ?? "", + Phone = identityUser.Phone ?? "", + Email = identityUser.Email ?? "", + BirthDate = identityUser.BirthDate ?? "", + Country = identityUser.Country ?? "", + City = identityUser.City ?? "", + Address = identityUser.Address ?? "", + About = identityUser.About ?? "", + Description = identityUser.Description ?? "", + SocialNetworks = identityUser.SocialNetworks, UserTransactions = transactions, TotalBalance = transactions.Sum(x => x.Amount), - UserRoles = roles + UserRoles = roles, }; return user; diff --git a/src/Application/Users/Queries/GetCurrentUser/UserDto.cs b/src/Application/Users/Queries/GetCurrentUser/UserDto.cs index c7d121d..c0b34c1 100644 --- a/src/Application/Users/Queries/GetCurrentUser/UserDto.cs +++ b/src/Application/Users/Queries/GetCurrentUser/UserDto.cs @@ -1,3 +1,5 @@ +using Hutopy.Application.Users.Models; + namespace Hutopy.Application.Users.Queries.GetCurrentUser; public class UserDto @@ -6,6 +8,16 @@ public class UserDto public required string FirstName { get; init; } public required string LastName { get; init; } public string UserName { get; init; } = String.Empty; + public string Occupation { get; init; } = String.Empty; + public string Email { get; init; } = String.Empty; + public string Phone { get; init; } = String.Empty; + public string BirthDate { get; init; } = String.Empty; + public string Country { get; init; } = String.Empty; + public string City { get; init; } = String.Empty; + public string Address { get; init; } = String.Empty; + public string About { get; init; } = String.Empty; + public string Description { get; init; } = String.Empty; + public SocialNetworksModel SocialNetworks { get; init; } = new(); public List UserTransactions { get; init; } = []; public IList UserRoles { get; init; } = []; public required decimal TotalBalance { get; init; } diff --git a/src/Infrastructure/Identity/ApplicationUser.cs b/src/Infrastructure/Identity/ApplicationUser.cs index 700a074..d956a9b 100644 --- a/src/Infrastructure/Identity/ApplicationUser.cs +++ b/src/Infrastructure/Identity/ApplicationUser.cs @@ -7,5 +7,12 @@ public class ApplicationUser : IdentityUser { public string FirstName { get; set; } = string.Empty; public string LastName { get; set; } = string.Empty; + public string Occupation { get; set; } = string.Empty; + public string BirthDate { get; set; } = string.Empty; + public string Country { get; set; } = string.Empty; + public string City { get; set; } = string.Empty; + public string Address { get; set; } = string.Empty; + public string About { get; set; } = string.Empty; + public string Description { get; set; } = string.Empty; public SocialNetworks SocialNetworks { get; set; } = new(); } diff --git a/src/Infrastructure/Identity/IdentityService.cs b/src/Infrastructure/Identity/IdentityService.cs index 7cdf080..d512ae5 100644 --- a/src/Infrastructure/Identity/IdentityService.cs +++ b/src/Infrastructure/Identity/IdentityService.cs @@ -3,6 +3,8 @@ using Google.Apis.Oauth2.v2.Data; using System.Security.Claims; using Hutopy.Application.Common.Interfaces; using Hutopy.Application.Common.Models; +using Hutopy.Application.Users.Models; +using Hutopy.Infrastructure.Identity.OwnedEntities; using Hutopy.Infrastructure.Utils; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; @@ -45,23 +47,10 @@ public class IdentityService( return userModel; } - - public async Task<(Result Result, string UserId)> CreateUserAsync(string userName, string password) - { - var user = new ApplicationUser - { - UserName = userName, - Email = userName, - }; - - var result = await userManager.CreateAsync(user, password); - - return (result.ToApplicationResult(), user.Id); - } - public async Task<(Result Result, string UserId)> CreateUserAsync(Userinfo userInfo) + public async Task> CreateUserAsync(Userinfo userInfo) { - var user = new ApplicationUser + var applicationUser = new ApplicationUser { UserName = userInfo.Name, Email = userInfo.Email, @@ -71,12 +60,18 @@ public class IdentityService( var password = Guid.NewGuid().ToString("N")[..32]; - var result = await userManager.CreateAsync(user, password); + var identityResult = await userManager.CreateAsync(applicationUser, password); - return (result.ToApplicationResult(), user.Id); + var applicationResult = identityResult.ToApplicationResult(); + + var result = new Result(applicationResult.Succeeded, applicationResult.Errors); + + result.Value = applicationUser.Id; + + return result; } - public async Task CreateUserAsync(string email, string userName, string firstName, string lastName, string password) + public async Task> CreateUserAsync(string email, string userName, string firstName, string lastName, string password) { var applicationUser = new ApplicationUser { @@ -88,7 +83,52 @@ public class IdentityService( var response = await userManager.CreateAsync(applicationUser, password); - return response.ToApplicationResult(); + var result = new Result(response.Succeeded, response.ToApplicationResult().Errors); + result.Value = applicationUser.Id; + + return result; + } + + public async Task> UpdateCurrentUserAsync(string id, string firstName, string lastName, string occupation, + string phoneNumber, string birthDate, string country, string city, string address, string about, string description, + SocialNetworksModel socialNetworks) + { + var applicationUser = await userManager.FindByIdAsync(id); + + if (applicationUser is null) return Result.Failure(new[] { "User not found." }); + + applicationUser.FirstName = firstName; + applicationUser.LastName = lastName; + applicationUser.Occupation = occupation; + applicationUser.PhoneNumber = phoneNumber; + applicationUser.BirthDate = birthDate; + applicationUser.Country = country; + applicationUser.City = city; + applicationUser.Address = address; + applicationUser.About = about; + applicationUser.Description = description; + applicationUser.SocialNetworks = new SocialNetworks() + { + FacebookUrl = socialNetworks.FacebookUrl, + InstagramUrl = socialNetworks.InstagramUrl, + XUrl = socialNetworks.XUrl, + LinkedInUrl = socialNetworks.LinkedInUrl, + TikTokUrl = socialNetworks.TikTokUrl, + YoutubeUrl = socialNetworks.YoutubeUrl, + RedditUrl = socialNetworks.RedditUrl, + YourWebsiteUrl = socialNetworks.YourWebsiteUrl + }; + + var response = await userManager.UpdateAsync(applicationUser); + + var applicationResult = response.ToApplicationResult(); + + var result = new Result(applicationResult.Succeeded, + applicationResult.Errors); + + result.Value = id; + + return result; } public async Task FindUserByIdAsync(string id) @@ -97,13 +137,32 @@ public class IdentityService( if (response == null) return null; - var userModel = new UserModel() + var userModel = new UserModel { Id = response.Id, UserName = response.UserName, FirstName = response.FirstName, LastName = response.LastName, Email = response.Email, + Occupation = response.Occupation, + Phone = response.PhoneNumber, + BirthDate = response.BirthDate, + Country = response.Country, + City = response.City, + Address = response.Address, + About = response.About, + Description = response.Description, + SocialNetworks = new SocialNetworksModel + { + FacebookUrl = response.SocialNetworks.FacebookUrl, + InstagramUrl = response.SocialNetworks.InstagramUrl, + XUrl = response.SocialNetworks.XUrl, + LinkedInUrl = response.SocialNetworks.LinkedInUrl, + TikTokUrl = response.SocialNetworks.TikTokUrl, + YoutubeUrl = response.SocialNetworks.YoutubeUrl, + RedditUrl = response.SocialNetworks.RedditUrl, + YourWebsiteUrl = response.SocialNetworks.YourWebsiteUrl, + } }; return userModel; diff --git a/src/Infrastructure/Migrations/20240630001806_AddMissingInformationsToUser.Designer.cs b/src/Infrastructure/Migrations/20240630001806_AddMissingInformationsToUser.Designer.cs new file mode 100644 index 0000000..2a9623e --- /dev/null +++ b/src/Infrastructure/Migrations/20240630001806_AddMissingInformationsToUser.Designer.cs @@ -0,0 +1,497 @@ +// +using System; +using Hutopy.Infrastructure.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Hutopy.Infrastructure.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + [Migration("20240630001806_AddMissingInformationsToUser")] + partial class AddMissingInformationsToUser + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.3") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("Hutopy.Domain.Entities.FutureCreator", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Created") + .HasColumnType("datetimeoffset"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("EmailAddress") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("FirstName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("LastModified") + .HasColumnType("datetimeoffset"); + + b.Property("LastModifiedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("LastName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumber") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("ReasonToJoin") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("SocialNetworkAccount") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("FutureCreators"); + }); + + modelBuilder.Entity("Hutopy.Domain.Entities.UserTransaction", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Amount") + .HasPrecision(18, 2) + .HasColumnType("decimal(18,2)"); + + b.Property("ApplicationUserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.Property("Created") + .HasColumnType("datetimeoffset"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("Currency") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("IsConfirmed") + .HasColumnType("bit"); + + b.Property("LastModified") + .HasColumnType("datetimeoffset"); + + b.Property("LastModifiedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("Paid") + .HasColumnType("bit"); + + b.Property("StripeBillingDetailEmail") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("StripeBillingDetailName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("StripeChargeId") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("StripeEventId") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("StripePaymentIntent") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("StripePaymentMethod") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("StripeReceiptUrl") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("TipMessage") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationUserId"); + + b.ToTable("UserTransactions"); + }); + + modelBuilder.Entity("Hutopy.Infrastructure.Identity.ApplicationUser", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("About") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("AccessFailedCount") + .HasColumnType("int"); + + b.Property("Address") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("BirthDate") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("City") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("nvarchar(max)"); + + b.Property("Country") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Description") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("EmailConfirmed") + .HasColumnType("bit"); + + b.Property("FirstName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("LastName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("LockoutEnabled") + .HasColumnType("bit"); + + b.Property("LockoutEnd") + .HasColumnType("datetimeoffset"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("Occupation") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("PasswordHash") + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumber") + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("bit"); + + b.Property("SecurityStamp") + .HasColumnType("nvarchar(max)"); + + b.Property("TwoFactorEnabled") + .HasColumnType("bit"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex") + .HasFilter("[NormalizedUserName] IS NOT NULL"); + + b.ToTable("AspNetUsers", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("nvarchar(max)"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex") + .HasFilter("[NormalizedName] IS NOT NULL"); + + b.ToTable("AspNetRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("nvarchar(max)"); + + b.Property("ClaimValue") + .HasColumnType("nvarchar(max)"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("nvarchar(max)"); + + b.Property("ClaimValue") + .HasColumnType("nvarchar(max)"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("nvarchar(450)"); + + b.Property("ProviderKey") + .HasColumnType("nvarchar(450)"); + + b.Property("ProviderDisplayName") + .HasColumnType("nvarchar(max)"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("nvarchar(450)"); + + b.Property("RoleId") + .HasColumnType("nvarchar(450)"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("nvarchar(450)"); + + b.Property("LoginProvider") + .HasColumnType("nvarchar(450)"); + + b.Property("Name") + .HasColumnType("nvarchar(450)"); + + b.Property("Value") + .HasColumnType("nvarchar(max)"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens", (string)null); + }); + + modelBuilder.Entity("Hutopy.Domain.Entities.UserTransaction", b => + { + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("ApplicationUserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Hutopy.Infrastructure.Identity.ApplicationUser", b => + { + b.OwnsOne("Hutopy.Infrastructure.Identity.OwnedEntities.SocialNetworks", "SocialNetworks", b1 => + { + b1.Property("ApplicationUserId") + .HasColumnType("nvarchar(450)"); + + b1.Property("FacebookUrl") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.Property("InstagramUrl") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.Property("LinkedInUrl") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.Property("RedditUrl") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.Property("TikTokUrl") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.Property("XUrl") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.Property("YourWebsiteUrl") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.Property("YoutubeUrl") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.HasKey("ApplicationUserId"); + + b1.ToTable("ApplicationUser_SocialNetworks", (string)null); + + b1.WithOwner() + .HasForeignKey("ApplicationUserId"); + }); + + b.Navigation("SocialNetworks") + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Infrastructure/Migrations/20240630001806_AddMissingInformationsToUser.cs b/src/Infrastructure/Migrations/20240630001806_AddMissingInformationsToUser.cs new file mode 100644 index 0000000..cd1a612 --- /dev/null +++ b/src/Infrastructure/Migrations/20240630001806_AddMissingInformationsToUser.cs @@ -0,0 +1,95 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Hutopy.Infrastructure.Migrations +{ + /// + public partial class AddMissingInformationsToUser : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "About", + table: "AspNetUsers", + type: "nvarchar(max)", + nullable: false, + defaultValue: ""); + + migrationBuilder.AddColumn( + name: "Address", + table: "AspNetUsers", + type: "nvarchar(max)", + nullable: false, + defaultValue: ""); + + migrationBuilder.AddColumn( + name: "BirthDate", + table: "AspNetUsers", + type: "nvarchar(max)", + nullable: false, + defaultValue: ""); + + migrationBuilder.AddColumn( + name: "City", + table: "AspNetUsers", + type: "nvarchar(max)", + nullable: false, + defaultValue: ""); + + migrationBuilder.AddColumn( + name: "Country", + table: "AspNetUsers", + type: "nvarchar(max)", + nullable: false, + defaultValue: ""); + + migrationBuilder.AddColumn( + name: "Description", + table: "AspNetUsers", + type: "nvarchar(max)", + nullable: false, + defaultValue: ""); + + migrationBuilder.AddColumn( + name: "Occupation", + table: "AspNetUsers", + type: "nvarchar(max)", + nullable: false, + defaultValue: ""); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "About", + table: "AspNetUsers"); + + migrationBuilder.DropColumn( + name: "Address", + table: "AspNetUsers"); + + migrationBuilder.DropColumn( + name: "BirthDate", + table: "AspNetUsers"); + + migrationBuilder.DropColumn( + name: "City", + table: "AspNetUsers"); + + migrationBuilder.DropColumn( + name: "Country", + table: "AspNetUsers"); + + migrationBuilder.DropColumn( + name: "Description", + table: "AspNetUsers"); + + migrationBuilder.DropColumn( + name: "Occupation", + table: "AspNetUsers"); + } + } +} diff --git a/src/Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs b/src/Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs index fcb6687..cd78f54 100644 --- a/src/Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs +++ b/src/Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs @@ -149,13 +149,37 @@ namespace Hutopy.Infrastructure.Migrations b.Property("Id") .HasColumnType("nvarchar(450)"); + b.Property("About") + .IsRequired() + .HasColumnType("nvarchar(max)"); + b.Property("AccessFailedCount") .HasColumnType("int"); + b.Property("Address") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("BirthDate") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("City") + .IsRequired() + .HasColumnType("nvarchar(max)"); + b.Property("ConcurrencyStamp") .IsConcurrencyToken() .HasColumnType("nvarchar(max)"); + b.Property("Country") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Description") + .IsRequired() + .HasColumnType("nvarchar(max)"); + b.Property("Email") .HasMaxLength(256) .HasColumnType("nvarchar(256)"); @@ -185,6 +209,10 @@ namespace Hutopy.Infrastructure.Migrations .HasMaxLength(256) .HasColumnType("nvarchar(256)"); + b.Property("Occupation") + .IsRequired() + .HasColumnType("nvarchar(max)"); + b.Property("PasswordHash") .HasColumnType("nvarchar(max)"); diff --git a/src/Web/Endpoints/UpdateMyUser.cs b/src/Web/Endpoints/UpdateMyUser.cs new file mode 100644 index 0000000..60121be --- /dev/null +++ b/src/Web/Endpoints/UpdateMyUser.cs @@ -0,0 +1,20 @@ +using Hutopy.Application.Users.Commands; + +namespace Hutopy.Web.Endpoints; + +public class UpdateMyUser : EndpointGroupBase +{ + public override void Map(WebApplication app) + { + app.MapGroup(this) + .RequireAuthorization() + .MapPatch("/profile", UpdateCurrentUser); + } + + private static async Task UpdateCurrentUser(ISender sender, UpdateCurrentUserCommand command) + { + return await sender.Send(command); + } + + +} From 2603582286646994c0d093cc4fe9df5abbbf1143 Mon Sep 17 00:00:00 2001 From: Dominic Villemure Date: Sun, 30 Jun 2024 12:35:14 -0400 Subject: [PATCH 074/229] Added profile ProfileColors and Profile images --- .../Constants/CommonFileNames.cs | 2 + .../Common/Interfaces/IIdentityService.cs | 8 +- src/Application/Common/Models/Result.cs | 11 +- src/Application/Common/Models/UserModel.cs | 30 +- .../Commands/ConfirmStripeTransaction.cs | 24 +- .../Commands/UpdateCurrentUserCommand.cs | 6 +- .../Users/Commands/UploadBannerPicture.cs | 27 + .../Users/Commands/UploadProfilePicture.cs | 2 + .../Users/Commands/UploadWebsiteIcon.cs | 27 + .../Users/Models/ProfileColorsModel.cs | 9 + .../Users/Models/SocialNetworksModel.cs | 16 +- .../Users/Queries/GetCurrentUser/UserDto.cs | 20 +- .../AzureBlob/AzureBlobStorageService.cs | 3 + .../Data/ApplicationDbContextInitializer.cs | 5 +- .../ApplicationUserConfiguration.cs | 10 + src/Infrastructure/DependencyInjection.cs | 3 +- .../Identity/ApplicationUser.cs | 2 + .../Identity/IdentityService.cs | 180 ++++-- .../Identity/OwnedEntities/ProfileColors.cs | 9 + .../Identity/OwnedEntities/SocialNetworks.cs | 16 +- .../Identity/OwnedEntities/StoredDataUrls.cs | 8 + ...3057_AddMoreInformationsToUser.Designer.cs | 557 ++++++++++++++++++ ...0240630163057_AddMoreInformationsToUser.cs | 77 +++ .../ApplicationDbContextModelSnapshot.cs | 60 ++ src/Infrastructure/Stripe/StripeService.cs | 3 + src/Web/Controllers/GoogleController.cs | 2 +- src/Web/Endpoints/UpdateMyUser.cs | 19 + 27 files changed, 1017 insertions(+), 119 deletions(-) create mode 100644 src/Application/Users/Commands/UploadBannerPicture.cs create mode 100644 src/Application/Users/Commands/UploadWebsiteIcon.cs create mode 100644 src/Application/Users/Models/ProfileColorsModel.cs create mode 100644 src/Infrastructure/Identity/OwnedEntities/ProfileColors.cs create mode 100644 src/Infrastructure/Identity/OwnedEntities/StoredDataUrls.cs create mode 100644 src/Infrastructure/Migrations/20240630163057_AddMoreInformationsToUser.Designer.cs create mode 100644 src/Infrastructure/Migrations/20240630163057_AddMoreInformationsToUser.cs diff --git a/src/Application/AzureBlobStorage/Constants/CommonFileNames.cs b/src/Application/AzureBlobStorage/Constants/CommonFileNames.cs index 7eabb9a..b6d44aa 100644 --- a/src/Application/AzureBlobStorage/Constants/CommonFileNames.cs +++ b/src/Application/AzureBlobStorage/Constants/CommonFileNames.cs @@ -3,4 +3,6 @@ public static class CommonFileNames { public static string ProfilePicture = "profilePicture"; + public static string BannerPicture = "bannerPicture"; + public static string WebsiteIcon = "websiteIcon"; } diff --git a/src/Application/Common/Interfaces/IIdentityService.cs b/src/Application/Common/Interfaces/IIdentityService.cs index d92663e..74e9240 100644 --- a/src/Application/Common/Interfaces/IIdentityService.cs +++ b/src/Application/Common/Interfaces/IIdentityService.cs @@ -9,10 +9,10 @@ public interface IIdentityService Task> CreateUserAsync(Userinfo userInfo); Task> CreateUserAsync(string email, string userName, string firstName, string lastName, string password); Task GetCurrentUserAsync(); - Task> UpdateCurrentUserAsync(string id, string firstName, string lastName, string occupation, - string phoneNumber, string birthDate, string country, string city, string address, string about, - string description, - SocialNetworksModel socialNetworks); + Task UpdateCurrentUserBannerPictureUrlAsync(string url); + Task UpdateCurrentUserProfilePictureUrlAsync(string url); + Task UpdateCurrentUserWebsiteIconUrlAsync(string url); + Task> UpdateCurrentUserAsync(UserModel userModel); Task> GetCurrentUserRolesAsync(); Task FindUserByIdAsync(string id); Task FindUserByEmailAsync(string email); diff --git a/src/Application/Common/Models/Result.cs b/src/Application/Common/Models/Result.cs index 9552531..294e2ed 100644 --- a/src/Application/Common/Models/Result.cs +++ b/src/Application/Common/Models/Result.cs @@ -19,25 +19,26 @@ public class Result( } public class Result( + T? value, bool succeeded, IEnumerable errors) { public bool Succeeded { get; init; } = succeeded; public string[] Errors { get; init; } = errors.ToArray(); - public T? Value { get; set; } + public T? Value { get; set; } = value; public T GetValueOrDefault() { return Value ?? default(T)!; } - public static Result Success() + public static Result Success(T value) { - return new Result(true, Array.Empty()); + return new Result(value, true, Array.Empty()); } - public static Result Failure(IEnumerable errors) + public static Result Failure(T value, IEnumerable errors) { - return new Result(false, errors); + return new Result(value, false, errors); } } diff --git a/src/Application/Common/Models/UserModel.cs b/src/Application/Common/Models/UserModel.cs index ac09db9..9fceab9 100644 --- a/src/Application/Common/Models/UserModel.cs +++ b/src/Application/Common/Models/UserModel.cs @@ -2,22 +2,22 @@ using Hutopy.Application.Users.Models; namespace Hutopy.Application.Common.Models; -// TODO: Review nullable affectation here public class UserModel { - public string? Id { get; set; } - public string? UserName { get; set; } - public string? FirstName { get; set; } - public string? LastName { get; set; } - public string? Occupation { get; set; } - public string? Email { get; init; } = String.Empty; - public string? Phone { get; init; } = String.Empty; - public string? BirthDate { get; init; } = String.Empty; - public string? Country { get; init; } = String.Empty; - public string? City { get; init; } = String.Empty; - public string? Address { get; init; } = String.Empty; - public string? About { get; init; } = String.Empty; - public string? Description { get; init; } = String.Empty; + public string Id { get; set; } = string.Empty; + public string UserName { get; set; } = string.Empty; + public string FirstName { get; set; } = string.Empty; + public string LastName { get; set; } = string.Empty; + public string Occupation { get; set; } = string.Empty; + public string Email { get; init; } = string.Empty; + public string Phone { get; init; } = string.Empty; + public string BirthDate { get; init; } = string.Empty; + public string Country { get; init; } = string.Empty; + public string City { get; init; } = string.Empty; + public string Address { get; init; } = string.Empty; + public string About { get; init; } = string.Empty; + public string Description { get; init; } = string.Empty; public SocialNetworksModel SocialNetworks { get; init; } = new(); - public string? PortraitUrl { get; set; } + public ProfileColorsModel ProfileColors { get; init; } = new(); + public string ProfilePictureUrl { get; set; } = string.Empty; } diff --git a/src/Application/Stripe/Commands/ConfirmStripeTransaction.cs b/src/Application/Stripe/Commands/ConfirmStripeTransaction.cs index 0ddd17e..0c74658 100644 --- a/src/Application/Stripe/Commands/ConfirmStripeTransaction.cs +++ b/src/Application/Stripe/Commands/ConfirmStripeTransaction.cs @@ -17,29 +17,29 @@ public class Data public class Object { - public string Id { get; set; } = String.Empty; + public string Id { get; set; } = string.Empty; public int Amount { get; set; } public BillingDetails Billing_details { get; set; } = new(); - public string Calculated_statement_descriptor { get; set; } = String.Empty; - public string Currency { get; set; } = String.Empty; + public string Calculated_statement_descriptor { get; set; } = string.Empty; + public string Currency { get; set; } = string.Empty; public bool Paid { get; set; } - public string Payment_intent { get; set; } = String.Empty; - public string Payment_method { get; set; } = String.Empty; - public string Receipt_url { get; set; } = String.Empty; - public string Status { get; set; } = String.Empty; - public string Failure_message { get; set; } = String.Empty; + public string Payment_intent { get; set; } = string.Empty; + public string Payment_method { get; set; } = string.Empty; + public string Receipt_url { get; set; } = string.Empty; + public string Status { get; set; } = string.Empty; + public string Failure_message { get; set; } = string.Empty; } public class BillingDetails { - public string Email { get; set; } = String.Empty; - public string Name { get; set; } = String.Empty; - public string Phone { get; set; } = String.Empty; + public string Email { get; set; } = string.Empty; + public string Name { get; set; } = string.Empty; + public string Phone { get; set; } = string.Empty; } public class Request { - public string Id { get; set; } = String.Empty; + public string Id { get; set; } = string.Empty; } public class ConfirmStripeTransactionCommandHandler( diff --git a/src/Application/Users/Commands/UpdateCurrentUserCommand.cs b/src/Application/Users/Commands/UpdateCurrentUserCommand.cs index 3a23915..708ea6b 100644 --- a/src/Application/Users/Commands/UpdateCurrentUserCommand.cs +++ b/src/Application/Users/Commands/UpdateCurrentUserCommand.cs @@ -16,6 +16,7 @@ public class UpdateCurrentUserCommand : IRequest public required string About { get; init; } public required string Description { get; init; } public required SocialNetworksModel SocialNetworks { get; init; } + public required ProfileColorsModel ProfileColors { get; init; } } public class UpdateCurrentUserCommandHandler(IApplicationDbContext context, IIdentityService identityService) : @@ -27,10 +28,7 @@ public class UpdateCurrentUserCommandHandler(IApplicationDbContext context, IIde if (identityUser?.Id is null) return string.Empty; - var result = await identityService.UpdateCurrentUserAsync(identityUser.Id, request.FirstName, request.LastName, - request.Occupation, request.PhoneNumber, request.BirthDate, - request.Country, request.City, request.Address, request.About, - request.Description, request.SocialNetworks); + var result = await identityService.UpdateCurrentUserAsync(identityUser); await context.SaveChangesAsync(cancellationToken); diff --git a/src/Application/Users/Commands/UploadBannerPicture.cs b/src/Application/Users/Commands/UploadBannerPicture.cs new file mode 100644 index 0000000..66922a6 --- /dev/null +++ b/src/Application/Users/Commands/UploadBannerPicture.cs @@ -0,0 +1,27 @@ +using Hutopy.Application.AzureBlobStorage.Constants; +using Hutopy.Application.Common.Interfaces; + +namespace Hutopy.Application.Users.Commands; + +public class UploadBannerPictureCommand : IRequest +{ + public required Stream BannerPicture { get; init; } +} + +public class UploadBannerPictureCommandHandler(IIdentityService identityService, IAzureBlobStorageService azureBlobStorageService) : IRequestHandler +{ + public async Task Handle(UploadBannerPictureCommand request, CancellationToken cancellationToken) + { + var identityUser = await identityService.GetCurrentUserAsync(); + var currentUserId = new Guid(identityUser?.Id ?? "").ToString(); + + var blobName = $"{currentUserId}/{SubDirectoryNames.Profile}/{CommonFileNames.BannerPicture}"; + + var url = await azureBlobStorageService.UploadFileAsync(ContainerNames.Users, blobName, request.BannerPicture); + + await identityService.UpdateCurrentUserBannerPictureUrlAsync(url); + + return url; + } +} + diff --git a/src/Application/Users/Commands/UploadProfilePicture.cs b/src/Application/Users/Commands/UploadProfilePicture.cs index 08746d9..6fc4714 100644 --- a/src/Application/Users/Commands/UploadProfilePicture.cs +++ b/src/Application/Users/Commands/UploadProfilePicture.cs @@ -19,6 +19,8 @@ public class UploadProfilePictureCommandHandler(IIdentityService identityService var url = await azureBlobStorageService.UploadFileAsync(ContainerNames.Users, blobName, request.ProfilePicture); + await identityService.UpdateCurrentUserProfilePictureUrlAsync(url); + return url; } } diff --git a/src/Application/Users/Commands/UploadWebsiteIcon.cs b/src/Application/Users/Commands/UploadWebsiteIcon.cs new file mode 100644 index 0000000..78a83a2 --- /dev/null +++ b/src/Application/Users/Commands/UploadWebsiteIcon.cs @@ -0,0 +1,27 @@ +using Hutopy.Application.AzureBlobStorage.Constants; +using Hutopy.Application.Common.Interfaces; + +namespace Hutopy.Application.Users.Commands; + +public class UploadWebsiteIconCommand : IRequest +{ + public required Stream WebsiteIcon { get; init; } +} + +public class UploadWebsiteIconCommandHandler(IIdentityService identityService, IAzureBlobStorageService azureBlobStorageService) : IRequestHandler +{ + public async Task Handle(UploadWebsiteIconCommand request, CancellationToken cancellationToken) + { + var identityUser = await identityService.GetCurrentUserAsync(); + var currentUserId = new Guid(identityUser?.Id ?? "").ToString(); + + var blobName = $"{currentUserId}/{SubDirectoryNames.Profile}/{CommonFileNames.WebsiteIcon}"; + + var url = await azureBlobStorageService.UploadFileAsync(ContainerNames.Users, blobName, request.WebsiteIcon); + + await identityService.UpdateCurrentUserWebsiteIconUrlAsync(url); + + return url; + } +} + diff --git a/src/Application/Users/Models/ProfileColorsModel.cs b/src/Application/Users/Models/ProfileColorsModel.cs new file mode 100644 index 0000000..04baadb --- /dev/null +++ b/src/Application/Users/Models/ProfileColorsModel.cs @@ -0,0 +1,9 @@ +namespace Hutopy.Application.Users.Models; + +public class ProfileColorsModel +{ + public string BannerTop { get; init; } = String.Empty; + public string BannerBottom { get; init; } = String.Empty; + public string Accent { get; init; } = String.Empty; + public string Menu { get; init; } = String.Empty; +} diff --git a/src/Application/Users/Models/SocialNetworksModel.cs b/src/Application/Users/Models/SocialNetworksModel.cs index edd3cce..19a2f02 100644 --- a/src/Application/Users/Models/SocialNetworksModel.cs +++ b/src/Application/Users/Models/SocialNetworksModel.cs @@ -2,12 +2,12 @@ public class SocialNetworksModel { - public string FacebookUrl { get; init; } = String.Empty; - public string InstagramUrl { get; init; } = String.Empty; - public string XUrl { get; init; } = String.Empty; - public string LinkedInUrl { get; init; } = String.Empty; - public string TikTokUrl { get; init; } = String.Empty; - public string YoutubeUrl { get; init; } = String.Empty; - public string RedditUrl { get; init; } = String.Empty; - public string YourWebsiteUrl { get; init; } = String.Empty; + public string FacebookUrl { get; init; } = string.Empty; + public string InstagramUrl { get; init; } = string.Empty; + public string XUrl { get; init; } = string.Empty; + public string LinkedInUrl { get; init; } = string.Empty; + public string TikTokUrl { get; init; } = string.Empty; + public string YoutubeUrl { get; init; } = string.Empty; + public string RedditUrl { get; init; } = string.Empty; + public string YourWebsiteUrl { get; init; } = string.Empty; } diff --git a/src/Application/Users/Queries/GetCurrentUser/UserDto.cs b/src/Application/Users/Queries/GetCurrentUser/UserDto.cs index c0b34c1..ec2cc5d 100644 --- a/src/Application/Users/Queries/GetCurrentUser/UserDto.cs +++ b/src/Application/Users/Queries/GetCurrentUser/UserDto.cs @@ -7,16 +7,16 @@ public class UserDto public Guid Id { get; init; } public required string FirstName { get; init; } public required string LastName { get; init; } - public string UserName { get; init; } = String.Empty; - public string Occupation { get; init; } = String.Empty; - public string Email { get; init; } = String.Empty; - public string Phone { get; init; } = String.Empty; - public string BirthDate { get; init; } = String.Empty; - public string Country { get; init; } = String.Empty; - public string City { get; init; } = String.Empty; - public string Address { get; init; } = String.Empty; - public string About { get; init; } = String.Empty; - public string Description { get; init; } = String.Empty; + public string UserName { get; init; } = string.Empty; + public string Occupation { get; init; } = string.Empty; + public string Email { get; init; } = string.Empty; + public string Phone { get; init; } = string.Empty; + public string BirthDate { get; init; } = string.Empty; + public string Country { get; init; } = string.Empty; + public string City { get; init; } = string.Empty; + public string Address { get; init; } = string.Empty; + public string About { get; init; } = string.Empty; + public string Description { get; init; } = string.Empty; public SocialNetworksModel SocialNetworks { get; init; } = new(); public List UserTransactions { get; init; } = []; public IList UserRoles { get; init; } = []; diff --git a/src/Infrastructure/AzureBlob/AzureBlobStorageService.cs b/src/Infrastructure/AzureBlob/AzureBlobStorageService.cs index f54f96b..b25521c 100644 --- a/src/Infrastructure/AzureBlob/AzureBlobStorageService.cs +++ b/src/Infrastructure/AzureBlob/AzureBlobStorageService.cs @@ -1,3 +1,6 @@ +using System; +using System.IO; +using System.Threading.Tasks; using Azure.Storage.Blobs; using Azure.Storage.Blobs.Models; using Hutopy.Application.Common.Interfaces; diff --git a/src/Infrastructure/Data/ApplicationDbContextInitializer.cs b/src/Infrastructure/Data/ApplicationDbContextInitializer.cs index 6a985de..b771d57 100644 --- a/src/Infrastructure/Data/ApplicationDbContextInitializer.cs +++ b/src/Infrastructure/Data/ApplicationDbContextInitializer.cs @@ -1,4 +1,7 @@ -using Hutopy.Domain.Constants; +using System; +using System.Linq; +using System.Threading.Tasks; +using Hutopy.Domain.Constants; using Hutopy.Infrastructure.Identity; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Identity; diff --git a/src/Infrastructure/Data/Configurations/ApplicationUserConfiguration.cs b/src/Infrastructure/Data/Configurations/ApplicationUserConfiguration.cs index 0624b7a..b3a3735 100644 --- a/src/Infrastructure/Data/Configurations/ApplicationUserConfiguration.cs +++ b/src/Infrastructure/Data/Configurations/ApplicationUserConfiguration.cs @@ -12,5 +12,15 @@ public class ApplicationUserConfiguration : IEntityTypeConfiguration u.SocialNetworks) .ToTable($"{nameof(ApplicationUser)}_SocialNetworks"); + + // Relationship between ApplicationUser and ProfileColors + builder + .OwnsOne(u => u.ProfileColors) + .ToTable($"{nameof(ApplicationUser)}_ProfileColors"); + + // Relationship between ApplicationUser and StoredDataUrls + builder + .OwnsOne(u => u.StoredDataUrls) + .ToTable($"{nameof(ApplicationUser)}_StoredDataUrls"); } } diff --git a/src/Infrastructure/DependencyInjection.cs b/src/Infrastructure/DependencyInjection.cs index b8f43d6..2dfccb2 100644 --- a/src/Infrastructure/DependencyInjection.cs +++ b/src/Infrastructure/DependencyInjection.cs @@ -1,4 +1,5 @@ -using Hutopy.Application.Common.Interfaces; +using System; +using Hutopy.Application.Common.Interfaces; using Hutopy.Domain.Constants; using Hutopy.Infrastructure.AzureBlob; using Hutopy.Infrastructure.Data; diff --git a/src/Infrastructure/Identity/ApplicationUser.cs b/src/Infrastructure/Identity/ApplicationUser.cs index d956a9b..fbf49f7 100644 --- a/src/Infrastructure/Identity/ApplicationUser.cs +++ b/src/Infrastructure/Identity/ApplicationUser.cs @@ -15,4 +15,6 @@ public class ApplicationUser : IdentityUser public string About { get; set; } = string.Empty; public string Description { get; set; } = string.Empty; public SocialNetworks SocialNetworks { get; set; } = new(); + public ProfileColors ProfileColors { get; set; } = new(); + public StoredDataUrls StoredDataUrls { get; set; } = new(); } diff --git a/src/Infrastructure/Identity/IdentityService.cs b/src/Infrastructure/Identity/IdentityService.cs index d512ae5..c0f8a9b 100644 --- a/src/Infrastructure/Identity/IdentityService.cs +++ b/src/Infrastructure/Identity/IdentityService.cs @@ -1,6 +1,8 @@ -using System.Diagnostics; +using System; +using System.Collections.Generic; using Google.Apis.Oauth2.v2.Data; using System.Security.Claims; +using System.Threading.Tasks; using Hutopy.Application.Common.Interfaces; using Hutopy.Application.Common.Models; using Hutopy.Application.Users.Models; @@ -64,10 +66,8 @@ public class IdentityService( var applicationResult = identityResult.ToApplicationResult(); - var result = new Result(applicationResult.Succeeded, applicationResult.Errors); + var result = new Result(applicationUser.Id, applicationResult.Succeeded, applicationResult.Errors); - result.Value = applicationUser.Id; - return result; } @@ -83,51 +83,53 @@ public class IdentityService( var response = await userManager.CreateAsync(applicationUser, password); - var result = new Result(response.Succeeded, response.ToApplicationResult().Errors); - result.Value = applicationUser.Id; + var result = new Result(applicationUser.Id, response.Succeeded, response.ToApplicationResult().Errors); return result; } - public async Task> UpdateCurrentUserAsync(string id, string firstName, string lastName, string occupation, - string phoneNumber, string birthDate, string country, string city, string address, string about, string description, - SocialNetworksModel socialNetworks) + public async Task> UpdateCurrentUserAsync(UserModel userModel) { - var applicationUser = await userManager.FindByIdAsync(id); + var applicationUser = await userManager.FindByIdAsync(userModel.Id); - if (applicationUser is null) return Result.Failure(new[] { "User not found." }); + if (applicationUser is null) return Result.Failure("", new[] { "User not found." }); - applicationUser.FirstName = firstName; - applicationUser.LastName = lastName; - applicationUser.Occupation = occupation; - applicationUser.PhoneNumber = phoneNumber; - applicationUser.BirthDate = birthDate; - applicationUser.Country = country; - applicationUser.City = city; - applicationUser.Address = address; - applicationUser.About = about; - applicationUser.Description = description; - applicationUser.SocialNetworks = new SocialNetworks() + applicationUser.FirstName = userModel.FirstName; + applicationUser.LastName = userModel.LastName; + applicationUser.Occupation = userModel.Occupation; + applicationUser.PhoneNumber = userModel.Phone; + applicationUser.BirthDate = userModel.BirthDate; + applicationUser.Country = userModel.Country; + applicationUser.City = userModel.City; + applicationUser.Address = userModel.Address; + applicationUser.About = userModel.About; + applicationUser.Description = userModel.Description; + applicationUser.SocialNetworks = new SocialNetworks { - FacebookUrl = socialNetworks.FacebookUrl, - InstagramUrl = socialNetworks.InstagramUrl, - XUrl = socialNetworks.XUrl, - LinkedInUrl = socialNetworks.LinkedInUrl, - TikTokUrl = socialNetworks.TikTokUrl, - YoutubeUrl = socialNetworks.YoutubeUrl, - RedditUrl = socialNetworks.RedditUrl, - YourWebsiteUrl = socialNetworks.YourWebsiteUrl + FacebookUrl = userModel.SocialNetworks.FacebookUrl, + InstagramUrl = userModel.SocialNetworks.InstagramUrl, + XUrl = userModel.SocialNetworks.XUrl, + LinkedInUrl = userModel.SocialNetworks.LinkedInUrl, + TikTokUrl = userModel.SocialNetworks.TikTokUrl, + YoutubeUrl = userModel.SocialNetworks.YoutubeUrl, + RedditUrl = userModel.SocialNetworks.RedditUrl, + YourWebsiteUrl = userModel.SocialNetworks.YourWebsiteUrl + }; + applicationUser.ProfileColors = new ProfileColors + { + BannerTop = userModel.ProfileColors.BannerTop, + BannerBottom = userModel.ProfileColors.BannerBottom, + Accent = userModel.ProfileColors.Accent, + Menu = userModel.ProfileColors.Menu }; var response = await userManager.UpdateAsync(applicationUser); var applicationResult = response.ToApplicationResult(); - var result = new Result(applicationResult.Succeeded, + var result = new Result(userModel.Id, applicationResult.Succeeded, applicationResult.Errors); - - result.Value = id; - + return result; } @@ -140,12 +142,12 @@ public class IdentityService( var userModel = new UserModel { Id = response.Id, - UserName = response.UserName, + UserName = response.UserName ?? string.Empty, FirstName = response.FirstName, LastName = response.LastName, - Email = response.Email, + Email = response.Email ?? string.Empty, Occupation = response.Occupation, - Phone = response.PhoneNumber, + Phone = response.PhoneNumber ?? string.Empty, BirthDate = response.BirthDate, Country = response.Country, City = response.City, @@ -162,6 +164,57 @@ public class IdentityService( YoutubeUrl = response.SocialNetworks.YoutubeUrl, RedditUrl = response.SocialNetworks.RedditUrl, YourWebsiteUrl = response.SocialNetworks.YourWebsiteUrl, + }, + ProfileColors = new ProfileColorsModel + { + BannerTop = response.ProfileColors.BannerTop, + BannerBottom = response.ProfileColors.BannerBottom, + Accent = response.ProfileColors.Accent, + Menu = response.ProfileColors.Menu + } + }; + + return userModel; + } + + public async Task FindUserByEmailAsync(string email) + { + var response = await userManager.FindByEmailAsync(email); + + if (response == null) return null; + + var userModel = new UserModel + { + Id = response.Id, + UserName = response.UserName ?? string.Empty, + FirstName = response.FirstName, + LastName = response.LastName, + Email = response.Email ?? string.Empty, + Occupation = response.Occupation, + Phone = response.PhoneNumber ?? string.Empty, + BirthDate = response.BirthDate, + Country = response.Country, + City = response.City, + Address = response.Address, + About = response.About, + Description = response.Description, + SocialNetworks = new SocialNetworksModel + { + FacebookUrl = response.SocialNetworks.FacebookUrl, + InstagramUrl = response.SocialNetworks.InstagramUrl, + XUrl = response.SocialNetworks.XUrl, + LinkedInUrl = response.SocialNetworks.LinkedInUrl, + TikTokUrl = response.SocialNetworks.TikTokUrl, + YoutubeUrl = response.SocialNetworks.YoutubeUrl, + RedditUrl = response.SocialNetworks.RedditUrl, + YourWebsiteUrl = response.SocialNetworks.YourWebsiteUrl, + }, + ProfileColors = new ProfileColorsModel + { + BannerTop = response.ProfileColors.BannerTop, + BannerBottom = response.ProfileColors.BannerBottom, + Accent = response.ProfileColors.Accent, + Menu = response.ProfileColors.Menu } }; @@ -179,22 +232,49 @@ public class IdentityService( return await FindUserByIdAsync(currentUserId); } - public async Task FindUserByEmailAsync(string email) + public async Task UpdateCurrentUserBannerPictureUrlAsync(string url) { - var response = await userManager.FindByEmailAsync(email); + var userModel = await GetCurrentUserAsync(); + if (userModel is null) return Result.Failure(new[] { "User not found." }); - if (response == null) return null; + var applicationUser = await userManager.FindByIdAsync(userModel.Id); + if (applicationUser is null) return Result.Failure(new[] { "ApplicationUser not found." }); - var userModel = new UserModel - { - Id = response.Id, - UserName = response.UserName, - FirstName = response.FirstName, - LastName = response.LastName, - Email = response.Email - }; + applicationUser.StoredDataUrls.BannerPictureUrl = url; + + var response = await userManager.UpdateAsync(applicationUser); - return userModel; + return response.ToApplicationResult(); + } + + public async Task UpdateCurrentUserProfilePictureUrlAsync(string url) + { + var userModel = await GetCurrentUserAsync(); + if (userModel is null) return Result.Failure(new[] { "User not found." }); + + var applicationUser = await userManager.FindByIdAsync(userModel.Id); + if (applicationUser is null) return Result.Failure(new[] { "ApplicationUser not found." }); + + applicationUser.StoredDataUrls.ProfilePictureUrl = url; + + var response = await userManager.UpdateAsync(applicationUser); + + return response.ToApplicationResult(); + } + + public async Task UpdateCurrentUserWebsiteIconUrlAsync(string url) + { + var userModel = await GetCurrentUserAsync(); + if (userModel is null) return Result.Failure(new[] { "User not found." }); + + var applicationUser = await userManager.FindByIdAsync(userModel.Id); + if (applicationUser is null) return Result.Failure(new[] { "ApplicationUser not found." }); + + applicationUser.StoredDataUrls.WebsiteIconUrl = url; + + var response = await userManager.UpdateAsync(applicationUser); + + return response.ToApplicationResult(); } public async Task IsInRoleAsync(string userId, string role) @@ -293,7 +373,7 @@ public class IdentityService( email: user.Email, firstname: user.FirstName, lastname: user.LastName, - portraitUrl: user.PortraitUrl); + portraitUrl: user.ProfilePictureUrl); return token; } diff --git a/src/Infrastructure/Identity/OwnedEntities/ProfileColors.cs b/src/Infrastructure/Identity/OwnedEntities/ProfileColors.cs new file mode 100644 index 0000000..3783044 --- /dev/null +++ b/src/Infrastructure/Identity/OwnedEntities/ProfileColors.cs @@ -0,0 +1,9 @@ +namespace Hutopy.Infrastructure.Identity.OwnedEntities; + +public class ProfileColors +{ + public string BannerTop { get; init; } = string.Empty; + public string BannerBottom { get; init; } = string.Empty; + public string Accent { get; init; } = string.Empty; + public string Menu { get; init; } = string.Empty; +} diff --git a/src/Infrastructure/Identity/OwnedEntities/SocialNetworks.cs b/src/Infrastructure/Identity/OwnedEntities/SocialNetworks.cs index 1e0d30e..a03e139 100644 --- a/src/Infrastructure/Identity/OwnedEntities/SocialNetworks.cs +++ b/src/Infrastructure/Identity/OwnedEntities/SocialNetworks.cs @@ -2,12 +2,12 @@ namespace Hutopy.Infrastructure.Identity.OwnedEntities; public class SocialNetworks { - public string FacebookUrl { get; init; } = String.Empty; - public string InstagramUrl { get; init; } = String.Empty; - public string XUrl { get; init; } = String.Empty; - public string LinkedInUrl { get; init; } = String.Empty; - public string TikTokUrl { get; init; } = String.Empty; - public string YoutubeUrl { get; init; } = String.Empty; - public string RedditUrl { get; init; } = String.Empty; - public string YourWebsiteUrl { get; init; } = String.Empty; + public string FacebookUrl { get; init; } = string.Empty; + public string InstagramUrl { get; init; } = string.Empty; + public string XUrl { get; init; } = string.Empty; + public string LinkedInUrl { get; init; } = string.Empty; + public string TikTokUrl { get; init; } = string.Empty; + public string YoutubeUrl { get; init; } = string.Empty; + public string RedditUrl { get; init; } = string.Empty; + public string YourWebsiteUrl { get; init; } = string.Empty; } diff --git a/src/Infrastructure/Identity/OwnedEntities/StoredDataUrls.cs b/src/Infrastructure/Identity/OwnedEntities/StoredDataUrls.cs new file mode 100644 index 0000000..bea6099 --- /dev/null +++ b/src/Infrastructure/Identity/OwnedEntities/StoredDataUrls.cs @@ -0,0 +1,8 @@ +namespace Hutopy.Infrastructure.Identity.OwnedEntities; + +public class StoredDataUrls +{ + public string BannerPictureUrl { get; set; } = string.Empty; + public string ProfilePictureUrl { get; set; } = string.Empty; + public string WebsiteIconUrl { get; set; } = string.Empty; +} diff --git a/src/Infrastructure/Migrations/20240630163057_AddMoreInformationsToUser.Designer.cs b/src/Infrastructure/Migrations/20240630163057_AddMoreInformationsToUser.Designer.cs new file mode 100644 index 0000000..af10f04 --- /dev/null +++ b/src/Infrastructure/Migrations/20240630163057_AddMoreInformationsToUser.Designer.cs @@ -0,0 +1,557 @@ +// +using System; +using Hutopy.Infrastructure.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Hutopy.Infrastructure.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + [Migration("20240630163057_AddMoreInformationsToUser")] + partial class AddMoreInformationsToUser + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.3") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("Hutopy.Domain.Entities.FutureCreator", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Created") + .HasColumnType("datetimeoffset"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("EmailAddress") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("FirstName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("LastModified") + .HasColumnType("datetimeoffset"); + + b.Property("LastModifiedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("LastName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumber") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("ReasonToJoin") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("SocialNetworkAccount") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("FutureCreators"); + }); + + modelBuilder.Entity("Hutopy.Domain.Entities.UserTransaction", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Amount") + .HasPrecision(18, 2) + .HasColumnType("decimal(18,2)"); + + b.Property("ApplicationUserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.Property("Created") + .HasColumnType("datetimeoffset"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("Currency") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("IsConfirmed") + .HasColumnType("bit"); + + b.Property("LastModified") + .HasColumnType("datetimeoffset"); + + b.Property("LastModifiedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("Paid") + .HasColumnType("bit"); + + b.Property("StripeBillingDetailEmail") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("StripeBillingDetailName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("StripeChargeId") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("StripeEventId") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("StripePaymentIntent") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("StripePaymentMethod") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("StripeReceiptUrl") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("TipMessage") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationUserId"); + + b.ToTable("UserTransactions"); + }); + + modelBuilder.Entity("Hutopy.Infrastructure.Identity.ApplicationUser", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("About") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("AccessFailedCount") + .HasColumnType("int"); + + b.Property("Address") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("BirthDate") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("City") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("nvarchar(max)"); + + b.Property("Country") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Description") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("EmailConfirmed") + .HasColumnType("bit"); + + b.Property("FirstName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("LastName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("LockoutEnabled") + .HasColumnType("bit"); + + b.Property("LockoutEnd") + .HasColumnType("datetimeoffset"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("Occupation") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("PasswordHash") + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumber") + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("bit"); + + b.Property("SecurityStamp") + .HasColumnType("nvarchar(max)"); + + b.Property("TwoFactorEnabled") + .HasColumnType("bit"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex") + .HasFilter("[NormalizedUserName] IS NOT NULL"); + + b.ToTable("AspNetUsers", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("nvarchar(max)"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex") + .HasFilter("[NormalizedName] IS NOT NULL"); + + b.ToTable("AspNetRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("nvarchar(max)"); + + b.Property("ClaimValue") + .HasColumnType("nvarchar(max)"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("nvarchar(max)"); + + b.Property("ClaimValue") + .HasColumnType("nvarchar(max)"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("nvarchar(450)"); + + b.Property("ProviderKey") + .HasColumnType("nvarchar(450)"); + + b.Property("ProviderDisplayName") + .HasColumnType("nvarchar(max)"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("nvarchar(450)"); + + b.Property("RoleId") + .HasColumnType("nvarchar(450)"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("nvarchar(450)"); + + b.Property("LoginProvider") + .HasColumnType("nvarchar(450)"); + + b.Property("Name") + .HasColumnType("nvarchar(450)"); + + b.Property("Value") + .HasColumnType("nvarchar(max)"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens", (string)null); + }); + + modelBuilder.Entity("Hutopy.Domain.Entities.UserTransaction", b => + { + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("ApplicationUserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Hutopy.Infrastructure.Identity.ApplicationUser", b => + { + b.OwnsOne("Hutopy.Infrastructure.Identity.OwnedEntities.ProfileColors", "ProfileColors", b1 => + { + b1.Property("ApplicationUserId") + .HasColumnType("nvarchar(450)"); + + b1.Property("Accent") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.Property("BannerBottom") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.Property("BannerTop") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.Property("Menu") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.HasKey("ApplicationUserId"); + + b1.ToTable("ApplicationUser_ProfileColors", (string)null); + + b1.WithOwner() + .HasForeignKey("ApplicationUserId"); + }); + + b.OwnsOne("Hutopy.Infrastructure.Identity.OwnedEntities.SocialNetworks", "SocialNetworks", b1 => + { + b1.Property("ApplicationUserId") + .HasColumnType("nvarchar(450)"); + + b1.Property("FacebookUrl") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.Property("InstagramUrl") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.Property("LinkedInUrl") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.Property("RedditUrl") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.Property("TikTokUrl") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.Property("XUrl") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.Property("YourWebsiteUrl") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.Property("YoutubeUrl") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.HasKey("ApplicationUserId"); + + b1.ToTable("ApplicationUser_SocialNetworks", (string)null); + + b1.WithOwner() + .HasForeignKey("ApplicationUserId"); + }); + + b.OwnsOne("Hutopy.Infrastructure.Identity.OwnedEntities.StoredDataUrls", "StoredDataUrls", b1 => + { + b1.Property("ApplicationUserId") + .HasColumnType("nvarchar(450)"); + + b1.Property("BannerPictureUrl") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.Property("ProfilePictureUrl") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.Property("WebsiteIconUrl") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.HasKey("ApplicationUserId"); + + b1.ToTable("ApplicationUser_StoredDataUrls", (string)null); + + b1.WithOwner() + .HasForeignKey("ApplicationUserId"); + }); + + b.Navigation("ProfileColors") + .IsRequired(); + + b.Navigation("SocialNetworks") + .IsRequired(); + + b.Navigation("StoredDataUrls") + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Infrastructure/Migrations/20240630163057_AddMoreInformationsToUser.cs b/src/Infrastructure/Migrations/20240630163057_AddMoreInformationsToUser.cs new file mode 100644 index 0000000..85e7b7e --- /dev/null +++ b/src/Infrastructure/Migrations/20240630163057_AddMoreInformationsToUser.cs @@ -0,0 +1,77 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Hutopy.Infrastructure.Migrations +{ + /// + public partial class AddMoreInformationsToUser : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "ApplicationUser_ProfileColors", + columns: table => new + { + ApplicationUserId = table.Column(type: "nvarchar(450)", nullable: false), + BannerTop = table.Column(type: "nvarchar(max)", nullable: false), + BannerBottom = table.Column(type: "nvarchar(max)", nullable: false), + Accent = table.Column(type: "nvarchar(max)", nullable: false), + Menu = table.Column(type: "nvarchar(max)", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_ApplicationUser_ProfileColors", x => x.ApplicationUserId); + table.ForeignKey( + name: "FK_ApplicationUser_ProfileColors_AspNetUsers_ApplicationUserId", + column: x => x.ApplicationUserId, + principalTable: "AspNetUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.Sql(@" + INSERT INTO ApplicationUser_ProfileColors (ApplicationUserId, BannerTop, BannerBottom, Accent, Menu) + SELECT Id, '', '', '', '' + FROM AspNetUsers + "); + + migrationBuilder.CreateTable( + name: "ApplicationUser_StoredDataUrls", + columns: table => new + { + ApplicationUserId = table.Column(type: "nvarchar(450)", nullable: false), + BannerPictureUrl = table.Column(type: "nvarchar(max)", nullable: false), + ProfilePictureUrl = table.Column(type: "nvarchar(max)", nullable: false), + WebsiteIconUrl = table.Column(type: "nvarchar(max)", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_ApplicationUser_StoredDataUrls", x => x.ApplicationUserId); + table.ForeignKey( + name: "FK_ApplicationUser_StoredDataUrls_AspNetUsers_ApplicationUserId", + column: x => x.ApplicationUserId, + principalTable: "AspNetUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.Sql(@" + INSERT INTO ApplicationUser_StoredDataUrls (ApplicationUserId, BannerPictureUrl, ProfilePictureUrl, WebsiteIconUrl) + SELECT Id, '', '', '' + FROM AspNetUsers + "); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "ApplicationUser_ProfileColors"); + + migrationBuilder.DropTable( + name: "ApplicationUser_StoredDataUrls"); + } + } +} diff --git a/src/Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs b/src/Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs index cd78f54..12a98ec 100644 --- a/src/Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs +++ b/src/Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs @@ -389,6 +389,35 @@ namespace Hutopy.Infrastructure.Migrations modelBuilder.Entity("Hutopy.Infrastructure.Identity.ApplicationUser", b => { + b.OwnsOne("Hutopy.Infrastructure.Identity.OwnedEntities.ProfileColors", "ProfileColors", b1 => + { + b1.Property("ApplicationUserId") + .HasColumnType("nvarchar(450)"); + + b1.Property("Accent") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.Property("BannerBottom") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.Property("BannerTop") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.Property("Menu") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.HasKey("ApplicationUserId"); + + b1.ToTable("ApplicationUser_ProfileColors", (string)null); + + b1.WithOwner() + .HasForeignKey("ApplicationUserId"); + }); + b.OwnsOne("Hutopy.Infrastructure.Identity.OwnedEntities.SocialNetworks", "SocialNetworks", b1 => { b1.Property("ApplicationUserId") @@ -434,8 +463,39 @@ namespace Hutopy.Infrastructure.Migrations .HasForeignKey("ApplicationUserId"); }); + b.OwnsOne("Hutopy.Infrastructure.Identity.OwnedEntities.StoredDataUrls", "StoredDataUrls", b1 => + { + b1.Property("ApplicationUserId") + .HasColumnType("nvarchar(450)"); + + b1.Property("BannerPictureUrl") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.Property("ProfilePictureUrl") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.Property("WebsiteIconUrl") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.HasKey("ApplicationUserId"); + + b1.ToTable("ApplicationUser_StoredDataUrls", (string)null); + + b1.WithOwner() + .HasForeignKey("ApplicationUserId"); + }); + + b.Navigation("ProfileColors") + .IsRequired(); + b.Navigation("SocialNetworks") .IsRequired(); + + b.Navigation("StoredDataUrls") + .IsRequired(); }); modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => diff --git a/src/Infrastructure/Stripe/StripeService.cs b/src/Infrastructure/Stripe/StripeService.cs index 7b78fff..3f4e366 100644 --- a/src/Infrastructure/Stripe/StripeService.cs +++ b/src/Infrastructure/Stripe/StripeService.cs @@ -1,3 +1,6 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; using Stripe; using Stripe.Checkout; using Hutopy.Application.Common.Interfaces; diff --git a/src/Web/Controllers/GoogleController.cs b/src/Web/Controllers/GoogleController.cs index dfaa91e..8206069 100644 --- a/src/Web/Controllers/GoogleController.cs +++ b/src/Web/Controllers/GoogleController.cs @@ -71,7 +71,7 @@ public class GoogleController(IIdentityService identityService, IHttpClientFacto user.Email, user.FirstName, user.LastName, - user.PortraitUrl); + user.ProfilePictureUrl); return Ok(new { accessToken = token, email }); } diff --git a/src/Web/Endpoints/UpdateMyUser.cs b/src/Web/Endpoints/UpdateMyUser.cs index 60121be..9aca4dc 100644 --- a/src/Web/Endpoints/UpdateMyUser.cs +++ b/src/Web/Endpoints/UpdateMyUser.cs @@ -8,6 +8,9 @@ public class UpdateMyUser : EndpointGroupBase { app.MapGroup(this) .RequireAuthorization() + .MapPost(UpdateCurrentUserProfilePicture, "/profile-picture") + .MapPost(UpdateCurrentUserBannerPicture, "/banner-picture") + .MapPost(UpdateCurrentUserWebsiteIcon, "/website-icon") .MapPatch("/profile", UpdateCurrentUser); } @@ -16,5 +19,21 @@ public class UpdateMyUser : EndpointGroupBase return await sender.Send(command); } + private static async Task UpdateCurrentUserProfilePicture(ISender sender, Stream stream) + { + var command = new UploadProfilePictureCommand { ProfilePicture = stream }; + return await sender.Send(command); + } + private static async Task UpdateCurrentUserBannerPicture(ISender sender, Stream stream) + { + var command = new UploadBannerPictureCommand { BannerPicture = stream }; + return await sender.Send(command); + } + + private static async Task UpdateCurrentUserWebsiteIcon(ISender sender, Stream stream) + { + var command = new UploadWebsiteIconCommand { WebsiteIcon = stream }; + return await sender.Send(command); + } } From 90d76c32ce9813aa5bcd0a3ef1d194ad1e050755 Mon Sep 17 00:00:00 2001 From: Dominic Villemure Date: Sun, 30 Jun 2024 12:39:24 -0400 Subject: [PATCH 075/229] Add storedDataUrls to GetCurrentUser --- src/Application/Common/Models/UserModel.cs | 1 + src/Application/Users/Models/StoredDataUrlsModel.cs | 8 ++++++++ .../Users/Queries/GetCurrentUser/GetCurrentUser.cs | 2 ++ .../Users/Queries/GetCurrentUser/UserDto.cs | 2 ++ src/Infrastructure/Identity/IdentityService.cs | 12 ++++++++++++ 5 files changed, 25 insertions(+) create mode 100644 src/Application/Users/Models/StoredDataUrlsModel.cs diff --git a/src/Application/Common/Models/UserModel.cs b/src/Application/Common/Models/UserModel.cs index 9fceab9..fb76755 100644 --- a/src/Application/Common/Models/UserModel.cs +++ b/src/Application/Common/Models/UserModel.cs @@ -19,5 +19,6 @@ public class UserModel public string Description { get; init; } = string.Empty; public SocialNetworksModel SocialNetworks { get; init; } = new(); public ProfileColorsModel ProfileColors { get; init; } = new(); + public StoredDataUrlsModel StoredDataUrls { get; init; } = new(); public string ProfilePictureUrl { get; set; } = string.Empty; } diff --git a/src/Application/Users/Models/StoredDataUrlsModel.cs b/src/Application/Users/Models/StoredDataUrlsModel.cs new file mode 100644 index 0000000..0539508 --- /dev/null +++ b/src/Application/Users/Models/StoredDataUrlsModel.cs @@ -0,0 +1,8 @@ +namespace Hutopy.Application.Users.Models; + +public class StoredDataUrlsModel +{ + public string BannerPictureUrl { get; set; } = string.Empty; + public string ProfilePictureUrl { get; set; } = string.Empty; + public string WebsiteIconUrl { get; set; } = string.Empty; +} diff --git a/src/Application/Users/Queries/GetCurrentUser/GetCurrentUser.cs b/src/Application/Users/Queries/GetCurrentUser/GetCurrentUser.cs index eeb9f7c..2fef51c 100644 --- a/src/Application/Users/Queries/GetCurrentUser/GetCurrentUser.cs +++ b/src/Application/Users/Queries/GetCurrentUser/GetCurrentUser.cs @@ -41,6 +41,8 @@ public class GetCurrentUserQueryHandler( About = identityUser.About ?? "", Description = identityUser.Description ?? "", SocialNetworks = identityUser.SocialNetworks, + ProfileColors = identityUser.ProfileColors, + StoredDataUrls = identityUser.StoredDataUrls, UserTransactions = transactions, TotalBalance = transactions.Sum(x => x.Amount), UserRoles = roles, diff --git a/src/Application/Users/Queries/GetCurrentUser/UserDto.cs b/src/Application/Users/Queries/GetCurrentUser/UserDto.cs index ec2cc5d..24cb7fd 100644 --- a/src/Application/Users/Queries/GetCurrentUser/UserDto.cs +++ b/src/Application/Users/Queries/GetCurrentUser/UserDto.cs @@ -18,6 +18,8 @@ public class UserDto public string About { get; init; } = string.Empty; public string Description { get; init; } = string.Empty; public SocialNetworksModel SocialNetworks { get; init; } = new(); + public ProfileColorsModel ProfileColors { get; init; } = new(); + public StoredDataUrlsModel StoredDataUrls { get; init; } = new(); public List UserTransactions { get; init; } = []; public IList UserRoles { get; init; } = []; public required decimal TotalBalance { get; init; } diff --git a/src/Infrastructure/Identity/IdentityService.cs b/src/Infrastructure/Identity/IdentityService.cs index c0f8a9b..d159de4 100644 --- a/src/Infrastructure/Identity/IdentityService.cs +++ b/src/Infrastructure/Identity/IdentityService.cs @@ -171,6 +171,12 @@ public class IdentityService( BannerBottom = response.ProfileColors.BannerBottom, Accent = response.ProfileColors.Accent, Menu = response.ProfileColors.Menu + }, + StoredDataUrls = new StoredDataUrlsModel + { + ProfilePictureUrl = response.StoredDataUrls.ProfilePictureUrl, + BannerPictureUrl = response.StoredDataUrls.BannerPictureUrl, + WebsiteIconUrl = response.StoredDataUrls.WebsiteIconUrl, } }; @@ -215,6 +221,12 @@ public class IdentityService( BannerBottom = response.ProfileColors.BannerBottom, Accent = response.ProfileColors.Accent, Menu = response.ProfileColors.Menu + }, + StoredDataUrls = new StoredDataUrlsModel + { + ProfilePictureUrl = response.StoredDataUrls.ProfilePictureUrl, + BannerPictureUrl = response.StoredDataUrls.BannerPictureUrl, + WebsiteIconUrl = response.StoredDataUrls.WebsiteIconUrl, } }; From 041b8178acbe798cc06fff0505b48e3b7687c1a5 Mon Sep 17 00:00:00 2001 From: Dominic Villemure Date: Sun, 30 Jun 2024 15:48:26 -0400 Subject: [PATCH 076/229] Mapping + changed Phone to PhoneNumber --- src/Application/Common/Models/UserModel.cs | 2 +- .../Commands/UpdateCurrentUserCommand.cs | 20 ++++++++++++++++--- .../Queries/GetCurrentUser/GetCurrentUser.cs | 2 +- .../Users/Queries/GetCurrentUser/UserDto.cs | 3 +-- .../Identity/IdentityService.cs | 6 +++--- 5 files changed, 23 insertions(+), 10 deletions(-) diff --git a/src/Application/Common/Models/UserModel.cs b/src/Application/Common/Models/UserModel.cs index fb76755..ccff715 100644 --- a/src/Application/Common/Models/UserModel.cs +++ b/src/Application/Common/Models/UserModel.cs @@ -10,7 +10,7 @@ public class UserModel public string LastName { get; set; } = string.Empty; public string Occupation { get; set; } = string.Empty; public string Email { get; init; } = string.Empty; - public string Phone { get; init; } = string.Empty; + public string PhoneNumber { get; init; } = string.Empty; public string BirthDate { get; init; } = string.Empty; public string Country { get; init; } = string.Empty; public string City { get; init; } = string.Empty; diff --git a/src/Application/Users/Commands/UpdateCurrentUserCommand.cs b/src/Application/Users/Commands/UpdateCurrentUserCommand.cs index 708ea6b..193d904 100644 --- a/src/Application/Users/Commands/UpdateCurrentUserCommand.cs +++ b/src/Application/Users/Commands/UpdateCurrentUserCommand.cs @@ -1,4 +1,6 @@ -using Hutopy.Application.Common.Interfaces; +using System.ComponentModel.DataAnnotations.Schema; +using Hutopy.Application.Common.Interfaces; +using Hutopy.Application.Common.Models; using Hutopy.Application.Users.Models; namespace Hutopy.Application.Users.Commands; @@ -17,9 +19,18 @@ public class UpdateCurrentUserCommand : IRequest public required string Description { get; init; } public required SocialNetworksModel SocialNetworks { get; init; } public required ProfileColorsModel ProfileColors { get; init; } + + [NotMapped] + private class Mapping : Profile + { + public Mapping() + { + CreateMap(); + } + } } -public class UpdateCurrentUserCommandHandler(IApplicationDbContext context, IIdentityService identityService) : +public class UpdateCurrentUserCommandHandler(IApplicationDbContext context, IIdentityService identityService, IMapper mapper) : IRequestHandler { public async Task Handle(UpdateCurrentUserCommand request, CancellationToken cancellationToken) @@ -27,8 +38,11 @@ public class UpdateCurrentUserCommandHandler(IApplicationDbContext context, IIde var identityUser = await identityService.GetCurrentUserAsync(); if (identityUser?.Id is null) return string.Empty; + + var userModel = mapper.Map(request); + userModel.Id = identityUser.Id; - var result = await identityService.UpdateCurrentUserAsync(identityUser); + var result = await identityService.UpdateCurrentUserAsync(userModel); await context.SaveChangesAsync(cancellationToken); diff --git a/src/Application/Users/Queries/GetCurrentUser/GetCurrentUser.cs b/src/Application/Users/Queries/GetCurrentUser/GetCurrentUser.cs index 2fef51c..f8cc1ab 100644 --- a/src/Application/Users/Queries/GetCurrentUser/GetCurrentUser.cs +++ b/src/Application/Users/Queries/GetCurrentUser/GetCurrentUser.cs @@ -32,7 +32,7 @@ public class GetCurrentUserQueryHandler( LastName = identityUser.LastName ?? "", UserName = identityUser.UserName ?? "", Occupation = identityUser.Occupation ?? "", - Phone = identityUser.Phone ?? "", + PhoneNumber = identityUser.PhoneNumber ?? "", Email = identityUser.Email ?? "", BirthDate = identityUser.BirthDate ?? "", Country = identityUser.Country ?? "", diff --git a/src/Application/Users/Queries/GetCurrentUser/UserDto.cs b/src/Application/Users/Queries/GetCurrentUser/UserDto.cs index 24cb7fd..23dfaa8 100644 --- a/src/Application/Users/Queries/GetCurrentUser/UserDto.cs +++ b/src/Application/Users/Queries/GetCurrentUser/UserDto.cs @@ -10,7 +10,7 @@ public class UserDto public string UserName { get; init; } = string.Empty; public string Occupation { get; init; } = string.Empty; public string Email { get; init; } = string.Empty; - public string Phone { get; init; } = string.Empty; + public string PhoneNumber { get; init; } = string.Empty; public string BirthDate { get; init; } = string.Empty; public string Country { get; init; } = string.Empty; public string City { get; init; } = string.Empty; @@ -23,5 +23,4 @@ public class UserDto public List UserTransactions { get; init; } = []; public IList UserRoles { get; init; } = []; public required decimal TotalBalance { get; init; } - } diff --git a/src/Infrastructure/Identity/IdentityService.cs b/src/Infrastructure/Identity/IdentityService.cs index d159de4..b0be8f2 100644 --- a/src/Infrastructure/Identity/IdentityService.cs +++ b/src/Infrastructure/Identity/IdentityService.cs @@ -97,7 +97,7 @@ public class IdentityService( applicationUser.FirstName = userModel.FirstName; applicationUser.LastName = userModel.LastName; applicationUser.Occupation = userModel.Occupation; - applicationUser.PhoneNumber = userModel.Phone; + applicationUser.PhoneNumber = userModel.PhoneNumber; applicationUser.BirthDate = userModel.BirthDate; applicationUser.Country = userModel.Country; applicationUser.City = userModel.City; @@ -147,7 +147,7 @@ public class IdentityService( LastName = response.LastName, Email = response.Email ?? string.Empty, Occupation = response.Occupation, - Phone = response.PhoneNumber ?? string.Empty, + PhoneNumber = response.PhoneNumber ?? string.Empty, BirthDate = response.BirthDate, Country = response.Country, City = response.City, @@ -197,7 +197,7 @@ public class IdentityService( LastName = response.LastName, Email = response.Email ?? string.Empty, Occupation = response.Occupation, - Phone = response.PhoneNumber ?? string.Empty, + PhoneNumber = response.PhoneNumber ?? string.Empty, BirthDate = response.BirthDate, Country = response.Country, City = response.City, From 9481840244ba0a2d2c4be3bd91828fa2f3684f60 Mon Sep 17 00:00:00 2001 From: Dominic Villemure Date: Sun, 30 Jun 2024 23:40:57 -0400 Subject: [PATCH 077/229] Added content type --- .../AzureBlobStorage/Constants/CommonFileNames.cs | 6 +++--- .../AzureBlobStorage/Constants/ContentTypes.cs | 6 ++++++ .../Common/Interfaces/IAzureBlobStorageService.cs | 2 +- .../Users/Commands/UploadBannerPicture.cs | 2 +- .../Users/Commands/UploadProfilePicture.cs | 2 +- .../Users/Commands/UploadWebsiteIcon.cs | 2 +- .../AzureBlob/AzureBlobStorageService.cs | 14 ++++++++++++-- 7 files changed, 25 insertions(+), 9 deletions(-) create mode 100644 src/Application/AzureBlobStorage/Constants/ContentTypes.cs diff --git a/src/Application/AzureBlobStorage/Constants/CommonFileNames.cs b/src/Application/AzureBlobStorage/Constants/CommonFileNames.cs index b6d44aa..8ffc63c 100644 --- a/src/Application/AzureBlobStorage/Constants/CommonFileNames.cs +++ b/src/Application/AzureBlobStorage/Constants/CommonFileNames.cs @@ -2,7 +2,7 @@ public static class CommonFileNames { - public static string ProfilePicture = "profilePicture"; - public static string BannerPicture = "bannerPicture"; - public static string WebsiteIcon = "websiteIcon"; + public static string ProfilePicture = "profilePicture.png"; + public static string BannerPicture = "bannerPicture.png"; + public static string WebsiteIcon = "websiteIcon.png"; } diff --git a/src/Application/AzureBlobStorage/Constants/ContentTypes.cs b/src/Application/AzureBlobStorage/Constants/ContentTypes.cs new file mode 100644 index 0000000..ff3bcf7 --- /dev/null +++ b/src/Application/AzureBlobStorage/Constants/ContentTypes.cs @@ -0,0 +1,6 @@ +namespace Hutopy.Application.AzureBlobStorage.Constants; + +public static class ContentTypes +{ + public static string ImagePng = "image/png"; +} diff --git a/src/Application/Common/Interfaces/IAzureBlobStorageService.cs b/src/Application/Common/Interfaces/IAzureBlobStorageService.cs index c8bdd20..a397ce0 100644 --- a/src/Application/Common/Interfaces/IAzureBlobStorageService.cs +++ b/src/Application/Common/Interfaces/IAzureBlobStorageService.cs @@ -2,6 +2,6 @@ public interface IAzureBlobStorageService { - Task UploadFileAsync(string containerName, string blobName, Stream fileStream); + Task UploadFileAsync(string containerName, string blobName, Stream fileStream, string contentType); Task DownloadFileAsync(string containerName, string blobName); } diff --git a/src/Application/Users/Commands/UploadBannerPicture.cs b/src/Application/Users/Commands/UploadBannerPicture.cs index 66922a6..ae8e783 100644 --- a/src/Application/Users/Commands/UploadBannerPicture.cs +++ b/src/Application/Users/Commands/UploadBannerPicture.cs @@ -17,7 +17,7 @@ public class UploadBannerPictureCommandHandler(IIdentityService identityService, var blobName = $"{currentUserId}/{SubDirectoryNames.Profile}/{CommonFileNames.BannerPicture}"; - var url = await azureBlobStorageService.UploadFileAsync(ContainerNames.Users, blobName, request.BannerPicture); + var url = await azureBlobStorageService.UploadFileAsync(ContainerNames.Users, blobName, request.BannerPicture, ContentTypes.ImagePng); await identityService.UpdateCurrentUserBannerPictureUrlAsync(url); diff --git a/src/Application/Users/Commands/UploadProfilePicture.cs b/src/Application/Users/Commands/UploadProfilePicture.cs index 6fc4714..154ace7 100644 --- a/src/Application/Users/Commands/UploadProfilePicture.cs +++ b/src/Application/Users/Commands/UploadProfilePicture.cs @@ -17,7 +17,7 @@ public class UploadProfilePictureCommandHandler(IIdentityService identityService var blobName = $"{currentUserId}/{SubDirectoryNames.Profile}/{CommonFileNames.ProfilePicture}"; - var url = await azureBlobStorageService.UploadFileAsync(ContainerNames.Users, blobName, request.ProfilePicture); + var url = await azureBlobStorageService.UploadFileAsync(ContainerNames.Users, blobName, request.ProfilePicture, ContentTypes.ImagePng); await identityService.UpdateCurrentUserProfilePictureUrlAsync(url); diff --git a/src/Application/Users/Commands/UploadWebsiteIcon.cs b/src/Application/Users/Commands/UploadWebsiteIcon.cs index 78a83a2..26caa25 100644 --- a/src/Application/Users/Commands/UploadWebsiteIcon.cs +++ b/src/Application/Users/Commands/UploadWebsiteIcon.cs @@ -17,7 +17,7 @@ public class UploadWebsiteIconCommandHandler(IIdentityService identityService, I var blobName = $"{currentUserId}/{SubDirectoryNames.Profile}/{CommonFileNames.WebsiteIcon}"; - var url = await azureBlobStorageService.UploadFileAsync(ContainerNames.Users, blobName, request.WebsiteIcon); + var url = await azureBlobStorageService.UploadFileAsync(ContainerNames.Users, blobName, request.WebsiteIcon, ContentTypes.ImagePng); await identityService.UpdateCurrentUserWebsiteIconUrlAsync(url); diff --git a/src/Infrastructure/AzureBlob/AzureBlobStorageService.cs b/src/Infrastructure/AzureBlob/AzureBlobStorageService.cs index b25521c..18d7856 100644 --- a/src/Infrastructure/AzureBlob/AzureBlobStorageService.cs +++ b/src/Infrastructure/AzureBlob/AzureBlobStorageService.cs @@ -25,8 +25,9 @@ public class AzureBlobStorageService : IAzureBlobStorageService /// The blob name (path within the container, include the file name). /// The name of the container where the file is stored. /// The stream. + /// The content type. /// - public async Task UploadFileAsync(string containerName, string blobName, Stream fileStream) + public async Task UploadFileAsync(string containerName, string blobName, Stream fileStream, string contentType) { // Get a reference to a container var containerClient = _blobServiceClient.GetBlobContainerClient(containerName); @@ -36,9 +37,18 @@ public class AzureBlobStorageService : IAzureBlobStorageService // Get a reference to a blob var blobClient = containerClient.GetBlobClient(blobName); + + // Define the BlobHttpHeaders to include the content type + var blobHttpHeaders = new BlobHttpHeaders + { + ContentType = contentType + }; // Upload the file - await blobClient.UploadAsync(fileStream, true); + await blobClient.UploadAsync(fileStream, new BlobUploadOptions + { + HttpHeaders = blobHttpHeaders + }); // Return the URI of the uploaded blob return blobClient.Uri.ToString(); From 006a566b93f47dc557cb8bfdd416ece48c19e701 Mon Sep 17 00:00:00 2001 From: Jonathan Bourdon Date: Thu, 20 Jun 2024 13:40:27 -0400 Subject: [PATCH 078/229] Cleanup of appsettings files --- src/Web/appsettings.Development.dist | 17 ----------------- src/Web/appsettings.json | 3 --- 2 files changed, 20 deletions(-) delete mode 100644 src/Web/appsettings.Development.dist diff --git a/src/Web/appsettings.Development.dist b/src/Web/appsettings.Development.dist deleted file mode 100644 index 25369fa..0000000 --- a/src/Web/appsettings.Development.dist +++ /dev/null @@ -1,17 +0,0 @@ -{ - "Logging": { - "LogLevel": { - "Default": "Information", - "Microsoft": "Information", - "Microsoft.AspNetCore.SpaProxy": "Information", - "Microsoft.Hosting.Lifetime": "Information" - } - }, - "Google-ClientId": "", - "Google-ClientSecret": "", - "Facebook-ClientId": "", - "Facebook-ClientSecret": "", - "Jwt-Audience": "", - "Jwt-Issuer": "", - "Jwt-Key": "", -} \ No newline at end of file diff --git a/src/Web/appsettings.json b/src/Web/appsettings.json index 76a510b..222224e 100644 --- a/src/Web/appsettings.json +++ b/src/Web/appsettings.json @@ -1,7 +1,4 @@ { - "ConnectionStrings": { - "DefaultConnection": "Server={DB_HOST},1433;Database=Hutopy;User Id=sa;Password={DB_PASSWORD};MultipleActiveResultSets=true;TrustServerCertificate=True" - }, "Logging": { "LogLevel": { "Default": "Information", From 1725008211d8724c33b8460f0ef298c3fbd9b823 Mon Sep 17 00:00:00 2001 From: Jonathan Bourdon Date: Thu, 20 Jun 2024 13:40:55 -0400 Subject: [PATCH 079/229] Fix issue with missing configuration for Facebook or Google --- .../Identity/IdentityService.cs | 11 ++- src/Web/DependencyInjection.cs | 74 ++++++++++++------- 2 files changed, 54 insertions(+), 31 deletions(-) diff --git a/src/Infrastructure/Identity/IdentityService.cs b/src/Infrastructure/Identity/IdentityService.cs index 02b5ce0..9997316 100644 --- a/src/Infrastructure/Identity/IdentityService.cs +++ b/src/Infrastructure/Identity/IdentityService.cs @@ -218,12 +218,15 @@ public class IdentityService( { return null; } - + var user = await GetUserByUserNameAsync(userName); + + var jwtSection = configuration.GetRequiredSection("Authentication:Jwt"); + var token = JwtTokenHelper.GenerateJwtToken( - issuer: configuration["Jwt-Issuer"] ?? "", - audience: configuration["Jwt-Audience"] ?? "", - key: configuration["Jwt-Key"] ?? "", + issuer: jwtSection["Issuer"] ?? "", + audience: jwtSection["Audience"] ?? "", + key: jwtSection["Key"] ?? "", userId: user?.Id ?? ""); return token; diff --git a/src/Web/DependencyInjection.cs b/src/Web/DependencyInjection.cs index 3a7eb61..27f1ac1 100644 --- a/src/Web/DependencyInjection.cs +++ b/src/Web/DependencyInjection.cs @@ -30,7 +30,7 @@ public static class DependencyInjection services.AddExceptionHandler(); services.AddRazorPages(); - + services.AddHttpClient(); // Customise default API behaviour @@ -44,13 +44,16 @@ public static class DependencyInjection configure.Title = "Hutopy API"; // Add JWT - configure.AddSecurity("JWT", Enumerable.Empty(), new OpenApiSecurityScheme - { - Type = OpenApiSecuritySchemeType.ApiKey, - Name = "Authorization", - In = OpenApiSecurityApiKeyLocation.Header, - Description = "Type into the textbox: Bearer {your JWT token}." - }); + 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")); }); @@ -58,7 +61,8 @@ public static class DependencyInjection return services; } - public static IServiceCollection AddKeyVaultIfConfigured(this IServiceCollection services, ConfigurationManager configuration) + public static IServiceCollection AddKeyVaultIfConfigured(this IServiceCollection services, + ConfigurationManager configuration) { var keyVaultUri = configuration["KeyVaultUri"]; if (!string.IsNullOrWhiteSpace(keyVaultUri)) @@ -70,10 +74,11 @@ public static class DependencyInjection return services; } - - public static IServiceCollection AddAuthorizationAndAuthentication(this IServiceCollection services, ConfigurationManager configuration) + + public static IServiceCollection AddAuthorizationAndAuthentication(this IServiceCollection services, + ConfigurationManager configuration) { - services.AddAuthentication(options => + var authenticationBuilder = services.AddAuthentication(options => { options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme; options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme; @@ -82,35 +87,50 @@ public static class DependencyInjection { options.LoginPath = "/api/Users/login"; }) - .AddCookie() - .AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, jwtBearerOptions => + .AddCookie(); + + var authJwt = configuration.GetSection("Authentication:Jwt"); + if (authJwt.Exists()) + { + authenticationBuilder.AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, jwtBearerOptions => { jwtBearerOptions.Authority = "https://hutopy.com"; jwtBearerOptions.TokenValidationParameters = new TokenValidationParameters { ValidateIssuer = true, - ValidIssuer = configuration["Jwt-Issuer"], + ValidIssuer = authJwt["Issuer"], ValidateAudience = true, - ValidAudience = configuration["Jwt-Audience"], + ValidAudience = authJwt["Audience"], ValidateLifetime = true, - IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(configuration["Jwt-Key"] ?? + IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(authJwt["Key"] ?? throw new ArgumentNullException("The Jwt Key is missing."))) }; - }) - .AddGoogle(GoogleDefaults.AuthenticationScheme, options => + }); + } + + var authGoogle = configuration.GetSection("Authentication:Google"); + if (authGoogle.Exists()) + { + authenticationBuilder.AddGoogle(GoogleDefaults.AuthenticationScheme, options => { - options.ClientId = configuration["Google-ClientId"] ?? - throw new ArgumentNullException("The Google ClientId is missing.");; - options.ClientSecret = configuration["Google-ClientSecret"] ?? - throw new ArgumentNullException("The Google ClientSecret is missing.");; - }) - .AddFacebook(FacebookDefaults.AuthenticationScheme, options => + options.ClientId = authGoogle["ClientId"] ?? + throw new ArgumentNullException("The Google ClientId is missing."); + options.ClientSecret = authGoogle["ClientSecret"] ?? + throw new ArgumentNullException("The Google ClientSecret is missing."); + }); + } + + var authFacebook = configuration.GetSection("Authentication:Facebook"); + if (authFacebook.Exists()) + { + authenticationBuilder.AddFacebook(FacebookDefaults.AuthenticationScheme, options => { - options.ClientId = configuration["Facebook-ClientId"] ?? + options.ClientId = authFacebook["ClientId"] ?? throw new ArgumentNullException("The Facebook ClientId is missing."); - options.ClientSecret = configuration["Facebook-ClientSecret"] ?? + options.ClientSecret = authFacebook["ClientSecret"] ?? throw new ArgumentNullException("The Facebook ClientSecret is missing."); }); + } return services; } From 128e68f63f9f160edd04cd5f46b30959a5fbe16b Mon Sep 17 00:00:00 2001 From: Jonathan Bourdon Date: Thu, 20 Jun 2024 13:44:45 -0400 Subject: [PATCH 080/229] Just cleanup --- .../Queries/GetCurrentUser/GetCurrentUser.cs | 8 +-- src/Infrastructure/Utils/GenerateJwtToken.cs | 14 ++--- src/Web/Controllers/FacebookController.cs | 44 ++++++++------- src/Web/Controllers/GoogleController.cs | 56 ++++++++++--------- 4 files changed, 63 insertions(+), 59 deletions(-) diff --git a/src/Application/Users/Queries/GetCurrentUser/GetCurrentUser.cs b/src/Application/Users/Queries/GetCurrentUser/GetCurrentUser.cs index 49f1152..7cbabd6 100644 --- a/src/Application/Users/Queries/GetCurrentUser/GetCurrentUser.cs +++ b/src/Application/Users/Queries/GetCurrentUser/GetCurrentUser.cs @@ -8,14 +8,14 @@ public class GetCurrentUserQueryHandler( IApplicationDbContext context, IMapper mapper, IIdentityService identityService - ) +) : IRequestHandler { public async Task Handle(GetCurrentUserQuery request, CancellationToken cancellationToken) { var identityUser = await identityService.GetCurrentUserAsync(); - var currentUserId = new Guid(identityUser?.Id ?? ""); - + var currentUserId = Guid.Parse(identityUser!.Id!); + var transactions = await context.UserTransactions .Where(x => x.ApplicationUserId == currentUserId.ToString()) .OrderBy(x => x.LastModified) @@ -30,7 +30,7 @@ public class GetCurrentUserQueryHandler( Id = currentUserId, FirstName = identityUser?.FirstName ?? "", LastName = identityUser?.LastName ?? "", - UserName =identityUser?.UserName ?? "", + UserName = identityUser?.UserName ?? "", UserTransactions = transactions, TotalBalance = transactions.Sum(x => x.Amount), UserRoles = roles diff --git a/src/Infrastructure/Utils/GenerateJwtToken.cs b/src/Infrastructure/Utils/GenerateJwtToken.cs index 9f01d6a..00423f9 100644 --- a/src/Infrastructure/Utils/GenerateJwtToken.cs +++ b/src/Infrastructure/Utils/GenerateJwtToken.cs @@ -9,20 +9,18 @@ public static class JwtTokenHelper { public static string GenerateJwtToken(string issuer, string audience, string key, string userId) { - var claims = new[] - { - new Claim(JwtRegisteredClaimNames.Sub, userId), - new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()), - new Claim(ClaimTypes.NameIdentifier, userId) - }; - var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(key)); var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256); var token = new JwtSecurityToken( issuer: issuer, audience: audience, - claims: claims, + claims: new[] + { + new Claim(JwtRegisteredClaimNames.Sub, userId), + new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()), + new Claim(ClaimTypes.NameIdentifier, userId) + }, expires: DateTime.Now.AddMinutes(30), signingCredentials: credentials); diff --git a/src/Web/Controllers/FacebookController.cs b/src/Web/Controllers/FacebookController.cs index 679502e..3178b5f 100644 --- a/src/Web/Controllers/FacebookController.cs +++ b/src/Web/Controllers/FacebookController.cs @@ -13,41 +13,45 @@ public class FacebookController(IIdentityService identityService) : Controller [HttpGet("/api/facebook/sign-in")] public async Task SignIn() { - await HttpContext.ChallengeAsync(FacebookDefaults.AuthenticationScheme, new AuthenticationProperties - { - RedirectUri = Url.Action("Authorize") - }); + await HttpContext.ChallengeAsync(FacebookDefaults.AuthenticationScheme, + new AuthenticationProperties { RedirectUri = Url.Action("Authorize") }); } public async Task Authorize() { var authenticateResult = await HttpContext.AuthenticateAsync(FacebookDefaults.AuthenticationScheme); - + if (!authenticateResult.Succeeded) return BadRequest(); - + var claims = authenticateResult.Principal.Claims.ToList(); - + var name = claims.FirstOrDefault(c => c.Type == ClaimTypes.Name)?.Value ?? ""; var email = claims.FirstOrDefault(c => c.Type == ClaimTypes.Email)?.Value ?? ""; var givenName = claims.FirstOrDefault(c => c.Type == ClaimTypes.GivenName)?.Value ?? ""; var familyName = claims.FirstOrDefault(c => c.Type == ClaimTypes.Surname)?.Value ?? ""; - - var claimsIdentity = new ClaimsIdentity(new List - { - new(ClaimTypes.Name, name), - new(ClaimTypes.Email, email), - new(ClaimTypes.GivenName, givenName), - new(ClaimTypes.Surname, familyName) - }, CookieAuthenticationDefaults.AuthenticationScheme); - + + var claimsIdentity = new ClaimsIdentity( + new List + { + new(ClaimTypes.Name, name), + new(ClaimTypes.Email, email), + new(ClaimTypes.GivenName, givenName), + new(ClaimTypes.Surname, familyName) + }, + CookieAuthenticationDefaults.AuthenticationScheme); + if (await identityService.FindUserByEmailAsync(email) != null) { - await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, new ClaimsPrincipal(claimsIdentity)); + await HttpContext.SignInAsync( + CookieAuthenticationDefaults.AuthenticationScheme, + new ClaimsPrincipal(claimsIdentity)); return Redirect("/"); } - - await identityService.CreateUserAsync(email, givenName, givenName, familyName, RandomGenerator.RandomString(24)); - await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, new ClaimsPrincipal(claimsIdentity)); + + await identityService.CreateUserAsync(email, givenName, givenName, familyName, + RandomGenerator.RandomString(24)); + await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, + new ClaimsPrincipal(claimsIdentity)); return Redirect("/"); } } diff --git a/src/Web/Controllers/GoogleController.cs b/src/Web/Controllers/GoogleController.cs index 6df233a..40e8adc 100644 --- a/src/Web/Controllers/GoogleController.cs +++ b/src/Web/Controllers/GoogleController.cs @@ -13,7 +13,8 @@ public class GoogleController(IIdentityService identityService, IHttpClientFacto [HttpPost("/api/google/sign-in")] public async Task SignIn([FromBody] GoogleSignInRequest request) { - var httpClient = httpClientFactory.CreateClient(); + using var httpClient = httpClientFactory.CreateClient(); + // Verify the token with Google var response = await httpClient.GetAsync($"https://www.googleapis.com/oauth2/v1/userinfo?access_token={request.AccessToken}"); if (!response.IsSuccessStatusCode) @@ -21,12 +22,11 @@ public class GoogleController(IIdentityService identityService, IHttpClientFacto return BadRequest("Invalid Google token."); } - var payload = JObject.Parse(await response.Content.ReadAsStringAsync()); - - var email = payload["email"]?.ToString() ?? ""; - var name = payload["name"]?.ToString() ?? ""; - var givenName = payload["given_name"]?.ToString() ?? ""; - var familyName = payload["family_name"]?.ToString() ?? ""; + var userInfo = JObject.Parse(await response.Content.ReadAsStringAsync()); + var email = userInfo["email"]?.ToString() ?? ""; + var name = userInfo["name"]?.ToString() ?? ""; + var givenName = userInfo["given_name"]?.ToString() ?? ""; + var familyName = userInfo["family_name"]?.ToString() ?? ""; if (string.IsNullOrEmpty(email)) { @@ -47,27 +47,29 @@ public class GoogleController(IIdentityService identityService, IHttpClientFacto } // Sign in the user - var claims = new List - { - new(ClaimTypes.Name, name), - new(ClaimTypes.Email, email), - new(ClaimTypes.GivenName, givenName), - new(ClaimTypes.Surname, familyName) - }; - - var claimsIdentity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme); - await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, new ClaimsPrincipal(claimsIdentity)); - - var issuer = configuration["Jwt-Issuer"] ?? - throw new ArgumentNullException("The Jwt issuer is missing."); - var audience = configuration["Jwt-Audience"] ?? - throw new ArgumentNullException("The Jwt audience is missing."); - var key = configuration["Jwt-Key"] ?? - throw new ArgumentNullException("The Jwt key is missing."); - - var jwtToken = JwtTokenHelper.GenerateJwtToken(issuer, audience, key, user.Id); + var claimsIdentity = new ClaimsIdentity( + new List + { + new(ClaimTypes.Name, name), + new(ClaimTypes.Email, email), + new(ClaimTypes.GivenName, givenName), + new(ClaimTypes.Surname, familyName) + }, + CookieAuthenticationDefaults.AuthenticationScheme); - return Ok(new { accessToken = jwtToken, email }); + await HttpContext.SignInAsync( + CookieAuthenticationDefaults.AuthenticationScheme, + new ClaimsPrincipal(claimsIdentity)); + + var jwtSection = configuration.GetRequiredSection("Authentication:Jwt"); + + var token = JwtTokenHelper.GenerateJwtToken( + issuer: jwtSection["Issuer"] ?? throw new ArgumentNullException("The Jwt issuer is missing."), + audience: jwtSection["Audience"] ?? throw new ArgumentNullException("The Jwt audience is missing."), + key: jwtSection["Key"] ?? throw new ArgumentNullException("The Jwt key is missing."), + userId: user.Id); + + return Ok(new { accessToken = token, email }); } public class GoogleSignInRequest From 390bf0b72afdc527228342355ea7915408f3f7ce Mon Sep 17 00:00:00 2001 From: Jonathan Bourdon Date: Thu, 20 Jun 2024 13:46:00 -0400 Subject: [PATCH 081/229] Fix some endpoints in web.http --- src/Web/Web.http | 114 ++++------------------------------- src/Web/http-client.env.json | 5 ++ 2 files changed, 17 insertions(+), 102 deletions(-) create mode 100644 src/Web/http-client.env.json diff --git a/src/Web/Web.http b/src/Web/Web.http index 105a254..c0ac5aa 100644 --- a/src/Web/Web.http +++ b/src/Web/Web.http @@ -1,12 +1,10 @@ # For more info on HTTP files go to https://aka.ms/vs/httpfile -@Web_HostAddress = https://localhost:5001 - @Email=administrator@localhost @Password=Administrator1! -@BearerToken= +@auth_token= # POST Users Register -POST {{Web_HostAddress}}/api/Users/Register +POST {{base_url}}/api/Users/Register Content-Type: application/json { @@ -17,7 +15,7 @@ Content-Type: application/json ### # POST Users Login -POST {{Web_HostAddress}}/api/Users/Login +POST {{base_url}}/api/Users/login Content-Type: application/json { @@ -25,11 +23,13 @@ Content-Type: application/json "password": "{{Password}}" } +> {% client.global.set("auth_token", response.body); %} + ### # POST Users Refresh -POST {{Web_HostAddress}}/api/Users/Refresh -Authorization: Bearer {{BearerToken}} +POST {{base_url}}/api/Users/Refresh +Authorization: Bearer {{auth_token}} Content-Type: application/json { @@ -39,101 +39,11 @@ Content-Type: application/json ### # GET WeatherForecast -GET {{Web_HostAddress}}/api/WeatherForecasts -Authorization: Bearer {{BearerToken}} +GET {{base_url}}/api/WeatherForecasts +Authorization: Bearer {{auth_token}} ### -# GET TodoLists -GET {{Web_HostAddress}}/api/TodoLists -Authorization: Bearer {{BearerToken}} - -### - -# POST TodoLists -POST {{Web_HostAddress}}/api/TodoLists -Authorization: Bearer {{BearerToken}} -Content-Type: application/json - -// CreateTodoListCommand -{ - "Title": "Backlog" -} - -### - -# PUT TodoLists -PUT {{Web_HostAddress}}/api/TodoLists/1 -Authorization: Bearer {{BearerToken}} -Content-Type: application/json - -// UpdateTodoListCommand -{ - "Id": 1, - "Title": "Product Backlog" -} - -### - -# DELETE TodoLists -DELETE {{Web_HostAddress}}/api/TodoLists/1 -Authorization: Bearer {{BearerToken}} - -### - -# GET TodoItems -@PageNumber = 1 -@PageSize = 10 -GET {{Web_HostAddress}}/api/TodoItems?ListId=1&PageNumber={{PageNumber}}&PageSize={{PageSize}} - -Authorization: Bearer {{BearerToken}} - -### - -# POST TodoItems -POST {{Web_HostAddress}}/api/TodoItems -Authorization: Bearer {{BearerToken}} -Content-Type: application/json - -// CreateTodoItemCommand -{ - "ListId": 1, - "Title": "Eat a burrito 🌯" -} - -### - -#PUT TodoItems UpdateItemDetails -PUT {{Web_HostAddress}}/api/TodoItems/UpdateItemDetails?Id=1 -Authorization: Bearer {{BearerToken}} -Content-Type: application/json - -// UpdateTodoItemDetailCommand -{ - "Id": 1, - "ListId": 1, - "Priority": 3, - "Note": "This is a good idea!" -} - -### - -# PUT TodoItems -PUT {{Web_HostAddress}}/api/TodoItems/1 -Authorization: Bearer {{BearerToken}} -Content-Type: application/json - -// UpdateTodoItemCommand -{ - "Id": 1, - "Title": "Eat a yummy burrito 🌯", - "Done": true -} - -### - -# DELETE TodoItem -DELETE {{Web_HostAddress}}/api/TodoItems/1 -Authorization: Bearer {{BearerToken}} - -### \ No newline at end of file +# GET GetMyUser +GET {{base_url}}/api/GetMyUser +Authorization: Bearer {{auth_token}} \ No newline at end of file diff --git a/src/Web/http-client.env.json b/src/Web/http-client.env.json new file mode 100644 index 0000000..4af4838 --- /dev/null +++ b/src/Web/http-client.env.json @@ -0,0 +1,5 @@ +{ + "dev": { + "base_url": "https://localhost:5001" + } +} \ No newline at end of file From b17d2f2366eb3e9a09eb3d1a2f6e32cb78bf81f0 Mon Sep 17 00:00:00 2001 From: Jonathan Bourdon Date: Thu, 20 Jun 2024 13:46:53 -0400 Subject: [PATCH 082/229] Fix login --- src/Application/Users/Commands/Login.cs | 36 ++++++++++++------------- src/Web/Endpoints/Users.cs | 2 +- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/Application/Users/Commands/Login.cs b/src/Application/Users/Commands/Login.cs index f61f810..8f232b5 100644 --- a/src/Application/Users/Commands/Login.cs +++ b/src/Application/Users/Commands/Login.cs @@ -1,27 +1,27 @@ using Hutopy.Application.Common.Interfaces; namespace Hutopy.Application.Users.Commands; -public record LoginCommand : IRequest + +public record LoginCommand( + string Email, + string Password) + : IRequest; + +public record LoginResponse( + string AccessToken, + string RefreshToken); + +public class LoginCommandHandler( + IApplicationDbContext Context, + IIdentityService identityService) + : IRequestHandler { - public required string EmailAddress { get; init; } - public required string Password { get; init; } -} - -public class LoginCommandHandler : IRequestHandler -{ - private readonly IApplicationDbContext _context; - private readonly IIdentityService _identityService; - - public LoginCommandHandler(IApplicationDbContext context, IIdentityService identityService) + public async Task Handle(LoginCommand request, CancellationToken cancellationToken) { - _context = context; - _identityService = identityService; - } + var accessToken = await identityService.LoginAsync(request.Email, request.Password); - public async Task Handle(LoginCommand request, CancellationToken cancellationToken) - { - var jwt = await _identityService.LoginAsync(request.EmailAddress, request.Password); + if (string.IsNullOrWhiteSpace(accessToken)) throw new InvalidOperationException("Invalid login credentials"); - return jwt ?? "Invalid login credentials"; + return new LoginResponse(accessToken, string.Empty); } } diff --git a/src/Web/Endpoints/Users.cs b/src/Web/Endpoints/Users.cs index b2a15c5..c344509 100644 --- a/src/Web/Endpoints/Users.cs +++ b/src/Web/Endpoints/Users.cs @@ -24,7 +24,7 @@ public class Users : EndpointGroupBase return await sender.Send(query); } - private static async Task Login(ISender sender, LoginCommand command) + private static async Task Login(ISender sender, LoginCommand command) { return await sender.Send(command); } From c1c542dc1a5b3ae034a699b5df341b90a1437d0d Mon Sep 17 00:00:00 2001 From: Jonathan Bourdon Date: Thu, 20 Jun 2024 13:55:24 -0400 Subject: [PATCH 083/229] Add ignored appsettings.Development.json --- src/Web/appsettings.Development.json | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 src/Web/appsettings.Development.json diff --git a/src/Web/appsettings.Development.json b/src/Web/appsettings.Development.json new file mode 100644 index 0000000..9dad30e --- /dev/null +++ b/src/Web/appsettings.Development.json @@ -0,0 +1,20 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft": "Information", + "Microsoft.AspNetCore.SpaProxy": "Information", + "Microsoft.Hosting.Lifetime": "Information" + } + }, + "ConnectionStrings": { + "DefaultConnection": "Server=localhost,1433;Database=Hutopy;User Id=sa;Password=P@ssword123!;MultipleActiveResultSets=true;TrustServerCertificate=True" + }, + "Authentication": { + "Jwt": { + "Audience": "hutopy", + "Issuer": "https://auth.hutopy.com", + "Key": "b2df428b9929d3ace7c598bbf4e496b2f0b71ab3cd4f94540356cfc35b000000" + } + } +} \ No newline at end of file From d78753573259e3afc3cdca36d062c627751dcdb0 Mon Sep 17 00:00:00 2001 From: Jonathan Bourdon Date: Thu, 20 Jun 2024 14:18:14 -0400 Subject: [PATCH 084/229] Add start-infrastructure script --- start-infrastructure.sh | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 start-infrastructure.sh diff --git a/start-infrastructure.sh b/start-infrastructure.sh new file mode 100644 index 0000000..d7a15c2 --- /dev/null +++ b/start-infrastructure.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +docker run \ + --cap-add SYS_PTRACE \ + -e 'ACCEPT_EULA=1' \ + -e 'MSSQL_SA_PASSWORD=P@ssword123!' \ + -p 1433:1433 \ + --name azuresqledge \ + -d mcr.microsoft.com/azure-sql-edge \ No newline at end of file From f57b693cd98787c70c6cf1b6197db298cc080a01 Mon Sep 17 00:00:00 2001 From: Jonathan Bourdon Date: Thu, 20 Jun 2024 16:27:44 -0400 Subject: [PATCH 085/229] Cleanup and more fixes --- Hutopy.sln | 1 + src/Infrastructure/DependencyInjection.cs | 29 +- src/Web/DependencyInjection.cs | 25 +- src/Web/Program.cs | 37 +- src/Web/Properties/launchSettings.json | 6 +- src/Web/Web.csproj | 46 +- src/Web/appsettings.Development.json | 2 +- src/Web/config.nswag | 63 -- src/Web/wwwroot/api/specification.json | 869 ------------------ .../TestcontainersTestDatabase.cs | 4 +- 10 files changed, 57 insertions(+), 1025 deletions(-) delete mode 100644 src/Web/config.nswag delete mode 100644 src/Web/wwwroot/api/specification.json diff --git a/Hutopy.sln b/Hutopy.sln index 5714f45..2fe5931 100644 --- a/Hutopy.sln +++ b/Hutopy.sln @@ -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}" diff --git a/src/Infrastructure/DependencyInjection.cs b/src/Infrastructure/DependencyInjection.cs index e03ce4c..b8f43d6 100644 --- a/src/Infrastructure/DependencyInjection.cs +++ b/src/Infrastructure/DependencyInjection.cs @@ -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(); services.AddScoped(); @@ -49,15 +40,9 @@ public static class DependencyInjection .AddBearerToken(IdentityConstants.BearerScheme); services.AddAuthorizationBuilder(); - - services.AddIdentityCore(options => - { - options.Password.RequireDigit = false; - options.Password.RequireLowercase = false; - options.Password.RequireUppercase = false; - options.Password.RequireNonAlphanumeric = false; - options.Password.RequiredLength = 8; - }) + + services + .AddIdentityCore() .AddRoles() .AddEntityFrameworkStores() .AddApiEndpoints() diff --git a/src/Web/DependencyInjection.cs b/src/Web/DependencyInjection.cs index 27f1ac1..2a76f33 100644 --- a/src/Web/DependencyInjection.cs +++ b/src/Web/DependencyInjection.cs @@ -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()) diff --git a/src/Web/Program.cs b/src/Web/Program.cs index 781bdc2..ea5b072 100644 --- a/src/Web/Program.cs +++ b/src/Web/Program.cs @@ -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(); diff --git a/src/Web/Properties/launchSettings.json b/src/Web/Properties/launchSettings.json index 6ef4f83..39a9650 100644 --- a/src/Web/Properties/launchSettings.json +++ b/src/Web/Properties/launchSettings.json @@ -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" } diff --git a/src/Web/Web.csproj b/src/Web/Web.csproj index 9193242..80a1ea9 100644 --- a/src/Web/Web.csproj +++ b/src/Web/Web.csproj @@ -7,46 +7,26 @@ - - + + - - - - - - - - - - + + + + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive - all - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - + - - - - OnBuildSuccess - - - - - - - - - - - - diff --git a/src/Web/appsettings.Development.json b/src/Web/appsettings.Development.json index 9dad30e..ec39dd6 100644 --- a/src/Web/appsettings.Development.json +++ b/src/Web/appsettings.Development.json @@ -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": { diff --git a/src/Web/config.nswag b/src/Web/config.nswag deleted file mode 100644 index 4af18f2..0000000 --- a/src/Web/config.nswag +++ /dev/null @@ -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 - } - } -} diff --git a/src/Web/wwwroot/api/specification.json b/src/Web/wwwroot/api/specification.json deleted file mode 100644 index bf1f109..0000000 --- a/src/Web/wwwroot/api/specification.json +++ /dev/null @@ -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": [] - } - ] -} \ No newline at end of file diff --git a/tests/Application.FunctionalTests/TestcontainersTestDatabase.cs b/tests/Application.FunctionalTests/TestcontainersTestDatabase.cs index eaf57f8..342336f 100644 --- a/tests/Application.FunctionalTests/TestcontainersTestDatabase.cs +++ b/tests/Application.FunctionalTests/TestcontainersTestDatabase.cs @@ -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"] }); } From 891597fb08a4a7dbfdefc64214bb3ce46852893a Mon Sep 17 00:00:00 2001 From: PascalMarchesseault <97350299+PascalMarchesseault@users.noreply.github.com> Date: Thu, 20 Jun 2024 16:35:04 -0400 Subject: [PATCH 086/229] add MultiSubnetFailover=True --- src/Web/appsettings.Development.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Web/appsettings.Development.json b/src/Web/appsettings.Development.json index ec39dd6..43ba880 100644 --- a/src/Web/appsettings.Development.json +++ b/src/Web/appsettings.Development.json @@ -8,7 +8,7 @@ } }, "ConnectionStrings": { - "DefaultConnection": "Server=localhost,1433;Initial Catalog=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;MultiSubnetFailover=True" }, "Authentication": { "Jwt": { From 72e243cf84203d8ac1969aa3ac190a79bc6a7ce8 Mon Sep 17 00:00:00 2001 From: Jonathan Bourdon Date: Thu, 27 Jun 2024 12:37:59 -0400 Subject: [PATCH 087/229] Adds messages api --- Directory.Packages.props | 1 + src/Application/Common/Models/UserModel.cs | 2 + .../Identity/IdentityService.cs | 11 ++- src/Infrastructure/Utils/GenerateJwtToken.cs | 25 +++++-- src/Web/Controllers/GoogleController.cs | 12 ++- src/Web/Endpoints/Users.cs | 10 +-- src/Web/Messages/Data/Message.cs | 13 ++++ src/Web/Messages/Data/MessagingDbContext.cs | 19 +++++ src/Web/Messages/Handlers/GetMessages.cs | 30 ++++++++ .../Messages/Handlers/GetMessagesByUser.cs | 33 ++++++++ src/Web/Messages/Handlers/PostMessage.cs | 34 +++++++++ src/Web/Messages/Handlers/PostReplyMessage.cs | 37 +++++++++ .../20240627081653_Initial.Designer.cs | 59 +++++++++++++++ .../Migrations/20240627081653_Initial.cs | 38 ++++++++++ .../MessagingDbContextModelSnapshot.cs | 56 ++++++++++++++ src/Web/Messages/Shared.cs | 42 +++++++++++ src/Web/Program.cs | 75 ++++++++++++------- src/Web/Web.csproj | 31 ++++---- src/Web/Web.http | 14 +++- src/Web/appsettings.Development.json | 3 +- .../CustomWebApplicationFactory.cs | 1 + 21 files changed, 485 insertions(+), 61 deletions(-) create mode 100644 src/Web/Messages/Data/Message.cs create mode 100644 src/Web/Messages/Data/MessagingDbContext.cs create mode 100644 src/Web/Messages/Handlers/GetMessages.cs create mode 100644 src/Web/Messages/Handlers/GetMessagesByUser.cs create mode 100644 src/Web/Messages/Handlers/PostMessage.cs create mode 100644 src/Web/Messages/Handlers/PostReplyMessage.cs create mode 100644 src/Web/Messages/Migrations/20240627081653_Initial.Designer.cs create mode 100644 src/Web/Messages/Migrations/20240627081653_Initial.cs create mode 100644 src/Web/Messages/Migrations/MessagingDbContextModelSnapshot.cs create mode 100644 src/Web/Messages/Shared.cs diff --git a/Directory.Packages.props b/Directory.Packages.props index a2b4869..3c60acd 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -10,6 +10,7 @@ + diff --git a/src/Application/Common/Models/UserModel.cs b/src/Application/Common/Models/UserModel.cs index 5c4358b..71a2680 100644 --- a/src/Application/Common/Models/UserModel.cs +++ b/src/Application/Common/Models/UserModel.cs @@ -1,5 +1,6 @@ namespace Hutopy.Application.Common.Models; +// TODO: Review nullable affectation here public class UserModel { public string? Id { get; set; } @@ -7,4 +8,5 @@ public class UserModel public string? FirstName { get; set; } public string? LastName { get; set; } public string? Email { get; set; } + public string? PortraitUrl { get; set; } } diff --git a/src/Infrastructure/Identity/IdentityService.cs b/src/Infrastructure/Identity/IdentityService.cs index 9997316..7cdf080 100644 --- a/src/Infrastructure/Identity/IdentityService.cs +++ b/src/Infrastructure/Identity/IdentityService.cs @@ -1,3 +1,4 @@ +using System.Diagnostics; using Google.Apis.Oauth2.v2.Data; using System.Security.Claims; using Hutopy.Application.Common.Interfaces; @@ -220,14 +221,20 @@ public class IdentityService( } var user = await GetUserByUserNameAsync(userName); + + if (user is null) throw new InvalidOperationException(); var jwtSection = configuration.GetRequiredSection("Authentication:Jwt"); - + var token = JwtTokenHelper.GenerateJwtToken( issuer: jwtSection["Issuer"] ?? "", audience: jwtSection["Audience"] ?? "", key: jwtSection["Key"] ?? "", - userId: user?.Id ?? ""); + userId: user.Id, + email: user.Email, + firstname: user.FirstName, + lastname: user.LastName, + portraitUrl: user.PortraitUrl); return token; } diff --git a/src/Infrastructure/Utils/GenerateJwtToken.cs b/src/Infrastructure/Utils/GenerateJwtToken.cs index 00423f9..19e6cbd 100644 --- a/src/Infrastructure/Utils/GenerateJwtToken.cs +++ b/src/Infrastructure/Utils/GenerateJwtToken.cs @@ -7,20 +7,31 @@ namespace Hutopy.Infrastructure.Utils; public static class JwtTokenHelper { - public static string GenerateJwtToken(string issuer, string audience, string key, string userId) + public static string GenerateJwtToken(string issuer, string audience, string key, string? userId, string? email, + string? firstname, string? lastname, string? portraitUrl) { var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(key)); var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256); + var claims = new List(new[] + { + new Claim(JwtRegisteredClaimNames.Sub, userId), + new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()), + new Claim(ClaimTypes.NameIdentifier, userId), + new Claim(ClaimTypes.Email, email), + new Claim(ClaimTypes.GivenName, firstname), + new Claim(ClaimTypes.Surname, lastname), + }); + + if (portraitUrl is not null) + { + claims.Add(new Claim("portrait-url", portraitUrl)); + } + var token = new JwtSecurityToken( issuer: issuer, audience: audience, - claims: new[] - { - new Claim(JwtRegisteredClaimNames.Sub, userId), - new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()), - new Claim(ClaimTypes.NameIdentifier, userId) - }, + claims: claims, expires: DateTime.Now.AddMinutes(30), signingCredentials: credentials); diff --git a/src/Web/Controllers/GoogleController.cs b/src/Web/Controllers/GoogleController.cs index 40e8adc..dfaa91e 100644 --- a/src/Web/Controllers/GoogleController.cs +++ b/src/Web/Controllers/GoogleController.cs @@ -64,10 +64,14 @@ public class GoogleController(IIdentityService identityService, IHttpClientFacto var jwtSection = configuration.GetRequiredSection("Authentication:Jwt"); var token = JwtTokenHelper.GenerateJwtToken( - issuer: jwtSection["Issuer"] ?? throw new ArgumentNullException("The Jwt issuer is missing."), - audience: jwtSection["Audience"] ?? throw new ArgumentNullException("The Jwt audience is missing."), - key: jwtSection["Key"] ?? throw new ArgumentNullException("The Jwt key is missing."), - userId: user.Id); + jwtSection["Issuer"] ?? throw new ArgumentNullException("The Jwt issuer is missing."), + jwtSection["Audience"] ?? throw new ArgumentNullException("The Jwt audience is missing."), + jwtSection["Key"] ?? throw new ArgumentNullException("The Jwt key is missing."), + user.Id, + user.Email, + user.FirstName, + user.LastName, + user.PortraitUrl); return Ok(new { accessToken = token, email }); } diff --git a/src/Web/Endpoints/Users.cs b/src/Web/Endpoints/Users.cs index c344509..bcfa964 100644 --- a/src/Web/Endpoints/Users.cs +++ b/src/Web/Endpoints/Users.cs @@ -23,18 +23,16 @@ public class Users : EndpointGroupBase { return await sender.Send(query); } - + private static async Task Login(ISender sender, LoginCommand command) { return await sender.Send(command); } - + private static async Task UploadProfilePicture(ISender sender, Stream stream) { - var command = new UploadProfilePictureCommand - { - ProfilePicture = stream - }; + var command = new UploadProfilePictureCommand { ProfilePicture = stream }; + return await sender.Send(command); } } diff --git a/src/Web/Messages/Data/Message.cs b/src/Web/Messages/Data/Message.cs new file mode 100644 index 0000000..df0fa50 --- /dev/null +++ b/src/Web/Messages/Data/Message.cs @@ -0,0 +1,13 @@ +namespace Hutopy.Web.Messages.Data; + +public class Message +{ + public Guid Id { get; init; } + public Guid ContentId { get; init; } // works for any - VideoId, ChatId, RoomId, xxxId, ForumId + public Guid CreatedBy { get; init; } + public DateTime CreatedAt { get; } + + public Guid ParentId { get; init; } + + public string Value { get; init; } = null!; +} diff --git a/src/Web/Messages/Data/MessagingDbContext.cs b/src/Web/Messages/Data/MessagingDbContext.cs new file mode 100644 index 0000000..28bb977 --- /dev/null +++ b/src/Web/Messages/Data/MessagingDbContext.cs @@ -0,0 +1,19 @@ +using Microsoft.EntityFrameworkCore; + +namespace Hutopy.Web.Messages.Data; + +public class MessagingDbContext( + DbContextOptions options) + : DbContext(options) +{ + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + modelBuilder + .Entity() + .Property(c => c.CreatedAt) + .ValueGeneratedOnAdd() + .HasDefaultValueSql("CURRENT_TIMESTAMP"); + } + + public DbSet Messages { get; set; } +} diff --git a/src/Web/Messages/Handlers/GetMessages.cs b/src/Web/Messages/Handlers/GetMessages.cs new file mode 100644 index 0000000..d7afb3f --- /dev/null +++ b/src/Web/Messages/Handlers/GetMessages.cs @@ -0,0 +1,30 @@ +using FastEndpoints; +using Hutopy.Web.Messages.Data; +using Microsoft.EntityFrameworkCore; + +namespace Hutopy.Web.Messages.Handlers; + +public class GetMessages( + MessagingDbContext context) + : EndpointWithoutRequest> +{ + public override void Configure() + { + Tags("Messages"); + Get("/api/messages/{ContentId:guid}"); + AllowAnonymous(); + } + + public override async Task HandleAsync( + CancellationToken ct) + { + var contentId = Route("ContentId"); + + var comments = await context + .Messages + .Where(c => c.ContentId == contentId) + .ToListAsync(cancellationToken: ct); + + await SendAsync(comments, cancellation: ct); + } +} diff --git a/src/Web/Messages/Handlers/GetMessagesByUser.cs b/src/Web/Messages/Handlers/GetMessagesByUser.cs new file mode 100644 index 0000000..d70cd11 --- /dev/null +++ b/src/Web/Messages/Handlers/GetMessagesByUser.cs @@ -0,0 +1,33 @@ +using FastEndpoints; +using Hutopy.Web.Messages.Data; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; + +namespace Hutopy.Web.Messages.Handlers; + +public record GetMessagesByUserRequest( + [FromRoute] Guid UserId); + +public class GetMessagesByUser( + MessagingDbContext context) + : EndpointWithoutRequest> +{ + public override void Configure() + { + Tags("Messages"); + Get("/api/messages/by-user/{UserId:guid}"); + } + + public override async Task HandleAsync( + CancellationToken ct) + { + var userId = Route("UserId"); + + var posts = await context + .Messages + .Where(c => c.CreatedBy == userId) + .ToListAsync(cancellationToken: ct); + + await SendAsync(posts, cancellation: ct); + } +} diff --git a/src/Web/Messages/Handlers/PostMessage.cs b/src/Web/Messages/Handlers/PostMessage.cs new file mode 100644 index 0000000..7460728 --- /dev/null +++ b/src/Web/Messages/Handlers/PostMessage.cs @@ -0,0 +1,34 @@ +using FastEndpoints; +using Hutopy.Web.Messages.Data; + +namespace Hutopy.Web.Messages.Handlers; + +public record PostMessageRequest( + Guid ContentId, + string Message); + +public class PostMessage( + MessagingDbContext context) + : Endpoint +{ + public override void Configure() + { + // TODO: Find how to specify the name we see in Swagger + Tags("Messages"); + Post("/api/messages"); + } + + public override async Task HandleAsync( + PostMessageRequest req, + CancellationToken ct) + { + await context.Messages.AddAsync( + new Message { + ContentId = req.ContentId, + CreatedBy = User.GetUserId(), + Value = req.Message }, + ct); + + await context.SaveChangesAsync(ct); + } +} diff --git a/src/Web/Messages/Handlers/PostReplyMessage.cs b/src/Web/Messages/Handlers/PostReplyMessage.cs new file mode 100644 index 0000000..2385765 --- /dev/null +++ b/src/Web/Messages/Handlers/PostReplyMessage.cs @@ -0,0 +1,37 @@ +using FastEndpoints; +using Hutopy.Web.Messages.Data; + +namespace Hutopy.Web.Messages.Handlers; + +public record PostReplyMessageRequest( + Guid ContentId, + Guid ParentId, + string Message); + +public sealed class PostReplyMessage( + MessagingDbContext context) + : Endpoint +{ + public override void Configure() + { + Tags("Messages"); + Post("/api/messages/reply"); + } + + public override async Task HandleAsync( + PostReplyMessageRequest req, + CancellationToken ct) + { + await context.Messages.AddAsync( + new Message + { + ContentId = req.ContentId, + ParentId = req.ParentId, + CreatedBy = User.GetUserId(), + Value = req.Message + }, + ct); + + await context.SaveChangesAsync(ct); + } +} diff --git a/src/Web/Messages/Migrations/20240627081653_Initial.Designer.cs b/src/Web/Messages/Migrations/20240627081653_Initial.Designer.cs new file mode 100644 index 0000000..72d8e1c --- /dev/null +++ b/src/Web/Messages/Migrations/20240627081653_Initial.Designer.cs @@ -0,0 +1,59 @@ +// +using System; +using Hutopy.Web.Messages.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Hutopy.Web.Messages.Migrations +{ + [DbContext(typeof(MessagingDbContext))] + [Migration("20240627081653_Initial")] + partial class Initial + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.3") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("Hutopy.Web.Messages.Data.Message", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("ContentId") + .HasColumnType("uniqueidentifier"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasDefaultValueSql("CURRENT_TIMESTAMP"); + + b.Property("CreatedBy") + .HasColumnType("uniqueidentifier"); + + b.Property("ParentId") + .HasColumnType("uniqueidentifier"); + + b.Property("Value") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("Messages"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Web/Messages/Migrations/20240627081653_Initial.cs b/src/Web/Messages/Migrations/20240627081653_Initial.cs new file mode 100644 index 0000000..bd5664e --- /dev/null +++ b/src/Web/Messages/Migrations/20240627081653_Initial.cs @@ -0,0 +1,38 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Hutopy.Web.Messages.Migrations +{ + /// + public partial class Initial : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "Messages", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + ContentId = table.Column(type: "uniqueidentifier", nullable: false), + CreatedBy = table.Column(type: "uniqueidentifier", nullable: false), + CreatedAt = table.Column(type: "datetime2", nullable: false, defaultValueSql: "CURRENT_TIMESTAMP"), + ParentId = table.Column(type: "uniqueidentifier", nullable: false), + Value = table.Column(type: "nvarchar(max)", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Messages", x => x.Id); + }); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "Messages"); + } + } +} diff --git a/src/Web/Messages/Migrations/MessagingDbContextModelSnapshot.cs b/src/Web/Messages/Migrations/MessagingDbContextModelSnapshot.cs new file mode 100644 index 0000000..be9a4b9 --- /dev/null +++ b/src/Web/Messages/Migrations/MessagingDbContextModelSnapshot.cs @@ -0,0 +1,56 @@ +// +using System; +using Hutopy.Web.Messages.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Hutopy.Web.Messages.Migrations +{ + [DbContext(typeof(MessagingDbContext))] + partial class MessagingDbContextModelSnapshot : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.3") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("Hutopy.Web.Messages.Data.Message", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("ContentId") + .HasColumnType("uniqueidentifier"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasDefaultValueSql("CURRENT_TIMESTAMP"); + + b.Property("CreatedBy") + .HasColumnType("uniqueidentifier"); + + b.Property("ParentId") + .HasColumnType("uniqueidentifier"); + + b.Property("Value") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("Messages"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Web/Messages/Shared.cs b/src/Web/Messages/Shared.cs new file mode 100644 index 0000000..eb48399 --- /dev/null +++ b/src/Web/Messages/Shared.cs @@ -0,0 +1,42 @@ +using System.Security.Claims; + +namespace Hutopy.Web.Messages; + +public class Shared(string claimName) : Exception; + +public static class ClaimsPrincipalExtensions +{ + public static Guid GetUserId(this ClaimsPrincipal claims) + { + return (Guid)claims.GetFirstValue(ClaimTypes.NameIdentifier); + } + + public static string GetFirstName(this ClaimsPrincipal claims) + { + return (string)claims.GetFirstValue(ClaimTypes.GivenName); + } + + public static string GetLastName(this ClaimsPrincipal claims) + { + return (string)claims.GetFirstValue(ClaimTypes.Surname); + } + + public static string GetEmail(this ClaimsPrincipal claims) + { + return (string)claims.GetFirstValue(ClaimTypes.Email); + } + + public static object GetFirstValue(this ClaimsPrincipal claims, string key) + { + var claim = claims.FindFirst(key); + + if (claim is null) throw new Shared(key); + + if (typeof(TValue) == typeof(Guid)) + { + return Guid.Parse(claim.Value); + } + + return Convert.ChangeType(claim.Value, typeof(TValue)); + } +} diff --git a/src/Web/Program.cs b/src/Web/Program.cs index ea5b072..78700bc 100644 --- a/src/Web/Program.cs +++ b/src/Web/Program.cs @@ -1,10 +1,14 @@ +using Azure.Identity; +using FastEndpoints; using Hutopy.Application; using Hutopy.Infrastructure; using Hutopy.Infrastructure.Data; using Hutopy.Web; -using Azure.Identity; +using Hutopy.Web.Messages.Data; using Microsoft.AspNetCore.HttpOverrides; +using Microsoft.EntityFrameworkCore; using NSwag; +using NSwag.Generation.AspNetCore.Processors; using NSwag.Generation.Processors.Security; var builder = WebApplication.CreateBuilder(args); @@ -16,31 +20,31 @@ if (!builder.Environment.IsDevelopment()) } builder.Services.AddCors(options => +{ + options.AddPolicy("AllowAll", builder => { - options.AddPolicy("AllowAll", builder => - { - builder.AllowAnyOrigin() - .AllowAnyMethod() - .AllowAnyHeader(); - }); - - options.AddPolicy("AllowHutopyUi", builder => - { - builder.WithOrigins("https://zealous-bay-08204590f.5.azurestaticapps.net") - .AllowAnyMethod() - .AllowAnyHeader() - .AllowCredentials(); - }); - - options.AddPolicy("AllowHutopyUiPreview", builder => - { - builder.WithOrigins("https://zealous-bay-08204590f-preview.eastus2.5.azurestaticapps.net") - .AllowAnyMethod() - .AllowAnyHeader() - .AllowCredentials(); - }); + builder.AllowAnyOrigin() + .AllowAnyMethod() + .AllowAnyHeader(); }); + options.AddPolicy("AllowHutopyUi", builder => + { + builder.WithOrigins("https://zealous-bay-08204590f.5.azurestaticapps.net") + .AllowAnyMethod() + .AllowAnyHeader() + .AllowCredentials(); + }); + + options.AddPolicy("AllowHutopyUiPreview", builder => + { + builder.WithOrigins("https://zealous-bay-08204590f-preview.eastus2.5.azurestaticapps.net") + .AllowAnyMethod() + .AllowAnyHeader() + .AllowCredentials(); + }); +}); + // Add services to the container. builder.Services.AddKeyVaultIfConfigured(builder.Configuration); @@ -48,6 +52,8 @@ builder.Services.AddApplicationServices(); builder.Services.AddInfrastructureServices(builder.Configuration); builder.Services.AddWebServices(); builder.Services.AddAuthorizationAndAuthentication(builder.Configuration); + +// TODO: This old tech should be remove - need to move Facebook / Google controllers to FastEndpoints builder.Services.AddControllers(); builder.Services.AddOpenApiDocument((configure, sp) => @@ -63,11 +69,19 @@ builder.Services.AddOpenApiDocument((configure, sp) => Type = OpenApiSecuritySchemeType.ApiKey, Name = "Authorization", In = OpenApiSecurityApiKeyLocation.Header, - Description = "Type into the textbox: Bearer {your JWT token}." + Description = "Type into the textbox: Bearer {your JWT token}.", }); - + + configure.OperationProcessors.Add(new AspNetCoreOperationTagsProcessor()); configure.OperationProcessors.Add(new AspNetCoreOperationSecurityScopeProcessor("JWT")); - }); +}); + +builder.Services.AddFastEndpoints(); + +builder.Services.AddDbContext((_, options) => +{ + options.UseSqlServer(builder.Configuration.GetConnectionString("CommentStore")); +}); var app = builder.Build(); @@ -110,6 +124,13 @@ app.MapControllerRoute( // app.UseExceptionHandler(); app.MapEndpoints(); +app.UseFastEndpoints(); + app.Run(); -public abstract partial class Program { } +namespace Hutopy.Web +{ + public abstract partial class Program + { + } +} diff --git a/src/Web/Web.csproj b/src/Web/Web.csproj index 80a1ea9..053126a 100644 --- a/src/Web/Web.csproj +++ b/src/Web/Web.csproj @@ -7,26 +7,31 @@ - - + + - - - - - - - - - - + + + + + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive all - + + + + + diff --git a/src/Web/Web.http b/src/Web/Web.http index c0ac5aa..054f4e4 100644 --- a/src/Web/Web.http +++ b/src/Web/Web.http @@ -23,7 +23,7 @@ Content-Type: application/json "password": "{{Password}}" } -> {% client.global.set("auth_token", response.body); %} +> {% client.global.set("auth_token", response.body.accessToken); %} ### @@ -46,4 +46,16 @@ Authorization: Bearer {{auth_token}} # GET GetMyUser GET {{base_url}}/api/GetMyUser +Authorization: Bearer {{auth_token}} + +### + +# GET /api/posts + +GET {{base_url}}/api/messages/00000001-0000-0000-0000-000000000001 + +### + +# GET /api/posts/by-user +GET {{base_url}}/api/messages/by-user/325C69E8-DBC4-4CEE-B56E-C3C90AEE7963 Authorization: Bearer {{auth_token}} \ No newline at end of file diff --git a/src/Web/appsettings.Development.json b/src/Web/appsettings.Development.json index 43ba880..9e2b285 100644 --- a/src/Web/appsettings.Development.json +++ b/src/Web/appsettings.Development.json @@ -8,7 +8,8 @@ } }, "ConnectionStrings": { - "DefaultConnection": "Server=localhost,1433;Initial Catalog=Hutopy;User Id=sa;Password=P@ssword123!;MultipleActiveResultSets=true;TrustServerCertificate=True;MultiSubnetFailover=True" + "DefaultConnection": "Server=localhost,1433;Initial Catalog=Hutopy;User Id=sa;Password=P@ssword123!;MultipleActiveResultSets=true;TrustServerCertificate=True;MultiSubnetFailover=True", + "CommentStore": "Server=localhost,1433;Initial Catalog=Hutopy;User Id=sa;Password=P@ssword123!;MultipleActiveResultSets=true;TrustServerCertificate=True;MultiSubnetFailover=True" }, "Authentication": { "Jwt": { diff --git a/tests/Application.FunctionalTests/CustomWebApplicationFactory.cs b/tests/Application.FunctionalTests/CustomWebApplicationFactory.cs index d99727f..c1d8a80 100644 --- a/tests/Application.FunctionalTests/CustomWebApplicationFactory.cs +++ b/tests/Application.FunctionalTests/CustomWebApplicationFactory.cs @@ -1,6 +1,7 @@ using System.Data.Common; using Hutopy.Application.Common.Interfaces; using Hutopy.Infrastructure.Data; +using Hutopy.Web; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Mvc.Testing; using Microsoft.AspNetCore.TestHost; From 5282fcfd49a2fbbab5242b7d5fbce0b1f2d21564 Mon Sep 17 00:00:00 2001 From: Dominic Villemure Date: Sat, 29 Jun 2024 22:45:17 -0400 Subject: [PATCH 088/229] update-current-user WIP --- .../Common/Interfaces/IIdentityService.cs | 20 +- src/Application/Common/Models/Result.cs | 27 +- src/Application/Common/Models/UserModel.cs | 13 +- .../Commands/UpdateCurrentUserCommand.cs | 40 ++ .../Users/Models/SocialNetworksModel.cs | 13 + .../Queries/GetCurrentUser/GetCurrentUser.cs | 18 +- .../Users/Queries/GetCurrentUser/UserDto.cs | 12 + .../Identity/ApplicationUser.cs | 7 + .../Identity/IdentityService.cs | 99 +++- ...6_AddMissingInformationsToUser.Designer.cs | 497 ++++++++++++++++++ ...0630001806_AddMissingInformationsToUser.cs | 95 ++++ .../ApplicationDbContextModelSnapshot.cs | 28 + src/Web/Endpoints/UpdateMyUser.cs | 20 + 13 files changed, 855 insertions(+), 34 deletions(-) create mode 100644 src/Application/Users/Commands/UpdateCurrentUserCommand.cs create mode 100644 src/Application/Users/Models/SocialNetworksModel.cs create mode 100644 src/Infrastructure/Migrations/20240630001806_AddMissingInformationsToUser.Designer.cs create mode 100644 src/Infrastructure/Migrations/20240630001806_AddMissingInformationsToUser.cs create mode 100644 src/Web/Endpoints/UpdateMyUser.cs diff --git a/src/Application/Common/Interfaces/IIdentityService.cs b/src/Application/Common/Interfaces/IIdentityService.cs index cd97117..d92663e 100644 --- a/src/Application/Common/Interfaces/IIdentityService.cs +++ b/src/Application/Common/Interfaces/IIdentityService.cs @@ -1,21 +1,27 @@ using Google.Apis.Oauth2.v2.Data; using Hutopy.Application.Common.Models; +using Hutopy.Application.Users.Models; namespace Hutopy.Application.Common.Interfaces; public interface IIdentityService { - Task GetUserNameAsync(string userId); - Task CreateUserAsync(string email, string userName, string firstName, string lastName, string password); - Task FindUserByIdAsync(string id); + Task> CreateUserAsync(Userinfo userInfo); + Task> CreateUserAsync(string email, string userName, string firstName, string lastName, string password); Task GetCurrentUserAsync(); - Task FindUserByEmailAsync(string id); - Task LoginAsync(string email, string password); + Task> UpdateCurrentUserAsync(string id, string firstName, string lastName, string occupation, + string phoneNumber, string birthDate, string country, string city, string address, string about, + string description, + SocialNetworksModel socialNetworks); + Task> GetCurrentUserRolesAsync(); + Task FindUserByIdAsync(string id); + Task FindUserByEmailAsync(string email); Task GetUserByUserNameAsync(string userName); + Task LoginAsync(string email, string password); Task IsInRoleAsync(string userId, string role); Task AuthorizeAsync(string userId, string policyName); + Task GetUserNameAsync(string userId); + Task AddRoleAsync(string userId, string role); - Task> GetCurrentUserRolesAsync(); - Task<(Result Result, string UserId)> CreateUserAsync(Userinfo userInfo); Task DeleteUserAsync(string userId); } diff --git a/src/Application/Common/Models/Result.cs b/src/Application/Common/Models/Result.cs index f99bb27..9552531 100644 --- a/src/Application/Common/Models/Result.cs +++ b/src/Application/Common/Models/Result.cs @@ -5,9 +5,8 @@ public class Result( IEnumerable errors) { public bool Succeeded { get; init; } = succeeded; - public string[] Errors { get; init; } = errors.ToArray(); - + public static Result Success() { return new Result(true, Array.Empty()); @@ -18,3 +17,27 @@ public class Result( return new Result(false, errors); } } + +public class Result( + bool succeeded, + IEnumerable errors) +{ + public bool Succeeded { get; init; } = succeeded; + public string[] Errors { get; init; } = errors.ToArray(); + public T? Value { get; set; } + + public T GetValueOrDefault() + { + return Value ?? default(T)!; + } + + public static Result Success() + { + return new Result(true, Array.Empty()); + } + + public static Result Failure(IEnumerable errors) + { + return new Result(false, errors); + } +} diff --git a/src/Application/Common/Models/UserModel.cs b/src/Application/Common/Models/UserModel.cs index 71a2680..ac09db9 100644 --- a/src/Application/Common/Models/UserModel.cs +++ b/src/Application/Common/Models/UserModel.cs @@ -1,3 +1,5 @@ +using Hutopy.Application.Users.Models; + namespace Hutopy.Application.Common.Models; // TODO: Review nullable affectation here @@ -7,6 +9,15 @@ public class UserModel public string? UserName { get; set; } public string? FirstName { get; set; } public string? LastName { get; set; } - public string? Email { get; set; } + public string? Occupation { get; set; } + public string? Email { get; init; } = String.Empty; + public string? Phone { get; init; } = String.Empty; + public string? BirthDate { get; init; } = String.Empty; + public string? Country { get; init; } = String.Empty; + public string? City { get; init; } = String.Empty; + public string? Address { get; init; } = String.Empty; + public string? About { get; init; } = String.Empty; + public string? Description { get; init; } = String.Empty; + public SocialNetworksModel SocialNetworks { get; init; } = new(); public string? PortraitUrl { get; set; } } diff --git a/src/Application/Users/Commands/UpdateCurrentUserCommand.cs b/src/Application/Users/Commands/UpdateCurrentUserCommand.cs new file mode 100644 index 0000000..3a23915 --- /dev/null +++ b/src/Application/Users/Commands/UpdateCurrentUserCommand.cs @@ -0,0 +1,40 @@ +using Hutopy.Application.Common.Interfaces; +using Hutopy.Application.Users.Models; + +namespace Hutopy.Application.Users.Commands; + +public class UpdateCurrentUserCommand : IRequest +{ + public required string FirstName { get; init; } + public required string LastName { get; init; } + public required string Occupation { get; init; } + public required string PhoneNumber { get; init; } + public required string BirthDate { get; init; } + public required string Country { get; init; } + public required string City { get; init; } + public required string Address { get; init; } + public required string About { get; init; } + public required string Description { get; init; } + public required SocialNetworksModel SocialNetworks { get; init; } +} + +public class UpdateCurrentUserCommandHandler(IApplicationDbContext context, IIdentityService identityService) : + IRequestHandler +{ + public async Task Handle(UpdateCurrentUserCommand request, CancellationToken cancellationToken) + { + var identityUser = await identityService.GetCurrentUserAsync(); + + if (identityUser?.Id is null) return string.Empty; + + var result = await identityService.UpdateCurrentUserAsync(identityUser.Id, request.FirstName, request.LastName, + request.Occupation, request.PhoneNumber, request.BirthDate, + request.Country, request.City, request.Address, request.About, + request.Description, request.SocialNetworks); + + await context.SaveChangesAsync(cancellationToken); + + return result.GetValueOrDefault(); + } +} + diff --git a/src/Application/Users/Models/SocialNetworksModel.cs b/src/Application/Users/Models/SocialNetworksModel.cs new file mode 100644 index 0000000..edd3cce --- /dev/null +++ b/src/Application/Users/Models/SocialNetworksModel.cs @@ -0,0 +1,13 @@ +namespace Hutopy.Application.Users.Models; + +public class SocialNetworksModel +{ + public string FacebookUrl { get; init; } = String.Empty; + public string InstagramUrl { get; init; } = String.Empty; + public string XUrl { get; init; } = String.Empty; + public string LinkedInUrl { get; init; } = String.Empty; + public string TikTokUrl { get; init; } = String.Empty; + public string YoutubeUrl { get; init; } = String.Empty; + public string RedditUrl { get; init; } = String.Empty; + public string YourWebsiteUrl { get; init; } = String.Empty; +} diff --git a/src/Application/Users/Queries/GetCurrentUser/GetCurrentUser.cs b/src/Application/Users/Queries/GetCurrentUser/GetCurrentUser.cs index 7cbabd6..eeb9f7c 100644 --- a/src/Application/Users/Queries/GetCurrentUser/GetCurrentUser.cs +++ b/src/Application/Users/Queries/GetCurrentUser/GetCurrentUser.cs @@ -28,12 +28,22 @@ public class GetCurrentUserQueryHandler( var user = new UserDto { Id = currentUserId, - FirstName = identityUser?.FirstName ?? "", - LastName = identityUser?.LastName ?? "", - UserName = identityUser?.UserName ?? "", + FirstName = identityUser.FirstName ?? "", + LastName = identityUser.LastName ?? "", + UserName = identityUser.UserName ?? "", + Occupation = identityUser.Occupation ?? "", + Phone = identityUser.Phone ?? "", + Email = identityUser.Email ?? "", + BirthDate = identityUser.BirthDate ?? "", + Country = identityUser.Country ?? "", + City = identityUser.City ?? "", + Address = identityUser.Address ?? "", + About = identityUser.About ?? "", + Description = identityUser.Description ?? "", + SocialNetworks = identityUser.SocialNetworks, UserTransactions = transactions, TotalBalance = transactions.Sum(x => x.Amount), - UserRoles = roles + UserRoles = roles, }; return user; diff --git a/src/Application/Users/Queries/GetCurrentUser/UserDto.cs b/src/Application/Users/Queries/GetCurrentUser/UserDto.cs index c7d121d..c0b34c1 100644 --- a/src/Application/Users/Queries/GetCurrentUser/UserDto.cs +++ b/src/Application/Users/Queries/GetCurrentUser/UserDto.cs @@ -1,3 +1,5 @@ +using Hutopy.Application.Users.Models; + namespace Hutopy.Application.Users.Queries.GetCurrentUser; public class UserDto @@ -6,6 +8,16 @@ public class UserDto public required string FirstName { get; init; } public required string LastName { get; init; } public string UserName { get; init; } = String.Empty; + public string Occupation { get; init; } = String.Empty; + public string Email { get; init; } = String.Empty; + public string Phone { get; init; } = String.Empty; + public string BirthDate { get; init; } = String.Empty; + public string Country { get; init; } = String.Empty; + public string City { get; init; } = String.Empty; + public string Address { get; init; } = String.Empty; + public string About { get; init; } = String.Empty; + public string Description { get; init; } = String.Empty; + public SocialNetworksModel SocialNetworks { get; init; } = new(); public List UserTransactions { get; init; } = []; public IList UserRoles { get; init; } = []; public required decimal TotalBalance { get; init; } diff --git a/src/Infrastructure/Identity/ApplicationUser.cs b/src/Infrastructure/Identity/ApplicationUser.cs index 700a074..d956a9b 100644 --- a/src/Infrastructure/Identity/ApplicationUser.cs +++ b/src/Infrastructure/Identity/ApplicationUser.cs @@ -7,5 +7,12 @@ public class ApplicationUser : IdentityUser { public string FirstName { get; set; } = string.Empty; public string LastName { get; set; } = string.Empty; + public string Occupation { get; set; } = string.Empty; + public string BirthDate { get; set; } = string.Empty; + public string Country { get; set; } = string.Empty; + public string City { get; set; } = string.Empty; + public string Address { get; set; } = string.Empty; + public string About { get; set; } = string.Empty; + public string Description { get; set; } = string.Empty; public SocialNetworks SocialNetworks { get; set; } = new(); } diff --git a/src/Infrastructure/Identity/IdentityService.cs b/src/Infrastructure/Identity/IdentityService.cs index 7cdf080..d512ae5 100644 --- a/src/Infrastructure/Identity/IdentityService.cs +++ b/src/Infrastructure/Identity/IdentityService.cs @@ -3,6 +3,8 @@ using Google.Apis.Oauth2.v2.Data; using System.Security.Claims; using Hutopy.Application.Common.Interfaces; using Hutopy.Application.Common.Models; +using Hutopy.Application.Users.Models; +using Hutopy.Infrastructure.Identity.OwnedEntities; using Hutopy.Infrastructure.Utils; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; @@ -45,23 +47,10 @@ public class IdentityService( return userModel; } - - public async Task<(Result Result, string UserId)> CreateUserAsync(string userName, string password) - { - var user = new ApplicationUser - { - UserName = userName, - Email = userName, - }; - - var result = await userManager.CreateAsync(user, password); - - return (result.ToApplicationResult(), user.Id); - } - public async Task<(Result Result, string UserId)> CreateUserAsync(Userinfo userInfo) + public async Task> CreateUserAsync(Userinfo userInfo) { - var user = new ApplicationUser + var applicationUser = new ApplicationUser { UserName = userInfo.Name, Email = userInfo.Email, @@ -71,12 +60,18 @@ public class IdentityService( var password = Guid.NewGuid().ToString("N")[..32]; - var result = await userManager.CreateAsync(user, password); + var identityResult = await userManager.CreateAsync(applicationUser, password); - return (result.ToApplicationResult(), user.Id); + var applicationResult = identityResult.ToApplicationResult(); + + var result = new Result(applicationResult.Succeeded, applicationResult.Errors); + + result.Value = applicationUser.Id; + + return result; } - public async Task CreateUserAsync(string email, string userName, string firstName, string lastName, string password) + public async Task> CreateUserAsync(string email, string userName, string firstName, string lastName, string password) { var applicationUser = new ApplicationUser { @@ -88,7 +83,52 @@ public class IdentityService( var response = await userManager.CreateAsync(applicationUser, password); - return response.ToApplicationResult(); + var result = new Result(response.Succeeded, response.ToApplicationResult().Errors); + result.Value = applicationUser.Id; + + return result; + } + + public async Task> UpdateCurrentUserAsync(string id, string firstName, string lastName, string occupation, + string phoneNumber, string birthDate, string country, string city, string address, string about, string description, + SocialNetworksModel socialNetworks) + { + var applicationUser = await userManager.FindByIdAsync(id); + + if (applicationUser is null) return Result.Failure(new[] { "User not found." }); + + applicationUser.FirstName = firstName; + applicationUser.LastName = lastName; + applicationUser.Occupation = occupation; + applicationUser.PhoneNumber = phoneNumber; + applicationUser.BirthDate = birthDate; + applicationUser.Country = country; + applicationUser.City = city; + applicationUser.Address = address; + applicationUser.About = about; + applicationUser.Description = description; + applicationUser.SocialNetworks = new SocialNetworks() + { + FacebookUrl = socialNetworks.FacebookUrl, + InstagramUrl = socialNetworks.InstagramUrl, + XUrl = socialNetworks.XUrl, + LinkedInUrl = socialNetworks.LinkedInUrl, + TikTokUrl = socialNetworks.TikTokUrl, + YoutubeUrl = socialNetworks.YoutubeUrl, + RedditUrl = socialNetworks.RedditUrl, + YourWebsiteUrl = socialNetworks.YourWebsiteUrl + }; + + var response = await userManager.UpdateAsync(applicationUser); + + var applicationResult = response.ToApplicationResult(); + + var result = new Result(applicationResult.Succeeded, + applicationResult.Errors); + + result.Value = id; + + return result; } public async Task FindUserByIdAsync(string id) @@ -97,13 +137,32 @@ public class IdentityService( if (response == null) return null; - var userModel = new UserModel() + var userModel = new UserModel { Id = response.Id, UserName = response.UserName, FirstName = response.FirstName, LastName = response.LastName, Email = response.Email, + Occupation = response.Occupation, + Phone = response.PhoneNumber, + BirthDate = response.BirthDate, + Country = response.Country, + City = response.City, + Address = response.Address, + About = response.About, + Description = response.Description, + SocialNetworks = new SocialNetworksModel + { + FacebookUrl = response.SocialNetworks.FacebookUrl, + InstagramUrl = response.SocialNetworks.InstagramUrl, + XUrl = response.SocialNetworks.XUrl, + LinkedInUrl = response.SocialNetworks.LinkedInUrl, + TikTokUrl = response.SocialNetworks.TikTokUrl, + YoutubeUrl = response.SocialNetworks.YoutubeUrl, + RedditUrl = response.SocialNetworks.RedditUrl, + YourWebsiteUrl = response.SocialNetworks.YourWebsiteUrl, + } }; return userModel; diff --git a/src/Infrastructure/Migrations/20240630001806_AddMissingInformationsToUser.Designer.cs b/src/Infrastructure/Migrations/20240630001806_AddMissingInformationsToUser.Designer.cs new file mode 100644 index 0000000..2a9623e --- /dev/null +++ b/src/Infrastructure/Migrations/20240630001806_AddMissingInformationsToUser.Designer.cs @@ -0,0 +1,497 @@ +// +using System; +using Hutopy.Infrastructure.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Hutopy.Infrastructure.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + [Migration("20240630001806_AddMissingInformationsToUser")] + partial class AddMissingInformationsToUser + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.3") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("Hutopy.Domain.Entities.FutureCreator", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Created") + .HasColumnType("datetimeoffset"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("EmailAddress") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("FirstName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("LastModified") + .HasColumnType("datetimeoffset"); + + b.Property("LastModifiedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("LastName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumber") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("ReasonToJoin") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("SocialNetworkAccount") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("FutureCreators"); + }); + + modelBuilder.Entity("Hutopy.Domain.Entities.UserTransaction", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Amount") + .HasPrecision(18, 2) + .HasColumnType("decimal(18,2)"); + + b.Property("ApplicationUserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.Property("Created") + .HasColumnType("datetimeoffset"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("Currency") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("IsConfirmed") + .HasColumnType("bit"); + + b.Property("LastModified") + .HasColumnType("datetimeoffset"); + + b.Property("LastModifiedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("Paid") + .HasColumnType("bit"); + + b.Property("StripeBillingDetailEmail") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("StripeBillingDetailName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("StripeChargeId") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("StripeEventId") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("StripePaymentIntent") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("StripePaymentMethod") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("StripeReceiptUrl") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("TipMessage") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationUserId"); + + b.ToTable("UserTransactions"); + }); + + modelBuilder.Entity("Hutopy.Infrastructure.Identity.ApplicationUser", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("About") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("AccessFailedCount") + .HasColumnType("int"); + + b.Property("Address") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("BirthDate") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("City") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("nvarchar(max)"); + + b.Property("Country") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Description") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("EmailConfirmed") + .HasColumnType("bit"); + + b.Property("FirstName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("LastName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("LockoutEnabled") + .HasColumnType("bit"); + + b.Property("LockoutEnd") + .HasColumnType("datetimeoffset"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("Occupation") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("PasswordHash") + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumber") + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("bit"); + + b.Property("SecurityStamp") + .HasColumnType("nvarchar(max)"); + + b.Property("TwoFactorEnabled") + .HasColumnType("bit"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex") + .HasFilter("[NormalizedUserName] IS NOT NULL"); + + b.ToTable("AspNetUsers", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("nvarchar(max)"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex") + .HasFilter("[NormalizedName] IS NOT NULL"); + + b.ToTable("AspNetRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("nvarchar(max)"); + + b.Property("ClaimValue") + .HasColumnType("nvarchar(max)"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("nvarchar(max)"); + + b.Property("ClaimValue") + .HasColumnType("nvarchar(max)"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("nvarchar(450)"); + + b.Property("ProviderKey") + .HasColumnType("nvarchar(450)"); + + b.Property("ProviderDisplayName") + .HasColumnType("nvarchar(max)"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("nvarchar(450)"); + + b.Property("RoleId") + .HasColumnType("nvarchar(450)"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("nvarchar(450)"); + + b.Property("LoginProvider") + .HasColumnType("nvarchar(450)"); + + b.Property("Name") + .HasColumnType("nvarchar(450)"); + + b.Property("Value") + .HasColumnType("nvarchar(max)"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens", (string)null); + }); + + modelBuilder.Entity("Hutopy.Domain.Entities.UserTransaction", b => + { + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("ApplicationUserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Hutopy.Infrastructure.Identity.ApplicationUser", b => + { + b.OwnsOne("Hutopy.Infrastructure.Identity.OwnedEntities.SocialNetworks", "SocialNetworks", b1 => + { + b1.Property("ApplicationUserId") + .HasColumnType("nvarchar(450)"); + + b1.Property("FacebookUrl") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.Property("InstagramUrl") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.Property("LinkedInUrl") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.Property("RedditUrl") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.Property("TikTokUrl") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.Property("XUrl") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.Property("YourWebsiteUrl") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.Property("YoutubeUrl") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.HasKey("ApplicationUserId"); + + b1.ToTable("ApplicationUser_SocialNetworks", (string)null); + + b1.WithOwner() + .HasForeignKey("ApplicationUserId"); + }); + + b.Navigation("SocialNetworks") + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Infrastructure/Migrations/20240630001806_AddMissingInformationsToUser.cs b/src/Infrastructure/Migrations/20240630001806_AddMissingInformationsToUser.cs new file mode 100644 index 0000000..cd1a612 --- /dev/null +++ b/src/Infrastructure/Migrations/20240630001806_AddMissingInformationsToUser.cs @@ -0,0 +1,95 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Hutopy.Infrastructure.Migrations +{ + /// + public partial class AddMissingInformationsToUser : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "About", + table: "AspNetUsers", + type: "nvarchar(max)", + nullable: false, + defaultValue: ""); + + migrationBuilder.AddColumn( + name: "Address", + table: "AspNetUsers", + type: "nvarchar(max)", + nullable: false, + defaultValue: ""); + + migrationBuilder.AddColumn( + name: "BirthDate", + table: "AspNetUsers", + type: "nvarchar(max)", + nullable: false, + defaultValue: ""); + + migrationBuilder.AddColumn( + name: "City", + table: "AspNetUsers", + type: "nvarchar(max)", + nullable: false, + defaultValue: ""); + + migrationBuilder.AddColumn( + name: "Country", + table: "AspNetUsers", + type: "nvarchar(max)", + nullable: false, + defaultValue: ""); + + migrationBuilder.AddColumn( + name: "Description", + table: "AspNetUsers", + type: "nvarchar(max)", + nullable: false, + defaultValue: ""); + + migrationBuilder.AddColumn( + name: "Occupation", + table: "AspNetUsers", + type: "nvarchar(max)", + nullable: false, + defaultValue: ""); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "About", + table: "AspNetUsers"); + + migrationBuilder.DropColumn( + name: "Address", + table: "AspNetUsers"); + + migrationBuilder.DropColumn( + name: "BirthDate", + table: "AspNetUsers"); + + migrationBuilder.DropColumn( + name: "City", + table: "AspNetUsers"); + + migrationBuilder.DropColumn( + name: "Country", + table: "AspNetUsers"); + + migrationBuilder.DropColumn( + name: "Description", + table: "AspNetUsers"); + + migrationBuilder.DropColumn( + name: "Occupation", + table: "AspNetUsers"); + } + } +} diff --git a/src/Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs b/src/Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs index fcb6687..cd78f54 100644 --- a/src/Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs +++ b/src/Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs @@ -149,13 +149,37 @@ namespace Hutopy.Infrastructure.Migrations b.Property("Id") .HasColumnType("nvarchar(450)"); + b.Property("About") + .IsRequired() + .HasColumnType("nvarchar(max)"); + b.Property("AccessFailedCount") .HasColumnType("int"); + b.Property("Address") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("BirthDate") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("City") + .IsRequired() + .HasColumnType("nvarchar(max)"); + b.Property("ConcurrencyStamp") .IsConcurrencyToken() .HasColumnType("nvarchar(max)"); + b.Property("Country") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Description") + .IsRequired() + .HasColumnType("nvarchar(max)"); + b.Property("Email") .HasMaxLength(256) .HasColumnType("nvarchar(256)"); @@ -185,6 +209,10 @@ namespace Hutopy.Infrastructure.Migrations .HasMaxLength(256) .HasColumnType("nvarchar(256)"); + b.Property("Occupation") + .IsRequired() + .HasColumnType("nvarchar(max)"); + b.Property("PasswordHash") .HasColumnType("nvarchar(max)"); diff --git a/src/Web/Endpoints/UpdateMyUser.cs b/src/Web/Endpoints/UpdateMyUser.cs new file mode 100644 index 0000000..60121be --- /dev/null +++ b/src/Web/Endpoints/UpdateMyUser.cs @@ -0,0 +1,20 @@ +using Hutopy.Application.Users.Commands; + +namespace Hutopy.Web.Endpoints; + +public class UpdateMyUser : EndpointGroupBase +{ + public override void Map(WebApplication app) + { + app.MapGroup(this) + .RequireAuthorization() + .MapPatch("/profile", UpdateCurrentUser); + } + + private static async Task UpdateCurrentUser(ISender sender, UpdateCurrentUserCommand command) + { + return await sender.Send(command); + } + + +} From ecaaaaad330051b2b67d8a6c2a983f2eea64586a Mon Sep 17 00:00:00 2001 From: Jonathan Bourdon Date: Mon, 1 Jul 2024 03:55:13 -0400 Subject: [PATCH 089/229] Add PortraitUrl to User --- .../Common/Interfaces/IIdentityService.cs | 3 +- .../Commands/UpdateCurrentUserCommand.cs | 24 +- .../Data/ApplicationDbContextInitializer.cs | 7 +- .../Identity/ApplicationUser.cs | 1 + .../Identity/IdentityService.cs | 76 +-- ...701072549_AddPortraitUrlToUser.Designer.cs | 500 ++++++++++++++++++ .../20240701072549_AddPortraitUrlToUser.cs | 28 + .../ApplicationDbContextModelSnapshot.cs | 3 + src/Infrastructure/Utils/GenerateJwtToken.cs | 14 +- 9 files changed, 614 insertions(+), 42 deletions(-) create mode 100644 src/Infrastructure/Migrations/20240701072549_AddPortraitUrlToUser.Designer.cs create mode 100644 src/Infrastructure/Migrations/20240701072549_AddPortraitUrlToUser.cs diff --git a/src/Application/Common/Interfaces/IIdentityService.cs b/src/Application/Common/Interfaces/IIdentityService.cs index d92663e..b5b40e6 100644 --- a/src/Application/Common/Interfaces/IIdentityService.cs +++ b/src/Application/Common/Interfaces/IIdentityService.cs @@ -12,7 +12,8 @@ public interface IIdentityService Task> UpdateCurrentUserAsync(string id, string firstName, string lastName, string occupation, string phoneNumber, string birthDate, string country, string city, string address, string about, string description, - SocialNetworksModel socialNetworks); + SocialNetworksModel socialNetworks, + string? portraitUrl); Task> GetCurrentUserRolesAsync(); Task FindUserByIdAsync(string id); Task FindUserByEmailAsync(string email); diff --git a/src/Application/Users/Commands/UpdateCurrentUserCommand.cs b/src/Application/Users/Commands/UpdateCurrentUserCommand.cs index 3a23915..50d576d 100644 --- a/src/Application/Users/Commands/UpdateCurrentUserCommand.cs +++ b/src/Application/Users/Commands/UpdateCurrentUserCommand.cs @@ -16,9 +16,10 @@ public class UpdateCurrentUserCommand : IRequest public required string About { get; init; } public required string Description { get; init; } public required SocialNetworksModel SocialNetworks { get; init; } + public required string PortraitUrl { get; init; } } -public class UpdateCurrentUserCommandHandler(IApplicationDbContext context, IIdentityService identityService) : +public class UpdateCurrentUserCommandHandler(IApplicationDbContext context, IIdentityService identityService) : IRequestHandler { public async Task Handle(UpdateCurrentUserCommand request, CancellationToken cancellationToken) @@ -26,15 +27,24 @@ public class UpdateCurrentUserCommandHandler(IApplicationDbContext context, IIde var identityUser = await identityService.GetCurrentUserAsync(); if (identityUser?.Id is null) return string.Empty; - - var result = await identityService.UpdateCurrentUserAsync(identityUser.Id, request.FirstName, request.LastName, - request.Occupation, request.PhoneNumber, request.BirthDate, - request.Country, request.City, request.Address, request.About, - request.Description, request.SocialNetworks); + + var result = await identityService.UpdateCurrentUserAsync( + identityUser.Id, + request.FirstName, + request.LastName, + request.Occupation, + request.PhoneNumber, + request.BirthDate, + request.Country, + request.City, + request.Address, + request.About, + request.Description, + request.SocialNetworks, + request.PortraitUrl); await context.SaveChangesAsync(cancellationToken); return result.GetValueOrDefault(); } } - diff --git a/src/Infrastructure/Data/ApplicationDbContextInitializer.cs b/src/Infrastructure/Data/ApplicationDbContextInitializer.cs index 6a985de..79d5e54 100644 --- a/src/Infrastructure/Data/ApplicationDbContextInitializer.cs +++ b/src/Infrastructure/Data/ApplicationDbContextInitializer.cs @@ -65,7 +65,12 @@ public class ApplicationDbContextInitializer( } // Default users - var administrator = new ApplicationUser { UserName = "administrator@localhost", Email = "administrator@localhost" }; + var administrator = new ApplicationUser + { + UserName = "administrator@localhost", + Email = "administrator@localhost", + PortraitUrl = "images/usersmedia/anonyme/profilepictures/profilePascal.jpg" + }; if (userManager.Users.All(u => u.UserName != administrator.UserName)) { diff --git a/src/Infrastructure/Identity/ApplicationUser.cs b/src/Infrastructure/Identity/ApplicationUser.cs index d956a9b..ccf91b8 100644 --- a/src/Infrastructure/Identity/ApplicationUser.cs +++ b/src/Infrastructure/Identity/ApplicationUser.cs @@ -15,4 +15,5 @@ public class ApplicationUser : IdentityUser public string About { get; set; } = string.Empty; public string Description { get; set; } = string.Empty; public SocialNetworks SocialNetworks { get; set; } = new(); + public string? PortraitUrl { get; set; } } diff --git a/src/Infrastructure/Identity/IdentityService.cs b/src/Infrastructure/Identity/IdentityService.cs index d512ae5..37a907e 100644 --- a/src/Infrastructure/Identity/IdentityService.cs +++ b/src/Infrastructure/Identity/IdentityService.cs @@ -20,7 +20,7 @@ public class IdentityService( IAuthorizationService authorizationService, IHttpContextAccessor contextAccessor, IConfiguration configuration - ) +) : IIdentityService { public async Task GetUserNameAsync(string userId) @@ -29,11 +29,11 @@ public class IdentityService( return user?.UserName; } - + public async Task GetUserByUserNameAsync(string userName) { var response = await userManager.FindByNameAsync(userName); - + if (response == null) return null; var userModel = new UserModel() @@ -42,12 +42,13 @@ public class IdentityService( UserName = response.UserName, FirstName = response.FirstName, LastName = response.LastName, - Email = response.Email, + Email = response.Email, + PortraitUrl = response.PortraitUrl, }; return userModel; } - + public async Task> CreateUserAsync(Userinfo userInfo) { var applicationUser = new ApplicationUser @@ -57,7 +58,7 @@ public class IdentityService( FirstName = userInfo.GivenName, LastName = userInfo.FamilyName }; - + var password = Guid.NewGuid().ToString("N")[..32]; var identityResult = await userManager.CreateAsync(applicationUser, password); @@ -65,13 +66,14 @@ public class IdentityService( var applicationResult = identityResult.ToApplicationResult(); var result = new Result(applicationResult.Succeeded, applicationResult.Errors); - + result.Value = applicationUser.Id; return result; } - - public async Task> CreateUserAsync(string email, string userName, string firstName, string lastName, string password) + + public async Task> CreateUserAsync(string email, string userName, string firstName, string lastName, + string password) { var applicationUser = new ApplicationUser { @@ -82,16 +84,24 @@ public class IdentityService( }; var response = await userManager.CreateAsync(applicationUser, password); - + var result = new Result(response.Succeeded, response.ToApplicationResult().Errors); result.Value = applicationUser.Id; return result; } - public async Task> UpdateCurrentUserAsync(string id, string firstName, string lastName, string occupation, - string phoneNumber, string birthDate, string country, string city, string address, string about, string description, - SocialNetworksModel socialNetworks) + public async Task> UpdateCurrentUserAsync(string id, string firstName, string lastName, + string occupation, + string phoneNumber, + string birthDate, + string country, + string city, + string address, + string about, + string description, + SocialNetworksModel socialNetworks, + string? portraitUrl) { var applicationUser = await userManager.FindByIdAsync(id); @@ -107,6 +117,7 @@ public class IdentityService( applicationUser.Address = address; applicationUser.About = about; applicationUser.Description = description; + applicationUser.PortraitUrl = portraitUrl; applicationUser.SocialNetworks = new SocialNetworks() { FacebookUrl = socialNetworks.FacebookUrl, @@ -130,7 +141,7 @@ public class IdentityService( return result; } - + public async Task FindUserByIdAsync(string id) { var response = await userManager.FindByIdAsync(id); @@ -152,6 +163,7 @@ public class IdentityService( Address = response.Address, About = response.About, Description = response.Description, + PortraitUrl = response.PortraitUrl, SocialNetworks = new SocialNetworksModel { FacebookUrl = response.SocialNetworks.FacebookUrl, @@ -167,7 +179,7 @@ public class IdentityService( return userModel; } - + public async Task GetCurrentUserAsync() { var currentUserId = contextAccessor.HttpContext?.User.FindFirst(ClaimTypes.NameIdentifier)?.Value; @@ -203,7 +215,7 @@ public class IdentityService( return user != null && await userManager.IsInRoleAsync(user, role); } - + public async Task CurrentUserIsInRoleAsync(string role) { var currentUserModel = await GetCurrentUserAsync(); @@ -241,44 +253,45 @@ public class IdentityService( return result.ToApplicationResult(); } - + public async Task AddRoleAsync(string userId, string role) { var hasAdminAccess = await CurrentUserIsInRoleAsync("Administrator"); - - if (!hasAdminAccess) return Result.Failure(new []{"Only administrator can assign new roles to a user."}); + + if (!hasAdminAccess) return Result.Failure(new[] { "Only administrator can assign new roles to a user." }); var user = await userManager.FindByIdAsync(userId); - - if (user is null) return Result.Failure(new []{"User not found."}); - + + if (user is null) return Result.Failure(new[] { "User not found." }); + var result = await userManager.AddToRoleAsync(user, role); return result.ToApplicationResult(); } - + public async Task> GetCurrentUserRolesAsync() { var currentUserModel = await GetCurrentUserAsync(); - + var currentUser = await userManager.FindByIdAsync(currentUserModel?.Id ?? ""); - - if (currentUser is null) return []; + + if (currentUser is null) return []; var userRoles = await userManager.GetRolesAsync(currentUser); return userRoles; } - + public async Task LoginAsync(string userName, string password) { - var result = await signInManager.PasswordSignInAsync(userName, password, isPersistent: false, lockoutOnFailure: false); - + var result = + await signInManager.PasswordSignInAsync(userName, password, isPersistent: false, lockoutOnFailure: false); + if (!result.Succeeded) { return null; } - + var user = await GetUserByUserNameAsync(userName); if (user is null) throw new InvalidOperationException(); @@ -298,3 +311,6 @@ public class IdentityService( return token; } } + +public class ConfigurationMissingException(string ConfigurationKey) + : Exception; diff --git a/src/Infrastructure/Migrations/20240701072549_AddPortraitUrlToUser.Designer.cs b/src/Infrastructure/Migrations/20240701072549_AddPortraitUrlToUser.Designer.cs new file mode 100644 index 0000000..2ce61d4 --- /dev/null +++ b/src/Infrastructure/Migrations/20240701072549_AddPortraitUrlToUser.Designer.cs @@ -0,0 +1,500 @@ +// +using System; +using Hutopy.Infrastructure.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Hutopy.Infrastructure.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + [Migration("20240701072549_AddPortraitUrlToUser")] + partial class AddPortraitUrlToUser + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.3") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("Hutopy.Domain.Entities.FutureCreator", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Created") + .HasColumnType("datetimeoffset"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("EmailAddress") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("FirstName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("LastModified") + .HasColumnType("datetimeoffset"); + + b.Property("LastModifiedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("LastName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumber") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("ReasonToJoin") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("SocialNetworkAccount") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("FutureCreators"); + }); + + modelBuilder.Entity("Hutopy.Domain.Entities.UserTransaction", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Amount") + .HasPrecision(18, 2) + .HasColumnType("decimal(18,2)"); + + b.Property("ApplicationUserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.Property("Created") + .HasColumnType("datetimeoffset"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("Currency") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("IsConfirmed") + .HasColumnType("bit"); + + b.Property("LastModified") + .HasColumnType("datetimeoffset"); + + b.Property("LastModifiedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("Paid") + .HasColumnType("bit"); + + b.Property("StripeBillingDetailEmail") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("StripeBillingDetailName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("StripeChargeId") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("StripeEventId") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("StripePaymentIntent") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("StripePaymentMethod") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("StripeReceiptUrl") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("TipMessage") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationUserId"); + + b.ToTable("UserTransactions"); + }); + + modelBuilder.Entity("Hutopy.Infrastructure.Identity.ApplicationUser", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("About") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("AccessFailedCount") + .HasColumnType("int"); + + b.Property("Address") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("BirthDate") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("City") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("nvarchar(max)"); + + b.Property("Country") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Description") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("EmailConfirmed") + .HasColumnType("bit"); + + b.Property("FirstName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("LastName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("LockoutEnabled") + .HasColumnType("bit"); + + b.Property("LockoutEnd") + .HasColumnType("datetimeoffset"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("Occupation") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("PasswordHash") + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumber") + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("bit"); + + b.Property("PortraitUrl") + .HasColumnType("nvarchar(max)"); + + b.Property("SecurityStamp") + .HasColumnType("nvarchar(max)"); + + b.Property("TwoFactorEnabled") + .HasColumnType("bit"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex") + .HasFilter("[NormalizedUserName] IS NOT NULL"); + + b.ToTable("AspNetUsers", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("nvarchar(max)"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex") + .HasFilter("[NormalizedName] IS NOT NULL"); + + b.ToTable("AspNetRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("nvarchar(max)"); + + b.Property("ClaimValue") + .HasColumnType("nvarchar(max)"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("nvarchar(max)"); + + b.Property("ClaimValue") + .HasColumnType("nvarchar(max)"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("nvarchar(450)"); + + b.Property("ProviderKey") + .HasColumnType("nvarchar(450)"); + + b.Property("ProviderDisplayName") + .HasColumnType("nvarchar(max)"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("nvarchar(450)"); + + b.Property("RoleId") + .HasColumnType("nvarchar(450)"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("nvarchar(450)"); + + b.Property("LoginProvider") + .HasColumnType("nvarchar(450)"); + + b.Property("Name") + .HasColumnType("nvarchar(450)"); + + b.Property("Value") + .HasColumnType("nvarchar(max)"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens", (string)null); + }); + + modelBuilder.Entity("Hutopy.Domain.Entities.UserTransaction", b => + { + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("ApplicationUserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Hutopy.Infrastructure.Identity.ApplicationUser", b => + { + b.OwnsOne("Hutopy.Infrastructure.Identity.OwnedEntities.SocialNetworks", "SocialNetworks", b1 => + { + b1.Property("ApplicationUserId") + .HasColumnType("nvarchar(450)"); + + b1.Property("FacebookUrl") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.Property("InstagramUrl") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.Property("LinkedInUrl") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.Property("RedditUrl") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.Property("TikTokUrl") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.Property("XUrl") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.Property("YourWebsiteUrl") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.Property("YoutubeUrl") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.HasKey("ApplicationUserId"); + + b1.ToTable("ApplicationUser_SocialNetworks", (string)null); + + b1.WithOwner() + .HasForeignKey("ApplicationUserId"); + }); + + b.Navigation("SocialNetworks") + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Infrastructure/Migrations/20240701072549_AddPortraitUrlToUser.cs b/src/Infrastructure/Migrations/20240701072549_AddPortraitUrlToUser.cs new file mode 100644 index 0000000..a279865 --- /dev/null +++ b/src/Infrastructure/Migrations/20240701072549_AddPortraitUrlToUser.cs @@ -0,0 +1,28 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Hutopy.Infrastructure.Migrations +{ + /// + public partial class AddPortraitUrlToUser : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "PortraitUrl", + table: "AspNetUsers", + type: "nvarchar(max)", + nullable: true); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "PortraitUrl", + table: "AspNetUsers"); + } + } +} diff --git a/src/Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs b/src/Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs index cd78f54..80e3d53 100644 --- a/src/Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs +++ b/src/Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs @@ -222,6 +222,9 @@ namespace Hutopy.Infrastructure.Migrations b.Property("PhoneNumberConfirmed") .HasColumnType("bit"); + b.Property("PortraitUrl") + .HasColumnType("nvarchar(max)"); + b.Property("SecurityStamp") .HasColumnType("nvarchar(max)"); diff --git a/src/Infrastructure/Utils/GenerateJwtToken.cs b/src/Infrastructure/Utils/GenerateJwtToken.cs index 19e6cbd..a4d74de 100644 --- a/src/Infrastructure/Utils/GenerateJwtToken.cs +++ b/src/Infrastructure/Utils/GenerateJwtToken.cs @@ -7,8 +7,15 @@ namespace Hutopy.Infrastructure.Utils; public static class JwtTokenHelper { - public static string GenerateJwtToken(string issuer, string audience, string key, string? userId, string? email, - string? firstname, string? lastname, string? portraitUrl) + public static string GenerateJwtToken( + string issuer, + string audience, + string key, + string? userId, + string? email, + string? firstname, + string? lastname, + string? portraitUrl) { var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(key)); var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256); @@ -19,7 +26,8 @@ public static class JwtTokenHelper new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()), new Claim(ClaimTypes.NameIdentifier, userId), new Claim(ClaimTypes.Email, email), - new Claim(ClaimTypes.GivenName, firstname), + new Claim(ClaimTypes.Name, email), + new Claim(ClaimTypes.GivenName, firstname), new Claim(ClaimTypes.Surname, lastname), }); From adb1cebc731c22aca561daf1455ec24671b11e0c Mon Sep 17 00:00:00 2001 From: Jonathan Bourdon Date: Mon, 1 Jul 2024 23:34:23 -0400 Subject: [PATCH 090/229] WIP --- src/Web/Program.cs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Web/Program.cs b/src/Web/Program.cs index 78700bc..8bcb1ae 100644 --- a/src/Web/Program.cs +++ b/src/Web/Program.cs @@ -21,24 +21,24 @@ if (!builder.Environment.IsDevelopment()) builder.Services.AddCors(options => { - options.AddPolicy("AllowAll", builder => + options.AddPolicy("AllowAll", policy => { - builder.AllowAnyOrigin() + policy.AllowAnyOrigin() .AllowAnyMethod() .AllowAnyHeader(); }); - options.AddPolicy("AllowHutopyUi", builder => + options.AddPolicy("AllowHutopyUi", policy => { - builder.WithOrigins("https://zealous-bay-08204590f.5.azurestaticapps.net") + policy.WithOrigins("https://zealous-bay-08204590f.5.azurestaticapps.net") .AllowAnyMethod() .AllowAnyHeader() .AllowCredentials(); }); - - options.AddPolicy("AllowHutopyUiPreview", builder => + + options.AddPolicy("AllowHutopyUiPreview", policy => { - builder.WithOrigins("https://zealous-bay-08204590f-preview.eastus2.5.azurestaticapps.net") + policy.WithOrigins("https://zealous-bay-08204590f-preview.eastus2.5.azurestaticapps.net") .AllowAnyMethod() .AllowAnyHeader() .AllowCredentials(); From 82699dae41fbbe2651dee14587643b43bc5b3cc7 Mon Sep 17 00:00:00 2001 From: Jonathan Bourdon Date: Mon, 1 Jul 2024 23:38:06 -0400 Subject: [PATCH 091/229] Split Common from Messages --- src/Web/{Messages => Common}/Shared.cs | 2 +- src/Web/Messages/Handlers/GetMessagesByUser.cs | 3 --- src/Web/Messages/Handlers/PostMessage.cs | 1 + src/Web/Messages/Handlers/PostReplyMessage.cs | 1 + 4 files changed, 3 insertions(+), 4 deletions(-) rename src/Web/{Messages => Common}/Shared.cs (97%) diff --git a/src/Web/Messages/Shared.cs b/src/Web/Common/Shared.cs similarity index 97% rename from src/Web/Messages/Shared.cs rename to src/Web/Common/Shared.cs index eb48399..e36a0ec 100644 --- a/src/Web/Messages/Shared.cs +++ b/src/Web/Common/Shared.cs @@ -1,6 +1,6 @@ using System.Security.Claims; -namespace Hutopy.Web.Messages; +namespace Hutopy.Web.Common; public class Shared(string claimName) : Exception; diff --git a/src/Web/Messages/Handlers/GetMessagesByUser.cs b/src/Web/Messages/Handlers/GetMessagesByUser.cs index d70cd11..d49c0d3 100644 --- a/src/Web/Messages/Handlers/GetMessagesByUser.cs +++ b/src/Web/Messages/Handlers/GetMessagesByUser.cs @@ -5,9 +5,6 @@ using Microsoft.EntityFrameworkCore; namespace Hutopy.Web.Messages.Handlers; -public record GetMessagesByUserRequest( - [FromRoute] Guid UserId); - public class GetMessagesByUser( MessagingDbContext context) : EndpointWithoutRequest> diff --git a/src/Web/Messages/Handlers/PostMessage.cs b/src/Web/Messages/Handlers/PostMessage.cs index 7460728..46a316c 100644 --- a/src/Web/Messages/Handlers/PostMessage.cs +++ b/src/Web/Messages/Handlers/PostMessage.cs @@ -1,4 +1,5 @@ using FastEndpoints; +using Hutopy.Web.Common; using Hutopy.Web.Messages.Data; namespace Hutopy.Web.Messages.Handlers; diff --git a/src/Web/Messages/Handlers/PostReplyMessage.cs b/src/Web/Messages/Handlers/PostReplyMessage.cs index 2385765..5a9bef9 100644 --- a/src/Web/Messages/Handlers/PostReplyMessage.cs +++ b/src/Web/Messages/Handlers/PostReplyMessage.cs @@ -1,4 +1,5 @@ using FastEndpoints; +using Hutopy.Web.Common; using Hutopy.Web.Messages.Data; namespace Hutopy.Web.Messages.Handlers; From bc2dc969ff6afc1503dd32ab07701dc974a4c29e Mon Sep 17 00:00:00 2001 From: Jonathan Bourdon Date: Tue, 2 Jul 2024 00:23:14 -0400 Subject: [PATCH 092/229] Add content system --- src/Web/Contents/Data/Content.cs | 13 +++++ src/Web/Contents/Data/ContentDbContext.cs | 19 ++++++ src/Web/Contents/Handlers/GetContents.cs | 30 ++++++++++ .../Contents/Handlers/GetContentsByUser.cs | 30 ++++++++++ src/Web/Contents/Handlers/PostMessage.cs | 39 +++++++++++++ .../20240702034957_Initial.Designer.cs | 58 +++++++++++++++++++ .../Migrations/20240702034957_Initial.cs | 38 ++++++++++++ .../ContentDbContextModelSnapshot.cs | 55 ++++++++++++++++++ src/Web/Program.cs | 6 ++ src/Web/Web.csproj | 4 -- src/Web/appsettings.Development.json | 3 +- 11 files changed, 290 insertions(+), 5 deletions(-) create mode 100644 src/Web/Contents/Data/Content.cs create mode 100644 src/Web/Contents/Data/ContentDbContext.cs create mode 100644 src/Web/Contents/Handlers/GetContents.cs create mode 100644 src/Web/Contents/Handlers/GetContentsByUser.cs create mode 100644 src/Web/Contents/Handlers/PostMessage.cs create mode 100644 src/Web/Contents/Migrations/20240702034957_Initial.Designer.cs create mode 100644 src/Web/Contents/Migrations/20240702034957_Initial.cs create mode 100644 src/Web/Contents/Migrations/ContentDbContextModelSnapshot.cs diff --git a/src/Web/Contents/Data/Content.cs b/src/Web/Contents/Data/Content.cs new file mode 100644 index 0000000..c13bd0b --- /dev/null +++ b/src/Web/Contents/Data/Content.cs @@ -0,0 +1,13 @@ +namespace Hutopy.Web.Contents.Data; + +public class Content +{ + public Guid Id { get; init; } + public Guid CreatedBy { get; init; } + public DateTime CreatedAt { get; } + + public string? Title { get; init; } = null!; + public string? Description { get; init; } = null!; + public string? Uri { get; init; } = null!; +} + diff --git a/src/Web/Contents/Data/ContentDbContext.cs b/src/Web/Contents/Data/ContentDbContext.cs new file mode 100644 index 0000000..f525cbf --- /dev/null +++ b/src/Web/Contents/Data/ContentDbContext.cs @@ -0,0 +1,19 @@ +using Microsoft.EntityFrameworkCore; + +namespace Hutopy.Web.Contents.Data; + +public class ContentDbContext( + DbContextOptions options) + : DbContext(options) +{ + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + modelBuilder + .Entity() + .Property(c => c.CreatedAt) + .ValueGeneratedOnAdd() + .HasDefaultValueSql("CURRENT_TIMESTAMP"); + } + + public DbSet Contents { get; set; } +} diff --git a/src/Web/Contents/Handlers/GetContents.cs b/src/Web/Contents/Handlers/GetContents.cs new file mode 100644 index 0000000..c9f3258 --- /dev/null +++ b/src/Web/Contents/Handlers/GetContents.cs @@ -0,0 +1,30 @@ +using FastEndpoints; +using Hutopy.Web.Contents.Data; +using Microsoft.EntityFrameworkCore; + +namespace Hutopy.Web.Contents.Handlers; + +public class GetContents( + ContentDbContext context) + : EndpointWithoutRequest +{ + public override void Configure() + { + Tags("Contents"); + Get("/api/contents/{ContentId:guid}"); + AllowAnonymous(); + } + + public override async Task HandleAsync( + CancellationToken ct) + { + var contentId = Route("ContentId"); + + var comments = await context + .Contents + .Where(c => c.Id == contentId) + .ToListAsync(cancellationToken: ct); + + await SendAsync(comments.First(), cancellation: ct); + } +} diff --git a/src/Web/Contents/Handlers/GetContentsByUser.cs b/src/Web/Contents/Handlers/GetContentsByUser.cs new file mode 100644 index 0000000..e3796d6 --- /dev/null +++ b/src/Web/Contents/Handlers/GetContentsByUser.cs @@ -0,0 +1,30 @@ +using FastEndpoints; +using Hutopy.Web.Messages.Data; +using Microsoft.EntityFrameworkCore; + +namespace Hutopy.Web.Contents.Handlers; + +public class GetContentsByUser( + MessagingDbContext context) + : EndpointWithoutRequest> +{ + public override void Configure() + { + Tags("Contents"); + Get("/api/contents/by-user/{UserId:guid}"); + AllowAnonymous(); + } + + public override async Task HandleAsync( + CancellationToken ct) + { + var userId = Route("UserId"); + + var posts = await context + .Messages + .Where(c => c.CreatedBy == userId) + .ToListAsync(cancellationToken: ct); + + await SendAsync(posts, cancellation: ct); + } +} diff --git a/src/Web/Contents/Handlers/PostMessage.cs b/src/Web/Contents/Handlers/PostMessage.cs new file mode 100644 index 0000000..850cfba --- /dev/null +++ b/src/Web/Contents/Handlers/PostMessage.cs @@ -0,0 +1,39 @@ +using FastEndpoints; +using Hutopy.Web.Common; +using Hutopy.Web.Contents.Data; + +namespace Hutopy.Web.Contents.Handlers; + +public record struct PostContentRequest( + string? Title, + string? Description, + string? Uri); + +public class PostMessage( + ContentDbContext context) + : Endpoint +{ + public override void Configure() + { + // TODO: Find how to specify the name we see in Swagger + Tags("Contents"); + Post("/api/contents"); + } + + public override async Task HandleAsync( + PostContentRequest req, + CancellationToken ct) + { + await context.Contents.AddAsync( + new Content + { + CreatedBy = User.GetUserId(), + Title = req.Title, + Description = req.Description, + Uri = req.Uri + }, + ct); + + await context.SaveChangesAsync(ct); + } +} diff --git a/src/Web/Contents/Migrations/20240702034957_Initial.Designer.cs b/src/Web/Contents/Migrations/20240702034957_Initial.Designer.cs new file mode 100644 index 0000000..c63f6b4 --- /dev/null +++ b/src/Web/Contents/Migrations/20240702034957_Initial.Designer.cs @@ -0,0 +1,58 @@ +// +using System; +using Hutopy.Web.Contents.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Hutopy.Web.Contents.Migrations +{ + [DbContext(typeof(ContentDbContext))] + [Migration("20240702034957_Initial")] + partial class Initial + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.3") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("Hutopy.Web.Contents.Data.Content", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasDefaultValueSql("CURRENT_TIMESTAMP"); + + b.Property("CreatedBy") + .HasColumnType("uniqueidentifier"); + + b.Property("Description") + .HasColumnType("nvarchar(max)"); + + b.Property("Title") + .HasColumnType("nvarchar(max)"); + + b.Property("Uri") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("Contents"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Web/Contents/Migrations/20240702034957_Initial.cs b/src/Web/Contents/Migrations/20240702034957_Initial.cs new file mode 100644 index 0000000..593cc49 --- /dev/null +++ b/src/Web/Contents/Migrations/20240702034957_Initial.cs @@ -0,0 +1,38 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Hutopy.Web.Contents.Migrations +{ + /// + public partial class Initial : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "Contents", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + CreatedBy = table.Column(type: "uniqueidentifier", nullable: false), + CreatedAt = table.Column(type: "datetime2", nullable: false, defaultValueSql: "CURRENT_TIMESTAMP"), + Title = table.Column(type: "nvarchar(max)", nullable: true), + Description = table.Column(type: "nvarchar(max)", nullable: true), + Uri = table.Column(type: "nvarchar(max)", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Contents", x => x.Id); + }); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "Contents"); + } + } +} diff --git a/src/Web/Contents/Migrations/ContentDbContextModelSnapshot.cs b/src/Web/Contents/Migrations/ContentDbContextModelSnapshot.cs new file mode 100644 index 0000000..1892c37 --- /dev/null +++ b/src/Web/Contents/Migrations/ContentDbContextModelSnapshot.cs @@ -0,0 +1,55 @@ +// +using System; +using Hutopy.Web.Contents.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Hutopy.Web.Contents.Migrations +{ + [DbContext(typeof(ContentDbContext))] + partial class ContentDbContextModelSnapshot : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.3") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("Hutopy.Web.Contents.Data.Content", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasDefaultValueSql("CURRENT_TIMESTAMP"); + + b.Property("CreatedBy") + .HasColumnType("uniqueidentifier"); + + b.Property("Description") + .HasColumnType("nvarchar(max)"); + + b.Property("Title") + .HasColumnType("nvarchar(max)"); + + b.Property("Uri") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("Contents"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Web/Program.cs b/src/Web/Program.cs index 8bcb1ae..097dac9 100644 --- a/src/Web/Program.cs +++ b/src/Web/Program.cs @@ -4,6 +4,7 @@ using Hutopy.Application; using Hutopy.Infrastructure; using Hutopy.Infrastructure.Data; using Hutopy.Web; +using Hutopy.Web.Contents.Data; using Hutopy.Web.Messages.Data; using Microsoft.AspNetCore.HttpOverrides; using Microsoft.EntityFrameworkCore; @@ -83,6 +84,11 @@ builder.Services.AddDbContext((_, options) => options.UseSqlServer(builder.Configuration.GetConnectionString("CommentStore")); }); +builder.Services.AddDbContext((_, options) => +{ + options.UseSqlServer(builder.Configuration.GetConnectionString("ContentStore")); +}); + var app = builder.Build(); app.UseForwardedHeaders( diff --git a/src/Web/Web.csproj b/src/Web/Web.csproj index 053126a..817e221 100644 --- a/src/Web/Web.csproj +++ b/src/Web/Web.csproj @@ -30,8 +30,4 @@ - - - - diff --git a/src/Web/appsettings.Development.json b/src/Web/appsettings.Development.json index 9e2b285..decba8e 100644 --- a/src/Web/appsettings.Development.json +++ b/src/Web/appsettings.Development.json @@ -9,7 +9,8 @@ }, "ConnectionStrings": { "DefaultConnection": "Server=localhost,1433;Initial Catalog=Hutopy;User Id=sa;Password=P@ssword123!;MultipleActiveResultSets=true;TrustServerCertificate=True;MultiSubnetFailover=True", - "CommentStore": "Server=localhost,1433;Initial Catalog=Hutopy;User Id=sa;Password=P@ssword123!;MultipleActiveResultSets=true;TrustServerCertificate=True;MultiSubnetFailover=True" + "CommentStore": "Server=localhost,1433;Initial Catalog=Hutopy;User Id=sa;Password=P@ssword123!;MultipleActiveResultSets=true;TrustServerCertificate=True;MultiSubnetFailover=True", + "ContentStore": "Server=localhost,1433;Initial Catalog=Hutopy;User Id=sa;Password=P@ssword123!;MultipleActiveResultSets=true;TrustServerCertificate=True;MultiSubnetFailover=True" }, "Authentication": { "Jwt": { From eb2136083b290f341673fc7653d7efb965550327 Mon Sep 17 00:00:00 2001 From: Jonathan Bourdon Date: Tue, 2 Jul 2024 03:11:06 -0400 Subject: [PATCH 093/229] Add GetCreatorByAlias and CreatorAlias to User --- .../Common/Interfaces/IIdentityService.cs | 7 +- src/Domain/Constants/Roles.cs | 3 +- .../Data/ApplicationDbContextInitializer.cs | 53 +- src/Infrastructure/DependencyInjection.cs | 1 + .../Identity/ApplicationUser.cs | 1 + .../Identity/ApplicationUserManager.cs | 42 ++ .../Identity/IdentityService.cs | 27 +- ...02055858_AddCreatorAliasTouser.Designer.cs | 560 ++++++++++++++++++ .../20240702055858_AddCreatorAliasTouser.cs | 28 + .../ApplicationDbContextModelSnapshot.cs | 3 + .../Creators/Handlers/GetCreatorByAlias.cs | 29 + src/Web/Pages/Shared/_LoginPartial.cshtml | 1 - tests/Application.FunctionalTests/Testing.cs | 2 +- 13 files changed, 737 insertions(+), 20 deletions(-) create mode 100644 src/Infrastructure/Identity/ApplicationUserManager.cs create mode 100644 src/Infrastructure/Migrations/20240702055858_AddCreatorAliasTouser.Designer.cs create mode 100644 src/Infrastructure/Migrations/20240702055858_AddCreatorAliasTouser.cs create mode 100644 src/Web/Creators/Handlers/GetCreatorByAlias.cs diff --git a/src/Application/Common/Interfaces/IIdentityService.cs b/src/Application/Common/Interfaces/IIdentityService.cs index 74e9240..e780b94 100644 --- a/src/Application/Common/Interfaces/IIdentityService.cs +++ b/src/Application/Common/Interfaces/IIdentityService.cs @@ -1,13 +1,15 @@ using Google.Apis.Oauth2.v2.Data; using Hutopy.Application.Common.Models; -using Hutopy.Application.Users.Models; namespace Hutopy.Application.Common.Interfaces; public interface IIdentityService { Task> CreateUserAsync(Userinfo userInfo); - Task> CreateUserAsync(string email, string userName, string firstName, string lastName, string password); + + Task> CreateUserAsync(string email, string userName, string firstName, string lastName, + string password); + Task GetCurrentUserAsync(); Task UpdateCurrentUserBannerPictureUrlAsync(string url); Task UpdateCurrentUserProfilePictureUrlAsync(string url); @@ -15,6 +17,7 @@ public interface IIdentityService Task> UpdateCurrentUserAsync(UserModel userModel); Task> GetCurrentUserRolesAsync(); Task FindUserByIdAsync(string id); + Task FindUserByCreatorAliasAsync(string creatorAlias, CancellationToken cancellationToken); Task FindUserByEmailAsync(string email); Task GetUserByUserNameAsync(string userName); Task LoginAsync(string email, string password); diff --git a/src/Domain/Constants/Roles.cs b/src/Domain/Constants/Roles.cs index 38d9bf3..b285a6e 100644 --- a/src/Domain/Constants/Roles.cs +++ b/src/Domain/Constants/Roles.cs @@ -3,4 +3,5 @@ public abstract class Roles { public const string Administrator = nameof(Administrator); -} \ No newline at end of file + public const string Creator = nameof(Creator); +} diff --git a/src/Infrastructure/Data/ApplicationDbContextInitializer.cs b/src/Infrastructure/Data/ApplicationDbContextInitializer.cs index b771d57..bc57199 100644 --- a/src/Infrastructure/Data/ApplicationDbContextInitializer.cs +++ b/src/Infrastructure/Data/ApplicationDbContextInitializer.cs @@ -1,8 +1,6 @@ -using System; -using System.Linq; -using System.Threading.Tasks; -using Hutopy.Domain.Constants; +using Hutopy.Domain.Constants; using Hutopy.Infrastructure.Identity; +using Hutopy.Infrastructure.Identity.OwnedEntities; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Identity; using Microsoft.EntityFrameworkCore; @@ -28,7 +26,7 @@ public static class InitializerExtensions public class ApplicationDbContextInitializer( ILogger logger, ApplicationDbContext context, - UserManager userManager, + ApplicationUserManager userManager, RoleManager roleManager) { public async Task InitialiseAsync() @@ -61,22 +59,57 @@ public class ApplicationDbContextInitializer( { // Default roles var administratorRole = new IdentityRole(Roles.Administrator); - if (roleManager.Roles.All(r => r.Name != administratorRole.Name)) { await roleManager.CreateAsync(administratorRole); } - // Default users - var administrator = new ApplicationUser { UserName = "administrator@localhost", Email = "administrator@localhost" }; + var roleCreator = new IdentityRole(Roles.Creator); + if (roleManager.Roles.All(r => r.Name != roleCreator.Name)) + { + await roleManager.CreateAsync(roleCreator); + } + // Default users + var administrator = + new ApplicationUser { UserName = "administrator@localhost", Email = "administrator@localhost" }; if (userManager.Users.All(u => u.UserName != administrator.UserName)) { await userManager.CreateAsync(administrator, "Administrator1!"); - if (!string.IsNullOrWhiteSpace(administratorRole.Name)) + await userManager.AddToRolesAsync(administrator, new[] { Roles.Administrator }); + } + + // ADD CREATORS + await AddDefaultCreator(new ApplicationUser + { + UserName = "hutopy@localhost", + Email = "hutopy@localhost", + CreatorAlias = "hutopy", + About = "Page officielle", + Description = "Site officiel pour Hutopy. Venez-nous-y retrouver avec tous vos fans!", + EmailConfirmed = true, + ProfileColors = new ProfileColors { BannerTop = "A30E79", BannerBottom = "6B0065", Accent = "23393B", Menu = "53B93B", }, + SocialNetworks = + new SocialNetworks + { + XUrl = "https://twitter.com/Hutopyinc", + FacebookUrl = "https://www.facebook.com/Hutopy", + InstagramUrl = "https://www.instagram.com/hutopy.inc/" + }, + StoredDataUrls = new StoredDataUrls { - await userManager.AddToRolesAsync(administrator, new[] { administratorRole.Name }); + BannerPictureUrl = "/images/usersmedia/HutopyProfile/banners/banner01.png", + ProfilePictureUrl = "/images/usersmedia/HutopyProfile/profilepictures/profileHutopyProfile01.png" } + }); + } + + private async Task AddDefaultCreator(ApplicationUser hutopy) + { + if (userManager.Users.All(u => u.UserName != hutopy.UserName)) + { + await userManager.CreateAsync(hutopy, "Test123!"); + await userManager.AddToRolesAsync(hutopy, new[] { Roles.Creator }); } } } diff --git a/src/Infrastructure/DependencyInjection.cs b/src/Infrastructure/DependencyInjection.cs index 2dfccb2..4aae695 100644 --- a/src/Infrastructure/DependencyInjection.cs +++ b/src/Infrastructure/DependencyInjection.cs @@ -44,6 +44,7 @@ public static class DependencyInjection services .AddIdentityCore() + .AddUserManager() .AddRoles() .AddEntityFrameworkStores() .AddApiEndpoints() diff --git a/src/Infrastructure/Identity/ApplicationUser.cs b/src/Infrastructure/Identity/ApplicationUser.cs index fbf49f7..74ad0cf 100644 --- a/src/Infrastructure/Identity/ApplicationUser.cs +++ b/src/Infrastructure/Identity/ApplicationUser.cs @@ -7,6 +7,7 @@ public class ApplicationUser : IdentityUser { public string FirstName { get; set; } = string.Empty; public string LastName { get; set; } = string.Empty; + public string? CreatorAlias { get; set; } public string Occupation { get; set; } = string.Empty; public string BirthDate { get; set; } = string.Empty; public string Country { get; set; } = string.Empty; diff --git a/src/Infrastructure/Identity/ApplicationUserManager.cs b/src/Infrastructure/Identity/ApplicationUserManager.cs new file mode 100644 index 0000000..987c8b6 --- /dev/null +++ b/src/Infrastructure/Identity/ApplicationUserManager.cs @@ -0,0 +1,42 @@ +using Microsoft.AspNetCore.Identity; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; + +namespace Hutopy.Infrastructure.Identity; + +public sealed class ApplicationUserManager( + IUserStore store, + IOptions optionsAccessor, + IPasswordHasher passwordHasher, + IEnumerable> userValidators, + IEnumerable> passwordValidators, + ILookupNormalizer keyNormalizer, + IdentityErrorDescriber errors, + IServiceProvider services, + ILogger> logger) + : UserManager( + store, + optionsAccessor, + passwordHasher, + userValidators, + passwordValidators, + keyNormalizer, + errors, + services, + logger) +{ + public async Task FindByCreatorAliasAsync(string creatorAlias, + CancellationToken cancellationToken = default) + { + ArgumentException.ThrowIfNullOrEmpty(creatorAlias); + ThrowIfDisposed(); + + var user = await Users.SingleOrDefaultAsync(u => EF.Functions.Like( + creatorAlias, + u.CreatorAlias), + cancellationToken: cancellationToken); + + return user; + } +} diff --git a/src/Infrastructure/Identity/IdentityService.cs b/src/Infrastructure/Identity/IdentityService.cs index b0be8f2..1208bc7 100644 --- a/src/Infrastructure/Identity/IdentityService.cs +++ b/src/Infrastructure/Identity/IdentityService.cs @@ -16,7 +16,7 @@ using Microsoft.Extensions.Configuration; namespace Hutopy.Infrastructure.Identity; public class IdentityService( - UserManager userManager, + ApplicationUserManager userManager, SignInManager signInManager, IUserClaimsPrincipalFactory userClaimsPrincipalFactory, IAuthorizationService authorizationService, @@ -135,10 +135,28 @@ public class IdentityService( public async Task FindUserByIdAsync(string id) { - var response = await userManager.FindByIdAsync(id); + var user = await userManager.FindByIdAsync(id); - if (response == null) return null; + if (user == null) return null; + var userModel = BuildModelFrom(user); + + return userModel; + } + + public async Task FindUserByCreatorAliasAsync(string creatorAlias, CancellationToken cancellationToken = default) + { + var user = await userManager.FindByCreatorAliasAsync(creatorAlias, cancellationToken); + + if (user == null) return null; + + var userModel = BuildModelFrom(user); + + return userModel; + } + + private static UserModel BuildModelFrom(ApplicationUser response) + { var userModel = new UserModel { Id = response.Id, @@ -179,10 +197,9 @@ public class IdentityService( WebsiteIconUrl = response.StoredDataUrls.WebsiteIconUrl, } }; - return userModel; } - + public async Task FindUserByEmailAsync(string email) { var response = await userManager.FindByEmailAsync(email); diff --git a/src/Infrastructure/Migrations/20240702055858_AddCreatorAliasTouser.Designer.cs b/src/Infrastructure/Migrations/20240702055858_AddCreatorAliasTouser.Designer.cs new file mode 100644 index 0000000..47946f4 --- /dev/null +++ b/src/Infrastructure/Migrations/20240702055858_AddCreatorAliasTouser.Designer.cs @@ -0,0 +1,560 @@ +// +using System; +using Hutopy.Infrastructure.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Hutopy.Infrastructure.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + [Migration("20240702055858_AddCreatorAliasTouser")] + partial class AddCreatorAliasTouser + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.3") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("Hutopy.Domain.Entities.FutureCreator", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Created") + .HasColumnType("datetimeoffset"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("EmailAddress") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("FirstName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("LastModified") + .HasColumnType("datetimeoffset"); + + b.Property("LastModifiedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("LastName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumber") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("ReasonToJoin") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("SocialNetworkAccount") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("FutureCreators"); + }); + + modelBuilder.Entity("Hutopy.Domain.Entities.UserTransaction", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Amount") + .HasPrecision(18, 2) + .HasColumnType("decimal(18,2)"); + + b.Property("ApplicationUserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.Property("Created") + .HasColumnType("datetimeoffset"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("Currency") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("IsConfirmed") + .HasColumnType("bit"); + + b.Property("LastModified") + .HasColumnType("datetimeoffset"); + + b.Property("LastModifiedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("Paid") + .HasColumnType("bit"); + + b.Property("StripeBillingDetailEmail") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("StripeBillingDetailName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("StripeChargeId") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("StripeEventId") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("StripePaymentIntent") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("StripePaymentMethod") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("StripeReceiptUrl") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("TipMessage") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationUserId"); + + b.ToTable("UserTransactions"); + }); + + modelBuilder.Entity("Hutopy.Infrastructure.Identity.ApplicationUser", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("About") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("AccessFailedCount") + .HasColumnType("int"); + + b.Property("Address") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("BirthDate") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("City") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("nvarchar(max)"); + + b.Property("Country") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("CreatorAlias") + .HasColumnType("nvarchar(max)"); + + b.Property("Description") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("EmailConfirmed") + .HasColumnType("bit"); + + b.Property("FirstName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("LastName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("LockoutEnabled") + .HasColumnType("bit"); + + b.Property("LockoutEnd") + .HasColumnType("datetimeoffset"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("Occupation") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("PasswordHash") + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumber") + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("bit"); + + b.Property("SecurityStamp") + .HasColumnType("nvarchar(max)"); + + b.Property("TwoFactorEnabled") + .HasColumnType("bit"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex") + .HasFilter("[NormalizedUserName] IS NOT NULL"); + + b.ToTable("AspNetUsers", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("nvarchar(max)"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex") + .HasFilter("[NormalizedName] IS NOT NULL"); + + b.ToTable("AspNetRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("nvarchar(max)"); + + b.Property("ClaimValue") + .HasColumnType("nvarchar(max)"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("nvarchar(max)"); + + b.Property("ClaimValue") + .HasColumnType("nvarchar(max)"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("nvarchar(450)"); + + b.Property("ProviderKey") + .HasColumnType("nvarchar(450)"); + + b.Property("ProviderDisplayName") + .HasColumnType("nvarchar(max)"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("nvarchar(450)"); + + b.Property("RoleId") + .HasColumnType("nvarchar(450)"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("nvarchar(450)"); + + b.Property("LoginProvider") + .HasColumnType("nvarchar(450)"); + + b.Property("Name") + .HasColumnType("nvarchar(450)"); + + b.Property("Value") + .HasColumnType("nvarchar(max)"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens", (string)null); + }); + + modelBuilder.Entity("Hutopy.Domain.Entities.UserTransaction", b => + { + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("ApplicationUserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Hutopy.Infrastructure.Identity.ApplicationUser", b => + { + b.OwnsOne("Hutopy.Infrastructure.Identity.OwnedEntities.ProfileColors", "ProfileColors", b1 => + { + b1.Property("ApplicationUserId") + .HasColumnType("nvarchar(450)"); + + b1.Property("Accent") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.Property("BannerBottom") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.Property("BannerTop") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.Property("Menu") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.HasKey("ApplicationUserId"); + + b1.ToTable("ApplicationUser_ProfileColors", (string)null); + + b1.WithOwner() + .HasForeignKey("ApplicationUserId"); + }); + + b.OwnsOne("Hutopy.Infrastructure.Identity.OwnedEntities.SocialNetworks", "SocialNetworks", b1 => + { + b1.Property("ApplicationUserId") + .HasColumnType("nvarchar(450)"); + + b1.Property("FacebookUrl") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.Property("InstagramUrl") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.Property("LinkedInUrl") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.Property("RedditUrl") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.Property("TikTokUrl") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.Property("XUrl") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.Property("YourWebsiteUrl") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.Property("YoutubeUrl") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.HasKey("ApplicationUserId"); + + b1.ToTable("ApplicationUser_SocialNetworks", (string)null); + + b1.WithOwner() + .HasForeignKey("ApplicationUserId"); + }); + + b.OwnsOne("Hutopy.Infrastructure.Identity.OwnedEntities.StoredDataUrls", "StoredDataUrls", b1 => + { + b1.Property("ApplicationUserId") + .HasColumnType("nvarchar(450)"); + + b1.Property("BannerPictureUrl") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.Property("ProfilePictureUrl") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.Property("WebsiteIconUrl") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.HasKey("ApplicationUserId"); + + b1.ToTable("ApplicationUser_StoredDataUrls", (string)null); + + b1.WithOwner() + .HasForeignKey("ApplicationUserId"); + }); + + b.Navigation("ProfileColors") + .IsRequired(); + + b.Navigation("SocialNetworks") + .IsRequired(); + + b.Navigation("StoredDataUrls") + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Infrastructure/Migrations/20240702055858_AddCreatorAliasTouser.cs b/src/Infrastructure/Migrations/20240702055858_AddCreatorAliasTouser.cs new file mode 100644 index 0000000..456b236 --- /dev/null +++ b/src/Infrastructure/Migrations/20240702055858_AddCreatorAliasTouser.cs @@ -0,0 +1,28 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Hutopy.Infrastructure.Migrations +{ + /// + public partial class AddCreatorAliasTouser : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "CreatorAlias", + table: "AspNetUsers", + type: "nvarchar(max)", + nullable: true); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "CreatorAlias", + table: "AspNetUsers"); + } + } +} diff --git a/src/Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs b/src/Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs index 12a98ec..3d3f44a 100644 --- a/src/Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs +++ b/src/Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs @@ -176,6 +176,9 @@ namespace Hutopy.Infrastructure.Migrations .IsRequired() .HasColumnType("nvarchar(max)"); + b.Property("CreatorAlias") + .HasColumnType("nvarchar(max)"); + b.Property("Description") .IsRequired() .HasColumnType("nvarchar(max)"); diff --git a/src/Web/Creators/Handlers/GetCreatorByAlias.cs b/src/Web/Creators/Handlers/GetCreatorByAlias.cs new file mode 100644 index 0000000..a46201f --- /dev/null +++ b/src/Web/Creators/Handlers/GetCreatorByAlias.cs @@ -0,0 +1,29 @@ +using FastEndpoints; +using Hutopy.Application.Common.Interfaces; +using Hutopy.Application.Common.Models; + +namespace Hutopy.Web.Creators.Handlers; + +public class GetCreatorByAlias( + IIdentityService identityService) + : EndpointWithoutRequest +{ + public override void Configure() + { + Tags("Creators"); + Get("/api/creators/@{CreatorAlias}"); + AllowAnonymous(); + } + + public override async Task HandleAsync( + CancellationToken ct) + { + var creatorAlias = Route("CreatorAlias"); + + ArgumentException.ThrowIfNullOrEmpty(creatorAlias); + + var user = await identityService.FindUserByCreatorAliasAsync(creatorAlias, ct); + + await SendAsync(user, cancellation: ct); + } +} diff --git a/src/Web/Pages/Shared/_LoginPartial.cshtml b/src/Web/Pages/Shared/_LoginPartial.cshtml index c16ebd7..b8197de 100644 --- a/src/Web/Pages/Shared/_LoginPartial.cshtml +++ b/src/Web/Pages/Shared/_LoginPartial.cshtml @@ -1,7 +1,6 @@ @using Hutopy.Infrastructure.Identity @using Microsoft.AspNetCore.Identity @inject SignInManager SignInManager -@inject UserManager UserManager @{ string? returnUrl = null; diff --git a/tests/Application.FunctionalTests/Testing.cs b/tests/Application.FunctionalTests/Testing.cs index 49d8384..8270718 100644 --- a/tests/Application.FunctionalTests/Testing.cs +++ b/tests/Application.FunctionalTests/Testing.cs @@ -63,7 +63,7 @@ public partial class Testing { using var scope = _scopeFactory.CreateScope(); - var userManager = scope.ServiceProvider.GetRequiredService>(); + var userManager = scope.ServiceProvider.GetRequiredService(); var user = new ApplicationUser { UserName = userName, Email = userName }; From 29fe6b51c129cb0df424e2d83f7297a712e2a5e1 Mon Sep 17 00:00:00 2001 From: Jonathan Bourdon Date: Tue, 2 Jul 2024 04:05:37 -0400 Subject: [PATCH 094/229] Normalization of route names --- src/Web/Contents/Handlers/GetContentsByUser.cs | 2 +- src/Web/Messages/Handlers/GetMessagesByUser.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Web/Contents/Handlers/GetContentsByUser.cs b/src/Web/Contents/Handlers/GetContentsByUser.cs index e3796d6..d96b487 100644 --- a/src/Web/Contents/Handlers/GetContentsByUser.cs +++ b/src/Web/Contents/Handlers/GetContentsByUser.cs @@ -11,7 +11,7 @@ public class GetContentsByUser( public override void Configure() { Tags("Contents"); - Get("/api/contents/by-user/{UserId:guid}"); + Get("/api/contents/user/{UserId:guid}"); AllowAnonymous(); } diff --git a/src/Web/Messages/Handlers/GetMessagesByUser.cs b/src/Web/Messages/Handlers/GetMessagesByUser.cs index d49c0d3..b5b25e0 100644 --- a/src/Web/Messages/Handlers/GetMessagesByUser.cs +++ b/src/Web/Messages/Handlers/GetMessagesByUser.cs @@ -12,7 +12,7 @@ public class GetMessagesByUser( public override void Configure() { Tags("Messages"); - Get("/api/messages/by-user/{UserId:guid}"); + Get("/api/messages/user/{UserId:guid}"); } public override async Task HandleAsync( From 92d6c30350abfcb6751c7eb49cbc881c8f23136e Mon Sep 17 00:00:00 2001 From: Jonathan Bourdon Date: Tue, 2 Jul 2024 04:29:52 -0400 Subject: [PATCH 095/229] Fix issue with GetContentsByUser --- src/Web/Contents/Handlers/GetContentsByUser.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Web/Contents/Handlers/GetContentsByUser.cs b/src/Web/Contents/Handlers/GetContentsByUser.cs index d96b487..a3e87ff 100644 --- a/src/Web/Contents/Handlers/GetContentsByUser.cs +++ b/src/Web/Contents/Handlers/GetContentsByUser.cs @@ -1,12 +1,12 @@ using FastEndpoints; -using Hutopy.Web.Messages.Data; +using Hutopy.Web.Contents.Data; using Microsoft.EntityFrameworkCore; namespace Hutopy.Web.Contents.Handlers; public class GetContentsByUser( - MessagingDbContext context) - : EndpointWithoutRequest> + ContentDbContext context) + : EndpointWithoutRequest> { public override void Configure() { @@ -21,7 +21,7 @@ public class GetContentsByUser( var userId = Route("UserId"); var posts = await context - .Messages + .Contents .Where(c => c.CreatedBy == userId) .ToListAsync(cancellationToken: ct); From 3558952634305f844b60d45f92add251878fb08e Mon Sep 17 00:00:00 2001 From: Dominic Villemure Date: Thu, 4 Jul 2024 20:47:07 -0400 Subject: [PATCH 096/229] merged --- .../Common/Interfaces/IIdentityService.cs | 2 +- .../Commands/UpdateCurrentUserCommand.cs | 2 +- .../Queries/GetMinimalUser/GetMinimalUser.cs | 10 +++-- .../Queries/GetMinimalUser/MinimalUserDto.cs | 6 +++ .../Identity/IdentityResultExtensions.cs | 3 +- .../Identity/IdentityService.cs | 42 ++++++++++++++++--- src/Infrastructure/Identity/RoleService.cs | 4 +- src/Infrastructure/Utils/GenerateJwtToken.cs | 10 +++-- src/Web/Controllers/GoogleController.cs | 2 +- 9 files changed, 62 insertions(+), 19 deletions(-) diff --git a/src/Application/Common/Interfaces/IIdentityService.cs b/src/Application/Common/Interfaces/IIdentityService.cs index edcbb9c..74e9240 100644 --- a/src/Application/Common/Interfaces/IIdentityService.cs +++ b/src/Application/Common/Interfaces/IIdentityService.cs @@ -12,7 +12,7 @@ public interface IIdentityService Task UpdateCurrentUserBannerPictureUrlAsync(string url); Task UpdateCurrentUserProfilePictureUrlAsync(string url); Task UpdateCurrentUserWebsiteIconUrlAsync(string url); - Task> UpdateCurrentUserAsync(UserModel userModel, string? portraitUrl); + Task> UpdateCurrentUserAsync(UserModel userModel); Task> GetCurrentUserRolesAsync(); Task FindUserByIdAsync(string id); Task FindUserByEmailAsync(string email); diff --git a/src/Application/Users/Commands/UpdateCurrentUserCommand.cs b/src/Application/Users/Commands/UpdateCurrentUserCommand.cs index d47985a..8c9766f 100644 --- a/src/Application/Users/Commands/UpdateCurrentUserCommand.cs +++ b/src/Application/Users/Commands/UpdateCurrentUserCommand.cs @@ -44,7 +44,7 @@ public class UpdateCurrentUserCommandHandler(IApplicationDbContext context, IIde var userModel = mapper.Map(request); userModel.Id = identityUser.Id; - var result = await identityService.UpdateCurrentUserAsync(userModel, request.PortraitUrl); + var result = await identityService.UpdateCurrentUserAsync(userModel); await context.SaveChangesAsync(cancellationToken); diff --git a/src/Application/Users/Queries/GetMinimalUser/GetMinimalUser.cs b/src/Application/Users/Queries/GetMinimalUser/GetMinimalUser.cs index e7e5940..124e9cf 100644 --- a/src/Application/Users/Queries/GetMinimalUser/GetMinimalUser.cs +++ b/src/Application/Users/Queries/GetMinimalUser/GetMinimalUser.cs @@ -28,15 +28,17 @@ public class GetMinimalUserQueryHandler( { identityUser = await identityService.GetUserByUserNameAsync(request.UserName); } - - + var user = new MinimalUserDto { FirstName = identityUser?.FirstName ?? string.Empty, LastName = identityUser?.LastName ?? string.Empty, - UserName = identityUser?.UserName ?? string.Empty + UserName = identityUser?.UserName ?? string.Empty, + SocialNetworks = identityUser?.SocialNetworks ?? new(), + ProfileColors = identityUser?.ProfileColors ?? new(), + StoredDataUrls = identityUser?.StoredDataUrls ?? new(), }; return user; } -} \ No newline at end of file +} diff --git a/src/Application/Users/Queries/GetMinimalUser/MinimalUserDto.cs b/src/Application/Users/Queries/GetMinimalUser/MinimalUserDto.cs index 97fa6a1..7648fa7 100644 --- a/src/Application/Users/Queries/GetMinimalUser/MinimalUserDto.cs +++ b/src/Application/Users/Queries/GetMinimalUser/MinimalUserDto.cs @@ -1,3 +1,5 @@ +using Hutopy.Application.Users.Models; + namespace Hutopy.Application.Users.Queries.GetMinimalUser; public class MinimalUserDto @@ -5,4 +7,8 @@ public class MinimalUserDto public required string FirstName { get; init; } public required string LastName { get; init; } public required string UserName { get; init; } = String.Empty; + + public SocialNetworksModel SocialNetworks { get; init; } = new(); + public ProfileColorsModel ProfileColors { get; init; } = new(); + public StoredDataUrlsModel StoredDataUrls { get; init; } = new(); } diff --git a/src/Infrastructure/Identity/IdentityResultExtensions.cs b/src/Infrastructure/Identity/IdentityResultExtensions.cs index 630c372..0902e4f 100644 --- a/src/Infrastructure/Identity/IdentityResultExtensions.cs +++ b/src/Infrastructure/Identity/IdentityResultExtensions.cs @@ -1,4 +1,5 @@ -using Hutopy.Application.Common.Models; +using System.Linq; +using Hutopy.Application.Common.Models; using Microsoft.AspNetCore.Identity; namespace Hutopy.Infrastructure.Identity; diff --git a/src/Infrastructure/Identity/IdentityService.cs b/src/Infrastructure/Identity/IdentityService.cs index fe0fc3d..2bc6ff4 100644 --- a/src/Infrastructure/Identity/IdentityService.cs +++ b/src/Infrastructure/Identity/IdentityService.cs @@ -41,10 +41,42 @@ public class IdentityService( var userModel = new UserModel() { Id = response.Id, - UserName = response.UserName, + UserName = response.UserName ?? string.Empty, FirstName = response.FirstName, LastName = response.LastName, - Email = response.Email, + Email = response.Email ?? string.Empty, + Occupation = response.Occupation, + PhoneNumber = response.PhoneNumber ?? string.Empty, + BirthDate = response.BirthDate, + Country = response.Country, + City = response.City, + Address = response.Address, + About = response.About, + Description = response.Description, + SocialNetworks = new SocialNetworksModel + { + FacebookUrl = response.SocialNetworks.FacebookUrl, + InstagramUrl = response.SocialNetworks.InstagramUrl, + XUrl = response.SocialNetworks.XUrl, + LinkedInUrl = response.SocialNetworks.LinkedInUrl, + TikTokUrl = response.SocialNetworks.TikTokUrl, + YoutubeUrl = response.SocialNetworks.YoutubeUrl, + RedditUrl = response.SocialNetworks.RedditUrl, + YourWebsiteUrl = response.SocialNetworks.YourWebsiteUrl, + }, + ProfileColors = new ProfileColorsModel + { + BannerTop = response.ProfileColors.BannerTop, + BannerBottom = response.ProfileColors.BannerBottom, + Accent = response.ProfileColors.Accent, + Menu = response.ProfileColors.Menu + }, + StoredDataUrls = new StoredDataUrlsModel + { + ProfilePictureUrl = response.StoredDataUrls.ProfilePictureUrl, + BannerPictureUrl = response.StoredDataUrls.BannerPictureUrl, + WebsiteIconUrl = response.StoredDataUrls.WebsiteIconUrl, + } }; return userModel; @@ -88,7 +120,7 @@ public class IdentityService( return result; } - public async Task> UpdateCurrentUserAsync(UserModel userModel, string? portraitUrl) + public async Task> UpdateCurrentUserAsync(UserModel userModel) { var applicationUser = await userManager.FindByIdAsync(userModel.Id); @@ -104,7 +136,6 @@ public class IdentityService( applicationUser.Address = userModel.Address; applicationUser.About = userModel.About; applicationUser.Description = userModel.Description; - applicationUser.PortraitUrl = portraitUrl; applicationUser.SocialNetworks = new SocialNetworks { FacebookUrl = userModel.SocialNetworks.FacebookUrl, @@ -155,7 +186,6 @@ public class IdentityService( Address = response.Address, About = response.About, Description = response.Description, - PortraitUrl = response.PortraitUrl, SocialNetworks = new SocialNetworksModel { FacebookUrl = response.SocialNetworks.FacebookUrl, @@ -387,7 +417,7 @@ public class IdentityService( email: user.Email, firstname: user.FirstName, lastname: user.LastName, - portraitUrl: user.PortraitUrl); + profilePictureUrl: user.StoredDataUrls.ProfilePictureUrl); return token; } diff --git a/src/Infrastructure/Identity/RoleService.cs b/src/Infrastructure/Identity/RoleService.cs index 71f0ed0..59fc22b 100644 --- a/src/Infrastructure/Identity/RoleService.cs +++ b/src/Infrastructure/Identity/RoleService.cs @@ -1,4 +1,6 @@ -using Hutopy.Application.Common.Interfaces; +using System; +using System.Threading.Tasks; +using Hutopy.Application.Common.Interfaces; using Hutopy.Application.Common.Models; using Microsoft.AspNetCore.Identity; diff --git a/src/Infrastructure/Utils/GenerateJwtToken.cs b/src/Infrastructure/Utils/GenerateJwtToken.cs index a4d74de..013da69 100644 --- a/src/Infrastructure/Utils/GenerateJwtToken.cs +++ b/src/Infrastructure/Utils/GenerateJwtToken.cs @@ -1,4 +1,6 @@ -using System.IdentityModel.Tokens.Jwt; +using System; +using System.Collections.Generic; +using System.IdentityModel.Tokens.Jwt; using System.Security.Claims; using System.Text; using Microsoft.IdentityModel.Tokens; @@ -15,7 +17,7 @@ public static class JwtTokenHelper string? email, string? firstname, string? lastname, - string? portraitUrl) + string? profilePictureUrl) { var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(key)); var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256); @@ -31,9 +33,9 @@ public static class JwtTokenHelper new Claim(ClaimTypes.Surname, lastname), }); - if (portraitUrl is not null) + if (profilePictureUrl is not null) { - claims.Add(new Claim("portrait-url", portraitUrl)); + claims.Add(new Claim("portrait-url", profilePictureUrl)); } var token = new JwtSecurityToken( diff --git a/src/Web/Controllers/GoogleController.cs b/src/Web/Controllers/GoogleController.cs index dfaa91e..38e04e7 100644 --- a/src/Web/Controllers/GoogleController.cs +++ b/src/Web/Controllers/GoogleController.cs @@ -71,7 +71,7 @@ public class GoogleController(IIdentityService identityService, IHttpClientFacto user.Email, user.FirstName, user.LastName, - user.PortraitUrl); + user.StoredDataUrls.ProfilePictureUrl); return Ok(new { accessToken = token, email }); } From 4a0502488e6a9af69b59d5cec7dbc4178cc557e4 Mon Sep 17 00:00:00 2001 From: Dominic Villemure Date: Thu, 4 Jul 2024 20:50:20 -0400 Subject: [PATCH 097/229] Merged with master --- src/Infrastructure/Data/ApplicationDbContextInitializer.cs | 5 ++++- src/Infrastructure/Identity/ApplicationUserManager.cs | 6 +++++- src/Infrastructure/Identity/IdentityService.cs | 1 + 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/Infrastructure/Data/ApplicationDbContextInitializer.cs b/src/Infrastructure/Data/ApplicationDbContextInitializer.cs index bc57199..71abda5 100644 --- a/src/Infrastructure/Data/ApplicationDbContextInitializer.cs +++ b/src/Infrastructure/Data/ApplicationDbContextInitializer.cs @@ -1,4 +1,7 @@ -using Hutopy.Domain.Constants; +using System; +using System.Linq; +using System.Threading.Tasks; +using Hutopy.Domain.Constants; using Hutopy.Infrastructure.Identity; using Hutopy.Infrastructure.Identity.OwnedEntities; using Microsoft.AspNetCore.Builder; diff --git a/src/Infrastructure/Identity/ApplicationUserManager.cs b/src/Infrastructure/Identity/ApplicationUserManager.cs index 987c8b6..8125aae 100644 --- a/src/Infrastructure/Identity/ApplicationUserManager.cs +++ b/src/Infrastructure/Identity/ApplicationUserManager.cs @@ -1,4 +1,8 @@ -using Microsoft.AspNetCore.Identity; +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Identity; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; diff --git a/src/Infrastructure/Identity/IdentityService.cs b/src/Infrastructure/Identity/IdentityService.cs index b03c9e2..3d9bbc0 100644 --- a/src/Infrastructure/Identity/IdentityService.cs +++ b/src/Infrastructure/Identity/IdentityService.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using Google.Apis.Oauth2.v2.Data; using System.Security.Claims; +using System.Threading; using System.Threading.Tasks; using Hutopy.Application.Common.Interfaces; using Hutopy.Application.Common.Models; From 4da28344f4634817df7a0ad10bd7e6e800f79b0d Mon Sep 17 00:00:00 2001 From: Dominic Villemure Date: Thu, 4 Jul 2024 21:12:46 -0400 Subject: [PATCH 098/229] Remove portraitUrl -> replaced by ProfilePictureUrl Removed duplicate ContentStore connectionString --- .../Commands/UpdateCurrentUserCommand.cs | 1 - .../Identity/ApplicationUser.cs | 1 - ...240705010235_RemovePortraitUrl.Designer.cs | 560 ++++++++++++++++++ .../20240705010235_RemovePortraitUrl.cs | 28 + .../ApplicationDbContextModelSnapshot.cs | 3 - src/Web/appsettings.Development.json | 1 - 6 files changed, 588 insertions(+), 6 deletions(-) create mode 100644 src/Infrastructure/Migrations/20240705010235_RemovePortraitUrl.Designer.cs create mode 100644 src/Infrastructure/Migrations/20240705010235_RemovePortraitUrl.cs diff --git a/src/Application/Users/Commands/UpdateCurrentUserCommand.cs b/src/Application/Users/Commands/UpdateCurrentUserCommand.cs index 8c9766f..7d55961 100644 --- a/src/Application/Users/Commands/UpdateCurrentUserCommand.cs +++ b/src/Application/Users/Commands/UpdateCurrentUserCommand.cs @@ -19,7 +19,6 @@ public class UpdateCurrentUserCommand : IRequest public required string Description { get; init; } public required SocialNetworksModel SocialNetworks { get; init; } public required ProfileColorsModel ProfileColors { get; init; } - public string PortraitUrl { get; init; } = string.Empty; [NotMapped] diff --git a/src/Infrastructure/Identity/ApplicationUser.cs b/src/Infrastructure/Identity/ApplicationUser.cs index 29e74ec..74ad0cf 100644 --- a/src/Infrastructure/Identity/ApplicationUser.cs +++ b/src/Infrastructure/Identity/ApplicationUser.cs @@ -18,5 +18,4 @@ public class ApplicationUser : IdentityUser public SocialNetworks SocialNetworks { get; set; } = new(); public ProfileColors ProfileColors { get; set; } = new(); public StoredDataUrls StoredDataUrls { get; set; } = new(); - public string? PortraitUrl { get; set; } } diff --git a/src/Infrastructure/Migrations/20240705010235_RemovePortraitUrl.Designer.cs b/src/Infrastructure/Migrations/20240705010235_RemovePortraitUrl.Designer.cs new file mode 100644 index 0000000..1df55e6 --- /dev/null +++ b/src/Infrastructure/Migrations/20240705010235_RemovePortraitUrl.Designer.cs @@ -0,0 +1,560 @@ +// +using System; +using Hutopy.Infrastructure.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Hutopy.Infrastructure.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + [Migration("20240705010235_RemovePortraitUrl")] + partial class RemovePortraitUrl + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.3") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("Hutopy.Domain.Entities.FutureCreator", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Created") + .HasColumnType("datetimeoffset"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("EmailAddress") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("FirstName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("LastModified") + .HasColumnType("datetimeoffset"); + + b.Property("LastModifiedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("LastName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumber") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("ReasonToJoin") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("SocialNetworkAccount") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("FutureCreators"); + }); + + modelBuilder.Entity("Hutopy.Domain.Entities.UserTransaction", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Amount") + .HasPrecision(18, 2) + .HasColumnType("decimal(18,2)"); + + b.Property("ApplicationUserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.Property("Created") + .HasColumnType("datetimeoffset"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("Currency") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("IsConfirmed") + .HasColumnType("bit"); + + b.Property("LastModified") + .HasColumnType("datetimeoffset"); + + b.Property("LastModifiedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("Paid") + .HasColumnType("bit"); + + b.Property("StripeBillingDetailEmail") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("StripeBillingDetailName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("StripeChargeId") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("StripeEventId") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("StripePaymentIntent") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("StripePaymentMethod") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("StripeReceiptUrl") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("TipMessage") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationUserId"); + + b.ToTable("UserTransactions"); + }); + + modelBuilder.Entity("Hutopy.Infrastructure.Identity.ApplicationUser", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("About") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("AccessFailedCount") + .HasColumnType("int"); + + b.Property("Address") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("BirthDate") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("City") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("nvarchar(max)"); + + b.Property("Country") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("CreatorAlias") + .HasColumnType("nvarchar(max)"); + + b.Property("Description") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("EmailConfirmed") + .HasColumnType("bit"); + + b.Property("FirstName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("LastName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("LockoutEnabled") + .HasColumnType("bit"); + + b.Property("LockoutEnd") + .HasColumnType("datetimeoffset"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("Occupation") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("PasswordHash") + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumber") + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("bit"); + + b.Property("SecurityStamp") + .HasColumnType("nvarchar(max)"); + + b.Property("TwoFactorEnabled") + .HasColumnType("bit"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex") + .HasFilter("[NormalizedUserName] IS NOT NULL"); + + b.ToTable("AspNetUsers", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("nvarchar(max)"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex") + .HasFilter("[NormalizedName] IS NOT NULL"); + + b.ToTable("AspNetRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("nvarchar(max)"); + + b.Property("ClaimValue") + .HasColumnType("nvarchar(max)"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("nvarchar(max)"); + + b.Property("ClaimValue") + .HasColumnType("nvarchar(max)"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("nvarchar(450)"); + + b.Property("ProviderKey") + .HasColumnType("nvarchar(450)"); + + b.Property("ProviderDisplayName") + .HasColumnType("nvarchar(max)"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("nvarchar(450)"); + + b.Property("RoleId") + .HasColumnType("nvarchar(450)"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("nvarchar(450)"); + + b.Property("LoginProvider") + .HasColumnType("nvarchar(450)"); + + b.Property("Name") + .HasColumnType("nvarchar(450)"); + + b.Property("Value") + .HasColumnType("nvarchar(max)"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens", (string)null); + }); + + modelBuilder.Entity("Hutopy.Domain.Entities.UserTransaction", b => + { + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("ApplicationUserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Hutopy.Infrastructure.Identity.ApplicationUser", b => + { + b.OwnsOne("Hutopy.Infrastructure.Identity.OwnedEntities.ProfileColors", "ProfileColors", b1 => + { + b1.Property("ApplicationUserId") + .HasColumnType("nvarchar(450)"); + + b1.Property("Accent") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.Property("BannerBottom") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.Property("BannerTop") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.Property("Menu") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.HasKey("ApplicationUserId"); + + b1.ToTable("ApplicationUser_ProfileColors", (string)null); + + b1.WithOwner() + .HasForeignKey("ApplicationUserId"); + }); + + b.OwnsOne("Hutopy.Infrastructure.Identity.OwnedEntities.SocialNetworks", "SocialNetworks", b1 => + { + b1.Property("ApplicationUserId") + .HasColumnType("nvarchar(450)"); + + b1.Property("FacebookUrl") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.Property("InstagramUrl") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.Property("LinkedInUrl") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.Property("RedditUrl") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.Property("TikTokUrl") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.Property("XUrl") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.Property("YourWebsiteUrl") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.Property("YoutubeUrl") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.HasKey("ApplicationUserId"); + + b1.ToTable("ApplicationUser_SocialNetworks", (string)null); + + b1.WithOwner() + .HasForeignKey("ApplicationUserId"); + }); + + b.OwnsOne("Hutopy.Infrastructure.Identity.OwnedEntities.StoredDataUrls", "StoredDataUrls", b1 => + { + b1.Property("ApplicationUserId") + .HasColumnType("nvarchar(450)"); + + b1.Property("BannerPictureUrl") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.Property("ProfilePictureUrl") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.Property("WebsiteIconUrl") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.HasKey("ApplicationUserId"); + + b1.ToTable("ApplicationUser_StoredDataUrls", (string)null); + + b1.WithOwner() + .HasForeignKey("ApplicationUserId"); + }); + + b.Navigation("ProfileColors") + .IsRequired(); + + b.Navigation("SocialNetworks") + .IsRequired(); + + b.Navigation("StoredDataUrls") + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Infrastructure/Migrations/20240705010235_RemovePortraitUrl.cs b/src/Infrastructure/Migrations/20240705010235_RemovePortraitUrl.cs new file mode 100644 index 0000000..e504870 --- /dev/null +++ b/src/Infrastructure/Migrations/20240705010235_RemovePortraitUrl.cs @@ -0,0 +1,28 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Hutopy.Infrastructure.Migrations +{ + /// + public partial class RemovePortraitUrl : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "PortraitUrl", + table: "AspNetUsers"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "PortraitUrl", + table: "AspNetUsers", + type: "nvarchar(max)", + nullable: true); + } + } +} diff --git a/src/Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs b/src/Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs index 0c4a193..3d3f44a 100644 --- a/src/Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs +++ b/src/Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs @@ -225,9 +225,6 @@ namespace Hutopy.Infrastructure.Migrations b.Property("PhoneNumberConfirmed") .HasColumnType("bit"); - b.Property("PortraitUrl") - .HasColumnType("nvarchar(max)"); - b.Property("SecurityStamp") .HasColumnType("nvarchar(max)"); diff --git a/src/Web/appsettings.Development.json b/src/Web/appsettings.Development.json index decba8e..d118e3b 100644 --- a/src/Web/appsettings.Development.json +++ b/src/Web/appsettings.Development.json @@ -9,7 +9,6 @@ }, "ConnectionStrings": { "DefaultConnection": "Server=localhost,1433;Initial Catalog=Hutopy;User Id=sa;Password=P@ssword123!;MultipleActiveResultSets=true;TrustServerCertificate=True;MultiSubnetFailover=True", - "CommentStore": "Server=localhost,1433;Initial Catalog=Hutopy;User Id=sa;Password=P@ssword123!;MultipleActiveResultSets=true;TrustServerCertificate=True;MultiSubnetFailover=True", "ContentStore": "Server=localhost,1433;Initial Catalog=Hutopy;User Id=sa;Password=P@ssword123!;MultipleActiveResultSets=true;TrustServerCertificate=True;MultiSubnetFailover=True" }, "Authentication": { From 44d86a1f5697331eef9b69b00756a1215ed1aadb Mon Sep 17 00:00:00 2001 From: Dominic Villemure Date: Thu, 4 Jul 2024 21:13:19 -0400 Subject: [PATCH 099/229] Commentstore --- src/Web/appsettings.Development.json | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Web/appsettings.Development.json b/src/Web/appsettings.Development.json index d118e3b..decba8e 100644 --- a/src/Web/appsettings.Development.json +++ b/src/Web/appsettings.Development.json @@ -9,6 +9,7 @@ }, "ConnectionStrings": { "DefaultConnection": "Server=localhost,1433;Initial Catalog=Hutopy;User Id=sa;Password=P@ssword123!;MultipleActiveResultSets=true;TrustServerCertificate=True;MultiSubnetFailover=True", + "CommentStore": "Server=localhost,1433;Initial Catalog=Hutopy;User Id=sa;Password=P@ssword123!;MultipleActiveResultSets=true;TrustServerCertificate=True;MultiSubnetFailover=True", "ContentStore": "Server=localhost,1433;Initial Catalog=Hutopy;User Id=sa;Password=P@ssword123!;MultipleActiveResultSets=true;TrustServerCertificate=True;MultiSubnetFailover=True" }, "Authentication": { From cb55989c715be7a73222fcd3dcb25ad9b2687bb6 Mon Sep 17 00:00:00 2001 From: Dominic Villemure Date: Fri, 5 Jul 2024 00:13:26 -0400 Subject: [PATCH 100/229] Fix some update / upload stuff with images. Added more info to minimalUser --- .../Users/Commands/UploadBannerPicture.cs | 10 ++++++++++ .../Users/Commands/UploadProfilePicture.cs | 10 ++++++++++ src/Application/Users/Commands/UploadWebsiteIcon.cs | 11 +++++++++++ .../Users/Queries/GetMinimalUser/GetMinimalUser.cs | 2 ++ .../Users/Queries/GetMinimalUser/MinimalUserDto.cs | 2 ++ src/Web/Endpoints/UpdateMyUser.cs | 12 ++++++------ 6 files changed, 41 insertions(+), 6 deletions(-) diff --git a/src/Application/Users/Commands/UploadBannerPicture.cs b/src/Application/Users/Commands/UploadBannerPicture.cs index ae8e783..e99f28a 100644 --- a/src/Application/Users/Commands/UploadBannerPicture.cs +++ b/src/Application/Users/Commands/UploadBannerPicture.cs @@ -3,15 +3,25 @@ using Hutopy.Application.Common.Interfaces; namespace Hutopy.Application.Users.Commands; +/// +/// Upload a banner picture. If the user has the url already, set the BannerPictureUrl in the user only without upload. +/// public class UploadBannerPictureCommand : IRequest { public required Stream BannerPicture { get; init; } + public string BannerPictureUrl { get; init; } = string.Empty; } public class UploadBannerPictureCommandHandler(IIdentityService identityService, IAzureBlobStorageService azureBlobStorageService) : IRequestHandler { public async Task Handle(UploadBannerPictureCommand request, CancellationToken cancellationToken) { + if (!string.IsNullOrEmpty(request.BannerPictureUrl)) + { + await identityService.UpdateCurrentUserBannerPictureUrlAsync(request.BannerPictureUrl); + return request.BannerPictureUrl; + } + var identityUser = await identityService.GetCurrentUserAsync(); var currentUserId = new Guid(identityUser?.Id ?? "").ToString(); diff --git a/src/Application/Users/Commands/UploadProfilePicture.cs b/src/Application/Users/Commands/UploadProfilePicture.cs index 154ace7..ae15d31 100644 --- a/src/Application/Users/Commands/UploadProfilePicture.cs +++ b/src/Application/Users/Commands/UploadProfilePicture.cs @@ -3,15 +3,25 @@ using Hutopy.Application.Common.Interfaces; namespace Hutopy.Application.Users.Commands; +/// +/// Upload a profile picture. If the user has the url already, set the ProfilePictureUrl in the user only without upload. +/// public class UploadProfilePictureCommand : IRequest { public required Stream ProfilePicture { get; init; } + public string ProfilePictureUrl { get; init; } = string.Empty; } public class UploadProfilePictureCommandHandler(IIdentityService identityService, IAzureBlobStorageService azureBlobStorageService) : IRequestHandler { public async Task Handle(UploadProfilePictureCommand request, CancellationToken cancellationToken) { + if (!string.IsNullOrEmpty(request.ProfilePictureUrl)) + { + await identityService.UpdateCurrentUserProfilePictureUrlAsync(request.ProfilePictureUrl); + return request.ProfilePictureUrl; + } + var identityUser = await identityService.GetCurrentUserAsync(); var currentUserId = new Guid(identityUser?.Id ?? "").ToString(); diff --git a/src/Application/Users/Commands/UploadWebsiteIcon.cs b/src/Application/Users/Commands/UploadWebsiteIcon.cs index 26caa25..31f3f5f 100644 --- a/src/Application/Users/Commands/UploadWebsiteIcon.cs +++ b/src/Application/Users/Commands/UploadWebsiteIcon.cs @@ -3,15 +3,26 @@ using Hutopy.Application.Common.Interfaces; namespace Hutopy.Application.Users.Commands; +/// +/// Upload a website icon. If the user has the url already, set the WebsitePictureUrl in the user only without upload. +/// public class UploadWebsiteIconCommand : IRequest { public required Stream WebsiteIcon { get; init; } + + public string WebsitePictureUrl { get; init; } = string.Empty; } public class UploadWebsiteIconCommandHandler(IIdentityService identityService, IAzureBlobStorageService azureBlobStorageService) : IRequestHandler { public async Task Handle(UploadWebsiteIconCommand request, CancellationToken cancellationToken) { + if (!string.IsNullOrEmpty(request.WebsitePictureUrl)) + { + await identityService.UpdateCurrentUserWebsiteIconUrlAsync(request.WebsitePictureUrl); + return request.WebsitePictureUrl; + } + var identityUser = await identityService.GetCurrentUserAsync(); var currentUserId = new Guid(identityUser?.Id ?? "").ToString(); diff --git a/src/Application/Users/Queries/GetMinimalUser/GetMinimalUser.cs b/src/Application/Users/Queries/GetMinimalUser/GetMinimalUser.cs index 124e9cf..454e8ae 100644 --- a/src/Application/Users/Queries/GetMinimalUser/GetMinimalUser.cs +++ b/src/Application/Users/Queries/GetMinimalUser/GetMinimalUser.cs @@ -31,9 +31,11 @@ public class GetMinimalUserQueryHandler( var user = new MinimalUserDto { + Id = identityUser?.Id ?? string.Empty, FirstName = identityUser?.FirstName ?? string.Empty, LastName = identityUser?.LastName ?? string.Empty, UserName = identityUser?.UserName ?? string.Empty, + Occupation = identityUser?.Occupation ?? string.Empty, SocialNetworks = identityUser?.SocialNetworks ?? new(), ProfileColors = identityUser?.ProfileColors ?? new(), StoredDataUrls = identityUser?.StoredDataUrls ?? new(), diff --git a/src/Application/Users/Queries/GetMinimalUser/MinimalUserDto.cs b/src/Application/Users/Queries/GetMinimalUser/MinimalUserDto.cs index 7648fa7..a38fd64 100644 --- a/src/Application/Users/Queries/GetMinimalUser/MinimalUserDto.cs +++ b/src/Application/Users/Queries/GetMinimalUser/MinimalUserDto.cs @@ -4,9 +4,11 @@ namespace Hutopy.Application.Users.Queries.GetMinimalUser; public class MinimalUserDto { + public required string Id { get; init; } public required string FirstName { get; init; } public required string LastName { get; init; } public required string UserName { get; init; } = String.Empty; + public required string Occupation { get; init; } = String.Empty; public SocialNetworksModel SocialNetworks { get; init; } = new(); public ProfileColorsModel ProfileColors { get; init; } = new(); diff --git a/src/Web/Endpoints/UpdateMyUser.cs b/src/Web/Endpoints/UpdateMyUser.cs index 9aca4dc..8f13133 100644 --- a/src/Web/Endpoints/UpdateMyUser.cs +++ b/src/Web/Endpoints/UpdateMyUser.cs @@ -19,21 +19,21 @@ public class UpdateMyUser : EndpointGroupBase return await sender.Send(command); } - private static async Task UpdateCurrentUserProfilePicture(ISender sender, Stream stream) + private static async Task UpdateCurrentUserProfilePicture(ISender sender, Stream stream, string url = "") { - var command = new UploadProfilePictureCommand { ProfilePicture = stream }; + var command = new UploadProfilePictureCommand { ProfilePicture = stream, ProfilePictureUrl = url}; return await sender.Send(command); } - private static async Task UpdateCurrentUserBannerPicture(ISender sender, Stream stream) + private static async Task UpdateCurrentUserBannerPicture(ISender sender, Stream stream, string url = "") { - var command = new UploadBannerPictureCommand { BannerPicture = stream }; + var command = new UploadBannerPictureCommand { BannerPicture = stream, BannerPictureUrl = url}; return await sender.Send(command); } - private static async Task UpdateCurrentUserWebsiteIcon(ISender sender, Stream stream) + private static async Task UpdateCurrentUserWebsiteIcon(ISender sender, Stream stream, string url = "") { - var command = new UploadWebsiteIconCommand { WebsiteIcon = stream }; + var command = new UploadWebsiteIconCommand { WebsiteIcon = stream, WebsitePictureUrl = url}; return await sender.Send(command); } } From b80374649bb21637887d8e71fb7c04ffda798661 Mon Sep 17 00:00:00 2001 From: Dominic Villemure Date: Fri, 5 Jul 2024 00:15:54 -0400 Subject: [PATCH 101/229] Renamed minimalUser to user --- .../GetMinimalUser.cs => GetUser/GetUser.cs} | 12 ++++++------ .../MinimalUserDto.cs => GetUser/UserDto.cs} | 4 ++-- src/Web/Endpoints/Users.cs | 6 +++--- 3 files changed, 11 insertions(+), 11 deletions(-) rename src/Application/Users/Queries/{GetMinimalUser/GetMinimalUser.cs => GetUser/GetUser.cs} (76%) rename src/Application/Users/Queries/{GetMinimalUser/MinimalUserDto.cs => GetUser/UserDto.cs} (86%) diff --git a/src/Application/Users/Queries/GetMinimalUser/GetMinimalUser.cs b/src/Application/Users/Queries/GetUser/GetUser.cs similarity index 76% rename from src/Application/Users/Queries/GetMinimalUser/GetMinimalUser.cs rename to src/Application/Users/Queries/GetUser/GetUser.cs index 454e8ae..3b36caa 100644 --- a/src/Application/Users/Queries/GetMinimalUser/GetMinimalUser.cs +++ b/src/Application/Users/Queries/GetUser/GetUser.cs @@ -1,20 +1,20 @@ using Hutopy.Application.Common.Interfaces; using Hutopy.Application.Common.Models; -namespace Hutopy.Application.Users.Queries.GetMinimalUser; +namespace Hutopy.Application.Users.Queries.GetUser; -public record GetMinimalUserQuery : IRequest +public record GetUserQuery : IRequest { public string? UserId { get; set; } = string.Empty; public string? UserName { get; set; } = string.Empty; }; -public class GetMinimalUserQueryHandler( +public class GetUserQueryHandler( IIdentityService identityService ) - : IRequestHandler + : IRequestHandler { - public async Task Handle(GetMinimalUserQuery request, CancellationToken cancellationToken) + public async Task Handle(GetUserQuery request, CancellationToken cancellationToken) { UserModel? identityUser = null; @@ -29,7 +29,7 @@ public class GetMinimalUserQueryHandler( identityUser = await identityService.GetUserByUserNameAsync(request.UserName); } - var user = new MinimalUserDto + var user = new UserDto { Id = identityUser?.Id ?? string.Empty, FirstName = identityUser?.FirstName ?? string.Empty, diff --git a/src/Application/Users/Queries/GetMinimalUser/MinimalUserDto.cs b/src/Application/Users/Queries/GetUser/UserDto.cs similarity index 86% rename from src/Application/Users/Queries/GetMinimalUser/MinimalUserDto.cs rename to src/Application/Users/Queries/GetUser/UserDto.cs index a38fd64..509743d 100644 --- a/src/Application/Users/Queries/GetMinimalUser/MinimalUserDto.cs +++ b/src/Application/Users/Queries/GetUser/UserDto.cs @@ -1,8 +1,8 @@ using Hutopy.Application.Users.Models; -namespace Hutopy.Application.Users.Queries.GetMinimalUser; +namespace Hutopy.Application.Users.Queries.GetUser; -public class MinimalUserDto +public class UserDto { public required string Id { get; init; } public required string FirstName { get; init; } diff --git a/src/Web/Endpoints/Users.cs b/src/Web/Endpoints/Users.cs index bcfa964..39bc408 100644 --- a/src/Web/Endpoints/Users.cs +++ b/src/Web/Endpoints/Users.cs @@ -1,5 +1,5 @@ using Hutopy.Application.Users.Commands; -using Hutopy.Application.Users.Queries.GetMinimalUser; +using Hutopy.Application.Users.Queries.GetUser; namespace Hutopy.Web.Endpoints; @@ -11,7 +11,7 @@ public class Users : EndpointGroupBase .MapPost(CreateUser) .MapPost(Login, "/login") .MapPost(UploadProfilePicture, "/upload-profile-picture") - .MapGet(GetMinimalUser); + .MapGet(GetUser); } private static async Task CreateUser(ISender sender, CreateUserCommand command) @@ -19,7 +19,7 @@ public class Users : EndpointGroupBase return await sender.Send(command); } - private static async Task GetMinimalUser(ISender sender, [AsParameters] GetMinimalUserQuery query) + private static async Task GetUser(ISender sender, [AsParameters] GetUserQuery query) { return await sender.Send(query); } From 4314e7f88877f088ee0f894fe9c35793428e899e Mon Sep 17 00:00:00 2001 From: Dominic Villemure Date: Fri, 5 Jul 2024 00:55:53 -0400 Subject: [PATCH 102/229] 1 day to jwt to stop relogging every 30 min while testing --- src/Infrastructure/Utils/GenerateJwtToken.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Infrastructure/Utils/GenerateJwtToken.cs b/src/Infrastructure/Utils/GenerateJwtToken.cs index 013da69..1139f25 100644 --- a/src/Infrastructure/Utils/GenerateJwtToken.cs +++ b/src/Infrastructure/Utils/GenerateJwtToken.cs @@ -42,7 +42,7 @@ public static class JwtTokenHelper issuer: issuer, audience: audience, claims: claims, - expires: DateTime.Now.AddMinutes(30), + expires: DateTime.Now.AddMinutes(1440), signingCredentials: credentials); return new JwtSecurityTokenHandler().WriteToken(token); From 256fa3df91214e4f3acdb6b5f5672516f76b932c Mon Sep 17 00:00:00 2001 From: Jonathan Bourdon Date: Sat, 6 Jul 2024 22:13:56 -0400 Subject: [PATCH 103/229] Adds Options for JwtAuthentication (30min prod - 1day dev) --- src/Infrastructure/Identity/IdentityService.cs | 17 ++++++----------- src/Infrastructure/Identity/JwtOptions.cs | 11 +++++++++++ src/Infrastructure/Utils/GenerateJwtToken.cs | 7 +++---- src/Web/Controllers/GoogleController.cs | 17 +++++++++++------ src/Web/Program.cs | 3 +++ src/Web/appsettings.Development.json | 1 + src/Web/appsettings.json | 7 ++++++- 7 files changed, 41 insertions(+), 22 deletions(-) create mode 100644 src/Infrastructure/Identity/JwtOptions.cs diff --git a/src/Infrastructure/Identity/IdentityService.cs b/src/Infrastructure/Identity/IdentityService.cs index 3d9bbc0..4842668 100644 --- a/src/Infrastructure/Identity/IdentityService.cs +++ b/src/Infrastructure/Identity/IdentityService.cs @@ -1,9 +1,5 @@ -using System; -using System.Collections.Generic; using Google.Apis.Oauth2.v2.Data; using System.Security.Claims; -using System.Threading; -using System.Threading.Tasks; using Hutopy.Application.Common.Interfaces; using Hutopy.Application.Common.Models; using Hutopy.Application.Users.Models; @@ -12,7 +8,7 @@ using Hutopy.Infrastructure.Utils; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Identity; -using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Options; namespace Hutopy.Infrastructure.Identity; @@ -22,7 +18,7 @@ public class IdentityService( IUserClaimsPrincipalFactory userClaimsPrincipalFactory, IAuthorizationService authorizationService, IHttpContextAccessor contextAccessor, - IConfiguration configuration + IOptionsSnapshot jwtOptions ) : IIdentityService { @@ -424,13 +420,12 @@ public class IdentityService( var user = await GetUserByUserNameAsync(userName); if (user is null) throw new InvalidOperationException(); - - var jwtSection = configuration.GetRequiredSection("Authentication:Jwt"); var token = JwtTokenHelper.GenerateJwtToken( - issuer: jwtSection["Issuer"] ?? "", - audience: jwtSection["Audience"] ?? "", - key: jwtSection["Key"] ?? "", + expiresIn: jwtOptions.Value.Lifetime, + issuer: jwtOptions.Value.Issuer, + audience: jwtOptions.Value.Audience, + key: jwtOptions.Value.Key, userId: user.Id, email: user.Email, firstname: user.FirstName, diff --git a/src/Infrastructure/Identity/JwtOptions.cs b/src/Infrastructure/Identity/JwtOptions.cs new file mode 100644 index 0000000..0f4214c --- /dev/null +++ b/src/Infrastructure/Identity/JwtOptions.cs @@ -0,0 +1,11 @@ +namespace Hutopy.Infrastructure.Identity; + +public record JwtOptions +{ + public const string SectionName = "Authentication:Jwt"; + + public required TimeSpan Lifetime { get; init; } + public required string Issuer { get; init; } + public required string Audience { get; init; } + public required string Key { get; init; } +} diff --git a/src/Infrastructure/Utils/GenerateJwtToken.cs b/src/Infrastructure/Utils/GenerateJwtToken.cs index 1139f25..a5613d6 100644 --- a/src/Infrastructure/Utils/GenerateJwtToken.cs +++ b/src/Infrastructure/Utils/GenerateJwtToken.cs @@ -1,6 +1,4 @@ -using System; -using System.Collections.Generic; -using System.IdentityModel.Tokens.Jwt; +using System.IdentityModel.Tokens.Jwt; using System.Security.Claims; using System.Text; using Microsoft.IdentityModel.Tokens; @@ -10,6 +8,7 @@ namespace Hutopy.Infrastructure.Utils; public static class JwtTokenHelper { public static string GenerateJwtToken( + TimeSpan expiresIn, string issuer, string audience, string key, @@ -42,7 +41,7 @@ public static class JwtTokenHelper issuer: issuer, audience: audience, claims: claims, - expires: DateTime.Now.AddMinutes(1440), + expires: DateTime.Now.Add(expiresIn), signingCredentials: credentials); return new JwtSecurityTokenHandler().WriteToken(token); diff --git a/src/Web/Controllers/GoogleController.cs b/src/Web/Controllers/GoogleController.cs index 38e04e7..db86eb4 100644 --- a/src/Web/Controllers/GoogleController.cs +++ b/src/Web/Controllers/GoogleController.cs @@ -1,14 +1,20 @@ using System.Security.Claims; using Hutopy.Application.Common.Interfaces; +using Hutopy.Infrastructure.Identity; using Hutopy.Infrastructure.Utils; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authentication.Cookies; using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Options; using Newtonsoft.Json.Linq; namespace Hutopy.Web.Controllers; -public class GoogleController(IIdentityService identityService, IHttpClientFactory httpClientFactory, IConfiguration configuration) : Controller +public class GoogleController( + IIdentityService identityService, + IHttpClientFactory httpClientFactory, + IOptionsSnapshot jwtOptions) + : Controller { [HttpPost("/api/google/sign-in")] public async Task SignIn([FromBody] GoogleSignInRequest request) @@ -61,12 +67,11 @@ public class GoogleController(IIdentityService identityService, IHttpClientFacto CookieAuthenticationDefaults.AuthenticationScheme, new ClaimsPrincipal(claimsIdentity)); - var jwtSection = configuration.GetRequiredSection("Authentication:Jwt"); - var token = JwtTokenHelper.GenerateJwtToken( - jwtSection["Issuer"] ?? throw new ArgumentNullException("The Jwt issuer is missing."), - jwtSection["Audience"] ?? throw new ArgumentNullException("The Jwt audience is missing."), - jwtSection["Key"] ?? throw new ArgumentNullException("The Jwt key is missing."), + jwtOptions.Value.Lifetime, + jwtOptions.Value.Issuer, + jwtOptions.Value.Audience, + jwtOptions.Value.Key, user.Id, user.Email, user.FirstName, diff --git a/src/Web/Program.cs b/src/Web/Program.cs index 097dac9..c7967fa 100644 --- a/src/Web/Program.cs +++ b/src/Web/Program.cs @@ -3,6 +3,7 @@ using FastEndpoints; using Hutopy.Application; using Hutopy.Infrastructure; using Hutopy.Infrastructure.Data; +using Hutopy.Infrastructure.Identity; using Hutopy.Web; using Hutopy.Web.Contents.Data; using Hutopy.Web.Messages.Data; @@ -89,6 +90,8 @@ builder.Services.AddDbContext((_, options) => options.UseSqlServer(builder.Configuration.GetConnectionString("ContentStore")); }); +builder.Services.Configure(builder.Configuration.GetRequiredSection(JwtOptions.SectionName)); + var app = builder.Build(); app.UseForwardedHeaders( diff --git a/src/Web/appsettings.Development.json b/src/Web/appsettings.Development.json index decba8e..f394dcb 100644 --- a/src/Web/appsettings.Development.json +++ b/src/Web/appsettings.Development.json @@ -14,6 +14,7 @@ }, "Authentication": { "Jwt": { + "Lifetime": "1.00:00:00", "Audience": "hutopy", "Issuer": "https://auth.hutopy.com", "Key": "b2df428b9929d3ace7c598bbf4e496b2f0b71ab3cd4f94540356cfc35b000000" diff --git a/src/Web/appsettings.json b/src/Web/appsettings.json index 222224e..d7257bd 100644 --- a/src/Web/appsettings.json +++ b/src/Web/appsettings.json @@ -6,5 +6,10 @@ "Microsoft.Hosting.Lifetime": "Information" } }, - "AllowedHosts": "*" + "AllowedHosts": "*", + "Authentication": { + "Jwt": { + "Lifetime": "00:30:00" + } + } } \ No newline at end of file From ca94dba08df2caab2bcdea7518dc0940b4591d8f Mon Sep 17 00:00:00 2001 From: Jonathan Bourdon Date: Sat, 6 Jul 2024 22:36:22 -0400 Subject: [PATCH 104/229] The MessageSystem is based on Subject instead of Content (just semantics) --- src/Web/Messages/Data/Message.cs | 4 +- src/Web/Messages/Handlers/GetMessages.cs | 6 +- src/Web/Messages/Handlers/PostMessage.cs | 4 +- src/Web/Messages/Handlers/PostReplyMessage.cs | 4 +- ...seSubjectId_InsteadOfContentId.Designer.cs | 58 +++++++++++++++++++ ...7023204_UseSubjectId_InsteadOfContentId.cs | 22 +++++++ 6 files changed, 88 insertions(+), 10 deletions(-) create mode 100644 src/Web/Migrations/20240707023204_UseSubjectId_InsteadOfContentId.Designer.cs create mode 100644 src/Web/Migrations/20240707023204_UseSubjectId_InsteadOfContentId.cs diff --git a/src/Web/Messages/Data/Message.cs b/src/Web/Messages/Data/Message.cs index df0fa50..3baf749 100644 --- a/src/Web/Messages/Data/Message.cs +++ b/src/Web/Messages/Data/Message.cs @@ -3,11 +3,9 @@ public class Message { public Guid Id { get; init; } - public Guid ContentId { get; init; } // works for any - VideoId, ChatId, RoomId, xxxId, ForumId + public Guid SubjectId { get; init; } public Guid CreatedBy { get; init; } public DateTime CreatedAt { get; } - public Guid ParentId { get; init; } - public string Value { get; init; } = null!; } diff --git a/src/Web/Messages/Handlers/GetMessages.cs b/src/Web/Messages/Handlers/GetMessages.cs index d7afb3f..28ed8f6 100644 --- a/src/Web/Messages/Handlers/GetMessages.cs +++ b/src/Web/Messages/Handlers/GetMessages.cs @@ -11,18 +11,18 @@ public class GetMessages( public override void Configure() { Tags("Messages"); - Get("/api/messages/{ContentId:guid}"); + Get("/api/messages/{SubjectId:guid}"); AllowAnonymous(); } public override async Task HandleAsync( CancellationToken ct) { - var contentId = Route("ContentId"); + var subjectId = Route("SubjectId"); var comments = await context .Messages - .Where(c => c.ContentId == contentId) + .Where(c => c.SubjectId == subjectId) .ToListAsync(cancellationToken: ct); await SendAsync(comments, cancellation: ct); diff --git a/src/Web/Messages/Handlers/PostMessage.cs b/src/Web/Messages/Handlers/PostMessage.cs index 46a316c..0380489 100644 --- a/src/Web/Messages/Handlers/PostMessage.cs +++ b/src/Web/Messages/Handlers/PostMessage.cs @@ -5,7 +5,7 @@ using Hutopy.Web.Messages.Data; namespace Hutopy.Web.Messages.Handlers; public record PostMessageRequest( - Guid ContentId, + Guid SubjectId, string Message); public class PostMessage( @@ -25,7 +25,7 @@ public class PostMessage( { await context.Messages.AddAsync( new Message { - ContentId = req.ContentId, + SubjectId = req.SubjectId, CreatedBy = User.GetUserId(), Value = req.Message }, ct); diff --git a/src/Web/Messages/Handlers/PostReplyMessage.cs b/src/Web/Messages/Handlers/PostReplyMessage.cs index 5a9bef9..616f6d9 100644 --- a/src/Web/Messages/Handlers/PostReplyMessage.cs +++ b/src/Web/Messages/Handlers/PostReplyMessage.cs @@ -5,7 +5,7 @@ using Hutopy.Web.Messages.Data; namespace Hutopy.Web.Messages.Handlers; public record PostReplyMessageRequest( - Guid ContentId, + Guid SubjectId, Guid ParentId, string Message); @@ -26,7 +26,7 @@ public sealed class PostReplyMessage( await context.Messages.AddAsync( new Message { - ContentId = req.ContentId, + SubjectId = req.SubjectId, ParentId = req.ParentId, CreatedBy = User.GetUserId(), Value = req.Message diff --git a/src/Web/Migrations/20240707023204_UseSubjectId_InsteadOfContentId.Designer.cs b/src/Web/Migrations/20240707023204_UseSubjectId_InsteadOfContentId.Designer.cs new file mode 100644 index 0000000..da741d4 --- /dev/null +++ b/src/Web/Migrations/20240707023204_UseSubjectId_InsteadOfContentId.Designer.cs @@ -0,0 +1,58 @@ +// +using System; +using Hutopy.Web.Contents.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Hutopy.Web.Migrations +{ + [DbContext(typeof(ContentDbContext))] + [Migration("20240707023204_UseSubjectId_InsteadOfContentId")] + partial class UseSubjectId_InsteadOfContentId + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.3") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("Hutopy.Web.Contents.Data.Content", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasDefaultValueSql("CURRENT_TIMESTAMP"); + + b.Property("CreatedBy") + .HasColumnType("uniqueidentifier"); + + b.Property("Description") + .HasColumnType("nvarchar(max)"); + + b.Property("Title") + .HasColumnType("nvarchar(max)"); + + b.Property("Uri") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("Contents"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Web/Migrations/20240707023204_UseSubjectId_InsteadOfContentId.cs b/src/Web/Migrations/20240707023204_UseSubjectId_InsteadOfContentId.cs new file mode 100644 index 0000000..02c3670 --- /dev/null +++ b/src/Web/Migrations/20240707023204_UseSubjectId_InsteadOfContentId.cs @@ -0,0 +1,22 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Hutopy.Web.Migrations +{ + /// + public partial class UseSubjectId_InsteadOfContentId : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + + } + } +} From f6a434c440642ea9931a0f41b7def03e7bc86c61 Mon Sep 17 00:00:00 2001 From: Jonathan Bourdon Date: Sat, 6 Jul 2024 23:12:39 -0400 Subject: [PATCH 105/229] Changing to database schema to ensure separations of concerns instead of connection string --- src/Web/Contents/Data/ContentDbContext.cs | 2 + ...8_ChangingContentDefaultSchema.Designer.cs | 59 ++++++++++++++++++ ...0707030928_ChangingContentDefaultSchema.cs | 31 ++++++++++ .../ContentDbContextModelSnapshot.cs | 3 +- src/Web/Messages/Data/MessagingDbContext.cs | 2 + ...seSubjectId_InsteadOfContentId.Designer.cs | 2 +- ...7023204_UseSubjectId_InsteadOfContentId.cs | 2 +- ...ChangingMessagingDefaultSchema.Designer.cs | 60 +++++++++++++++++++ ...07030834_ChangingMessagingDefaultSchema.cs | 42 +++++++++++++ .../MessagingDbContextModelSnapshot.cs | 9 +-- src/Web/Program.cs | 7 ++- src/Web/appsettings.Development.json | 4 +- 12 files changed, 211 insertions(+), 12 deletions(-) create mode 100644 src/Web/Contents/Migrations/20240707030928_ChangingContentDefaultSchema.Designer.cs create mode 100644 src/Web/Contents/Migrations/20240707030928_ChangingContentDefaultSchema.cs rename src/Web/{ => Messages}/Migrations/20240707023204_UseSubjectId_InsteadOfContentId.Designer.cs (97%) rename src/Web/{ => Messages}/Migrations/20240707023204_UseSubjectId_InsteadOfContentId.cs (91%) create mode 100644 src/Web/Messages/Migrations/20240707030834_ChangingMessagingDefaultSchema.Designer.cs create mode 100644 src/Web/Messages/Migrations/20240707030834_ChangingMessagingDefaultSchema.cs diff --git a/src/Web/Contents/Data/ContentDbContext.cs b/src/Web/Contents/Data/ContentDbContext.cs index f525cbf..bf6eaf5 100644 --- a/src/Web/Contents/Data/ContentDbContext.cs +++ b/src/Web/Contents/Data/ContentDbContext.cs @@ -8,6 +8,8 @@ public class ContentDbContext( { protected override void OnModelCreating(ModelBuilder modelBuilder) { + modelBuilder.HasDefaultSchema("Content"); + modelBuilder .Entity() .Property(c => c.CreatedAt) diff --git a/src/Web/Contents/Migrations/20240707030928_ChangingContentDefaultSchema.Designer.cs b/src/Web/Contents/Migrations/20240707030928_ChangingContentDefaultSchema.Designer.cs new file mode 100644 index 0000000..2555444 --- /dev/null +++ b/src/Web/Contents/Migrations/20240707030928_ChangingContentDefaultSchema.Designer.cs @@ -0,0 +1,59 @@ +// +using System; +using Hutopy.Web.Contents.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Hutopy.Web.Contents.Migrations +{ + [DbContext(typeof(ContentDbContext))] + [Migration("20240707030928_ChangingContentDefaultSchema")] + partial class ChangingContentDefaultSchema + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasDefaultSchema("Content") + .HasAnnotation("ProductVersion", "8.0.3") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("Hutopy.Web.Contents.Data.Content", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasDefaultValueSql("CURRENT_TIMESTAMP"); + + b.Property("CreatedBy") + .HasColumnType("uniqueidentifier"); + + b.Property("Description") + .HasColumnType("nvarchar(max)"); + + b.Property("Title") + .HasColumnType("nvarchar(max)"); + + b.Property("Uri") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("Contents", "Content"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Web/Contents/Migrations/20240707030928_ChangingContentDefaultSchema.cs b/src/Web/Contents/Migrations/20240707030928_ChangingContentDefaultSchema.cs new file mode 100644 index 0000000..df1bb9f --- /dev/null +++ b/src/Web/Contents/Migrations/20240707030928_ChangingContentDefaultSchema.cs @@ -0,0 +1,31 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Hutopy.Web.Contents.Migrations +{ + /// + public partial class ChangingContentDefaultSchema : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.EnsureSchema( + name: "Content"); + + migrationBuilder.RenameTable( + name: "Contents", + newName: "Contents", + newSchema: "Content"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.RenameTable( + name: "Contents", + schema: "Content", + newName: "Contents"); + } + } +} diff --git a/src/Web/Contents/Migrations/ContentDbContextModelSnapshot.cs b/src/Web/Contents/Migrations/ContentDbContextModelSnapshot.cs index 1892c37..4f2d601 100644 --- a/src/Web/Contents/Migrations/ContentDbContextModelSnapshot.cs +++ b/src/Web/Contents/Migrations/ContentDbContextModelSnapshot.cs @@ -17,6 +17,7 @@ namespace Hutopy.Web.Contents.Migrations { #pragma warning disable 612, 618 modelBuilder + .HasDefaultSchema("Content") .HasAnnotation("ProductVersion", "8.0.3") .HasAnnotation("Relational:MaxIdentifierLength", 128); @@ -47,7 +48,7 @@ namespace Hutopy.Web.Contents.Migrations b.HasKey("Id"); - b.ToTable("Contents"); + b.ToTable("Contents", "Content"); }); #pragma warning restore 612, 618 } diff --git a/src/Web/Messages/Data/MessagingDbContext.cs b/src/Web/Messages/Data/MessagingDbContext.cs index 28bb977..e343a2b 100644 --- a/src/Web/Messages/Data/MessagingDbContext.cs +++ b/src/Web/Messages/Data/MessagingDbContext.cs @@ -8,6 +8,8 @@ public class MessagingDbContext( { protected override void OnModelCreating(ModelBuilder modelBuilder) { + modelBuilder.HasDefaultSchema("Messaging"); + modelBuilder .Entity() .Property(c => c.CreatedAt) diff --git a/src/Web/Migrations/20240707023204_UseSubjectId_InsteadOfContentId.Designer.cs b/src/Web/Messages/Migrations/20240707023204_UseSubjectId_InsteadOfContentId.Designer.cs similarity index 97% rename from src/Web/Migrations/20240707023204_UseSubjectId_InsteadOfContentId.Designer.cs rename to src/Web/Messages/Migrations/20240707023204_UseSubjectId_InsteadOfContentId.Designer.cs index da741d4..86ed4f1 100644 --- a/src/Web/Migrations/20240707023204_UseSubjectId_InsteadOfContentId.Designer.cs +++ b/src/Web/Messages/Migrations/20240707023204_UseSubjectId_InsteadOfContentId.Designer.cs @@ -9,7 +9,7 @@ using Microsoft.EntityFrameworkCore.Storage.ValueConversion; #nullable disable -namespace Hutopy.Web.Migrations +namespace Hutopy.Web.Messages.Migrations { [DbContext(typeof(ContentDbContext))] [Migration("20240707023204_UseSubjectId_InsteadOfContentId")] diff --git a/src/Web/Migrations/20240707023204_UseSubjectId_InsteadOfContentId.cs b/src/Web/Messages/Migrations/20240707023204_UseSubjectId_InsteadOfContentId.cs similarity index 91% rename from src/Web/Migrations/20240707023204_UseSubjectId_InsteadOfContentId.cs rename to src/Web/Messages/Migrations/20240707023204_UseSubjectId_InsteadOfContentId.cs index 02c3670..760efd1 100644 --- a/src/Web/Migrations/20240707023204_UseSubjectId_InsteadOfContentId.cs +++ b/src/Web/Messages/Migrations/20240707023204_UseSubjectId_InsteadOfContentId.cs @@ -2,7 +2,7 @@ #nullable disable -namespace Hutopy.Web.Migrations +namespace Hutopy.Web.Messages.Migrations { /// public partial class UseSubjectId_InsteadOfContentId : Migration diff --git a/src/Web/Messages/Migrations/20240707030834_ChangingMessagingDefaultSchema.Designer.cs b/src/Web/Messages/Migrations/20240707030834_ChangingMessagingDefaultSchema.Designer.cs new file mode 100644 index 0000000..dacf0b2 --- /dev/null +++ b/src/Web/Messages/Migrations/20240707030834_ChangingMessagingDefaultSchema.Designer.cs @@ -0,0 +1,60 @@ +// +using System; +using Hutopy.Web.Messages.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Hutopy.Web.Messages.Migrations +{ + [DbContext(typeof(MessagingDbContext))] + [Migration("20240707030834_ChangingMessagingDefaultSchema")] + partial class ChangingMessagingDefaultSchema + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasDefaultSchema("Messaging") + .HasAnnotation("ProductVersion", "8.0.3") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("Hutopy.Web.Messages.Data.Message", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasDefaultValueSql("CURRENT_TIMESTAMP"); + + b.Property("CreatedBy") + .HasColumnType("uniqueidentifier"); + + b.Property("ParentId") + .HasColumnType("uniqueidentifier"); + + b.Property("SubjectId") + .HasColumnType("uniqueidentifier"); + + b.Property("Value") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("Messages", "Messaging"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Web/Messages/Migrations/20240707030834_ChangingMessagingDefaultSchema.cs b/src/Web/Messages/Migrations/20240707030834_ChangingMessagingDefaultSchema.cs new file mode 100644 index 0000000..c788df7 --- /dev/null +++ b/src/Web/Messages/Migrations/20240707030834_ChangingMessagingDefaultSchema.cs @@ -0,0 +1,42 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Hutopy.Web.Messages.Migrations +{ + /// + public partial class ChangingMessagingDefaultSchema : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.EnsureSchema( + name: "Messaging"); + + migrationBuilder.RenameTable( + name: "Messages", + newName: "Messages", + newSchema: "Messaging"); + + migrationBuilder.RenameColumn( + name: "ContentId", + schema: "Messaging", + table: "Messages", + newName: "SubjectId"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.RenameTable( + name: "Messages", + schema: "Messaging", + newName: "Messages"); + + migrationBuilder.RenameColumn( + name: "SubjectId", + table: "Messages", + newName: "ContentId"); + } + } +} diff --git a/src/Web/Messages/Migrations/MessagingDbContextModelSnapshot.cs b/src/Web/Messages/Migrations/MessagingDbContextModelSnapshot.cs index be9a4b9..dcaa429 100644 --- a/src/Web/Messages/Migrations/MessagingDbContextModelSnapshot.cs +++ b/src/Web/Messages/Migrations/MessagingDbContextModelSnapshot.cs @@ -17,6 +17,7 @@ namespace Hutopy.Web.Messages.Migrations { #pragma warning disable 612, 618 modelBuilder + .HasDefaultSchema("Messaging") .HasAnnotation("ProductVersion", "8.0.3") .HasAnnotation("Relational:MaxIdentifierLength", 128); @@ -28,9 +29,6 @@ namespace Hutopy.Web.Messages.Migrations .ValueGeneratedOnAdd() .HasColumnType("uniqueidentifier"); - b.Property("ContentId") - .HasColumnType("uniqueidentifier"); - b.Property("CreatedAt") .ValueGeneratedOnAdd() .HasColumnType("datetime2") @@ -42,13 +40,16 @@ namespace Hutopy.Web.Messages.Migrations b.Property("ParentId") .HasColumnType("uniqueidentifier"); + b.Property("SubjectId") + .HasColumnType("uniqueidentifier"); + b.Property("Value") .IsRequired() .HasColumnType("nvarchar(max)"); b.HasKey("Id"); - b.ToTable("Messages"); + b.ToTable("Messages", "Messaging"); }); #pragma warning restore 612, 618 } diff --git a/src/Web/Program.cs b/src/Web/Program.cs index c7967fa..3aad5cb 100644 --- a/src/Web/Program.cs +++ b/src/Web/Program.cs @@ -80,14 +80,17 @@ builder.Services.AddOpenApiDocument((configure, sp) => builder.Services.AddFastEndpoints(); +var connectionString = builder.Configuration.GetConnectionString("DefaultConnection") + ?? throw new InvalidOperationException("Missing ConnectionStrings:DefaultConnection"); + builder.Services.AddDbContext((_, options) => { - options.UseSqlServer(builder.Configuration.GetConnectionString("CommentStore")); + options.UseSqlServer(connectionString); }); builder.Services.AddDbContext((_, options) => { - options.UseSqlServer(builder.Configuration.GetConnectionString("ContentStore")); + options.UseSqlServer(connectionString); }); builder.Services.Configure(builder.Configuration.GetRequiredSection(JwtOptions.SectionName)); diff --git a/src/Web/appsettings.Development.json b/src/Web/appsettings.Development.json index f394dcb..d249e8e 100644 --- a/src/Web/appsettings.Development.json +++ b/src/Web/appsettings.Development.json @@ -8,9 +8,7 @@ } }, "ConnectionStrings": { - "DefaultConnection": "Server=localhost,1433;Initial Catalog=Hutopy;User Id=sa;Password=P@ssword123!;MultipleActiveResultSets=true;TrustServerCertificate=True;MultiSubnetFailover=True", - "CommentStore": "Server=localhost,1433;Initial Catalog=Hutopy;User Id=sa;Password=P@ssword123!;MultipleActiveResultSets=true;TrustServerCertificate=True;MultiSubnetFailover=True", - "ContentStore": "Server=localhost,1433;Initial Catalog=Hutopy;User Id=sa;Password=P@ssword123!;MultipleActiveResultSets=true;TrustServerCertificate=True;MultiSubnetFailover=True" + "DefaultConnection": "Server=localhost,1433;Initial Catalog=Hutopy;User Id=sa;Password=P@ssword123!;MultipleActiveResultSets=true;TrustServerCertificate=True;MultiSubnetFailover=True" }, "Authentication": { "Jwt": { From 715bad702b23f69073f7a7a5ae33cb914ebabd56 Mon Sep 17 00:00:00 2001 From: Jonathan Bourdon Date: Sat, 6 Jul 2024 23:15:19 -0400 Subject: [PATCH 106/229] Fix PostContent name --- src/Web/Contents/Handlers/{PostMessage.cs => PostContent.cs} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename src/Web/Contents/Handlers/{PostMessage.cs => PostContent.cs} (97%) diff --git a/src/Web/Contents/Handlers/PostMessage.cs b/src/Web/Contents/Handlers/PostContent.cs similarity index 97% rename from src/Web/Contents/Handlers/PostMessage.cs rename to src/Web/Contents/Handlers/PostContent.cs index 850cfba..9e9a779 100644 --- a/src/Web/Contents/Handlers/PostMessage.cs +++ b/src/Web/Contents/Handlers/PostContent.cs @@ -9,7 +9,7 @@ public record struct PostContentRequest( string? Description, string? Uri); -public class PostMessage( +public class PostContent( ContentDbContext context) : Endpoint { From 349999722bfcc74038f5763ffdcdf4213f05020c Mon Sep 17 00:00:00 2001 From: Jonathan Bourdon Date: Tue, 9 Jul 2024 15:19:12 -0400 Subject: [PATCH 107/229] Fix the Tags within swagger --- src/Web/Contents/Handlers/GetContents.cs | 2 +- src/Web/Contents/Handlers/GetContentsByUser.cs | 2 +- src/Web/Contents/Handlers/PostContent.cs | 3 +-- src/Web/Creators/Handlers/GetCreatorByAlias.cs | 6 +++--- src/Web/Messages/Handlers/GetMessages.cs | 2 +- src/Web/Messages/Handlers/GetMessagesByUser.cs | 2 +- src/Web/Messages/Handlers/PostMessage.cs | 3 +-- src/Web/Messages/Handlers/PostReplyMessage.cs | 2 +- 8 files changed, 10 insertions(+), 12 deletions(-) diff --git a/src/Web/Contents/Handlers/GetContents.cs b/src/Web/Contents/Handlers/GetContents.cs index c9f3258..aa73599 100644 --- a/src/Web/Contents/Handlers/GetContents.cs +++ b/src/Web/Contents/Handlers/GetContents.cs @@ -10,8 +10,8 @@ public class GetContents( { public override void Configure() { - Tags("Contents"); Get("/api/contents/{ContentId:guid}"); + Options( o => o.WithTags("Contents")); AllowAnonymous(); } diff --git a/src/Web/Contents/Handlers/GetContentsByUser.cs b/src/Web/Contents/Handlers/GetContentsByUser.cs index a3e87ff..70152af 100644 --- a/src/Web/Contents/Handlers/GetContentsByUser.cs +++ b/src/Web/Contents/Handlers/GetContentsByUser.cs @@ -10,8 +10,8 @@ public class GetContentsByUser( { public override void Configure() { - Tags("Contents"); Get("/api/contents/user/{UserId:guid}"); + Options( o => o.WithTags("Contents")); AllowAnonymous(); } diff --git a/src/Web/Contents/Handlers/PostContent.cs b/src/Web/Contents/Handlers/PostContent.cs index 9e9a779..fd8ecbd 100644 --- a/src/Web/Contents/Handlers/PostContent.cs +++ b/src/Web/Contents/Handlers/PostContent.cs @@ -15,9 +15,8 @@ public class PostContent( { public override void Configure() { - // TODO: Find how to specify the name we see in Swagger - Tags("Contents"); Post("/api/contents"); + Options( o => o.WithTags("Contents")); } public override async Task HandleAsync( diff --git a/src/Web/Creators/Handlers/GetCreatorByAlias.cs b/src/Web/Creators/Handlers/GetCreatorByAlias.cs index a46201f..eaea0aa 100644 --- a/src/Web/Creators/Handlers/GetCreatorByAlias.cs +++ b/src/Web/Creators/Handlers/GetCreatorByAlias.cs @@ -10,7 +10,7 @@ public class GetCreatorByAlias( { public override void Configure() { - Tags("Creators"); + Options((o => o.WithTags("Creators"))); Get("/api/creators/@{CreatorAlias}"); AllowAnonymous(); } @@ -19,9 +19,9 @@ public class GetCreatorByAlias( CancellationToken ct) { var creatorAlias = Route("CreatorAlias"); - + ArgumentException.ThrowIfNullOrEmpty(creatorAlias); - + var user = await identityService.FindUserByCreatorAliasAsync(creatorAlias, ct); await SendAsync(user, cancellation: ct); diff --git a/src/Web/Messages/Handlers/GetMessages.cs b/src/Web/Messages/Handlers/GetMessages.cs index 28ed8f6..59bb41e 100644 --- a/src/Web/Messages/Handlers/GetMessages.cs +++ b/src/Web/Messages/Handlers/GetMessages.cs @@ -10,8 +10,8 @@ public class GetMessages( { public override void Configure() { - Tags("Messages"); Get("/api/messages/{SubjectId:guid}"); + Options(o => o.WithTags("Messages")); AllowAnonymous(); } diff --git a/src/Web/Messages/Handlers/GetMessagesByUser.cs b/src/Web/Messages/Handlers/GetMessagesByUser.cs index b5b25e0..5d101f6 100644 --- a/src/Web/Messages/Handlers/GetMessagesByUser.cs +++ b/src/Web/Messages/Handlers/GetMessagesByUser.cs @@ -11,8 +11,8 @@ public class GetMessagesByUser( { public override void Configure() { - Tags("Messages"); Get("/api/messages/user/{UserId:guid}"); + Options(o => o.WithTags("Messages")); } public override async Task HandleAsync( diff --git a/src/Web/Messages/Handlers/PostMessage.cs b/src/Web/Messages/Handlers/PostMessage.cs index 0380489..d5d9202 100644 --- a/src/Web/Messages/Handlers/PostMessage.cs +++ b/src/Web/Messages/Handlers/PostMessage.cs @@ -14,9 +14,8 @@ public class PostMessage( { public override void Configure() { - // TODO: Find how to specify the name we see in Swagger - Tags("Messages"); Post("/api/messages"); + Options(o => o.WithTags("Messages")); } public override async Task HandleAsync( diff --git a/src/Web/Messages/Handlers/PostReplyMessage.cs b/src/Web/Messages/Handlers/PostReplyMessage.cs index 616f6d9..975da57 100644 --- a/src/Web/Messages/Handlers/PostReplyMessage.cs +++ b/src/Web/Messages/Handlers/PostReplyMessage.cs @@ -15,8 +15,8 @@ public sealed class PostReplyMessage( { public override void Configure() { - Tags("Messages"); Post("/api/messages/reply"); + Options(o => o.WithTags("Messages")); } public override async Task HandleAsync( From 25ea9b50c7977a39bb2c965e9b97ad19ad95fc71 Mon Sep 17 00:00:00 2001 From: Jonathan Bourdon Date: Tue, 9 Jul 2024 15:24:58 -0400 Subject: [PATCH 108/229] Remove sample 'weather' endpoint --- .../GetWeatherForecastsQuery.cs | 25 ------------------- .../GetWeatherForecasts/WeatherForecast.cs | 12 --------- src/Web/Endpoints/WeatherForecasts.cs | 18 ------------- src/Web/Web.http | 6 ----- 4 files changed, 61 deletions(-) delete mode 100644 src/Application/WeatherForecasts/Queries/GetWeatherForecasts/GetWeatherForecastsQuery.cs delete mode 100644 src/Application/WeatherForecasts/Queries/GetWeatherForecasts/WeatherForecast.cs delete mode 100644 src/Web/Endpoints/WeatherForecasts.cs diff --git a/src/Application/WeatherForecasts/Queries/GetWeatherForecasts/GetWeatherForecastsQuery.cs b/src/Application/WeatherForecasts/Queries/GetWeatherForecasts/GetWeatherForecastsQuery.cs deleted file mode 100644 index cf75269..0000000 --- a/src/Application/WeatherForecasts/Queries/GetWeatherForecasts/GetWeatherForecastsQuery.cs +++ /dev/null @@ -1,25 +0,0 @@ -namespace Hutopy.Application.WeatherForecasts.Queries.GetWeatherForecasts; - -public record GetWeatherForecastsQuery : IRequest>; - -public class GetWeatherForecastsQueryHandler : IRequestHandler> -{ - private static readonly string[] Summaries = new[] - { - "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" - }; - -#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously - public async Task> Handle(GetWeatherForecastsQuery request, CancellationToken cancellationToken) -#pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously - { - var rng = new Random(); - - return Enumerable.Range(1, 5).Select(index => new WeatherForecast - { - Date = DateTime.Now.AddDays(index), - TemperatureC = rng.Next(-20, 55), - Summary = Summaries[rng.Next(Summaries.Length)] - }); - } -} diff --git a/src/Application/WeatherForecasts/Queries/GetWeatherForecasts/WeatherForecast.cs b/src/Application/WeatherForecasts/Queries/GetWeatherForecasts/WeatherForecast.cs deleted file mode 100644 index e01216a..0000000 --- a/src/Application/WeatherForecasts/Queries/GetWeatherForecasts/WeatherForecast.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace Hutopy.Application.WeatherForecasts.Queries.GetWeatherForecasts; - -public class WeatherForecast -{ - public DateTime Date { get; init; } - - public int TemperatureC { get; init; } - - public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); - - public string? Summary { get; init; } -} diff --git a/src/Web/Endpoints/WeatherForecasts.cs b/src/Web/Endpoints/WeatherForecasts.cs deleted file mode 100644 index 75f26c4..0000000 --- a/src/Web/Endpoints/WeatherForecasts.cs +++ /dev/null @@ -1,18 +0,0 @@ -using Hutopy.Application.WeatherForecasts.Queries.GetWeatherForecasts; - -namespace Hutopy.Web.Endpoints; - -public class WeatherForecasts : EndpointGroupBase -{ - public override void Map(WebApplication app) - { - app.MapGroup(this) - .RequireAuthorization() - .MapGet(GetWeatherForecasts); - } - - private static async Task> GetWeatherForecasts(ISender sender) - { - return await sender.Send(new GetWeatherForecastsQuery()); - } -} diff --git a/src/Web/Web.http b/src/Web/Web.http index 054f4e4..5dfb87a 100644 --- a/src/Web/Web.http +++ b/src/Web/Web.http @@ -38,12 +38,6 @@ Content-Type: application/json ### -# GET WeatherForecast -GET {{base_url}}/api/WeatherForecasts -Authorization: Bearer {{auth_token}} - -### - # GET GetMyUser GET {{base_url}}/api/GetMyUser Authorization: Bearer {{auth_token}} From 86c9fb51faa164d1319e5b75865771ee32feeb53 Mon Sep 17 00:00:00 2001 From: Dominic Villemure Date: Tue, 9 Jul 2024 23:45:51 -0400 Subject: [PATCH 109/229] Logs for blob storage and some improvements --- Directory.Packages.props | 1 + src/Application/Application.csproj | 1 + src/Application/Common/Models/Result.cs | 5 + src/Application/Users/Commands/CreateUser.cs | 9 +- .../Commands/UpdateCurrentUserCommand.cs | 13 +-- .../Users/Commands/UploadBannerPicture.cs | 29 +++-- .../Users/Commands/UploadProfilePicture.cs | 12 ++- .../Users/Commands/UploadWebsiteIcon.cs | 12 ++- .../AzureBlob/AzureBlobStorageService.cs | 102 +++++++++++++----- src/Web/Endpoints/UpdateMyUser.cs | 8 +- src/Web/Endpoints/Users.cs | 10 +- 11 files changed, 133 insertions(+), 69 deletions(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 3c60acd..f6e9876 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -36,6 +36,7 @@ + diff --git a/src/Application/Application.csproj b/src/Application/Application.csproj index 34570d3..996edb9 100644 --- a/src/Application/Application.csproj +++ b/src/Application/Application.csproj @@ -11,6 +11,7 @@ + diff --git a/src/Application/Common/Models/Result.cs b/src/Application/Common/Models/Result.cs index 294e2ed..8c30b4a 100644 --- a/src/Application/Common/Models/Result.cs +++ b/src/Application/Common/Models/Result.cs @@ -31,6 +31,11 @@ public class Result( { return Value ?? default(T)!; } + + public string GetErrorsAsString() + { + return Errors.Length == 0 ? string.Empty : string.Join(", ", Errors); + } public static Result Success(T value) { diff --git a/src/Application/Users/Commands/CreateUser.cs b/src/Application/Users/Commands/CreateUser.cs index 54077eb..703066c 100644 --- a/src/Application/Users/Commands/CreateUser.cs +++ b/src/Application/Users/Commands/CreateUser.cs @@ -1,7 +1,8 @@ using Hutopy.Application.Common.Interfaces; +using Microsoft.AspNetCore.Http; namespace Hutopy.Application.Users.Commands; -public record CreateUserCommand : IRequest +public record CreateUserCommand : IRequest { public required string FirstName { get; init; } public required string LastName { get; init; } @@ -10,7 +11,7 @@ public record CreateUserCommand : IRequest public required string Password { get; init; } } -public class CreateUserCommandHandler : IRequestHandler +public class CreateUserCommandHandler : IRequestHandler { private readonly IApplicationDbContext _context; private readonly IIdentityService _identityService; @@ -21,7 +22,7 @@ public class CreateUserCommandHandler : IRequestHandler _identityService = identityService; } - public async Task Handle(CreateUserCommand request, CancellationToken cancellationToken) + public async Task Handle(CreateUserCommand request, CancellationToken cancellationToken) { await _identityService.CreateUserAsync(request.EmailAddress, request.UserName, request.FirstName, request.LastName, request.Password); @@ -29,6 +30,6 @@ public class CreateUserCommandHandler : IRequestHandler await _context.SaveChangesAsync(cancellationToken); - return new Guid(user?.Id ?? string.Empty); + return Results.Ok(new Guid(user?.Id ?? string.Empty)); } } diff --git a/src/Application/Users/Commands/UpdateCurrentUserCommand.cs b/src/Application/Users/Commands/UpdateCurrentUserCommand.cs index 7d55961..682cc3e 100644 --- a/src/Application/Users/Commands/UpdateCurrentUserCommand.cs +++ b/src/Application/Users/Commands/UpdateCurrentUserCommand.cs @@ -2,10 +2,11 @@ using System.ComponentModel.DataAnnotations.Schema; using Hutopy.Application.Common.Interfaces; using Hutopy.Application.Common.Models; using Hutopy.Application.Users.Models; +using Microsoft.AspNetCore.Http; namespace Hutopy.Application.Users.Commands; -public class UpdateCurrentUserCommand : IRequest +public class UpdateCurrentUserCommand : IRequest { public required string FirstName { get; init; } public required string LastName { get; init; } @@ -32,13 +33,13 @@ public class UpdateCurrentUserCommand : IRequest } public class UpdateCurrentUserCommandHandler(IApplicationDbContext context, IIdentityService identityService, IMapper mapper) : - IRequestHandler + IRequestHandler { - public async Task Handle(UpdateCurrentUserCommand request, CancellationToken cancellationToken) + public async Task Handle(UpdateCurrentUserCommand request, CancellationToken cancellationToken) { var identityUser = await identityService.GetCurrentUserAsync(); - if (identityUser?.Id is null) return string.Empty; + if (identityUser?.Id is null) return Results.Problem("Current user not found."); var userModel = mapper.Map(request); userModel.Id = identityUser.Id; @@ -46,8 +47,8 @@ public class UpdateCurrentUserCommandHandler(IApplicationDbContext context, IIde var result = await identityService.UpdateCurrentUserAsync(userModel); await context.SaveChangesAsync(cancellationToken); - - return result.GetValueOrDefault(); + + return result.Succeeded ? Results.Ok(result.GetValueOrDefault()) : Results.Problem(result.GetErrorsAsString()); } } diff --git a/src/Application/Users/Commands/UploadBannerPicture.cs b/src/Application/Users/Commands/UploadBannerPicture.cs index e99f28a..96728b8 100644 --- a/src/Application/Users/Commands/UploadBannerPicture.cs +++ b/src/Application/Users/Commands/UploadBannerPicture.cs @@ -1,37 +1,50 @@ using Hutopy.Application.AzureBlobStorage.Constants; using Hutopy.Application.Common.Interfaces; +using Microsoft.AspNetCore.Http; namespace Hutopy.Application.Users.Commands; /// /// Upload a banner picture. If the user has the url already, set the BannerPictureUrl in the user only without upload. /// -public class UploadBannerPictureCommand : IRequest +public class UploadBannerPictureCommand : IRequest { public required Stream BannerPicture { get; init; } public string BannerPictureUrl { get; init; } = string.Empty; } -public class UploadBannerPictureCommandHandler(IIdentityService identityService, IAzureBlobStorageService azureBlobStorageService) : IRequestHandler +public class UploadBannerPictureCommandHandler(IIdentityService identityService, IAzureBlobStorageService azureBlobStorageService) : IRequestHandler { - public async Task Handle(UploadBannerPictureCommand request, CancellationToken cancellationToken) + public async Task Handle(UploadBannerPictureCommand request, CancellationToken cancellationToken) { + // If an url to the picture is provided, use it right away and don't upload anything. if (!string.IsNullOrEmpty(request.BannerPictureUrl)) { await identityService.UpdateCurrentUserBannerPictureUrlAsync(request.BannerPictureUrl); - return request.BannerPictureUrl; + return Results.Ok(request.BannerPictureUrl); } var identityUser = await identityService.GetCurrentUserAsync(); var currentUserId = new Guid(identityUser?.Id ?? "").ToString(); var blobName = $"{currentUserId}/{SubDirectoryNames.Profile}/{CommonFileNames.BannerPicture}"; - - var url = await azureBlobStorageService.UploadFileAsync(ContainerNames.Users, blobName, request.BannerPicture, ContentTypes.ImagePng); - await identityService.UpdateCurrentUserBannerPictureUrlAsync(url); + try + { + var url = await azureBlobStorageService.UploadFileAsync(ContainerNames.Users, blobName, request.BannerPicture, ContentTypes.ImagePng); + + await identityService.UpdateCurrentUserBannerPictureUrlAsync(url); - return url; + return Results.Ok(url); + } + catch (InvalidOperationException ex) + { + return Results.BadRequest(ex.Message); + } + catch (Exception) + { + return Results.StatusCode(StatusCodes.Status500InternalServerError); + } } } diff --git a/src/Application/Users/Commands/UploadProfilePicture.cs b/src/Application/Users/Commands/UploadProfilePicture.cs index ae15d31..daefbe7 100644 --- a/src/Application/Users/Commands/UploadProfilePicture.cs +++ b/src/Application/Users/Commands/UploadProfilePicture.cs @@ -1,25 +1,27 @@ using Hutopy.Application.AzureBlobStorage.Constants; using Hutopy.Application.Common.Interfaces; +using Microsoft.AspNetCore.Http; namespace Hutopy.Application.Users.Commands; /// /// Upload a profile picture. If the user has the url already, set the ProfilePictureUrl in the user only without upload. /// -public class UploadProfilePictureCommand : IRequest +public class UploadProfilePictureCommand : IRequest { public required Stream ProfilePicture { get; init; } public string ProfilePictureUrl { get; init; } = string.Empty; } -public class UploadProfilePictureCommandHandler(IIdentityService identityService, IAzureBlobStorageService azureBlobStorageService) : IRequestHandler +public class UploadProfilePictureCommandHandler(IIdentityService identityService, IAzureBlobStorageService azureBlobStorageService) : IRequestHandler { - public async Task Handle(UploadProfilePictureCommand request, CancellationToken cancellationToken) + public async Task Handle(UploadProfilePictureCommand request, CancellationToken cancellationToken) { + // If an url to the picture is provided, use it right away and don't upload anything. if (!string.IsNullOrEmpty(request.ProfilePictureUrl)) { await identityService.UpdateCurrentUserProfilePictureUrlAsync(request.ProfilePictureUrl); - return request.ProfilePictureUrl; + return Results.Ok(request.ProfilePictureUrl); } var identityUser = await identityService.GetCurrentUserAsync(); @@ -31,7 +33,7 @@ public class UploadProfilePictureCommandHandler(IIdentityService identityService await identityService.UpdateCurrentUserProfilePictureUrlAsync(url); - return url; + return Results.Ok(url); } } diff --git a/src/Application/Users/Commands/UploadWebsiteIcon.cs b/src/Application/Users/Commands/UploadWebsiteIcon.cs index 31f3f5f..2c18756 100644 --- a/src/Application/Users/Commands/UploadWebsiteIcon.cs +++ b/src/Application/Users/Commands/UploadWebsiteIcon.cs @@ -1,26 +1,28 @@ using Hutopy.Application.AzureBlobStorage.Constants; using Hutopy.Application.Common.Interfaces; +using Microsoft.AspNetCore.Http; namespace Hutopy.Application.Users.Commands; /// /// Upload a website icon. If the user has the url already, set the WebsitePictureUrl in the user only without upload. /// -public class UploadWebsiteIconCommand : IRequest +public class UploadWebsiteIconCommand : IRequest { public required Stream WebsiteIcon { get; init; } public string WebsitePictureUrl { get; init; } = string.Empty; } -public class UploadWebsiteIconCommandHandler(IIdentityService identityService, IAzureBlobStorageService azureBlobStorageService) : IRequestHandler +public class UploadWebsiteIconCommandHandler(IIdentityService identityService, IAzureBlobStorageService azureBlobStorageService) : IRequestHandler { - public async Task Handle(UploadWebsiteIconCommand request, CancellationToken cancellationToken) + public async Task Handle(UploadWebsiteIconCommand request, CancellationToken cancellationToken) { + // If an url to the picture is provided, use it right away and don't upload anything. if (!string.IsNullOrEmpty(request.WebsitePictureUrl)) { await identityService.UpdateCurrentUserWebsiteIconUrlAsync(request.WebsitePictureUrl); - return request.WebsitePictureUrl; + return Results.Ok(request.WebsitePictureUrl); } var identityUser = await identityService.GetCurrentUserAsync(); @@ -32,7 +34,7 @@ public class UploadWebsiteIconCommandHandler(IIdentityService identityService, I await identityService.UpdateCurrentUserWebsiteIconUrlAsync(url); - return url; + return Results.Ok(request.WebsitePictureUrl); } } diff --git a/src/Infrastructure/AzureBlob/AzureBlobStorageService.cs b/src/Infrastructure/AzureBlob/AzureBlobStorageService.cs index 18d7856..275b5a3 100644 --- a/src/Infrastructure/AzureBlob/AzureBlobStorageService.cs +++ b/src/Infrastructure/AzureBlob/AzureBlobStorageService.cs @@ -1,22 +1,27 @@ using System; using System.IO; using System.Threading.Tasks; +using Azure; using Azure.Storage.Blobs; using Azure.Storage.Blobs.Models; using Hutopy.Application.Common.Interfaces; using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Logging; namespace Hutopy.Infrastructure.AzureBlob; public class AzureBlobStorageService : IAzureBlobStorageService { private readonly BlobServiceClient _blobServiceClient; + private readonly ILogger _logger; + private readonly long _maxUploadSize = 10 * 1024 * 1024; // 10 MB in bytes - public AzureBlobStorageService(IConfiguration configuration) + + public AzureBlobStorageService(IConfiguration configuration, ILogger logger) { + _logger = logger; var connectionString = configuration["Azure-Blob-Connection-String"] ?? ""; _blobServiceClient = new BlobServiceClient(connectionString); - } /// @@ -29,29 +34,65 @@ public class AzureBlobStorageService : IAzureBlobStorageService /// public async Task UploadFileAsync(string containerName, string blobName, Stream fileStream, string contentType) { - // Get a reference to a container - var containerClient = _blobServiceClient.GetBlobContainerClient(containerName); - - // Create the container if it does not exist - await containerClient.CreateIfNotExistsAsync(); + // Read the file stream into a memory stream to determine the length + // WATCH FOR MEMORY USAGE USING THE MEMORY STREAM. + var memoryStream = new MemoryStream(); + await fileStream.CopyToAsync(memoryStream); + memoryStream.Position = 0; - // Get a reference to a blob - var blobClient = containerClient.GetBlobClient(blobName); - - // Define the BlobHttpHeaders to include the content type - var blobHttpHeaders = new BlobHttpHeaders + // Check if the file size exceeds the maximum upload size + if (memoryStream.Length > _maxUploadSize) { - ContentType = contentType - }; + _logger.LogInformation($"Blob storage: File size exceeds the maximum allowed size of {_maxUploadSize} bytes."); + throw new InvalidOperationException($"Blob storage: File size exceeds the maximum allowed size of {_maxUploadSize} bytes."); + } + + try + { + // Get a reference to a container + var containerClient = _blobServiceClient.GetBlobContainerClient(containerName); - // Upload the file - await blobClient.UploadAsync(fileStream, new BlobUploadOptions + // Create the container if it does not exist + await containerClient.CreateIfNotExistsAsync(); + + // Get a reference to a blob + var blobClient = containerClient.GetBlobClient(blobName); + + // Define the BlobHttpHeaders to include the content type + var blobHttpHeaders = new BlobHttpHeaders + { + ContentType = contentType + }; + + // Upload the file + var response = await blobClient.UploadAsync(memoryStream, new BlobUploadOptions + { + HttpHeaders = blobHttpHeaders + }); + + var fileUri = blobClient.Uri.ToString(); + + _logger.LogInformation( + $"Blob storage: Status [ {response.GetRawResponse().Status.ToString()} ] " + + $"Uploaded [ {blobName} ] to the container [ {containerName} ] " + + $"with contentType [ {contentType} ] " + + $"with a length of [ {memoryStream.Length} bytes ]" + + $"with the uri [ {fileUri} ]" + ); + + // Return the URI of the uploaded blob + return fileUri; + } + catch (RequestFailedException ex) { - HttpHeaders = blobHttpHeaders - }); - - // Return the URI of the uploaded blob - return blobClient.Uri.ToString(); + _logger.LogError($"Blob storage: Azure Storage request failed: {ex.Message}"); + throw new Exception("Error uploading file to Azure Blob Storage", ex); + } + catch (Exception ex) + { + _logger.LogError($"Blob storage: An error occurred: {ex.Message}"); + throw; + } } /// @@ -62,14 +103,14 @@ public class AzureBlobStorageService : IAzureBlobStorageService /// public async Task DownloadFileAsync(string containerName, string blobName) { - // Get a reference to a container - var containerClient = _blobServiceClient.GetBlobContainerClient(containerName); - - // Get a reference to a blob - var blobClient = containerClient.GetBlobClient(blobName); - try { + // Get a reference to a container + var containerClient = _blobServiceClient.GetBlobContainerClient(containerName); + + // Get a reference to a blob + var blobClient = containerClient.GetBlobClient(blobName); + // Download the blob to a stream BlobDownloadInfo download = await blobClient.DownloadAsync(); MemoryStream memoryStream = new(); @@ -78,9 +119,14 @@ public class AzureBlobStorageService : IAzureBlobStorageService return memoryStream; } + catch (RequestFailedException ex) + { + _logger.LogError($"Azure Storage request failed: {ex.Message}"); + throw new Exception("Error downloading file from Azure Blob Storage", ex); + } catch (Exception ex) { - // Log and handle the exception as needed + _logger.LogError($"An error occurred: {ex.Message}"); throw new ApplicationException("Error downloading file from Azure Blob Storage.", ex); } } diff --git a/src/Web/Endpoints/UpdateMyUser.cs b/src/Web/Endpoints/UpdateMyUser.cs index 8f13133..b26303a 100644 --- a/src/Web/Endpoints/UpdateMyUser.cs +++ b/src/Web/Endpoints/UpdateMyUser.cs @@ -14,24 +14,24 @@ public class UpdateMyUser : EndpointGroupBase .MapPatch("/profile", UpdateCurrentUser); } - private static async Task UpdateCurrentUser(ISender sender, UpdateCurrentUserCommand command) + private static async Task UpdateCurrentUser(ISender sender, UpdateCurrentUserCommand command) { return await sender.Send(command); } - private static async Task UpdateCurrentUserProfilePicture(ISender sender, Stream stream, string url = "") + private static async Task UpdateCurrentUserProfilePicture(ISender sender, Stream stream, string url = "") { var command = new UploadProfilePictureCommand { ProfilePicture = stream, ProfilePictureUrl = url}; return await sender.Send(command); } - private static async Task UpdateCurrentUserBannerPicture(ISender sender, Stream stream, string url = "") + private static async Task UpdateCurrentUserBannerPicture(ISender sender, Stream stream, string url = "") { var command = new UploadBannerPictureCommand { BannerPicture = stream, BannerPictureUrl = url}; return await sender.Send(command); } - private static async Task UpdateCurrentUserWebsiteIcon(ISender sender, Stream stream, string url = "") + private static async Task UpdateCurrentUserWebsiteIcon(ISender sender, Stream stream, string url = "") { var command = new UploadWebsiteIconCommand { WebsiteIcon = stream, WebsitePictureUrl = url}; return await sender.Send(command); diff --git a/src/Web/Endpoints/Users.cs b/src/Web/Endpoints/Users.cs index 39bc408..bbdeb4c 100644 --- a/src/Web/Endpoints/Users.cs +++ b/src/Web/Endpoints/Users.cs @@ -10,11 +10,10 @@ public class Users : EndpointGroupBase app.MapGroup(this) .MapPost(CreateUser) .MapPost(Login, "/login") - .MapPost(UploadProfilePicture, "/upload-profile-picture") .MapGet(GetUser); } - private static async Task CreateUser(ISender sender, CreateUserCommand command) + private static async Task CreateUser(ISender sender, CreateUserCommand command) { return await sender.Send(command); } @@ -28,11 +27,4 @@ public class Users : EndpointGroupBase { return await sender.Send(command); } - - private static async Task UploadProfilePicture(ISender sender, Stream stream) - { - var command = new UploadProfilePictureCommand { ProfilePicture = stream }; - - return await sender.Send(command); - } } From 0c549fd262e43abf6867a38a5a5e333741a87aa9 Mon Sep 17 00:00:00 2001 From: Dominic Villemure Date: Tue, 9 Jul 2024 23:52:25 -0400 Subject: [PATCH 110/229] Some global using for infra --- src/Infrastructure/GlobalUsings.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Infrastructure/GlobalUsings.cs b/src/Infrastructure/GlobalUsings.cs index 4668da2..f176ce1 100644 --- a/src/Infrastructure/GlobalUsings.cs +++ b/src/Infrastructure/GlobalUsings.cs @@ -1 +1,4 @@ -global using Ardalis.GuardClauses; \ No newline at end of file +global using System; +global using System.Linq; +global using System.Threading; +global using System.Threading.Tasks; From d2c6209954c614099da2c262b17fbb92c4925628 Mon Sep 17 00:00:00 2001 From: Dominic Villemure Date: Wed, 10 Jul 2024 01:38:27 -0400 Subject: [PATCH 111/229] Force contentType from the headers to be .png, .jpeg or .jpg --- .../Constants/CommonFileNames.cs | 6 ++-- .../Constants/ContentTypes.cs | 6 ---- .../Users/Commands/UploadBannerPicture.cs | 26 ++++++----------- .../Users/Commands/UploadProfilePicture.cs | 7 +++-- .../Users/Commands/UploadWebsiteIcon.cs | 7 +++-- .../Utils/HttpContextAccessorExtensions.cs | 29 +++++++++++++++++++ .../AzureBlob/AzureBlobStorageService.cs | 11 ++++--- src/Infrastructure/AzureBlob/ContentTypes.cs | 15 ++++++++++ 8 files changed, 73 insertions(+), 34 deletions(-) delete mode 100644 src/Application/AzureBlobStorage/Constants/ContentTypes.cs create mode 100644 src/Application/Utils/HttpContextAccessorExtensions.cs create mode 100644 src/Infrastructure/AzureBlob/ContentTypes.cs diff --git a/src/Application/AzureBlobStorage/Constants/CommonFileNames.cs b/src/Application/AzureBlobStorage/Constants/CommonFileNames.cs index 8ffc63c..b6d44aa 100644 --- a/src/Application/AzureBlobStorage/Constants/CommonFileNames.cs +++ b/src/Application/AzureBlobStorage/Constants/CommonFileNames.cs @@ -2,7 +2,7 @@ public static class CommonFileNames { - public static string ProfilePicture = "profilePicture.png"; - public static string BannerPicture = "bannerPicture.png"; - public static string WebsiteIcon = "websiteIcon.png"; + public static string ProfilePicture = "profilePicture"; + public static string BannerPicture = "bannerPicture"; + public static string WebsiteIcon = "websiteIcon"; } diff --git a/src/Application/AzureBlobStorage/Constants/ContentTypes.cs b/src/Application/AzureBlobStorage/Constants/ContentTypes.cs deleted file mode 100644 index ff3bcf7..0000000 --- a/src/Application/AzureBlobStorage/Constants/ContentTypes.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace Hutopy.Application.AzureBlobStorage.Constants; - -public static class ContentTypes -{ - public static string ImagePng = "image/png"; -} diff --git a/src/Application/Users/Commands/UploadBannerPicture.cs b/src/Application/Users/Commands/UploadBannerPicture.cs index 96728b8..3bab003 100644 --- a/src/Application/Users/Commands/UploadBannerPicture.cs +++ b/src/Application/Users/Commands/UploadBannerPicture.cs @@ -1,5 +1,6 @@ using Hutopy.Application.AzureBlobStorage.Constants; using Hutopy.Application.Common.Interfaces; +using Hutopy.Application.Utils; using Microsoft.AspNetCore.Http; namespace Hutopy.Application.Users.Commands; @@ -13,10 +14,12 @@ public class UploadBannerPictureCommand : IRequest public string BannerPictureUrl { get; init; } = string.Empty; } -public class UploadBannerPictureCommandHandler(IIdentityService identityService, IAzureBlobStorageService azureBlobStorageService) : IRequestHandler +public class UploadBannerPictureCommandHandler(IHttpContextAccessor contextAccessor, IIdentityService identityService, IAzureBlobStorageService azureBlobStorageService) : IRequestHandler { public async Task Handle(UploadBannerPictureCommand request, CancellationToken cancellationToken) { + var contentType = contextAccessor.EnsureContentType(); + // If an url to the picture is provided, use it right away and don't upload anything. if (!string.IsNullOrEmpty(request.BannerPictureUrl)) { @@ -28,23 +31,12 @@ public class UploadBannerPictureCommandHandler(IIdentityService identityService, var currentUserId = new Guid(identityUser?.Id ?? "").ToString(); var blobName = $"{currentUserId}/{SubDirectoryNames.Profile}/{CommonFileNames.BannerPicture}"; - - try - { - var url = await azureBlobStorageService.UploadFileAsync(ContainerNames.Users, blobName, request.BannerPicture, ContentTypes.ImagePng); - - await identityService.UpdateCurrentUserBannerPictureUrlAsync(url); - return Results.Ok(url); - } - catch (InvalidOperationException ex) - { - return Results.BadRequest(ex.Message); - } - catch (Exception) - { - return Results.StatusCode(StatusCodes.Status500InternalServerError); - } + var url = await azureBlobStorageService.UploadFileAsync(ContainerNames.Users, blobName, request.BannerPicture, contentType); + + await identityService.UpdateCurrentUserBannerPictureUrlAsync(url); + + return Results.Ok(url); } } diff --git a/src/Application/Users/Commands/UploadProfilePicture.cs b/src/Application/Users/Commands/UploadProfilePicture.cs index daefbe7..0dbb394 100644 --- a/src/Application/Users/Commands/UploadProfilePicture.cs +++ b/src/Application/Users/Commands/UploadProfilePicture.cs @@ -1,5 +1,6 @@ using Hutopy.Application.AzureBlobStorage.Constants; using Hutopy.Application.Common.Interfaces; +using Hutopy.Application.Utils; using Microsoft.AspNetCore.Http; namespace Hutopy.Application.Users.Commands; @@ -13,10 +14,12 @@ public class UploadProfilePictureCommand : IRequest public string ProfilePictureUrl { get; init; } = string.Empty; } -public class UploadProfilePictureCommandHandler(IIdentityService identityService, IAzureBlobStorageService azureBlobStorageService) : IRequestHandler +public class UploadProfilePictureCommandHandler(IHttpContextAccessor contextAccessor, IIdentityService identityService, IAzureBlobStorageService azureBlobStorageService) : IRequestHandler { public async Task Handle(UploadProfilePictureCommand request, CancellationToken cancellationToken) { + var contentType = contextAccessor.EnsureContentType(); + // If an url to the picture is provided, use it right away and don't upload anything. if (!string.IsNullOrEmpty(request.ProfilePictureUrl)) { @@ -29,7 +32,7 @@ public class UploadProfilePictureCommandHandler(IIdentityService identityService var blobName = $"{currentUserId}/{SubDirectoryNames.Profile}/{CommonFileNames.ProfilePicture}"; - var url = await azureBlobStorageService.UploadFileAsync(ContainerNames.Users, blobName, request.ProfilePicture, ContentTypes.ImagePng); + var url = await azureBlobStorageService.UploadFileAsync(ContainerNames.Users, blobName, request.ProfilePicture, contentType); await identityService.UpdateCurrentUserProfilePictureUrlAsync(url); diff --git a/src/Application/Users/Commands/UploadWebsiteIcon.cs b/src/Application/Users/Commands/UploadWebsiteIcon.cs index 2c18756..29158b2 100644 --- a/src/Application/Users/Commands/UploadWebsiteIcon.cs +++ b/src/Application/Users/Commands/UploadWebsiteIcon.cs @@ -1,5 +1,6 @@ using Hutopy.Application.AzureBlobStorage.Constants; using Hutopy.Application.Common.Interfaces; +using Hutopy.Application.Utils; using Microsoft.AspNetCore.Http; namespace Hutopy.Application.Users.Commands; @@ -14,10 +15,12 @@ public class UploadWebsiteIconCommand : IRequest public string WebsitePictureUrl { get; init; } = string.Empty; } -public class UploadWebsiteIconCommandHandler(IIdentityService identityService, IAzureBlobStorageService azureBlobStorageService) : IRequestHandler +public class UploadWebsiteIconCommandHandler(IHttpContextAccessor contextAccessor, IIdentityService identityService, IAzureBlobStorageService azureBlobStorageService) : IRequestHandler { public async Task Handle(UploadWebsiteIconCommand request, CancellationToken cancellationToken) { + var contentType = contextAccessor.EnsureContentType(); + // If an url to the picture is provided, use it right away and don't upload anything. if (!string.IsNullOrEmpty(request.WebsitePictureUrl)) { @@ -30,7 +33,7 @@ public class UploadWebsiteIconCommandHandler(IIdentityService identityService, I var blobName = $"{currentUserId}/{SubDirectoryNames.Profile}/{CommonFileNames.WebsiteIcon}"; - var url = await azureBlobStorageService.UploadFileAsync(ContainerNames.Users, blobName, request.WebsiteIcon, ContentTypes.ImagePng); + var url = await azureBlobStorageService.UploadFileAsync(ContainerNames.Users, blobName, request.WebsiteIcon, contentType); await identityService.UpdateCurrentUserWebsiteIconUrlAsync(url); diff --git a/src/Application/Utils/HttpContextAccessorExtensions.cs b/src/Application/Utils/HttpContextAccessorExtensions.cs new file mode 100644 index 0000000..849e1a8 --- /dev/null +++ b/src/Application/Utils/HttpContextAccessorExtensions.cs @@ -0,0 +1,29 @@ +using Microsoft.AspNetCore.Http; + +namespace Hutopy.Application.Utils; + +public static class HttpContextAccessorExtensions +{ + public static HttpContext EnsureHttpContext(this IHttpContextAccessor httpContextAccessor) + { + if (httpContextAccessor.HttpContext == null) + { + throw new InvalidOperationException("HttpContext is null."); + } + + return httpContextAccessor.HttpContext; + } + + public static string EnsureContentType(this IHttpContextAccessor httpContextAccessor) + { + var httpContext = EnsureHttpContext(httpContextAccessor); + var contentType = httpContext.Request.ContentType; + + if (string.IsNullOrEmpty(contentType)) + { + throw new InvalidOperationException("Content-Type header is missing."); + } + + return contentType; + } +} diff --git a/src/Infrastructure/AzureBlob/AzureBlobStorageService.cs b/src/Infrastructure/AzureBlob/AzureBlobStorageService.cs index 275b5a3..a7598a7 100644 --- a/src/Infrastructure/AzureBlob/AzureBlobStorageService.cs +++ b/src/Infrastructure/AzureBlob/AzureBlobStorageService.cs @@ -1,6 +1,3 @@ -using System; -using System.IO; -using System.Threading.Tasks; using Azure; using Azure.Storage.Blobs; using Azure.Storage.Blobs.Models; @@ -16,7 +13,6 @@ public class AzureBlobStorageService : IAzureBlobStorageService private readonly ILogger _logger; private readonly long _maxUploadSize = 10 * 1024 * 1024; // 10 MB in bytes - public AzureBlobStorageService(IConfiguration configuration, ILogger logger) { _logger = logger; @@ -47,6 +43,13 @@ public class AzureBlobStorageService : IAzureBlobStorageService throw new InvalidOperationException($"Blob storage: File size exceeds the maximum allowed size of {_maxUploadSize} bytes."); } + // Validate content type + if (!ContentTypes.IsAllowed(contentType)) + { + _logger.LogInformation($"Blob storage: Unsupported file type {contentType}. Only PNG and JPEG are allowed."); + throw new InvalidOperationException("Unsupported file type. Only PNG and JPEG are allowed."); + } + try { // Get a reference to a container diff --git a/src/Infrastructure/AzureBlob/ContentTypes.cs b/src/Infrastructure/AzureBlob/ContentTypes.cs new file mode 100644 index 0000000..ae4261b --- /dev/null +++ b/src/Infrastructure/AzureBlob/ContentTypes.cs @@ -0,0 +1,15 @@ +namespace Hutopy.Infrastructure.AzureBlob; + +public static class ContentTypes +{ + private static string ImagePng = "image/png"; + private static string ImageJpeg = "image/jpeg"; + private static string ImageJpg = "image/jpg"; + + public static HashSet AllowedContentTypes = new HashSet { ImagePng, ImageJpeg, ImageJpg }; + + public static bool IsAllowed(string contentType) + { + return AllowedContentTypes.Contains(contentType); + } +} From df55125c48d17e9c7d467280be33d549ae12fb0f Mon Sep 17 00:00:00 2001 From: Dominic Villemure Date: Wed, 10 Jul 2024 01:51:08 -0400 Subject: [PATCH 112/229] Look signature for file type --- .../AzureBlob/AzureBlobStorageService.cs | 2 +- src/Infrastructure/AzureBlob/ContentTypes.cs | 25 +++++++++++++++++-- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/src/Infrastructure/AzureBlob/AzureBlobStorageService.cs b/src/Infrastructure/AzureBlob/AzureBlobStorageService.cs index a7598a7..8f12630 100644 --- a/src/Infrastructure/AzureBlob/AzureBlobStorageService.cs +++ b/src/Infrastructure/AzureBlob/AzureBlobStorageService.cs @@ -44,7 +44,7 @@ public class AzureBlobStorageService : IAzureBlobStorageService } // Validate content type - if (!ContentTypes.IsAllowed(contentType)) + if (!ContentTypes.IsAllowed(contentType, memoryStream)) { _logger.LogInformation($"Blob storage: Unsupported file type {contentType}. Only PNG and JPEG are allowed."); throw new InvalidOperationException("Unsupported file type. Only PNG and JPEG are allowed."); diff --git a/src/Infrastructure/AzureBlob/ContentTypes.cs b/src/Infrastructure/AzureBlob/ContentTypes.cs index ae4261b..2637fc9 100644 --- a/src/Infrastructure/AzureBlob/ContentTypes.cs +++ b/src/Infrastructure/AzureBlob/ContentTypes.cs @@ -8,8 +8,29 @@ public static class ContentTypes public static HashSet AllowedContentTypes = new HashSet { ImagePng, ImageJpeg, ImageJpg }; - public static bool IsAllowed(string contentType) + public static bool IsAllowed(string contentType, Stream fileStream) { - return AllowedContentTypes.Contains(contentType); + return IsValidFileType(fileStream) && AllowedContentTypes.Contains(contentType); + } + + private static bool IsValidFileType(Stream fileStream) + { + byte[] buffer = new byte[4]; + fileStream.Read(buffer, 0, buffer.Length); + fileStream.Position = 0; + + // PNG file signature: 89 50 4E 47 (in hex) + if (buffer[0] == 0x89 && buffer[1] == 0x50 && buffer[2] == 0x4E && buffer[3] == 0x47) + { + return true; + } + + // JPEG file signature: FF D8 FF (in hex) + if (buffer[0] == 0xFF && buffer[1] == 0xD8 && buffer[2] == 0xFF) + { + return true; + } + + return false; } } From 9a884d78b6442b03f50a5c9820c39823828c008a Mon Sep 17 00:00:00 2001 From: Dominic Villemure Date: Wed, 10 Jul 2024 01:56:06 -0400 Subject: [PATCH 113/229] Dont check contentType before we know if the url is provided --- src/Application/Users/Commands/UploadBannerPicture.cs | 4 ++-- src/Application/Users/Commands/UploadProfilePicture.cs | 4 ++-- src/Application/Users/Commands/UploadWebsiteIcon.cs | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Application/Users/Commands/UploadBannerPicture.cs b/src/Application/Users/Commands/UploadBannerPicture.cs index 3bab003..be7590f 100644 --- a/src/Application/Users/Commands/UploadBannerPicture.cs +++ b/src/Application/Users/Commands/UploadBannerPicture.cs @@ -18,8 +18,6 @@ public class UploadBannerPictureCommandHandler(IHttpContextAccessor contextAcces { public async Task Handle(UploadBannerPictureCommand request, CancellationToken cancellationToken) { - var contentType = contextAccessor.EnsureContentType(); - // If an url to the picture is provided, use it right away and don't upload anything. if (!string.IsNullOrEmpty(request.BannerPictureUrl)) { @@ -27,6 +25,8 @@ public class UploadBannerPictureCommandHandler(IHttpContextAccessor contextAcces return Results.Ok(request.BannerPictureUrl); } + var contentType = contextAccessor.EnsureContentType(); + var identityUser = await identityService.GetCurrentUserAsync(); var currentUserId = new Guid(identityUser?.Id ?? "").ToString(); diff --git a/src/Application/Users/Commands/UploadProfilePicture.cs b/src/Application/Users/Commands/UploadProfilePicture.cs index 0dbb394..2e017d2 100644 --- a/src/Application/Users/Commands/UploadProfilePicture.cs +++ b/src/Application/Users/Commands/UploadProfilePicture.cs @@ -18,8 +18,6 @@ public class UploadProfilePictureCommandHandler(IHttpContextAccessor contextAcce { public async Task Handle(UploadProfilePictureCommand request, CancellationToken cancellationToken) { - var contentType = contextAccessor.EnsureContentType(); - // If an url to the picture is provided, use it right away and don't upload anything. if (!string.IsNullOrEmpty(request.ProfilePictureUrl)) { @@ -27,6 +25,8 @@ public class UploadProfilePictureCommandHandler(IHttpContextAccessor contextAcce return Results.Ok(request.ProfilePictureUrl); } + var contentType = contextAccessor.EnsureContentType(); + var identityUser = await identityService.GetCurrentUserAsync(); var currentUserId = new Guid(identityUser?.Id ?? "").ToString(); diff --git a/src/Application/Users/Commands/UploadWebsiteIcon.cs b/src/Application/Users/Commands/UploadWebsiteIcon.cs index 29158b2..eaa8cd6 100644 --- a/src/Application/Users/Commands/UploadWebsiteIcon.cs +++ b/src/Application/Users/Commands/UploadWebsiteIcon.cs @@ -19,8 +19,6 @@ public class UploadWebsiteIconCommandHandler(IHttpContextAccessor contextAccesso { public async Task Handle(UploadWebsiteIconCommand request, CancellationToken cancellationToken) { - var contentType = contextAccessor.EnsureContentType(); - // If an url to the picture is provided, use it right away and don't upload anything. if (!string.IsNullOrEmpty(request.WebsitePictureUrl)) { @@ -28,6 +26,8 @@ public class UploadWebsiteIconCommandHandler(IHttpContextAccessor contextAccesso return Results.Ok(request.WebsitePictureUrl); } + var contentType = contextAccessor.EnsureContentType(); + var identityUser = await identityService.GetCurrentUserAsync(); var currentUserId = new Guid(identityUser?.Id ?? "").ToString(); From bc873319039505f7dd322a2686c4fbe6224957bd Mon Sep 17 00:00:00 2001 From: Jonathan Bourdon Date: Wed, 17 Jul 2024 21:47:31 -0400 Subject: [PATCH 114/229] Adds streaming to GetContents --- .../Data/ApplicationDbContextInitializer.cs | 2 +- ...Shared.cs => ClaimsPrincipalExtensions.cs} | 4 +- src/Web/Common/GuidExtensions.cs | 30 ++++++++ src/Web/Common/MissingClaimException.cs | 3 + .../Data/ContentDbContextInitializer.cs | 71 +++++++++++++++++++ src/Web/Contents/DependencyInjection.cs | 18 +++++ src/Web/Contents/Handlers/GetContents.cs | 24 ++++--- .../Contents/Handlers/GetContentsByUser.cs | 28 ++++++-- src/Web/Messages/DependencyInjection.cs | 16 +++++ src/Web/Messages/Handlers/GetMessages.cs | 12 ++-- .../Messages/Handlers/GetMessagesByUser.cs | 13 ++-- src/Web/Program.cs | 22 +++--- 12 files changed, 201 insertions(+), 42 deletions(-) rename src/Web/Common/{Shared.cs => ClaimsPrincipalExtensions.cs} (91%) create mode 100644 src/Web/Common/GuidExtensions.cs create mode 100644 src/Web/Common/MissingClaimException.cs create mode 100644 src/Web/Contents/Data/ContentDbContextInitializer.cs create mode 100644 src/Web/Contents/DependencyInjection.cs create mode 100644 src/Web/Messages/DependencyInjection.cs diff --git a/src/Infrastructure/Data/ApplicationDbContextInitializer.cs b/src/Infrastructure/Data/ApplicationDbContextInitializer.cs index 71abda5..233b97a 100644 --- a/src/Infrastructure/Data/ApplicationDbContextInitializer.cs +++ b/src/Infrastructure/Data/ApplicationDbContextInitializer.cs @@ -14,7 +14,7 @@ namespace Hutopy.Infrastructure.Data; public static class InitializerExtensions { - public static async Task InitialiseDatabaseAsync(this WebApplication app) + public static async Task InitialiseApplicationDatabaseAsync(this WebApplication app) { using var scope = app.Services.CreateScope(); diff --git a/src/Web/Common/Shared.cs b/src/Web/Common/ClaimsPrincipalExtensions.cs similarity index 91% rename from src/Web/Common/Shared.cs rename to src/Web/Common/ClaimsPrincipalExtensions.cs index e36a0ec..3f57da4 100644 --- a/src/Web/Common/Shared.cs +++ b/src/Web/Common/ClaimsPrincipalExtensions.cs @@ -2,8 +2,6 @@ namespace Hutopy.Web.Common; -public class Shared(string claimName) : Exception; - public static class ClaimsPrincipalExtensions { public static Guid GetUserId(this ClaimsPrincipal claims) @@ -30,7 +28,7 @@ public static class ClaimsPrincipalExtensions { var claim = claims.FindFirst(key); - if (claim is null) throw new Shared(key); + if (claim is null) throw new MissingClaimException(key); if (typeof(TValue) == typeof(Guid)) { diff --git a/src/Web/Common/GuidExtensions.cs b/src/Web/Common/GuidExtensions.cs new file mode 100644 index 0000000..d02c4a7 --- /dev/null +++ b/src/Web/Common/GuidExtensions.cs @@ -0,0 +1,30 @@ +using System.Buffers.Binary; +using System.Security.Cryptography; + +namespace Hutopy.Web.Common; + +public static class GuidHelper +{ + // TODO: Delete when NET9 is release! + public static Guid GenerateUuidV7() + { + Span uuidv7 = stackalloc byte[16]; + ulong unixTimeTicks = (ulong)DateTimeOffset.UtcNow.Subtract(DateTimeOffset.UnixEpoch).Ticks; + ulong unixTsMs = (unixTimeTicks & 0x0FFFFFFFFFFFF000) << 4; + ulong unixTsMsVer = unixTsMs | 0b0111UL << 12; + ulong randA = unixTimeTicks & 0x0000000000000FFF; + // merge "unix_ts_ms", "ver" and "rand_a" + ulong hi = unixTsMsVer | randA; + BinaryPrimitives.WriteUInt64BigEndian(uuidv7, hi); + // fill "rand_b" and "var" + RandomNumberGenerator.Fill(uuidv7[8..]); + // set "var" + byte varOctet = uuidv7[8]; + varOctet = (byte)(varOctet & 0b00111111); + varOctet = (byte)(varOctet | 0b10111111); + uuidv7[8] = varOctet; + + var value = Convert.ToHexString(uuidv7); + return Guid.Parse(value); + } +} diff --git a/src/Web/Common/MissingClaimException.cs b/src/Web/Common/MissingClaimException.cs new file mode 100644 index 0000000..266d109 --- /dev/null +++ b/src/Web/Common/MissingClaimException.cs @@ -0,0 +1,3 @@ +namespace Hutopy.Web.Common; + +public class MissingClaimException(string claimName) : Exception; diff --git a/src/Web/Contents/Data/ContentDbContextInitializer.cs b/src/Web/Contents/Data/ContentDbContextInitializer.cs new file mode 100644 index 0000000..b5726ff --- /dev/null +++ b/src/Web/Contents/Data/ContentDbContextInitializer.cs @@ -0,0 +1,71 @@ +using Hutopy.Infrastructure.Identity; +using Hutopy.Web.Common; +using Microsoft.EntityFrameworkCore; + +namespace Hutopy.Web.Contents.Data; + +public static class InitializerExtensions +{ + public static async Task InitialiseContentDatabaseAsync(this WebApplication app, CancellationToken ct = default) + { + using var scope = app.Services.CreateScope(); + + var initializer = scope.ServiceProvider.GetRequiredService(); + + await initializer.InitialiseAsync(ct); + + await initializer.SeedAsync(ct); + } +} + +internal class ContentDbContextInitializer( + ILogger logger, + ApplicationUserManager userManager, + ContentDbContext context) +{ + public async Task InitialiseAsync(CancellationToken ct = default) + { + try + { + await context.Database.MigrateAsync(ct); + } + catch (Exception ex) + { + logger.LogError(ex, "An error occurred while initialising the database."); + throw; + } + } + + public async Task SeedAsync(CancellationToken ct = default) + { + try + { + var administratorUser = await userManager.FindByNameAsync("administrator@localhost"); + var administratorId= Guid.Parse(administratorUser!.Id); + await TrySeedAsync(administratorId, 100, ct); + + await context.SaveChangesAsync(ct); + } + catch (Exception ex) + { + logger.LogError(ex, "An error occurred while seeding the database."); + throw; + } + } + + private async Task TrySeedAsync(Guid creatorId, int contentCount, CancellationToken ct = default) + { + for (var c = 0; c < contentCount; c++) + { + await context.Contents.AddAsync( + new Content + { + Id = GuidHelper.GenerateUuidV7(), + CreatedBy = creatorId, + Title = $"Title {c}", + Description = $"Description {c}" + }, + ct); + } + } +} diff --git a/src/Web/Contents/DependencyInjection.cs b/src/Web/Contents/DependencyInjection.cs new file mode 100644 index 0000000..7946338 --- /dev/null +++ b/src/Web/Contents/DependencyInjection.cs @@ -0,0 +1,18 @@ +using Hutopy.Web.Contents.Data; +using Microsoft.EntityFrameworkCore; + +namespace Hutopy.Web.Contents; + +public static class DependencyInjection +{ + public static IServiceCollection AddContentModule( + this IServiceCollection services, + Action? configureAction = null) + { + services.AddDbContext(configureAction); + + services.AddScoped(); + + return services; + } +} diff --git a/src/Web/Contents/Handlers/GetContents.cs b/src/Web/Contents/Handlers/GetContents.cs index aa73599..26d1348 100644 --- a/src/Web/Contents/Handlers/GetContents.cs +++ b/src/Web/Contents/Handlers/GetContents.cs @@ -4,27 +4,35 @@ using Microsoft.EntityFrameworkCore; namespace Hutopy.Web.Contents.Handlers; +public sealed class GetContentsRequest +{ + public Guid ContentId { get; set; } +} + public class GetContents( ContentDbContext context) - : EndpointWithoutRequest + : Endpoint { public override void Configure() { Get("/api/contents/{ContentId:guid}"); - Options( o => o.WithTags("Contents")); + Options(o => o.WithTags("Contents")); AllowAnonymous(); } public override async Task HandleAsync( + GetContentsRequest req, CancellationToken ct) { - var contentId = Route("ContentId"); - - var comments = await context + var content = await context .Contents - .Where(c => c.Id == contentId) - .ToListAsync(cancellationToken: ct); + .FirstOrDefaultAsync( + c => c.Id == req.ContentId, + cancellationToken: ct); - await SendAsync(comments.First(), cancellation: ct); + if (content is null) + await SendNotFoundAsync(cancellation: ct); + else + await SendAsync(content, cancellation: ct); } } diff --git a/src/Web/Contents/Handlers/GetContentsByUser.cs b/src/Web/Contents/Handlers/GetContentsByUser.cs index 70152af..a5e0a8f 100644 --- a/src/Web/Contents/Handlers/GetContentsByUser.cs +++ b/src/Web/Contents/Handlers/GetContentsByUser.cs @@ -4,26 +4,40 @@ using Microsoft.EntityFrameworkCore; namespace Hutopy.Web.Contents.Handlers; +public sealed class GetContentsByUserRequest +{ + public Guid UserId { get; set; } + [BindFrom("max_items")] public int MaxItems { get; set; } = 10; + [BindFrom("last_id")] public Guid? LastId { get; set; } +} + public class GetContentsByUser( ContentDbContext context) - : EndpointWithoutRequest> + : Endpoint> { public override void Configure() { Get("/api/contents/user/{UserId:guid}"); - Options( o => o.WithTags("Contents")); + Options(o => o.WithTags("Contents")); AllowAnonymous(); } public override async Task HandleAsync( + GetContentsByUserRequest req, CancellationToken ct) { - var userId = Route("UserId"); - - var posts = await context + var query = context .Contents - .Where(c => c.CreatedBy == userId) - .ToListAsync(cancellationToken: ct); + .Where(c => c.CreatedBy == req.UserId); + + if (req.LastId is not null) + query = query.OrderBy(c => c.Id).Where(c => c.Id > req.LastId.Value); + else + query = query.OrderBy(c => c.Id); + + query = query.Take(req.MaxItems); + + var posts = await query.ToListAsync(cancellationToken: ct); await SendAsync(posts, cancellation: ct); } diff --git a/src/Web/Messages/DependencyInjection.cs b/src/Web/Messages/DependencyInjection.cs new file mode 100644 index 0000000..8e89468 --- /dev/null +++ b/src/Web/Messages/DependencyInjection.cs @@ -0,0 +1,16 @@ +using Hutopy.Web.Messages.Data; +using Microsoft.EntityFrameworkCore; + +namespace Hutopy.Web.Messages; + +public static class DependencyInjection +{ + public static IServiceCollection AddMessagingModule( + this IServiceCollection services, + Action? configureAction = null) + { + services.AddDbContext(configureAction); + + return services; + } +} diff --git a/src/Web/Messages/Handlers/GetMessages.cs b/src/Web/Messages/Handlers/GetMessages.cs index 59bb41e..6325548 100644 --- a/src/Web/Messages/Handlers/GetMessages.cs +++ b/src/Web/Messages/Handlers/GetMessages.cs @@ -4,9 +4,14 @@ using Microsoft.EntityFrameworkCore; namespace Hutopy.Web.Messages.Handlers; +public sealed class GetMessagesRequest +{ + public Guid SubjectId { get; set; } +} + public class GetMessages( MessagingDbContext context) - : EndpointWithoutRequest> + : Endpoint> { public override void Configure() { @@ -16,13 +21,12 @@ public class GetMessages( } public override async Task HandleAsync( + GetMessagesRequest req, CancellationToken ct) { - var subjectId = Route("SubjectId"); - var comments = await context .Messages - .Where(c => c.SubjectId == subjectId) + .Where(c => c.SubjectId == req.SubjectId) .ToListAsync(cancellationToken: ct); await SendAsync(comments, cancellation: ct); diff --git a/src/Web/Messages/Handlers/GetMessagesByUser.cs b/src/Web/Messages/Handlers/GetMessagesByUser.cs index 5d101f6..6f1e447 100644 --- a/src/Web/Messages/Handlers/GetMessagesByUser.cs +++ b/src/Web/Messages/Handlers/GetMessagesByUser.cs @@ -1,13 +1,17 @@ using FastEndpoints; using Hutopy.Web.Messages.Data; -using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; namespace Hutopy.Web.Messages.Handlers; +public sealed class GetMessagesByUserRequest +{ + public Guid UserId { get; set; } +} + public class GetMessagesByUser( MessagingDbContext context) - : EndpointWithoutRequest> + : Endpoint> { public override void Configure() { @@ -16,13 +20,12 @@ public class GetMessagesByUser( } public override async Task HandleAsync( + GetMessagesByUserRequest req, CancellationToken ct) { - var userId = Route("UserId"); - var posts = await context .Messages - .Where(c => c.CreatedBy == userId) + .Where(c => c.CreatedBy == req.UserId) .ToListAsync(cancellationToken: ct); await SendAsync(posts, cancellation: ct); diff --git a/src/Web/Program.cs b/src/Web/Program.cs index 3aad5cb..fec1d10 100644 --- a/src/Web/Program.cs +++ b/src/Web/Program.cs @@ -5,8 +5,9 @@ using Hutopy.Infrastructure; using Hutopy.Infrastructure.Data; using Hutopy.Infrastructure.Identity; using Hutopy.Web; +using Hutopy.Web.Contents; using Hutopy.Web.Contents.Data; -using Hutopy.Web.Messages.Data; +using Hutopy.Web.Messages; using Microsoft.AspNetCore.HttpOverrides; using Microsoft.EntityFrameworkCore; using NSwag; @@ -37,7 +38,7 @@ builder.Services.AddCors(options => .AllowAnyHeader() .AllowCredentials(); }); - + options.AddPolicy("AllowHutopyUiPreview", policy => { policy.WithOrigins("https://zealous-bay-08204590f-preview.eastus2.5.azurestaticapps.net") @@ -78,20 +79,12 @@ builder.Services.AddOpenApiDocument((configure, sp) => configure.OperationProcessors.Add(new AspNetCoreOperationSecurityScopeProcessor("JWT")); }); -builder.Services.AddFastEndpoints(); - var connectionString = builder.Configuration.GetConnectionString("DefaultConnection") ?? throw new InvalidOperationException("Missing ConnectionStrings:DefaultConnection"); -builder.Services.AddDbContext((_, options) => -{ - options.UseSqlServer(connectionString); -}); - -builder.Services.AddDbContext((_, options) => -{ - options.UseSqlServer(connectionString); -}); +builder.Services.AddFastEndpoints(); +builder.Services.AddContentModule(options => options.UseSqlServer(connectionString)); +builder.Services.AddMessagingModule(options => options.UseSqlServer(connectionString)); builder.Services.Configure(builder.Configuration.GetRequiredSection(JwtOptions.SectionName)); @@ -109,7 +102,8 @@ app.UseAuthentication(); app.UseAuthorization(); // Initialize and seed the db. -await app.InitialiseDatabaseAsync(); +await app.InitialiseApplicationDatabaseAsync(); +await app.InitialiseContentDatabaseAsync(); // Configure the HTTP request pipeline. if (!app.Environment.IsDevelopment()) From 769586cc15632811332deb885e0378c9f44845ba Mon Sep 17 00:00:00 2001 From: Jonathan Bourdon Date: Thu, 18 Jul 2024 00:02:30 -0400 Subject: [PATCH 115/229] Add azure-pipelines to solution items --- Hutopy.sln | 1 + 1 file changed, 1 insertion(+) diff --git a/Hutopy.sln b/Hutopy.sln index 2fe5931..feb84bd 100644 --- a/Hutopy.sln +++ b/Hutopy.sln @@ -26,6 +26,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution global.json = global.json README.md = README.md start-infrastructure.sh = start-infrastructure.sh + azure-pipelines.yml = azure-pipelines.yml EndProjectSection EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Web", "src\Web\Web.csproj", "{4E4EE20C-F06A-4A1B-851F-C5577796941C}" From a8b7860fd8895b643d4bbb5664ef9b677df12b29 Mon Sep 17 00:00:00 2001 From: Jonathan Bourdon Date: Thu, 18 Jul 2024 00:03:19 -0400 Subject: [PATCH 116/229] Changed database provider to Postgres since it handle UUID/GUID correctly --- Directory.Packages.props | 1 + src/Infrastructure/DependencyInjection.cs | 4 +- src/Web/Contents/Data/Content.cs | 9 ++- .../Contents/Handlers/GetContentsByUser.cs | 4 +- src/Web/Contents/Handlers/PostContent.cs | 1 + .../20240702034957_Initial.Designer.cs | 58 ------------------ ...0707030928_ChangingContentDefaultSchema.cs | 31 ---------- ....cs => 20240718034516_Initial.Designer.cs} | 26 ++++---- ...7_Initial.cs => 20240718034516_Initial.cs} | 19 +++--- .../ContentDbContextModelSnapshot.cs | 22 +++---- src/Web/Messages/Data/Message.cs | 4 +- src/Web/Messages/Data/MessagingDbContext.cs | 2 +- src/Web/Messages/Handlers/PostMessage.cs | 11 ++-- src/Web/Messages/Handlers/PostReplyMessage.cs | 1 + .../20240627081653_Initial.Designer.cs | 59 ------------------- ...seSubjectId_InsteadOfContentId.Designer.cs | 58 ------------------ ...7023204_UseSubjectId_InsteadOfContentId.cs | 22 ------- ...07030834_ChangingMessagingDefaultSchema.cs | 42 ------------- ....cs => 20240718041130_Initial.Designer.cs} | 26 ++++---- ...3_Initial.cs => 20240718041130_Initial.cs} | 19 +++--- .../MessagingDbContextModelSnapshot.cs | 22 +++---- src/Web/Program.cs | 8 +-- src/Web/Web.csproj | 6 ++ src/Web/appsettings.Development.json | 3 +- .../SqlServerTestDatabase.cs | 2 +- .../appsettings.json | 2 +- 26 files changed, 107 insertions(+), 355 deletions(-) delete mode 100644 src/Web/Contents/Migrations/20240702034957_Initial.Designer.cs delete mode 100644 src/Web/Contents/Migrations/20240707030928_ChangingContentDefaultSchema.cs rename src/Web/Contents/Migrations/{20240707030928_ChangingContentDefaultSchema.Designer.cs => 20240718034516_Initial.Designer.cs} (65%) rename src/Web/Contents/Migrations/{20240702034957_Initial.cs => 20240718034516_Initial.cs} (51%) delete mode 100644 src/Web/Messages/Migrations/20240627081653_Initial.Designer.cs delete mode 100644 src/Web/Messages/Migrations/20240707023204_UseSubjectId_InsteadOfContentId.Designer.cs delete mode 100644 src/Web/Messages/Migrations/20240707023204_UseSubjectId_InsteadOfContentId.cs delete mode 100644 src/Web/Messages/Migrations/20240707030834_ChangingMessagingDefaultSchema.cs rename src/Web/Messages/Migrations/{20240707030834_ChangingMessagingDefaultSchema.Designer.cs => 20240718041130_Initial.Designer.cs} (65%) rename src/Web/Messages/Migrations/{20240627081653_Initial.cs => 20240718041130_Initial.cs} (51%) diff --git a/Directory.Packages.props b/Directory.Packages.props index 3c60acd..be8b079 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -37,6 +37,7 @@ + diff --git a/src/Infrastructure/DependencyInjection.cs b/src/Infrastructure/DependencyInjection.cs index 4aae695..c4abf71 100644 --- a/src/Infrastructure/DependencyInjection.cs +++ b/src/Infrastructure/DependencyInjection.cs @@ -21,8 +21,8 @@ public static class DependencyInjection { // 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") - ?? throw new InvalidOperationException("Missing ConnectionString: DefaultConnection"); + var connectionString = configuration.GetConnectionString("MssqlConnection") + ?? throw new InvalidOperationException("Missing ConnectionStrings:MssqlConnection"); services.AddScoped(); services.AddScoped(); diff --git a/src/Web/Contents/Data/Content.cs b/src/Web/Contents/Data/Content.cs index c13bd0b..b67a92f 100644 --- a/src/Web/Contents/Data/Content.cs +++ b/src/Web/Contents/Data/Content.cs @@ -4,10 +4,9 @@ public class Content { public Guid Id { get; init; } public Guid CreatedBy { get; init; } - public DateTime CreatedAt { get; } + public DateTimeOffset CreatedAt { get; } - public string? Title { get; init; } = null!; - public string? Description { get; init; } = null!; - public string? Uri { get; init; } = null!; + public string? Title { get; init; } + public string? Description { get; init; } + public string? Uri { get; init; } } - diff --git a/src/Web/Contents/Handlers/GetContentsByUser.cs b/src/Web/Contents/Handlers/GetContentsByUser.cs index a5e0a8f..50cb478 100644 --- a/src/Web/Contents/Handlers/GetContentsByUser.cs +++ b/src/Web/Contents/Handlers/GetContentsByUser.cs @@ -31,9 +31,9 @@ public class GetContentsByUser( .Where(c => c.CreatedBy == req.UserId); if (req.LastId is not null) - query = query.OrderBy(c => c.Id).Where(c => c.Id > req.LastId.Value); + query = query.OrderByDescending(c => c.Id).Where(c => c.Id < req.LastId.Value); else - query = query.OrderBy(c => c.Id); + query = query.OrderByDescending(c => c.Id); query = query.Take(req.MaxItems); diff --git a/src/Web/Contents/Handlers/PostContent.cs b/src/Web/Contents/Handlers/PostContent.cs index fd8ecbd..e741c18 100644 --- a/src/Web/Contents/Handlers/PostContent.cs +++ b/src/Web/Contents/Handlers/PostContent.cs @@ -26,6 +26,7 @@ public class PostContent( await context.Contents.AddAsync( new Content { + Id = GuidHelper.GenerateUuidV7(), CreatedBy = User.GetUserId(), Title = req.Title, Description = req.Description, diff --git a/src/Web/Contents/Migrations/20240702034957_Initial.Designer.cs b/src/Web/Contents/Migrations/20240702034957_Initial.Designer.cs deleted file mode 100644 index c63f6b4..0000000 --- a/src/Web/Contents/Migrations/20240702034957_Initial.Designer.cs +++ /dev/null @@ -1,58 +0,0 @@ -// -using System; -using Hutopy.Web.Contents.Data; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -#nullable disable - -namespace Hutopy.Web.Contents.Migrations -{ - [DbContext(typeof(ContentDbContext))] - [Migration("20240702034957_Initial")] - partial class Initial - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "8.0.3") - .HasAnnotation("Relational:MaxIdentifierLength", 128); - - SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); - - modelBuilder.Entity("Hutopy.Web.Contents.Data.Content", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uniqueidentifier"); - - b.Property("CreatedAt") - .ValueGeneratedOnAdd() - .HasColumnType("datetime2") - .HasDefaultValueSql("CURRENT_TIMESTAMP"); - - b.Property("CreatedBy") - .HasColumnType("uniqueidentifier"); - - b.Property("Description") - .HasColumnType("nvarchar(max)"); - - b.Property("Title") - .HasColumnType("nvarchar(max)"); - - b.Property("Uri") - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.ToTable("Contents"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Web/Contents/Migrations/20240707030928_ChangingContentDefaultSchema.cs b/src/Web/Contents/Migrations/20240707030928_ChangingContentDefaultSchema.cs deleted file mode 100644 index df1bb9f..0000000 --- a/src/Web/Contents/Migrations/20240707030928_ChangingContentDefaultSchema.cs +++ /dev/null @@ -1,31 +0,0 @@ -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace Hutopy.Web.Contents.Migrations -{ - /// - public partial class ChangingContentDefaultSchema : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.EnsureSchema( - name: "Content"); - - migrationBuilder.RenameTable( - name: "Contents", - newName: "Contents", - newSchema: "Content"); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.RenameTable( - name: "Contents", - schema: "Content", - newName: "Contents"); - } - } -} diff --git a/src/Web/Contents/Migrations/20240707030928_ChangingContentDefaultSchema.Designer.cs b/src/Web/Contents/Migrations/20240718034516_Initial.Designer.cs similarity index 65% rename from src/Web/Contents/Migrations/20240707030928_ChangingContentDefaultSchema.Designer.cs rename to src/Web/Contents/Migrations/20240718034516_Initial.Designer.cs index 2555444..9fb4610 100644 --- a/src/Web/Contents/Migrations/20240707030928_ChangingContentDefaultSchema.Designer.cs +++ b/src/Web/Contents/Migrations/20240718034516_Initial.Designer.cs @@ -3,17 +3,17 @@ using System; using Hutopy.Web.Contents.Data; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; #nullable disable namespace Hutopy.Web.Contents.Migrations { [DbContext(typeof(ContentDbContext))] - [Migration("20240707030928_ChangingContentDefaultSchema")] - partial class ChangingContentDefaultSchema + [Migration("20240718034516_Initial")] + partial class Initial { /// protected override void BuildTargetModel(ModelBuilder modelBuilder) @@ -21,33 +21,33 @@ namespace Hutopy.Web.Contents.Migrations #pragma warning disable 612, 618 modelBuilder .HasDefaultSchema("Content") - .HasAnnotation("ProductVersion", "8.0.3") - .HasAnnotation("Relational:MaxIdentifierLength", 128); + .HasAnnotation("ProductVersion", "8.0.4") + .HasAnnotation("Relational:MaxIdentifierLength", 63); - SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); modelBuilder.Entity("Hutopy.Web.Contents.Data.Content", b => { b.Property("Id") .ValueGeneratedOnAdd() - .HasColumnType("uniqueidentifier"); + .HasColumnType("uuid"); - b.Property("CreatedAt") + b.Property("CreatedAt") .ValueGeneratedOnAdd() - .HasColumnType("datetime2") + .HasColumnType("timestamp with time zone") .HasDefaultValueSql("CURRENT_TIMESTAMP"); b.Property("CreatedBy") - .HasColumnType("uniqueidentifier"); + .HasColumnType("uuid"); b.Property("Description") - .HasColumnType("nvarchar(max)"); + .HasColumnType("text"); b.Property("Title") - .HasColumnType("nvarchar(max)"); + .HasColumnType("text"); b.Property("Uri") - .HasColumnType("nvarchar(max)"); + .HasColumnType("text"); b.HasKey("Id"); diff --git a/src/Web/Contents/Migrations/20240702034957_Initial.cs b/src/Web/Contents/Migrations/20240718034516_Initial.cs similarity index 51% rename from src/Web/Contents/Migrations/20240702034957_Initial.cs rename to src/Web/Contents/Migrations/20240718034516_Initial.cs index 593cc49..d2ed5d8 100644 --- a/src/Web/Contents/Migrations/20240702034957_Initial.cs +++ b/src/Web/Contents/Migrations/20240718034516_Initial.cs @@ -11,16 +11,20 @@ namespace Hutopy.Web.Contents.Migrations /// protected override void Up(MigrationBuilder migrationBuilder) { + migrationBuilder.EnsureSchema( + name: "Content"); + migrationBuilder.CreateTable( name: "Contents", + schema: "Content", columns: table => new { - Id = table.Column(type: "uniqueidentifier", nullable: false), - CreatedBy = table.Column(type: "uniqueidentifier", nullable: false), - CreatedAt = table.Column(type: "datetime2", nullable: false, defaultValueSql: "CURRENT_TIMESTAMP"), - Title = table.Column(type: "nvarchar(max)", nullable: true), - Description = table.Column(type: "nvarchar(max)", nullable: true), - Uri = table.Column(type: "nvarchar(max)", nullable: true) + Id = table.Column(type: "uuid", nullable: false), + CreatedBy = table.Column(type: "uuid", nullable: false), + CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, defaultValueSql: "CURRENT_TIMESTAMP"), + Title = table.Column(type: "text", nullable: true), + Description = table.Column(type: "text", nullable: true), + Uri = table.Column(type: "text", nullable: true) }, constraints: table => { @@ -32,7 +36,8 @@ namespace Hutopy.Web.Contents.Migrations protected override void Down(MigrationBuilder migrationBuilder) { migrationBuilder.DropTable( - name: "Contents"); + name: "Contents", + schema: "Content"); } } } diff --git a/src/Web/Contents/Migrations/ContentDbContextModelSnapshot.cs b/src/Web/Contents/Migrations/ContentDbContextModelSnapshot.cs index 4f2d601..5a7fbbf 100644 --- a/src/Web/Contents/Migrations/ContentDbContextModelSnapshot.cs +++ b/src/Web/Contents/Migrations/ContentDbContextModelSnapshot.cs @@ -3,8 +3,8 @@ using System; using Hutopy.Web.Contents.Data; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; #nullable disable @@ -18,33 +18,33 @@ namespace Hutopy.Web.Contents.Migrations #pragma warning disable 612, 618 modelBuilder .HasDefaultSchema("Content") - .HasAnnotation("ProductVersion", "8.0.3") - .HasAnnotation("Relational:MaxIdentifierLength", 128); + .HasAnnotation("ProductVersion", "8.0.4") + .HasAnnotation("Relational:MaxIdentifierLength", 63); - SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); modelBuilder.Entity("Hutopy.Web.Contents.Data.Content", b => { b.Property("Id") .ValueGeneratedOnAdd() - .HasColumnType("uniqueidentifier"); + .HasColumnType("uuid"); - b.Property("CreatedAt") + b.Property("CreatedAt") .ValueGeneratedOnAdd() - .HasColumnType("datetime2") + .HasColumnType("timestamp with time zone") .HasDefaultValueSql("CURRENT_TIMESTAMP"); b.Property("CreatedBy") - .HasColumnType("uniqueidentifier"); + .HasColumnType("uuid"); b.Property("Description") - .HasColumnType("nvarchar(max)"); + .HasColumnType("text"); b.Property("Title") - .HasColumnType("nvarchar(max)"); + .HasColumnType("text"); b.Property("Uri") - .HasColumnType("nvarchar(max)"); + .HasColumnType("text"); b.HasKey("Id"); diff --git a/src/Web/Messages/Data/Message.cs b/src/Web/Messages/Data/Message.cs index 3baf749..09d3b6b 100644 --- a/src/Web/Messages/Data/Message.cs +++ b/src/Web/Messages/Data/Message.cs @@ -5,7 +5,7 @@ public class Message public Guid Id { get; init; } public Guid SubjectId { get; init; } public Guid CreatedBy { get; init; } - public DateTime CreatedAt { get; } + public DateTimeOffset CreatedAt { get; } public Guid ParentId { get; init; } - public string Value { get; init; } = null!; + public string Value { get; init; } } diff --git a/src/Web/Messages/Data/MessagingDbContext.cs b/src/Web/Messages/Data/MessagingDbContext.cs index e343a2b..7674b30 100644 --- a/src/Web/Messages/Data/MessagingDbContext.cs +++ b/src/Web/Messages/Data/MessagingDbContext.cs @@ -17,5 +17,5 @@ public class MessagingDbContext( .HasDefaultValueSql("CURRENT_TIMESTAMP"); } - public DbSet Messages { get; set; } + public DbSet Messages { get; set; } } diff --git a/src/Web/Messages/Handlers/PostMessage.cs b/src/Web/Messages/Handlers/PostMessage.cs index d5d9202..65d7882 100644 --- a/src/Web/Messages/Handlers/PostMessage.cs +++ b/src/Web/Messages/Handlers/PostMessage.cs @@ -23,10 +23,13 @@ public class PostMessage( CancellationToken ct) { await context.Messages.AddAsync( - new Message { - SubjectId = req.SubjectId, - CreatedBy = User.GetUserId(), - Value = req.Message }, + new Message + { + Id = GuidHelper.GenerateUuidV7(), + SubjectId = req.SubjectId, + CreatedBy = User.GetUserId(), + Value = req.Message + }, ct); await context.SaveChangesAsync(ct); diff --git a/src/Web/Messages/Handlers/PostReplyMessage.cs b/src/Web/Messages/Handlers/PostReplyMessage.cs index 975da57..6e7b995 100644 --- a/src/Web/Messages/Handlers/PostReplyMessage.cs +++ b/src/Web/Messages/Handlers/PostReplyMessage.cs @@ -26,6 +26,7 @@ public sealed class PostReplyMessage( await context.Messages.AddAsync( new Message { + Id = GuidHelper.GenerateUuidV7(), SubjectId = req.SubjectId, ParentId = req.ParentId, CreatedBy = User.GetUserId(), diff --git a/src/Web/Messages/Migrations/20240627081653_Initial.Designer.cs b/src/Web/Messages/Migrations/20240627081653_Initial.Designer.cs deleted file mode 100644 index 72d8e1c..0000000 --- a/src/Web/Messages/Migrations/20240627081653_Initial.Designer.cs +++ /dev/null @@ -1,59 +0,0 @@ -// -using System; -using Hutopy.Web.Messages.Data; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -#nullable disable - -namespace Hutopy.Web.Messages.Migrations -{ - [DbContext(typeof(MessagingDbContext))] - [Migration("20240627081653_Initial")] - partial class Initial - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "8.0.3") - .HasAnnotation("Relational:MaxIdentifierLength", 128); - - SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); - - modelBuilder.Entity("Hutopy.Web.Messages.Data.Message", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uniqueidentifier"); - - b.Property("ContentId") - .HasColumnType("uniqueidentifier"); - - b.Property("CreatedAt") - .ValueGeneratedOnAdd() - .HasColumnType("datetime2") - .HasDefaultValueSql("CURRENT_TIMESTAMP"); - - b.Property("CreatedBy") - .HasColumnType("uniqueidentifier"); - - b.Property("ParentId") - .HasColumnType("uniqueidentifier"); - - b.Property("Value") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.ToTable("Messages"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Web/Messages/Migrations/20240707023204_UseSubjectId_InsteadOfContentId.Designer.cs b/src/Web/Messages/Migrations/20240707023204_UseSubjectId_InsteadOfContentId.Designer.cs deleted file mode 100644 index 86ed4f1..0000000 --- a/src/Web/Messages/Migrations/20240707023204_UseSubjectId_InsteadOfContentId.Designer.cs +++ /dev/null @@ -1,58 +0,0 @@ -// -using System; -using Hutopy.Web.Contents.Data; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -#nullable disable - -namespace Hutopy.Web.Messages.Migrations -{ - [DbContext(typeof(ContentDbContext))] - [Migration("20240707023204_UseSubjectId_InsteadOfContentId")] - partial class UseSubjectId_InsteadOfContentId - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "8.0.3") - .HasAnnotation("Relational:MaxIdentifierLength", 128); - - SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); - - modelBuilder.Entity("Hutopy.Web.Contents.Data.Content", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uniqueidentifier"); - - b.Property("CreatedAt") - .ValueGeneratedOnAdd() - .HasColumnType("datetime2") - .HasDefaultValueSql("CURRENT_TIMESTAMP"); - - b.Property("CreatedBy") - .HasColumnType("uniqueidentifier"); - - b.Property("Description") - .HasColumnType("nvarchar(max)"); - - b.Property("Title") - .HasColumnType("nvarchar(max)"); - - b.Property("Uri") - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.ToTable("Contents"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Web/Messages/Migrations/20240707023204_UseSubjectId_InsteadOfContentId.cs b/src/Web/Messages/Migrations/20240707023204_UseSubjectId_InsteadOfContentId.cs deleted file mode 100644 index 760efd1..0000000 --- a/src/Web/Messages/Migrations/20240707023204_UseSubjectId_InsteadOfContentId.cs +++ /dev/null @@ -1,22 +0,0 @@ -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace Hutopy.Web.Messages.Migrations -{ - /// - public partial class UseSubjectId_InsteadOfContentId : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - - } - } -} diff --git a/src/Web/Messages/Migrations/20240707030834_ChangingMessagingDefaultSchema.cs b/src/Web/Messages/Migrations/20240707030834_ChangingMessagingDefaultSchema.cs deleted file mode 100644 index c788df7..0000000 --- a/src/Web/Messages/Migrations/20240707030834_ChangingMessagingDefaultSchema.cs +++ /dev/null @@ -1,42 +0,0 @@ -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace Hutopy.Web.Messages.Migrations -{ - /// - public partial class ChangingMessagingDefaultSchema : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.EnsureSchema( - name: "Messaging"); - - migrationBuilder.RenameTable( - name: "Messages", - newName: "Messages", - newSchema: "Messaging"); - - migrationBuilder.RenameColumn( - name: "ContentId", - schema: "Messaging", - table: "Messages", - newName: "SubjectId"); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.RenameTable( - name: "Messages", - schema: "Messaging", - newName: "Messages"); - - migrationBuilder.RenameColumn( - name: "SubjectId", - table: "Messages", - newName: "ContentId"); - } - } -} diff --git a/src/Web/Messages/Migrations/20240707030834_ChangingMessagingDefaultSchema.Designer.cs b/src/Web/Messages/Migrations/20240718041130_Initial.Designer.cs similarity index 65% rename from src/Web/Messages/Migrations/20240707030834_ChangingMessagingDefaultSchema.Designer.cs rename to src/Web/Messages/Migrations/20240718041130_Initial.Designer.cs index dacf0b2..c375b1b 100644 --- a/src/Web/Messages/Migrations/20240707030834_ChangingMessagingDefaultSchema.Designer.cs +++ b/src/Web/Messages/Migrations/20240718041130_Initial.Designer.cs @@ -3,17 +3,17 @@ using System; using Hutopy.Web.Messages.Data; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; #nullable disable namespace Hutopy.Web.Messages.Migrations { [DbContext(typeof(MessagingDbContext))] - [Migration("20240707030834_ChangingMessagingDefaultSchema")] - partial class ChangingMessagingDefaultSchema + [Migration("20240718041130_Initial")] + partial class Initial { /// protected override void BuildTargetModel(ModelBuilder modelBuilder) @@ -21,34 +21,34 @@ namespace Hutopy.Web.Messages.Migrations #pragma warning disable 612, 618 modelBuilder .HasDefaultSchema("Messaging") - .HasAnnotation("ProductVersion", "8.0.3") - .HasAnnotation("Relational:MaxIdentifierLength", 128); + .HasAnnotation("ProductVersion", "8.0.4") + .HasAnnotation("Relational:MaxIdentifierLength", 63); - SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); modelBuilder.Entity("Hutopy.Web.Messages.Data.Message", b => { b.Property("Id") .ValueGeneratedOnAdd() - .HasColumnType("uniqueidentifier"); + .HasColumnType("uuid"); - b.Property("CreatedAt") + b.Property("CreatedAt") .ValueGeneratedOnAdd() - .HasColumnType("datetime2") + .HasColumnType("timestamp with time zone") .HasDefaultValueSql("CURRENT_TIMESTAMP"); b.Property("CreatedBy") - .HasColumnType("uniqueidentifier"); + .HasColumnType("uuid"); b.Property("ParentId") - .HasColumnType("uniqueidentifier"); + .HasColumnType("uuid"); b.Property("SubjectId") - .HasColumnType("uniqueidentifier"); + .HasColumnType("uuid"); b.Property("Value") .IsRequired() - .HasColumnType("nvarchar(max)"); + .HasColumnType("text"); b.HasKey("Id"); diff --git a/src/Web/Messages/Migrations/20240627081653_Initial.cs b/src/Web/Messages/Migrations/20240718041130_Initial.cs similarity index 51% rename from src/Web/Messages/Migrations/20240627081653_Initial.cs rename to src/Web/Messages/Migrations/20240718041130_Initial.cs index bd5664e..fbb3817 100644 --- a/src/Web/Messages/Migrations/20240627081653_Initial.cs +++ b/src/Web/Messages/Migrations/20240718041130_Initial.cs @@ -11,16 +11,20 @@ namespace Hutopy.Web.Messages.Migrations /// protected override void Up(MigrationBuilder migrationBuilder) { + migrationBuilder.EnsureSchema( + name: "Messaging"); + migrationBuilder.CreateTable( name: "Messages", + schema: "Messaging", columns: table => new { - Id = table.Column(type: "uniqueidentifier", nullable: false), - ContentId = table.Column(type: "uniqueidentifier", nullable: false), - CreatedBy = table.Column(type: "uniqueidentifier", nullable: false), - CreatedAt = table.Column(type: "datetime2", nullable: false, defaultValueSql: "CURRENT_TIMESTAMP"), - ParentId = table.Column(type: "uniqueidentifier", nullable: false), - Value = table.Column(type: "nvarchar(max)", nullable: false) + Id = table.Column(type: "uuid", nullable: false), + SubjectId = table.Column(type: "uuid", nullable: false), + CreatedBy = table.Column(type: "uuid", nullable: false), + CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, defaultValueSql: "CURRENT_TIMESTAMP"), + ParentId = table.Column(type: "uuid", nullable: false), + Value = table.Column(type: "text", nullable: false) }, constraints: table => { @@ -32,7 +36,8 @@ namespace Hutopy.Web.Messages.Migrations protected override void Down(MigrationBuilder migrationBuilder) { migrationBuilder.DropTable( - name: "Messages"); + name: "Messages", + schema: "Messaging"); } } } diff --git a/src/Web/Messages/Migrations/MessagingDbContextModelSnapshot.cs b/src/Web/Messages/Migrations/MessagingDbContextModelSnapshot.cs index dcaa429..64c03fb 100644 --- a/src/Web/Messages/Migrations/MessagingDbContextModelSnapshot.cs +++ b/src/Web/Messages/Migrations/MessagingDbContextModelSnapshot.cs @@ -3,8 +3,8 @@ using System; using Hutopy.Web.Messages.Data; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; #nullable disable @@ -18,34 +18,34 @@ namespace Hutopy.Web.Messages.Migrations #pragma warning disable 612, 618 modelBuilder .HasDefaultSchema("Messaging") - .HasAnnotation("ProductVersion", "8.0.3") - .HasAnnotation("Relational:MaxIdentifierLength", 128); + .HasAnnotation("ProductVersion", "8.0.4") + .HasAnnotation("Relational:MaxIdentifierLength", 63); - SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); modelBuilder.Entity("Hutopy.Web.Messages.Data.Message", b => { b.Property("Id") .ValueGeneratedOnAdd() - .HasColumnType("uniqueidentifier"); + .HasColumnType("uuid"); - b.Property("CreatedAt") + b.Property("CreatedAt") .ValueGeneratedOnAdd() - .HasColumnType("datetime2") + .HasColumnType("timestamp with time zone") .HasDefaultValueSql("CURRENT_TIMESTAMP"); b.Property("CreatedBy") - .HasColumnType("uniqueidentifier"); + .HasColumnType("uuid"); b.Property("ParentId") - .HasColumnType("uniqueidentifier"); + .HasColumnType("uuid"); b.Property("SubjectId") - .HasColumnType("uniqueidentifier"); + .HasColumnType("uuid"); b.Property("Value") .IsRequired() - .HasColumnType("nvarchar(max)"); + .HasColumnType("text"); b.HasKey("Id"); diff --git a/src/Web/Program.cs b/src/Web/Program.cs index fec1d10..3698029 100644 --- a/src/Web/Program.cs +++ b/src/Web/Program.cs @@ -79,12 +79,12 @@ builder.Services.AddOpenApiDocument((configure, sp) => configure.OperationProcessors.Add(new AspNetCoreOperationSecurityScopeProcessor("JWT")); }); -var connectionString = builder.Configuration.GetConnectionString("DefaultConnection") - ?? throw new InvalidOperationException("Missing ConnectionStrings:DefaultConnection"); +var postgresConnectionString = builder.Configuration.GetConnectionString("PostgresConnection") + ?? throw new InvalidOperationException("Missing ConnectionStrings:PostgresConnection"); builder.Services.AddFastEndpoints(); -builder.Services.AddContentModule(options => options.UseSqlServer(connectionString)); -builder.Services.AddMessagingModule(options => options.UseSqlServer(connectionString)); +builder.Services.AddContentModule(options => options.UseNpgsql(postgresConnectionString)); +builder.Services.AddMessagingModule(options => options.UseNpgsql(postgresConnectionString)); builder.Services.Configure(builder.Configuration.GetRequiredSection(JwtOptions.SectionName)); diff --git a/src/Web/Web.csproj b/src/Web/Web.csproj index 817e221..761a54d 100644 --- a/src/Web/Web.csproj +++ b/src/Web/Web.csproj @@ -22,6 +22,7 @@ + runtime; build; native; contentfiles; analyzers; buildtransitive @@ -30,4 +31,9 @@ + + + + + diff --git a/src/Web/appsettings.Development.json b/src/Web/appsettings.Development.json index d249e8e..f7ec248 100644 --- a/src/Web/appsettings.Development.json +++ b/src/Web/appsettings.Development.json @@ -8,7 +8,8 @@ } }, "ConnectionStrings": { - "DefaultConnection": "Server=localhost,1433;Initial Catalog=Hutopy;User Id=sa;Password=P@ssword123!;MultipleActiveResultSets=true;TrustServerCertificate=True;MultiSubnetFailover=True" + "MssqlConnection": "Server=localhost,1433;Initial Catalog=Hutopy;User Id=sa;Password=P@ssword123!;MultipleActiveResultSets=true;TrustServerCertificate=True;MultiSubnetFailover=True", + "PostgresConnection": "Server=localhost,5432;Database=Hutopy;Uid=sa;Pwd=P@ssword123!;" }, "Authentication": { "Jwt": { diff --git a/tests/Application.FunctionalTests/SqlServerTestDatabase.cs b/tests/Application.FunctionalTests/SqlServerTestDatabase.cs index 57e7acc..bd88b6d 100644 --- a/tests/Application.FunctionalTests/SqlServerTestDatabase.cs +++ b/tests/Application.FunctionalTests/SqlServerTestDatabase.cs @@ -20,7 +20,7 @@ public class SqlServerTestDatabase : ITestDatabase .AddEnvironmentVariables() .Build(); - var connectionString = configuration.GetConnectionString("DefaultConnection"); + var connectionString = configuration.GetConnectionString("MssqlConnection"); Guard.Against.Null(connectionString); diff --git a/tests/Application.FunctionalTests/appsettings.json b/tests/Application.FunctionalTests/appsettings.json index ea0855a..31e3e45 100644 --- a/tests/Application.FunctionalTests/appsettings.json +++ b/tests/Application.FunctionalTests/appsettings.json @@ -1,5 +1,5 @@ { "ConnectionStrings": { - "DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=HutopyTestDb;Trusted_Connection=True;MultipleActiveResultSets=true" + "MssqlConnection": "Server=(localdb)\\mssqllocaldb;Database=HutopyTestDb;Trusted_Connection=True;MultipleActiveResultSets=true" } } From ed8f41cf96783a296f767703276b78747351900e Mon Sep 17 00:00:00 2001 From: Jonathan Bourdon Date: Thu, 18 Jul 2024 13:19:40 -0400 Subject: [PATCH 117/229] Changed the way the test-data is generated --- .../Data/ApplicationDbContextInitializer.cs | 51 +---- .../Data/ContentDbContextInitializer.cs | 71 ------- src/Web/Contents/DependencyInjection.cs | 2 - src/Web/Program.cs | 3 +- src/Web/TestDataSeeder.cs | 201 ++++++++++++++++++ 5 files changed, 203 insertions(+), 125 deletions(-) delete mode 100644 src/Web/Contents/Data/ContentDbContextInitializer.cs create mode 100644 src/Web/TestDataSeeder.cs diff --git a/src/Infrastructure/Data/ApplicationDbContextInitializer.cs b/src/Infrastructure/Data/ApplicationDbContextInitializer.cs index 233b97a..ef35783 100644 --- a/src/Infrastructure/Data/ApplicationDbContextInitializer.cs +++ b/src/Infrastructure/Data/ApplicationDbContextInitializer.cs @@ -1,9 +1,4 @@ -using System; -using System.Linq; -using System.Threading.Tasks; -using Hutopy.Domain.Constants; -using Hutopy.Infrastructure.Identity; -using Hutopy.Infrastructure.Identity.OwnedEntities; +using Hutopy.Domain.Constants; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Identity; using Microsoft.EntityFrameworkCore; @@ -29,7 +24,6 @@ public static class InitializerExtensions public class ApplicationDbContextInitializer( ILogger logger, ApplicationDbContext context, - ApplicationUserManager userManager, RoleManager roleManager) { public async Task InitialiseAsync() @@ -60,7 +54,6 @@ public class ApplicationDbContextInitializer( private async Task TrySeedAsync() { - // Default roles var administratorRole = new IdentityRole(Roles.Administrator); if (roleManager.Roles.All(r => r.Name != administratorRole.Name)) { @@ -72,47 +65,5 @@ public class ApplicationDbContextInitializer( { await roleManager.CreateAsync(roleCreator); } - - // Default users - var administrator = - new ApplicationUser { UserName = "administrator@localhost", Email = "administrator@localhost" }; - if (userManager.Users.All(u => u.UserName != administrator.UserName)) - { - await userManager.CreateAsync(administrator, "Administrator1!"); - await userManager.AddToRolesAsync(administrator, new[] { Roles.Administrator }); - } - - // ADD CREATORS - await AddDefaultCreator(new ApplicationUser - { - UserName = "hutopy@localhost", - Email = "hutopy@localhost", - CreatorAlias = "hutopy", - About = "Page officielle", - Description = "Site officiel pour Hutopy. Venez-nous-y retrouver avec tous vos fans!", - EmailConfirmed = true, - ProfileColors = new ProfileColors { BannerTop = "A30E79", BannerBottom = "6B0065", Accent = "23393B", Menu = "53B93B", }, - SocialNetworks = - new SocialNetworks - { - XUrl = "https://twitter.com/Hutopyinc", - FacebookUrl = "https://www.facebook.com/Hutopy", - InstagramUrl = "https://www.instagram.com/hutopy.inc/" - }, - StoredDataUrls = new StoredDataUrls - { - BannerPictureUrl = "/images/usersmedia/HutopyProfile/banners/banner01.png", - ProfilePictureUrl = "/images/usersmedia/HutopyProfile/profilepictures/profileHutopyProfile01.png" - } - }); - } - - private async Task AddDefaultCreator(ApplicationUser hutopy) - { - if (userManager.Users.All(u => u.UserName != hutopy.UserName)) - { - await userManager.CreateAsync(hutopy, "Test123!"); - await userManager.AddToRolesAsync(hutopy, new[] { Roles.Creator }); - } } } diff --git a/src/Web/Contents/Data/ContentDbContextInitializer.cs b/src/Web/Contents/Data/ContentDbContextInitializer.cs deleted file mode 100644 index b5726ff..0000000 --- a/src/Web/Contents/Data/ContentDbContextInitializer.cs +++ /dev/null @@ -1,71 +0,0 @@ -using Hutopy.Infrastructure.Identity; -using Hutopy.Web.Common; -using Microsoft.EntityFrameworkCore; - -namespace Hutopy.Web.Contents.Data; - -public static class InitializerExtensions -{ - public static async Task InitialiseContentDatabaseAsync(this WebApplication app, CancellationToken ct = default) - { - using var scope = app.Services.CreateScope(); - - var initializer = scope.ServiceProvider.GetRequiredService(); - - await initializer.InitialiseAsync(ct); - - await initializer.SeedAsync(ct); - } -} - -internal class ContentDbContextInitializer( - ILogger logger, - ApplicationUserManager userManager, - ContentDbContext context) -{ - public async Task InitialiseAsync(CancellationToken ct = default) - { - try - { - await context.Database.MigrateAsync(ct); - } - catch (Exception ex) - { - logger.LogError(ex, "An error occurred while initialising the database."); - throw; - } - } - - public async Task SeedAsync(CancellationToken ct = default) - { - try - { - var administratorUser = await userManager.FindByNameAsync("administrator@localhost"); - var administratorId= Guid.Parse(administratorUser!.Id); - await TrySeedAsync(administratorId, 100, ct); - - await context.SaveChangesAsync(ct); - } - catch (Exception ex) - { - logger.LogError(ex, "An error occurred while seeding the database."); - throw; - } - } - - private async Task TrySeedAsync(Guid creatorId, int contentCount, CancellationToken ct = default) - { - for (var c = 0; c < contentCount; c++) - { - await context.Contents.AddAsync( - new Content - { - Id = GuidHelper.GenerateUuidV7(), - CreatedBy = creatorId, - Title = $"Title {c}", - Description = $"Description {c}" - }, - ct); - } - } -} diff --git a/src/Web/Contents/DependencyInjection.cs b/src/Web/Contents/DependencyInjection.cs index 7946338..a62df6c 100644 --- a/src/Web/Contents/DependencyInjection.cs +++ b/src/Web/Contents/DependencyInjection.cs @@ -11,8 +11,6 @@ public static class DependencyInjection { services.AddDbContext(configureAction); - services.AddScoped(); - return services; } } diff --git a/src/Web/Program.cs b/src/Web/Program.cs index 3698029..bef36d9 100644 --- a/src/Web/Program.cs +++ b/src/Web/Program.cs @@ -6,7 +6,6 @@ using Hutopy.Infrastructure.Data; using Hutopy.Infrastructure.Identity; using Hutopy.Web; using Hutopy.Web.Contents; -using Hutopy.Web.Contents.Data; using Hutopy.Web.Messages; using Microsoft.AspNetCore.HttpOverrides; using Microsoft.EntityFrameworkCore; @@ -103,7 +102,7 @@ app.UseAuthorization(); // Initialize and seed the db. await app.InitialiseApplicationDatabaseAsync(); -await app.InitialiseContentDatabaseAsync(); +await app.SeedDatabaseWithTestDataOnlyIfNoDataIsPresentAsync(); // Configure the HTTP request pipeline. if (!app.Environment.IsDevelopment()) diff --git a/src/Web/TestDataSeeder.cs b/src/Web/TestDataSeeder.cs new file mode 100644 index 0000000..4e1e7f9 --- /dev/null +++ b/src/Web/TestDataSeeder.cs @@ -0,0 +1,201 @@ +using Hutopy.Domain.Constants; +using Hutopy.Infrastructure.Identity; +using Hutopy.Infrastructure.Identity.OwnedEntities; +using Hutopy.Web.Common; +using Hutopy.Web.Contents.Data; +using Hutopy.Web.Messages.Data; + +namespace Hutopy.Web; + +public static class WebApplicationExtensions +{ + public static async Task SeedDatabaseWithTestDataOnlyIfNoDataIsPresentAsync( + this WebApplication app, + CancellationToken ct = default) + { + using var scope = app.Services.CreateScope(); + + var seeder = new TestDataSeeder( + scope.ServiceProvider.GetRequiredService(), + scope.ServiceProvider.GetRequiredService(), + scope.ServiceProvider.GetRequiredService()); + + await seeder.SeedAsync(); + } +} + +internal class TestDataSeeder( + ApplicationUserManager userManager, + ContentDbContext contentContext, + MessagingDbContext messagingContext) +{ + private const string DefaultPassword = "Test123#"; + + public async Task SeedAsync() + { + if (contentContext.Contents.Any()) return; + + _ = await CreateAdministratorAsync("admin"); + _ = await CreateUserAsync("userA"); + _ = await CreateUserAsync("userB"); + + foreach (var creator in _creators) + { + _ = await CreateCreatorAsync(creator); + + var contents = GenerateContent(creator, 100); + foreach (var content in contents) + { + var messages = GenerateMessages(content, 100); + var parentMessages = messages.Where((_, index) => index % 2 == 0).ToList(); + + foreach (var parentMessage in parentMessages) + { + _ = GenerateReplies(content, parentMessage, 10); + } + + await messagingContext.SaveChangesAsync(); + } + } + } + + private List GenerateContent(ApplicationUser user, int contentCount) + { + var contents = new List(); + + for (var c = 0; c < contentCount; c++) + { + var content = new Content + { + Id = GuidHelper.GenerateUuidV7(), + CreatedBy = Guid.Parse(user.Id), + Title = $"Title {user.UserName}-{c}", + Description = $"Description {user.UserName}-{c}" + }; + + contentContext.Contents.Add(content); + + contents.Add(content); + } + + contentContext.SaveChanges(); + + return contents; + } + + private List GenerateMessages(Content content, int messageCount) + { + var messages = new List(); + + for (var m = 0; m < messageCount; m++) + { + var author = Random.Shared.GetItems(_creators, 1)[0]; + + var message = new Message + { + Id = GuidHelper.GenerateUuidV7(), + SubjectId = content.Id, + CreatedBy = Guid.Parse(author.Id), + Value = $"Message #{m} from {author.UserName} on {content.Title}" + }; + + messagingContext.Messages.Add(message); + + messages.Add(message); + } + + return messages; + } + + private List GenerateReplies(Content content, Message parent, int replyCount) + { + var replies = new List(); + + for (var r = 0; r < replyCount; r++) + { + var author = Random.Shared.GetItems(_creators, 1)[0]; + + var message = new Message + { + Id = GuidHelper.GenerateUuidV7(), + SubjectId = content.Id, + ParentId = parent.Id, + CreatedBy = Guid.Parse(author.Id), + Value = $"Reply {r} to {parent.Value}" + }; + + messagingContext.Messages.Add(message); + + replies.Add(message); + } + + return replies; + } + + private async Task CreateAdministratorAsync(string name) + { + ArgumentException.ThrowIfNullOrWhiteSpace(name); + + var administrator = new ApplicationUser { UserName = $"{name}@test", Email = $"{name}@test" }; + + await userManager.CreateAsync(administrator, DefaultPassword); + await userManager.AddToRolesAsync(administrator, new[] { Roles.Administrator }); + + return administrator; + } + + private async Task CreateUserAsync(string name) + { + var user = new ApplicationUser + { + UserName = $"{name}@test", + Email = $"{name}@test", + EmailConfirmed = true, + FirstName = $"FirstName of {name}", + LastName = $"LastName of {name}" + }; + + await userManager.CreateAsync(user, DefaultPassword); + + return user; + } + + private async Task CreateCreatorAsync(ApplicationUser creator) + { + await userManager.CreateAsync(creator, DefaultPassword); + await userManager.AddToRolesAsync(creator, new[] { Roles.Creator }); + return creator; + } + + + private readonly static ApplicationUser Hutopy = new() + { + UserName = "hutopy@test", + Email = "hutopy@test", + EmailConfirmed = true, + CreatorAlias = "hutopy", + About = "Page officielle", + Description = "Site officiel pour Hutopy. Venez-nous-y retrouver avec tous vos fans!", + ProfileColors = new ProfileColors + { + BannerTop = "A30E79", BannerBottom = "6B0065", Accent = "23393B", Menu = "53B93B", + }, + SocialNetworks = + new SocialNetworks + { + XUrl = "https://twitter.com/Hutopyinc", + FacebookUrl = "https://www.facebook.com/Hutopy", + InstagramUrl = "https://www.instagram.com/hutopy.inc/" + }, + StoredDataUrls = new StoredDataUrls + { + BannerPictureUrl = "/images/usersmedia/HutopyProfile/banners/banner01.png", + ProfilePictureUrl = "/images/usersmedia/HutopyProfile/profilepictures/profileHutopyProfile01.png" + } + }; + + private readonly ApplicationUser[] _creators = + [ + Hutopy + ]; +} From 841daef4d8ff3aae1fbf3fb41b8e3a47dbc9730b Mon Sep 17 00:00:00 2001 From: Jonathan Bourdon Date: Thu, 18 Jul 2024 20:49:05 -0400 Subject: [PATCH 118/229] Adding replies to the Messaging system --- src/Web/Messages/Data/Message.cs | 2 +- src/Web/Messages/Handlers/GetMessages.cs | 3 +- .../Messages/Handlers/GetMessagesByParent.cs | 34 +++++++++++++++++++ .../Messages/Handlers/GetMessagesByUser.cs | 4 ++- src/Web/Messages/Handlers/PostMessage.cs | 26 +++++++------- src/Web/Messages/Handlers/PostReplyMessage.cs | 34 ++++++++++--------- ....cs => 20240718173016_Initial.Designer.cs} | 4 +-- ...0_Initial.cs => 20240718173016_Initial.cs} | 2 +- .../MessagingDbContextModelSnapshot.cs | 2 +- 9 files changed, 76 insertions(+), 35 deletions(-) create mode 100644 src/Web/Messages/Handlers/GetMessagesByParent.cs rename src/Web/Messages/Migrations/{20240718041130_Initial.Designer.cs => 20240718173016_Initial.Designer.cs} (95%) rename src/Web/Messages/Migrations/{20240718041130_Initial.cs => 20240718173016_Initial.cs} (98%) diff --git a/src/Web/Messages/Data/Message.cs b/src/Web/Messages/Data/Message.cs index 09d3b6b..f1255ed 100644 --- a/src/Web/Messages/Data/Message.cs +++ b/src/Web/Messages/Data/Message.cs @@ -6,6 +6,6 @@ public class Message public Guid SubjectId { get; init; } public Guid CreatedBy { get; init; } public DateTimeOffset CreatedAt { get; } - public Guid ParentId { get; init; } + public Guid? ParentId { get; init; } public string Value { get; init; } } diff --git a/src/Web/Messages/Handlers/GetMessages.cs b/src/Web/Messages/Handlers/GetMessages.cs index 6325548..b29c9c4 100644 --- a/src/Web/Messages/Handlers/GetMessages.cs +++ b/src/Web/Messages/Handlers/GetMessages.cs @@ -4,7 +4,7 @@ using Microsoft.EntityFrameworkCore; namespace Hutopy.Web.Messages.Handlers; -public sealed class GetMessagesRequest +public class GetMessagesRequest { public Guid SubjectId { get; set; } } @@ -27,6 +27,7 @@ public class GetMessages( var comments = await context .Messages .Where(c => c.SubjectId == req.SubjectId) + .Where(c => c.ParentId == null) .ToListAsync(cancellationToken: ct); await SendAsync(comments, cancellation: ct); diff --git a/src/Web/Messages/Handlers/GetMessagesByParent.cs b/src/Web/Messages/Handlers/GetMessagesByParent.cs new file mode 100644 index 0000000..39ff534 --- /dev/null +++ b/src/Web/Messages/Handlers/GetMessagesByParent.cs @@ -0,0 +1,34 @@ +using FastEndpoints; +using Hutopy.Web.Messages.Data; +using Microsoft.EntityFrameworkCore; + +namespace Hutopy.Web.Messages.Handlers; + +public class GetMessagesRepliesRequest +{ + public Guid ParentId { get; set; } +} + +public class GetMessagesByParent( + MessagingDbContext context) + : Endpoint> +{ + public override void Configure() + { + Get("/api/messages/{ParentId:guid}/replies"); + Options(o => o.WithTags("Messages")); + AllowAnonymous(); + } + + public override async Task HandleAsync( + GetMessagesRepliesRequest req, + CancellationToken ct) + { + var posts = await context + .Messages + .Where(c => c.ParentId == req.ParentId) + .ToListAsync(cancellationToken: ct); + + await SendAsync(posts, cancellation: ct); + } +} diff --git a/src/Web/Messages/Handlers/GetMessagesByUser.cs b/src/Web/Messages/Handlers/GetMessagesByUser.cs index 6f1e447..c6f6a72 100644 --- a/src/Web/Messages/Handlers/GetMessagesByUser.cs +++ b/src/Web/Messages/Handlers/GetMessagesByUser.cs @@ -4,7 +4,7 @@ using Microsoft.EntityFrameworkCore; namespace Hutopy.Web.Messages.Handlers; -public sealed class GetMessagesByUserRequest +public class GetMessagesByUserRequest { public Guid UserId { get; set; } } @@ -17,6 +17,7 @@ public class GetMessagesByUser( { Get("/api/messages/user/{UserId:guid}"); Options(o => o.WithTags("Messages")); + AllowAnonymous(); } public override async Task HandleAsync( @@ -26,6 +27,7 @@ public class GetMessagesByUser( var posts = await context .Messages .Where(c => c.CreatedBy == req.UserId) + .Where(c => c.ParentId == null) .ToListAsync(cancellationToken: ct); await SendAsync(posts, cancellation: ct); diff --git a/src/Web/Messages/Handlers/PostMessage.cs b/src/Web/Messages/Handlers/PostMessage.cs index 65d7882..a4d5240 100644 --- a/src/Web/Messages/Handlers/PostMessage.cs +++ b/src/Web/Messages/Handlers/PostMessage.cs @@ -4,9 +4,11 @@ using Hutopy.Web.Messages.Data; namespace Hutopy.Web.Messages.Handlers; -public record PostMessageRequest( - Guid SubjectId, - string Message); +public class PostMessageRequest +{ + public Guid SubjectId { get; set; } + public string Message { get; set; } +} public class PostMessage( MessagingDbContext context) @@ -22,15 +24,15 @@ public class PostMessage( PostMessageRequest req, CancellationToken ct) { - await context.Messages.AddAsync( - new Message - { - Id = GuidHelper.GenerateUuidV7(), - SubjectId = req.SubjectId, - CreatedBy = User.GetUserId(), - Value = req.Message - }, - ct); + var message = new Message + { + Id = GuidHelper.GenerateUuidV7(), + SubjectId = req.SubjectId, + CreatedBy = User.GetUserId(), + Value = req.Message + }; + + await context.Messages.AddAsync(message, ct); await context.SaveChangesAsync(ct); } diff --git a/src/Web/Messages/Handlers/PostReplyMessage.cs b/src/Web/Messages/Handlers/PostReplyMessage.cs index 6e7b995..277b3f1 100644 --- a/src/Web/Messages/Handlers/PostReplyMessage.cs +++ b/src/Web/Messages/Handlers/PostReplyMessage.cs @@ -4,18 +4,20 @@ using Hutopy.Web.Messages.Data; namespace Hutopy.Web.Messages.Handlers; -public record PostReplyMessageRequest( - Guid SubjectId, - Guid ParentId, - string Message); +internal sealed class PostReplyMessageRequest +{ + public required Guid SubjectId { get; set; } + public required Guid ParentId { get; set; } + public required string Message { get; set; } +} -public sealed class PostReplyMessage( +internal sealed class PostReplyMessage( MessagingDbContext context) : Endpoint { public override void Configure() { - Post("/api/messages/reply"); + Post("/api/messages/{ParentId:guid}/replies"); Options(o => o.WithTags("Messages")); } @@ -23,16 +25,16 @@ public sealed class PostReplyMessage( PostReplyMessageRequest req, CancellationToken ct) { - await context.Messages.AddAsync( - new Message - { - Id = GuidHelper.GenerateUuidV7(), - SubjectId = req.SubjectId, - ParentId = req.ParentId, - CreatedBy = User.GetUserId(), - Value = req.Message - }, - ct); + var message = new Message + { + Id = GuidHelper.GenerateUuidV7(), + SubjectId = req.SubjectId, + ParentId = req.ParentId, + CreatedBy = User.GetUserId(), + Value = req.Message + }; + + await context.Messages.AddAsync(message, ct); await context.SaveChangesAsync(ct); } diff --git a/src/Web/Messages/Migrations/20240718041130_Initial.Designer.cs b/src/Web/Messages/Migrations/20240718173016_Initial.Designer.cs similarity index 95% rename from src/Web/Messages/Migrations/20240718041130_Initial.Designer.cs rename to src/Web/Messages/Migrations/20240718173016_Initial.Designer.cs index c375b1b..e5d2cf2 100644 --- a/src/Web/Messages/Migrations/20240718041130_Initial.Designer.cs +++ b/src/Web/Messages/Migrations/20240718173016_Initial.Designer.cs @@ -12,7 +12,7 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; namespace Hutopy.Web.Messages.Migrations { [DbContext(typeof(MessagingDbContext))] - [Migration("20240718041130_Initial")] + [Migration("20240718173016_Initial")] partial class Initial { /// @@ -40,7 +40,7 @@ namespace Hutopy.Web.Messages.Migrations b.Property("CreatedBy") .HasColumnType("uuid"); - b.Property("ParentId") + b.Property("ParentId") .HasColumnType("uuid"); b.Property("SubjectId") diff --git a/src/Web/Messages/Migrations/20240718041130_Initial.cs b/src/Web/Messages/Migrations/20240718173016_Initial.cs similarity index 98% rename from src/Web/Messages/Migrations/20240718041130_Initial.cs rename to src/Web/Messages/Migrations/20240718173016_Initial.cs index fbb3817..6a194da 100644 --- a/src/Web/Messages/Migrations/20240718041130_Initial.cs +++ b/src/Web/Messages/Migrations/20240718173016_Initial.cs @@ -23,7 +23,7 @@ namespace Hutopy.Web.Messages.Migrations SubjectId = table.Column(type: "uuid", nullable: false), CreatedBy = table.Column(type: "uuid", nullable: false), CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, defaultValueSql: "CURRENT_TIMESTAMP"), - ParentId = table.Column(type: "uuid", nullable: false), + ParentId = table.Column(type: "uuid", nullable: true), Value = table.Column(type: "text", nullable: false) }, constraints: table => diff --git a/src/Web/Messages/Migrations/MessagingDbContextModelSnapshot.cs b/src/Web/Messages/Migrations/MessagingDbContextModelSnapshot.cs index 64c03fb..22fe571 100644 --- a/src/Web/Messages/Migrations/MessagingDbContextModelSnapshot.cs +++ b/src/Web/Messages/Migrations/MessagingDbContextModelSnapshot.cs @@ -37,7 +37,7 @@ namespace Hutopy.Web.Messages.Migrations b.Property("CreatedBy") .HasColumnType("uuid"); - b.Property("ParentId") + b.Property("ParentId") .HasColumnType("uuid"); b.Property("SubjectId") From a59b0f5c05a225bf93a40db3f68010b3e85518e0 Mon Sep 17 00:00:00 2001 From: Jonathan Bourdon Date: Thu, 18 Jul 2024 20:49:05 -0400 Subject: [PATCH 119/229] Adding replies to the Messaging system --- src/Web/Messages/Data/Message.cs | 2 +- src/Web/Messages/Handlers/GetMessages.cs | 3 +- .../Messages/Handlers/GetMessagesByParent.cs | 34 +++++++++++++++++++ .../Messages/Handlers/GetMessagesByUser.cs | 4 ++- src/Web/Messages/Handlers/PostMessage.cs | 26 +++++++------- src/Web/Messages/Handlers/PostReplyMessage.cs | 34 ++++++++++--------- ....cs => 20240718173016_Initial.Designer.cs} | 4 +-- ...0_Initial.cs => 20240718173016_Initial.cs} | 2 +- .../MessagingDbContextModelSnapshot.cs | 2 +- start-infrastructure.sh | 10 +++++- 10 files changed, 85 insertions(+), 36 deletions(-) create mode 100644 src/Web/Messages/Handlers/GetMessagesByParent.cs rename src/Web/Messages/Migrations/{20240718041130_Initial.Designer.cs => 20240718173016_Initial.Designer.cs} (95%) rename src/Web/Messages/Migrations/{20240718041130_Initial.cs => 20240718173016_Initial.cs} (98%) diff --git a/src/Web/Messages/Data/Message.cs b/src/Web/Messages/Data/Message.cs index 09d3b6b..f1255ed 100644 --- a/src/Web/Messages/Data/Message.cs +++ b/src/Web/Messages/Data/Message.cs @@ -6,6 +6,6 @@ public class Message public Guid SubjectId { get; init; } public Guid CreatedBy { get; init; } public DateTimeOffset CreatedAt { get; } - public Guid ParentId { get; init; } + public Guid? ParentId { get; init; } public string Value { get; init; } } diff --git a/src/Web/Messages/Handlers/GetMessages.cs b/src/Web/Messages/Handlers/GetMessages.cs index 6325548..b29c9c4 100644 --- a/src/Web/Messages/Handlers/GetMessages.cs +++ b/src/Web/Messages/Handlers/GetMessages.cs @@ -4,7 +4,7 @@ using Microsoft.EntityFrameworkCore; namespace Hutopy.Web.Messages.Handlers; -public sealed class GetMessagesRequest +public class GetMessagesRequest { public Guid SubjectId { get; set; } } @@ -27,6 +27,7 @@ public class GetMessages( var comments = await context .Messages .Where(c => c.SubjectId == req.SubjectId) + .Where(c => c.ParentId == null) .ToListAsync(cancellationToken: ct); await SendAsync(comments, cancellation: ct); diff --git a/src/Web/Messages/Handlers/GetMessagesByParent.cs b/src/Web/Messages/Handlers/GetMessagesByParent.cs new file mode 100644 index 0000000..39ff534 --- /dev/null +++ b/src/Web/Messages/Handlers/GetMessagesByParent.cs @@ -0,0 +1,34 @@ +using FastEndpoints; +using Hutopy.Web.Messages.Data; +using Microsoft.EntityFrameworkCore; + +namespace Hutopy.Web.Messages.Handlers; + +public class GetMessagesRepliesRequest +{ + public Guid ParentId { get; set; } +} + +public class GetMessagesByParent( + MessagingDbContext context) + : Endpoint> +{ + public override void Configure() + { + Get("/api/messages/{ParentId:guid}/replies"); + Options(o => o.WithTags("Messages")); + AllowAnonymous(); + } + + public override async Task HandleAsync( + GetMessagesRepliesRequest req, + CancellationToken ct) + { + var posts = await context + .Messages + .Where(c => c.ParentId == req.ParentId) + .ToListAsync(cancellationToken: ct); + + await SendAsync(posts, cancellation: ct); + } +} diff --git a/src/Web/Messages/Handlers/GetMessagesByUser.cs b/src/Web/Messages/Handlers/GetMessagesByUser.cs index 6f1e447..c6f6a72 100644 --- a/src/Web/Messages/Handlers/GetMessagesByUser.cs +++ b/src/Web/Messages/Handlers/GetMessagesByUser.cs @@ -4,7 +4,7 @@ using Microsoft.EntityFrameworkCore; namespace Hutopy.Web.Messages.Handlers; -public sealed class GetMessagesByUserRequest +public class GetMessagesByUserRequest { public Guid UserId { get; set; } } @@ -17,6 +17,7 @@ public class GetMessagesByUser( { Get("/api/messages/user/{UserId:guid}"); Options(o => o.WithTags("Messages")); + AllowAnonymous(); } public override async Task HandleAsync( @@ -26,6 +27,7 @@ public class GetMessagesByUser( var posts = await context .Messages .Where(c => c.CreatedBy == req.UserId) + .Where(c => c.ParentId == null) .ToListAsync(cancellationToken: ct); await SendAsync(posts, cancellation: ct); diff --git a/src/Web/Messages/Handlers/PostMessage.cs b/src/Web/Messages/Handlers/PostMessage.cs index 65d7882..a4d5240 100644 --- a/src/Web/Messages/Handlers/PostMessage.cs +++ b/src/Web/Messages/Handlers/PostMessage.cs @@ -4,9 +4,11 @@ using Hutopy.Web.Messages.Data; namespace Hutopy.Web.Messages.Handlers; -public record PostMessageRequest( - Guid SubjectId, - string Message); +public class PostMessageRequest +{ + public Guid SubjectId { get; set; } + public string Message { get; set; } +} public class PostMessage( MessagingDbContext context) @@ -22,15 +24,15 @@ public class PostMessage( PostMessageRequest req, CancellationToken ct) { - await context.Messages.AddAsync( - new Message - { - Id = GuidHelper.GenerateUuidV7(), - SubjectId = req.SubjectId, - CreatedBy = User.GetUserId(), - Value = req.Message - }, - ct); + var message = new Message + { + Id = GuidHelper.GenerateUuidV7(), + SubjectId = req.SubjectId, + CreatedBy = User.GetUserId(), + Value = req.Message + }; + + await context.Messages.AddAsync(message, ct); await context.SaveChangesAsync(ct); } diff --git a/src/Web/Messages/Handlers/PostReplyMessage.cs b/src/Web/Messages/Handlers/PostReplyMessage.cs index 6e7b995..277b3f1 100644 --- a/src/Web/Messages/Handlers/PostReplyMessage.cs +++ b/src/Web/Messages/Handlers/PostReplyMessage.cs @@ -4,18 +4,20 @@ using Hutopy.Web.Messages.Data; namespace Hutopy.Web.Messages.Handlers; -public record PostReplyMessageRequest( - Guid SubjectId, - Guid ParentId, - string Message); +internal sealed class PostReplyMessageRequest +{ + public required Guid SubjectId { get; set; } + public required Guid ParentId { get; set; } + public required string Message { get; set; } +} -public sealed class PostReplyMessage( +internal sealed class PostReplyMessage( MessagingDbContext context) : Endpoint { public override void Configure() { - Post("/api/messages/reply"); + Post("/api/messages/{ParentId:guid}/replies"); Options(o => o.WithTags("Messages")); } @@ -23,16 +25,16 @@ public sealed class PostReplyMessage( PostReplyMessageRequest req, CancellationToken ct) { - await context.Messages.AddAsync( - new Message - { - Id = GuidHelper.GenerateUuidV7(), - SubjectId = req.SubjectId, - ParentId = req.ParentId, - CreatedBy = User.GetUserId(), - Value = req.Message - }, - ct); + var message = new Message + { + Id = GuidHelper.GenerateUuidV7(), + SubjectId = req.SubjectId, + ParentId = req.ParentId, + CreatedBy = User.GetUserId(), + Value = req.Message + }; + + await context.Messages.AddAsync(message, ct); await context.SaveChangesAsync(ct); } diff --git a/src/Web/Messages/Migrations/20240718041130_Initial.Designer.cs b/src/Web/Messages/Migrations/20240718173016_Initial.Designer.cs similarity index 95% rename from src/Web/Messages/Migrations/20240718041130_Initial.Designer.cs rename to src/Web/Messages/Migrations/20240718173016_Initial.Designer.cs index c375b1b..e5d2cf2 100644 --- a/src/Web/Messages/Migrations/20240718041130_Initial.Designer.cs +++ b/src/Web/Messages/Migrations/20240718173016_Initial.Designer.cs @@ -12,7 +12,7 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; namespace Hutopy.Web.Messages.Migrations { [DbContext(typeof(MessagingDbContext))] - [Migration("20240718041130_Initial")] + [Migration("20240718173016_Initial")] partial class Initial { /// @@ -40,7 +40,7 @@ namespace Hutopy.Web.Messages.Migrations b.Property("CreatedBy") .HasColumnType("uuid"); - b.Property("ParentId") + b.Property("ParentId") .HasColumnType("uuid"); b.Property("SubjectId") diff --git a/src/Web/Messages/Migrations/20240718041130_Initial.cs b/src/Web/Messages/Migrations/20240718173016_Initial.cs similarity index 98% rename from src/Web/Messages/Migrations/20240718041130_Initial.cs rename to src/Web/Messages/Migrations/20240718173016_Initial.cs index fbb3817..6a194da 100644 --- a/src/Web/Messages/Migrations/20240718041130_Initial.cs +++ b/src/Web/Messages/Migrations/20240718173016_Initial.cs @@ -23,7 +23,7 @@ namespace Hutopy.Web.Messages.Migrations SubjectId = table.Column(type: "uuid", nullable: false), CreatedBy = table.Column(type: "uuid", nullable: false), CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, defaultValueSql: "CURRENT_TIMESTAMP"), - ParentId = table.Column(type: "uuid", nullable: false), + ParentId = table.Column(type: "uuid", nullable: true), Value = table.Column(type: "text", nullable: false) }, constraints: table => diff --git a/src/Web/Messages/Migrations/MessagingDbContextModelSnapshot.cs b/src/Web/Messages/Migrations/MessagingDbContextModelSnapshot.cs index 64c03fb..22fe571 100644 --- a/src/Web/Messages/Migrations/MessagingDbContextModelSnapshot.cs +++ b/src/Web/Messages/Migrations/MessagingDbContextModelSnapshot.cs @@ -37,7 +37,7 @@ namespace Hutopy.Web.Messages.Migrations b.Property("CreatedBy") .HasColumnType("uuid"); - b.Property("ParentId") + b.Property("ParentId") .HasColumnType("uuid"); b.Property("SubjectId") diff --git a/start-infrastructure.sh b/start-infrastructure.sh index d7a15c2..cf9b7cc 100644 --- a/start-infrastructure.sh +++ b/start-infrastructure.sh @@ -6,4 +6,12 @@ docker run \ -e 'MSSQL_SA_PASSWORD=P@ssword123!' \ -p 1433:1433 \ --name azuresqledge \ - -d mcr.microsoft.com/azure-sql-edge \ No newline at end of file + -d mcr.microsoft.com/azure-sql-edge + + docker run \ + --cap-add SYS_PTRACE \ + -e 'POSTGRES_USER=sa' \ + -e 'POSTGRES_PASSWORD=P@ssword123!' \ + -p 5432:5432 \ + --name postgres \ + -d postgres \ No newline at end of file From b34a775a4bf12e23f3e4b50d86767e2633ba9d15 Mon Sep 17 00:00:00 2001 From: Jonathan Bourdon Date: Thu, 18 Jul 2024 22:22:44 -0400 Subject: [PATCH 120/229] Moved features to a specific folder --- src/Web/{ => Features}/Contents/Data/Content.cs | 2 +- src/Web/{ => Features}/Contents/Data/ContentDbContext.cs | 2 +- src/Web/{ => Features}/Contents/DependencyInjection.cs | 4 ++-- src/Web/{ => Features}/Contents/Handlers/GetContents.cs | 4 ++-- .../{ => Features}/Contents/Handlers/GetContentsByUser.cs | 4 ++-- src/Web/{ => Features}/Contents/Handlers/PostContent.cs | 4 ++-- .../Contents/Migrations/20240718034516_Initial.Designer.cs | 2 +- .../Contents/Migrations/20240718034516_Initial.cs | 0 .../Contents/Migrations/ContentDbContextModelSnapshot.cs | 2 +- src/Web/{ => Features}/Messages/Data/Message.cs | 2 +- src/Web/{ => Features}/Messages/Data/MessagingDbContext.cs | 2 +- src/Web/{ => Features}/Messages/DependencyInjection.cs | 4 ++-- src/Web/{ => Features}/Messages/Handlers/GetMessages.cs | 4 ++-- .../{ => Features}/Messages/Handlers/GetMessagesByParent.cs | 4 ++-- .../{ => Features}/Messages/Handlers/GetMessagesByUser.cs | 4 ++-- src/Web/{ => Features}/Messages/Handlers/PostMessage.cs | 4 ++-- src/Web/{ => Features}/Messages/Handlers/PostReplyMessage.cs | 4 ++-- .../Messages/Migrations/20240718173016_Initial.Designer.cs | 2 +- .../Messages/Migrations/20240718173016_Initial.cs | 0 .../Messages/Migrations/MessagingDbContextModelSnapshot.cs | 2 +- src/Web/Program.cs | 4 ++-- src/Web/TestDataSeeder.cs | 4 ++-- src/Web/Web.csproj | 5 ----- 23 files changed, 32 insertions(+), 37 deletions(-) rename src/Web/{ => Features}/Contents/Data/Content.cs (84%) rename src/Web/{ => Features}/Contents/Data/ContentDbContext.cs (91%) rename src/Web/{ => Features}/Contents/DependencyInjection.cs (80%) rename src/Web/{ => Features}/Contents/Handlers/GetContents.cs (90%) rename src/Web/{ => Features}/Contents/Handlers/GetContentsByUser.cs (92%) rename src/Web/{ => Features}/Contents/Handlers/PostContent.cs (90%) rename src/Web/{ => Features}/Contents/Migrations/20240718034516_Initial.Designer.cs (97%) rename src/Web/{ => Features}/Contents/Migrations/20240718034516_Initial.cs (100%) rename src/Web/{ => Features}/Contents/Migrations/ContentDbContextModelSnapshot.cs (97%) rename src/Web/{ => Features}/Messages/Data/Message.cs (84%) rename src/Web/{ => Features}/Messages/Data/MessagingDbContext.cs (92%) rename src/Web/{ => Features}/Messages/DependencyInjection.cs (81%) rename src/Web/{ => Features}/Messages/Handlers/GetMessages.cs (89%) rename src/Web/{ => Features}/Messages/Handlers/GetMessagesByParent.cs (89%) rename src/Web/{ => Features}/Messages/Handlers/GetMessagesByUser.cs (90%) rename src/Web/{ => Features}/Messages/Handlers/PostMessage.cs (90%) rename src/Web/{ => Features}/Messages/Handlers/PostReplyMessage.cs (91%) rename src/Web/{ => Features}/Messages/Migrations/20240718173016_Initial.Designer.cs (97%) rename src/Web/{ => Features}/Messages/Migrations/20240718173016_Initial.cs (100%) rename src/Web/{ => Features}/Messages/Migrations/MessagingDbContextModelSnapshot.cs (97%) diff --git a/src/Web/Contents/Data/Content.cs b/src/Web/Features/Contents/Data/Content.cs similarity index 84% rename from src/Web/Contents/Data/Content.cs rename to src/Web/Features/Contents/Data/Content.cs index b67a92f..c4bdea1 100644 --- a/src/Web/Contents/Data/Content.cs +++ b/src/Web/Features/Contents/Data/Content.cs @@ -1,4 +1,4 @@ -namespace Hutopy.Web.Contents.Data; +namespace Hutopy.Web.Features.Contents.Data; public class Content { diff --git a/src/Web/Contents/Data/ContentDbContext.cs b/src/Web/Features/Contents/Data/ContentDbContext.cs similarity index 91% rename from src/Web/Contents/Data/ContentDbContext.cs rename to src/Web/Features/Contents/Data/ContentDbContext.cs index bf6eaf5..657ab6d 100644 --- a/src/Web/Contents/Data/ContentDbContext.cs +++ b/src/Web/Features/Contents/Data/ContentDbContext.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore; -namespace Hutopy.Web.Contents.Data; +namespace Hutopy.Web.Features.Contents.Data; public class ContentDbContext( DbContextOptions options) diff --git a/src/Web/Contents/DependencyInjection.cs b/src/Web/Features/Contents/DependencyInjection.cs similarity index 80% rename from src/Web/Contents/DependencyInjection.cs rename to src/Web/Features/Contents/DependencyInjection.cs index a62df6c..8cac7cb 100644 --- a/src/Web/Contents/DependencyInjection.cs +++ b/src/Web/Features/Contents/DependencyInjection.cs @@ -1,7 +1,7 @@ -using Hutopy.Web.Contents.Data; +using Hutopy.Web.Features.Contents.Data; using Microsoft.EntityFrameworkCore; -namespace Hutopy.Web.Contents; +namespace Hutopy.Web.Features.Contents; public static class DependencyInjection { diff --git a/src/Web/Contents/Handlers/GetContents.cs b/src/Web/Features/Contents/Handlers/GetContents.cs similarity index 90% rename from src/Web/Contents/Handlers/GetContents.cs rename to src/Web/Features/Contents/Handlers/GetContents.cs index 26d1348..6fe1674 100644 --- a/src/Web/Contents/Handlers/GetContents.cs +++ b/src/Web/Features/Contents/Handlers/GetContents.cs @@ -1,8 +1,8 @@ using FastEndpoints; -using Hutopy.Web.Contents.Data; +using Hutopy.Web.Features.Contents.Data; using Microsoft.EntityFrameworkCore; -namespace Hutopy.Web.Contents.Handlers; +namespace Hutopy.Web.Features.Contents.Handlers; public sealed class GetContentsRequest { diff --git a/src/Web/Contents/Handlers/GetContentsByUser.cs b/src/Web/Features/Contents/Handlers/GetContentsByUser.cs similarity index 92% rename from src/Web/Contents/Handlers/GetContentsByUser.cs rename to src/Web/Features/Contents/Handlers/GetContentsByUser.cs index 50cb478..34c085f 100644 --- a/src/Web/Contents/Handlers/GetContentsByUser.cs +++ b/src/Web/Features/Contents/Handlers/GetContentsByUser.cs @@ -1,8 +1,8 @@ using FastEndpoints; -using Hutopy.Web.Contents.Data; +using Hutopy.Web.Features.Contents.Data; using Microsoft.EntityFrameworkCore; -namespace Hutopy.Web.Contents.Handlers; +namespace Hutopy.Web.Features.Contents.Handlers; public sealed class GetContentsByUserRequest { diff --git a/src/Web/Contents/Handlers/PostContent.cs b/src/Web/Features/Contents/Handlers/PostContent.cs similarity index 90% rename from src/Web/Contents/Handlers/PostContent.cs rename to src/Web/Features/Contents/Handlers/PostContent.cs index e741c18..71bebd5 100644 --- a/src/Web/Contents/Handlers/PostContent.cs +++ b/src/Web/Features/Contents/Handlers/PostContent.cs @@ -1,8 +1,8 @@ using FastEndpoints; using Hutopy.Web.Common; -using Hutopy.Web.Contents.Data; +using Hutopy.Web.Features.Contents.Data; -namespace Hutopy.Web.Contents.Handlers; +namespace Hutopy.Web.Features.Contents.Handlers; public record struct PostContentRequest( string? Title, diff --git a/src/Web/Contents/Migrations/20240718034516_Initial.Designer.cs b/src/Web/Features/Contents/Migrations/20240718034516_Initial.Designer.cs similarity index 97% rename from src/Web/Contents/Migrations/20240718034516_Initial.Designer.cs rename to src/Web/Features/Contents/Migrations/20240718034516_Initial.Designer.cs index 9fb4610..4ea464a 100644 --- a/src/Web/Contents/Migrations/20240718034516_Initial.Designer.cs +++ b/src/Web/Features/Contents/Migrations/20240718034516_Initial.Designer.cs @@ -1,6 +1,6 @@ // using System; -using Hutopy.Web.Contents.Data; +using Hutopy.Web.Features.Contents.Data; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; diff --git a/src/Web/Contents/Migrations/20240718034516_Initial.cs b/src/Web/Features/Contents/Migrations/20240718034516_Initial.cs similarity index 100% rename from src/Web/Contents/Migrations/20240718034516_Initial.cs rename to src/Web/Features/Contents/Migrations/20240718034516_Initial.cs diff --git a/src/Web/Contents/Migrations/ContentDbContextModelSnapshot.cs b/src/Web/Features/Contents/Migrations/ContentDbContextModelSnapshot.cs similarity index 97% rename from src/Web/Contents/Migrations/ContentDbContextModelSnapshot.cs rename to src/Web/Features/Contents/Migrations/ContentDbContextModelSnapshot.cs index 5a7fbbf..e01f3a9 100644 --- a/src/Web/Contents/Migrations/ContentDbContextModelSnapshot.cs +++ b/src/Web/Features/Contents/Migrations/ContentDbContextModelSnapshot.cs @@ -1,6 +1,6 @@ // using System; -using Hutopy.Web.Contents.Data; +using Hutopy.Web.Features.Contents.Data; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; diff --git a/src/Web/Messages/Data/Message.cs b/src/Web/Features/Messages/Data/Message.cs similarity index 84% rename from src/Web/Messages/Data/Message.cs rename to src/Web/Features/Messages/Data/Message.cs index f1255ed..8bcd258 100644 --- a/src/Web/Messages/Data/Message.cs +++ b/src/Web/Features/Messages/Data/Message.cs @@ -1,4 +1,4 @@ -namespace Hutopy.Web.Messages.Data; +namespace Hutopy.Web.Features.Messages.Data; public class Message { diff --git a/src/Web/Messages/Data/MessagingDbContext.cs b/src/Web/Features/Messages/Data/MessagingDbContext.cs similarity index 92% rename from src/Web/Messages/Data/MessagingDbContext.cs rename to src/Web/Features/Messages/Data/MessagingDbContext.cs index 7674b30..16fc14a 100644 --- a/src/Web/Messages/Data/MessagingDbContext.cs +++ b/src/Web/Features/Messages/Data/MessagingDbContext.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore; -namespace Hutopy.Web.Messages.Data; +namespace Hutopy.Web.Features.Messages.Data; public class MessagingDbContext( DbContextOptions options) diff --git a/src/Web/Messages/DependencyInjection.cs b/src/Web/Features/Messages/DependencyInjection.cs similarity index 81% rename from src/Web/Messages/DependencyInjection.cs rename to src/Web/Features/Messages/DependencyInjection.cs index 8e89468..0693a3e 100644 --- a/src/Web/Messages/DependencyInjection.cs +++ b/src/Web/Features/Messages/DependencyInjection.cs @@ -1,7 +1,7 @@ -using Hutopy.Web.Messages.Data; +using Hutopy.Web.Features.Messages.Data; using Microsoft.EntityFrameworkCore; -namespace Hutopy.Web.Messages; +namespace Hutopy.Web.Features.Messages; public static class DependencyInjection { diff --git a/src/Web/Messages/Handlers/GetMessages.cs b/src/Web/Features/Messages/Handlers/GetMessages.cs similarity index 89% rename from src/Web/Messages/Handlers/GetMessages.cs rename to src/Web/Features/Messages/Handlers/GetMessages.cs index b29c9c4..c14c11f 100644 --- a/src/Web/Messages/Handlers/GetMessages.cs +++ b/src/Web/Features/Messages/Handlers/GetMessages.cs @@ -1,8 +1,8 @@ using FastEndpoints; -using Hutopy.Web.Messages.Data; +using Hutopy.Web.Features.Messages.Data; using Microsoft.EntityFrameworkCore; -namespace Hutopy.Web.Messages.Handlers; +namespace Hutopy.Web.Features.Messages.Handlers; public class GetMessagesRequest { diff --git a/src/Web/Messages/Handlers/GetMessagesByParent.cs b/src/Web/Features/Messages/Handlers/GetMessagesByParent.cs similarity index 89% rename from src/Web/Messages/Handlers/GetMessagesByParent.cs rename to src/Web/Features/Messages/Handlers/GetMessagesByParent.cs index 39ff534..ab05d51 100644 --- a/src/Web/Messages/Handlers/GetMessagesByParent.cs +++ b/src/Web/Features/Messages/Handlers/GetMessagesByParent.cs @@ -1,8 +1,8 @@ using FastEndpoints; -using Hutopy.Web.Messages.Data; +using Hutopy.Web.Features.Messages.Data; using Microsoft.EntityFrameworkCore; -namespace Hutopy.Web.Messages.Handlers; +namespace Hutopy.Web.Features.Messages.Handlers; public class GetMessagesRepliesRequest { diff --git a/src/Web/Messages/Handlers/GetMessagesByUser.cs b/src/Web/Features/Messages/Handlers/GetMessagesByUser.cs similarity index 90% rename from src/Web/Messages/Handlers/GetMessagesByUser.cs rename to src/Web/Features/Messages/Handlers/GetMessagesByUser.cs index c6f6a72..0b39cef 100644 --- a/src/Web/Messages/Handlers/GetMessagesByUser.cs +++ b/src/Web/Features/Messages/Handlers/GetMessagesByUser.cs @@ -1,8 +1,8 @@ using FastEndpoints; -using Hutopy.Web.Messages.Data; +using Hutopy.Web.Features.Messages.Data; using Microsoft.EntityFrameworkCore; -namespace Hutopy.Web.Messages.Handlers; +namespace Hutopy.Web.Features.Messages.Handlers; public class GetMessagesByUserRequest { diff --git a/src/Web/Messages/Handlers/PostMessage.cs b/src/Web/Features/Messages/Handlers/PostMessage.cs similarity index 90% rename from src/Web/Messages/Handlers/PostMessage.cs rename to src/Web/Features/Messages/Handlers/PostMessage.cs index a4d5240..401f0c7 100644 --- a/src/Web/Messages/Handlers/PostMessage.cs +++ b/src/Web/Features/Messages/Handlers/PostMessage.cs @@ -1,8 +1,8 @@ using FastEndpoints; using Hutopy.Web.Common; -using Hutopy.Web.Messages.Data; +using Hutopy.Web.Features.Messages.Data; -namespace Hutopy.Web.Messages.Handlers; +namespace Hutopy.Web.Features.Messages.Handlers; public class PostMessageRequest { diff --git a/src/Web/Messages/Handlers/PostReplyMessage.cs b/src/Web/Features/Messages/Handlers/PostReplyMessage.cs similarity index 91% rename from src/Web/Messages/Handlers/PostReplyMessage.cs rename to src/Web/Features/Messages/Handlers/PostReplyMessage.cs index 277b3f1..9b3d905 100644 --- a/src/Web/Messages/Handlers/PostReplyMessage.cs +++ b/src/Web/Features/Messages/Handlers/PostReplyMessage.cs @@ -1,8 +1,8 @@ using FastEndpoints; using Hutopy.Web.Common; -using Hutopy.Web.Messages.Data; +using Hutopy.Web.Features.Messages.Data; -namespace Hutopy.Web.Messages.Handlers; +namespace Hutopy.Web.Features.Messages.Handlers; internal sealed class PostReplyMessageRequest { diff --git a/src/Web/Messages/Migrations/20240718173016_Initial.Designer.cs b/src/Web/Features/Messages/Migrations/20240718173016_Initial.Designer.cs similarity index 97% rename from src/Web/Messages/Migrations/20240718173016_Initial.Designer.cs rename to src/Web/Features/Messages/Migrations/20240718173016_Initial.Designer.cs index e5d2cf2..21a45b2 100644 --- a/src/Web/Messages/Migrations/20240718173016_Initial.Designer.cs +++ b/src/Web/Features/Messages/Migrations/20240718173016_Initial.Designer.cs @@ -1,6 +1,6 @@ // using System; -using Hutopy.Web.Messages.Data; +using Hutopy.Web.Features.Messages.Data; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; diff --git a/src/Web/Messages/Migrations/20240718173016_Initial.cs b/src/Web/Features/Messages/Migrations/20240718173016_Initial.cs similarity index 100% rename from src/Web/Messages/Migrations/20240718173016_Initial.cs rename to src/Web/Features/Messages/Migrations/20240718173016_Initial.cs diff --git a/src/Web/Messages/Migrations/MessagingDbContextModelSnapshot.cs b/src/Web/Features/Messages/Migrations/MessagingDbContextModelSnapshot.cs similarity index 97% rename from src/Web/Messages/Migrations/MessagingDbContextModelSnapshot.cs rename to src/Web/Features/Messages/Migrations/MessagingDbContextModelSnapshot.cs index 22fe571..c01bd22 100644 --- a/src/Web/Messages/Migrations/MessagingDbContextModelSnapshot.cs +++ b/src/Web/Features/Messages/Migrations/MessagingDbContextModelSnapshot.cs @@ -1,6 +1,6 @@ // using System; -using Hutopy.Web.Messages.Data; +using Hutopy.Web.Features.Messages.Data; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; diff --git a/src/Web/Program.cs b/src/Web/Program.cs index bef36d9..759f533 100644 --- a/src/Web/Program.cs +++ b/src/Web/Program.cs @@ -5,8 +5,8 @@ using Hutopy.Infrastructure; using Hutopy.Infrastructure.Data; using Hutopy.Infrastructure.Identity; using Hutopy.Web; -using Hutopy.Web.Contents; -using Hutopy.Web.Messages; +using Hutopy.Web.Features.Contents; +using Hutopy.Web.Features.Messages; using Microsoft.AspNetCore.HttpOverrides; using Microsoft.EntityFrameworkCore; using NSwag; diff --git a/src/Web/TestDataSeeder.cs b/src/Web/TestDataSeeder.cs index 4e1e7f9..a34ea8a 100644 --- a/src/Web/TestDataSeeder.cs +++ b/src/Web/TestDataSeeder.cs @@ -2,8 +2,8 @@ using Hutopy.Infrastructure.Identity; using Hutopy.Infrastructure.Identity.OwnedEntities; using Hutopy.Web.Common; -using Hutopy.Web.Contents.Data; -using Hutopy.Web.Messages.Data; +using Hutopy.Web.Features.Contents.Data; +using Hutopy.Web.Features.Messages.Data; namespace Hutopy.Web; diff --git a/src/Web/Web.csproj b/src/Web/Web.csproj index 761a54d..ead4845 100644 --- a/src/Web/Web.csproj +++ b/src/Web/Web.csproj @@ -31,9 +31,4 @@ - - - - - From 8b5ab2d7699ba1928c3db8bc54b75242c8a61740 Mon Sep 17 00:00:00 2001 From: Jonathan Bourdon Date: Fri, 19 Jul 2024 00:43:13 -0400 Subject: [PATCH 121/229] TestData seeding now creates items at different times --- src/Web/TestDataSeeder.cs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/Web/TestDataSeeder.cs b/src/Web/TestDataSeeder.cs index a34ea8a..84f56b3 100644 --- a/src/Web/TestDataSeeder.cs +++ b/src/Web/TestDataSeeder.cs @@ -61,6 +61,8 @@ internal class TestDataSeeder( private List GenerateContent(ApplicationUser user, int contentCount) { + var currentDate = DateTimeOffset.UtcNow; + var contents = new List(); for (var c = 0; c < contentCount; c++) @@ -69,6 +71,7 @@ internal class TestDataSeeder( { Id = GuidHelper.GenerateUuidV7(), CreatedBy = Guid.Parse(user.Id), + CreatedAt = currentDate, Title = $"Title {user.UserName}-{c}", Description = $"Description {user.UserName}-{c}" }; @@ -76,6 +79,8 @@ internal class TestDataSeeder( contentContext.Contents.Add(content); contents.Add(content); + + currentDate = currentDate.AddSeconds(Random.Shared.Next(100, 100_000)); } contentContext.SaveChanges(); @@ -85,10 +90,12 @@ internal class TestDataSeeder( private List GenerateMessages(Content content, int messageCount) { + var currentDate = content.CreatedAt; var messages = new List(); for (var m = 0; m < messageCount; m++) { + currentDate = currentDate.AddSeconds(Random.Shared.Next(100, 100_000)); var author = Random.Shared.GetItems(_creators, 1)[0]; var message = new Message @@ -96,6 +103,7 @@ internal class TestDataSeeder( Id = GuidHelper.GenerateUuidV7(), SubjectId = content.Id, CreatedBy = Guid.Parse(author.Id), + CreatedAt = currentDate, Value = $"Message #{m} from {author.UserName} on {content.Title}" }; @@ -109,10 +117,13 @@ internal class TestDataSeeder( private List GenerateReplies(Content content, Message parent, int replyCount) { + var currentDate = parent.CreatedAt; var replies = new List(); for (var r = 0; r < replyCount; r++) { + currentDate = currentDate.AddSeconds(Random.Shared.Next(100, 100_000)); + var author = Random.Shared.GetItems(_creators, 1)[0]; var message = new Message @@ -121,6 +132,7 @@ internal class TestDataSeeder( SubjectId = content.Id, ParentId = parent.Id, CreatedBy = Guid.Parse(author.Id), + CreatedAt = currentDate, Value = $"Reply {r} to {parent.Value}" }; From d268625f19a301e121d1c7c2e3744bb0599ec547 Mon Sep 17 00:00:00 2001 From: Jonathan Bourdon Date: Fri, 19 Jul 2024 00:44:03 -0400 Subject: [PATCH 122/229] Adds Messaging streaming --- src/Web/Features/Contents/Data/Content.cs | 2 +- .../{GetContents.cs => GetContent.cs} | 8 ++-- .../Contents/Handlers/GetContentsByUser.cs | 12 ++--- src/Web/Features/Messages/Data/Message.cs | 2 +- .../{PostMessage.cs => AddMessage.cs} | 8 ++-- .../{PostReplyMessage.cs => AddReply.cs} | 8 ++-- .../Features/Messages/Handlers/GetMessages.cs | 18 ++++++-- .../Messages/Handlers/GetMessagesByParent.cs | 34 -------------- .../Features/Messages/Handlers/GetReplies.cs | 46 +++++++++++++++++++ 9 files changed, 80 insertions(+), 58 deletions(-) rename src/Web/Features/Contents/Handlers/{GetContents.cs => GetContent.cs} (85%) rename src/Web/Features/Messages/Handlers/{PostMessage.cs => AddMessage.cs} (86%) rename src/Web/Features/Messages/Handlers/{PostReplyMessage.cs => AddReply.cs} (84%) delete mode 100644 src/Web/Features/Messages/Handlers/GetMessagesByParent.cs create mode 100644 src/Web/Features/Messages/Handlers/GetReplies.cs diff --git a/src/Web/Features/Contents/Data/Content.cs b/src/Web/Features/Contents/Data/Content.cs index c4bdea1..c5c3dec 100644 --- a/src/Web/Features/Contents/Data/Content.cs +++ b/src/Web/Features/Contents/Data/Content.cs @@ -4,7 +4,7 @@ public class Content { public Guid Id { get; init; } public Guid CreatedBy { get; init; } - public DateTimeOffset CreatedAt { get; } + public DateTimeOffset CreatedAt { get; init; } public string? Title { get; init; } public string? Description { get; init; } diff --git a/src/Web/Features/Contents/Handlers/GetContents.cs b/src/Web/Features/Contents/Handlers/GetContent.cs similarity index 85% rename from src/Web/Features/Contents/Handlers/GetContents.cs rename to src/Web/Features/Contents/Handlers/GetContent.cs index 6fe1674..95dd16a 100644 --- a/src/Web/Features/Contents/Handlers/GetContents.cs +++ b/src/Web/Features/Contents/Handlers/GetContent.cs @@ -4,14 +4,14 @@ using Microsoft.EntityFrameworkCore; namespace Hutopy.Web.Features.Contents.Handlers; -public sealed class GetContentsRequest +public sealed class GetContentRequest { public Guid ContentId { get; set; } } -public class GetContents( +public class GetContent( ContentDbContext context) - : Endpoint + : Endpoint { public override void Configure() { @@ -21,7 +21,7 @@ public class GetContents( } public override async Task HandleAsync( - GetContentsRequest req, + GetContentRequest req, CancellationToken ct) { var content = await context diff --git a/src/Web/Features/Contents/Handlers/GetContentsByUser.cs b/src/Web/Features/Contents/Handlers/GetContentsByUser.cs index 34c085f..f17214e 100644 --- a/src/Web/Features/Contents/Handlers/GetContentsByUser.cs +++ b/src/Web/Features/Contents/Handlers/GetContentsByUser.cs @@ -7,7 +7,7 @@ namespace Hutopy.Web.Features.Contents.Handlers; public sealed class GetContentsByUserRequest { public Guid UserId { get; set; } - [BindFrom("max_items")] public int MaxItems { get; set; } = 10; + [BindFrom("page_size")] public int PageSize { get; set; } = 10; [BindFrom("last_id")] public Guid? LastId { get; set; } } @@ -30,12 +30,12 @@ public class GetContentsByUser( .Contents .Where(c => c.CreatedBy == req.UserId); - if (req.LastId is not null) - query = query.OrderByDescending(c => c.Id).Where(c => c.Id < req.LastId.Value); - else - query = query.OrderByDescending(c => c.Id); + query = query.OrderByDescending(c => c.CreatedAt); - query = query.Take(req.MaxItems); + if (req.LastId is not null) + query = query.Where(c => c.Id < req.LastId.Value); + + query = query.Take(req.PageSize); var posts = await query.ToListAsync(cancellationToken: ct); diff --git a/src/Web/Features/Messages/Data/Message.cs b/src/Web/Features/Messages/Data/Message.cs index 8bcd258..9368718 100644 --- a/src/Web/Features/Messages/Data/Message.cs +++ b/src/Web/Features/Messages/Data/Message.cs @@ -5,7 +5,7 @@ public class Message public Guid Id { get; init; } public Guid SubjectId { get; init; } public Guid CreatedBy { get; init; } - public DateTimeOffset CreatedAt { get; } + public DateTimeOffset CreatedAt { get; init; } public Guid? ParentId { get; init; } public string Value { get; init; } } diff --git a/src/Web/Features/Messages/Handlers/PostMessage.cs b/src/Web/Features/Messages/Handlers/AddMessage.cs similarity index 86% rename from src/Web/Features/Messages/Handlers/PostMessage.cs rename to src/Web/Features/Messages/Handlers/AddMessage.cs index 401f0c7..222b781 100644 --- a/src/Web/Features/Messages/Handlers/PostMessage.cs +++ b/src/Web/Features/Messages/Handlers/AddMessage.cs @@ -4,15 +4,15 @@ using Hutopy.Web.Features.Messages.Data; namespace Hutopy.Web.Features.Messages.Handlers; -public class PostMessageRequest +public class AddMessageRequest { public Guid SubjectId { get; set; } public string Message { get; set; } } -public class PostMessage( +public class AddMessage( MessagingDbContext context) - : Endpoint + : Endpoint { public override void Configure() { @@ -21,7 +21,7 @@ public class PostMessage( } public override async Task HandleAsync( - PostMessageRequest req, + AddMessageRequest req, CancellationToken ct) { var message = new Message diff --git a/src/Web/Features/Messages/Handlers/PostReplyMessage.cs b/src/Web/Features/Messages/Handlers/AddReply.cs similarity index 84% rename from src/Web/Features/Messages/Handlers/PostReplyMessage.cs rename to src/Web/Features/Messages/Handlers/AddReply.cs index 9b3d905..1ab824d 100644 --- a/src/Web/Features/Messages/Handlers/PostReplyMessage.cs +++ b/src/Web/Features/Messages/Handlers/AddReply.cs @@ -4,16 +4,16 @@ using Hutopy.Web.Features.Messages.Data; namespace Hutopy.Web.Features.Messages.Handlers; -internal sealed class PostReplyMessageRequest +internal sealed class AddReplyRequest { public required Guid SubjectId { get; set; } public required Guid ParentId { get; set; } public required string Message { get; set; } } -internal sealed class PostReplyMessage( +internal sealed class AddReply( MessagingDbContext context) - : Endpoint + : Endpoint { public override void Configure() { @@ -22,7 +22,7 @@ internal sealed class PostReplyMessage( } public override async Task HandleAsync( - PostReplyMessageRequest req, + AddReplyRequest req, CancellationToken ct) { var message = new Message diff --git a/src/Web/Features/Messages/Handlers/GetMessages.cs b/src/Web/Features/Messages/Handlers/GetMessages.cs index c14c11f..188dd7e 100644 --- a/src/Web/Features/Messages/Handlers/GetMessages.cs +++ b/src/Web/Features/Messages/Handlers/GetMessages.cs @@ -7,6 +7,8 @@ namespace Hutopy.Web.Features.Messages.Handlers; public class GetMessagesRequest { public Guid SubjectId { get; set; } + [BindFrom("page_size")] public int PageSize { get; set; } = 10; + [BindFrom("last_id")] public Guid? LastId { get; set; } } public class GetMessages( @@ -24,12 +26,20 @@ public class GetMessages( GetMessagesRequest req, CancellationToken ct) { - var comments = await context + var query = context .Messages .Where(c => c.SubjectId == req.SubjectId) - .Where(c => c.ParentId == null) - .ToListAsync(cancellationToken: ct); + .Where(c => c.ParentId == null); - await SendAsync(comments, cancellation: ct); + query = query.OrderByDescending(c => c.CreatedAt); + + if (req.LastId is not null) + query = query.Where(c => c.Id < req.LastId.Value); + + query = query.Take(req.PageSize); + + var messages = await query.ToListAsync(cancellationToken: ct); + + await SendAsync(messages, cancellation: ct); } } diff --git a/src/Web/Features/Messages/Handlers/GetMessagesByParent.cs b/src/Web/Features/Messages/Handlers/GetMessagesByParent.cs deleted file mode 100644 index ab05d51..0000000 --- a/src/Web/Features/Messages/Handlers/GetMessagesByParent.cs +++ /dev/null @@ -1,34 +0,0 @@ -using FastEndpoints; -using Hutopy.Web.Features.Messages.Data; -using Microsoft.EntityFrameworkCore; - -namespace Hutopy.Web.Features.Messages.Handlers; - -public class GetMessagesRepliesRequest -{ - public Guid ParentId { get; set; } -} - -public class GetMessagesByParent( - MessagingDbContext context) - : Endpoint> -{ - public override void Configure() - { - Get("/api/messages/{ParentId:guid}/replies"); - Options(o => o.WithTags("Messages")); - AllowAnonymous(); - } - - public override async Task HandleAsync( - GetMessagesRepliesRequest req, - CancellationToken ct) - { - var posts = await context - .Messages - .Where(c => c.ParentId == req.ParentId) - .ToListAsync(cancellationToken: ct); - - await SendAsync(posts, cancellation: ct); - } -} diff --git a/src/Web/Features/Messages/Handlers/GetReplies.cs b/src/Web/Features/Messages/Handlers/GetReplies.cs new file mode 100644 index 0000000..891dbb3 --- /dev/null +++ b/src/Web/Features/Messages/Handlers/GetReplies.cs @@ -0,0 +1,46 @@ +using FastEndpoints; +using Hutopy.Web.Features.Messages.Data; +using Microsoft.EntityFrameworkCore; + +namespace Hutopy.Web.Features.Messages.Handlers; + +public class GetRepliesRequest +{ + public Guid SubjectId { get; set; } + public Guid ParentId { get; set; } + [BindFrom("page_size")] public int PageSize { get; set; } = 10; + [BindFrom("last_id")] public Guid? LastId { get; set; } +} + +public class GetReplies( + MessagingDbContext context) + : Endpoint> +{ + public override void Configure() + { + Get("/api/messages/{ParentId:guid}/replies"); + Options(o => o.WithTags("Messages")); + AllowAnonymous(); + } + + public override async Task HandleAsync( + GetRepliesRequest req, + CancellationToken ct) + { + var query = context + .Messages + .Where(c => c.SubjectId == req.SubjectId) + .Where(c => c.ParentId == req.ParentId); + + query = query.OrderByDescending(c => c.CreatedAt); + + if (req.LastId is not null) + query = query.Where(c => c.Id < req.LastId.Value); + + query = query.Take(req.PageSize); + + var replies = await query.ToListAsync(cancellationToken: ct); + + await SendAsync(replies, cancellation: ct); + } +} From d1d35aa2c8e875cc1244d373e6c7ed3bc9561042 Mon Sep 17 00:00:00 2001 From: Jonathan Bourdon Date: Fri, 19 Jul 2024 12:45:13 -0400 Subject: [PATCH 123/229] Moved to Creators to features --- src/Web/{ => Features}/Creators/Handlers/GetCreatorByAlias.cs | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/Web/{ => Features}/Creators/Handlers/GetCreatorByAlias.cs (100%) diff --git a/src/Web/Creators/Handlers/GetCreatorByAlias.cs b/src/Web/Features/Creators/Handlers/GetCreatorByAlias.cs similarity index 100% rename from src/Web/Creators/Handlers/GetCreatorByAlias.cs rename to src/Web/Features/Creators/Handlers/GetCreatorByAlias.cs From 2c88dc05d6be878b0e39b4bfffa64f6c6b364ee2 Mon Sep 17 00:00:00 2001 From: Jonathan Bourdon Date: Fri, 19 Jul 2024 12:45:31 -0400 Subject: [PATCH 124/229] Fix namespaces --- src/Web/Features/Creators/Handlers/GetCreatorByAlias.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Web/Features/Creators/Handlers/GetCreatorByAlias.cs b/src/Web/Features/Creators/Handlers/GetCreatorByAlias.cs index eaea0aa..b606a13 100644 --- a/src/Web/Features/Creators/Handlers/GetCreatorByAlias.cs +++ b/src/Web/Features/Creators/Handlers/GetCreatorByAlias.cs @@ -2,7 +2,7 @@ using Hutopy.Application.Common.Interfaces; using Hutopy.Application.Common.Models; -namespace Hutopy.Web.Creators.Handlers; +namespace Hutopy.Web.Features.Creators.Handlers; public class GetCreatorByAlias( IIdentityService identityService) From 997cbe2ddc9334e2e36e74e236ebfa8075456b5d Mon Sep 17 00:00:00 2001 From: Jonathan Bourdon Date: Sat, 20 Jul 2024 01:09:45 -0400 Subject: [PATCH 125/229] Adds CreatorAlias User responses --- src/Application/Common/Models/UserModel.cs | 1 + .../Queries/GetCurrentUser/GetCurrentUser.cs | 28 ++++++++++--------- .../Users/Queries/GetCurrentUser/UserDto.cs | 1 + .../Users/Queries/GetUser/UserDto.cs | 1 + .../Identity/IdentityService.cs | 3 ++ .../Creators/Handlers/GetCreatorByAlias.cs | 27 ++++++++++++++---- 6 files changed, 42 insertions(+), 19 deletions(-) diff --git a/src/Application/Common/Models/UserModel.cs b/src/Application/Common/Models/UserModel.cs index ccff715..d7324a1 100644 --- a/src/Application/Common/Models/UserModel.cs +++ b/src/Application/Common/Models/UserModel.cs @@ -5,6 +5,7 @@ namespace Hutopy.Application.Common.Models; public class UserModel { public string Id { get; set; } = string.Empty; + public string? CreatorAlias { get; set; } public string UserName { get; set; } = string.Empty; public string FirstName { get; set; } = string.Empty; public string LastName { get; set; } = string.Empty; diff --git a/src/Application/Users/Queries/GetCurrentUser/GetCurrentUser.cs b/src/Application/Users/Queries/GetCurrentUser/GetCurrentUser.cs index f8cc1ab..6a90585 100644 --- a/src/Application/Users/Queries/GetCurrentUser/GetCurrentUser.cs +++ b/src/Application/Users/Queries/GetCurrentUser/GetCurrentUser.cs @@ -16,7 +16,8 @@ public class GetCurrentUserQueryHandler( var identityUser = await identityService.GetCurrentUserAsync(); var currentUserId = Guid.Parse(identityUser!.Id!); - var transactions = await context.UserTransactions + var transactions = await context + .UserTransactions .Where(x => x.ApplicationUserId == currentUserId.ToString()) .OrderBy(x => x.LastModified) .ProjectTo(mapper.ConfigurationProvider) @@ -28,18 +29,19 @@ public class GetCurrentUserQueryHandler( var user = new UserDto { Id = currentUserId, - FirstName = identityUser.FirstName ?? "", - LastName = identityUser.LastName ?? "", - UserName = identityUser.UserName ?? "", - Occupation = identityUser.Occupation ?? "", - PhoneNumber = identityUser.PhoneNumber ?? "", - Email = identityUser.Email ?? "", - BirthDate = identityUser.BirthDate ?? "", - Country = identityUser.Country ?? "", - City = identityUser.City ?? "", - Address = identityUser.Address ?? "", - About = identityUser.About ?? "", - Description = identityUser.Description ?? "", + FirstName = identityUser.FirstName, + LastName = identityUser.LastName, + UserName = identityUser.UserName, + CreatorAlias= identityUser.CreatorAlias, + Occupation = identityUser.Occupation, + PhoneNumber = identityUser.PhoneNumber, + Email = identityUser.Email, + BirthDate = identityUser.BirthDate, + Country = identityUser.Country, + City = identityUser.City, + Address = identityUser.Address, + About = identityUser.About, + Description = identityUser.Description, SocialNetworks = identityUser.SocialNetworks, ProfileColors = identityUser.ProfileColors, StoredDataUrls = identityUser.StoredDataUrls, diff --git a/src/Application/Users/Queries/GetCurrentUser/UserDto.cs b/src/Application/Users/Queries/GetCurrentUser/UserDto.cs index 23dfaa8..4964a3b 100644 --- a/src/Application/Users/Queries/GetCurrentUser/UserDto.cs +++ b/src/Application/Users/Queries/GetCurrentUser/UserDto.cs @@ -7,6 +7,7 @@ public class UserDto public Guid Id { get; init; } public required string FirstName { get; init; } public required string LastName { get; init; } + public string? CreatorAlias { get; set; } public string UserName { get; init; } = string.Empty; public string Occupation { get; init; } = string.Empty; public string Email { get; init; } = string.Empty; diff --git a/src/Application/Users/Queries/GetUser/UserDto.cs b/src/Application/Users/Queries/GetUser/UserDto.cs index 509743d..6c1dc13 100644 --- a/src/Application/Users/Queries/GetUser/UserDto.cs +++ b/src/Application/Users/Queries/GetUser/UserDto.cs @@ -7,6 +7,7 @@ public class UserDto public required string Id { get; init; } public required string FirstName { get; init; } public required string LastName { get; init; } + public string CreatorAlias { get; set; } public required string UserName { get; init; } = String.Empty; public required string Occupation { get; init; } = String.Empty; diff --git a/src/Infrastructure/Identity/IdentityService.cs b/src/Infrastructure/Identity/IdentityService.cs index 4842668..747fff4 100644 --- a/src/Infrastructure/Identity/IdentityService.cs +++ b/src/Infrastructure/Identity/IdentityService.cs @@ -38,6 +38,7 @@ public class IdentityService( var userModel = new UserModel() { Id = response.Id, + CreatorAlias = response.CreatorAlias, UserName = response.UserName ?? string.Empty, FirstName = response.FirstName, LastName = response.LastName, @@ -189,6 +190,7 @@ public class IdentityService( var userModel = new UserModel { Id = response.Id, + CreatorAlias = response.CreatorAlias, UserName = response.UserName ?? string.Empty, FirstName = response.FirstName, LastName = response.LastName, @@ -238,6 +240,7 @@ public class IdentityService( var userModel = new UserModel { Id = response.Id, + CreatorAlias = response.CreatorAlias, UserName = response.UserName ?? string.Empty, FirstName = response.FirstName, LastName = response.LastName, diff --git a/src/Web/Features/Creators/Handlers/GetCreatorByAlias.cs b/src/Web/Features/Creators/Handlers/GetCreatorByAlias.cs index b606a13..0c798e9 100644 --- a/src/Web/Features/Creators/Handlers/GetCreatorByAlias.cs +++ b/src/Web/Features/Creators/Handlers/GetCreatorByAlias.cs @@ -1,12 +1,28 @@ using FastEndpoints; +using FluentValidation; using Hutopy.Application.Common.Interfaces; using Hutopy.Application.Common.Models; namespace Hutopy.Web.Features.Creators.Handlers; +public sealed class GetCreatorByAliasRequest +{ + public string CreatorAlias { get; set; } +} + +public sealed class GetCreatorByAliasRequestValidator + : Validator +{ + public GetCreatorByAliasRequestValidator() + { + RuleFor(r => r.CreatorAlias) + .NotNull().WithMessage("You must specify a creator-alias"); + } +} + public class GetCreatorByAlias( IIdentityService identityService) - : EndpointWithoutRequest + : Endpoint { public override void Configure() { @@ -16,13 +32,12 @@ public class GetCreatorByAlias( } public override async Task HandleAsync( + GetCreatorByAliasRequest req, CancellationToken ct) { - var creatorAlias = Route("CreatorAlias"); - - ArgumentException.ThrowIfNullOrEmpty(creatorAlias); - - var user = await identityService.FindUserByCreatorAliasAsync(creatorAlias, ct); + var user = await identityService.FindUserByCreatorAliasAsync( + req.CreatorAlias, + ct); await SendAsync(user, cancellation: ct); } From 06886a0e4a9d2e2f92f890fe66f2cc3accc48574 Mon Sep 17 00:00:00 2001 From: Jonathan Bourdon Date: Sat, 20 Jul 2024 03:07:18 -0400 Subject: [PATCH 126/229] Adds the possibility for the client to specify the message id when adding them --- src/Web/Features/Messages/Handlers/AddMessage.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Web/Features/Messages/Handlers/AddMessage.cs b/src/Web/Features/Messages/Handlers/AddMessage.cs index 222b781..fcb6df3 100644 --- a/src/Web/Features/Messages/Handlers/AddMessage.cs +++ b/src/Web/Features/Messages/Handlers/AddMessage.cs @@ -6,6 +6,7 @@ namespace Hutopy.Web.Features.Messages.Handlers; public class AddMessageRequest { + public Guid? Id { get; set; } public Guid SubjectId { get; set; } public string Message { get; set; } } @@ -26,7 +27,7 @@ public class AddMessage( { var message = new Message { - Id = GuidHelper.GenerateUuidV7(), + Id = req.Id ?? GuidHelper.GenerateUuidV7(), SubjectId = req.SubjectId, CreatedBy = User.GetUserId(), Value = req.Message From b513f10ed68a950e125c249fe7acd3c0206ab1be Mon Sep 17 00:00:00 2001 From: Jonathan Bourdon Date: Sat, 20 Jul 2024 04:32:11 -0400 Subject: [PATCH 127/229] Use uuidv7 algorithm from javascript --- src/Web/Common/GuidExtensions.cs | 108 ++++++++++++++++++++++++------- 1 file changed, 86 insertions(+), 22 deletions(-) diff --git a/src/Web/Common/GuidExtensions.cs b/src/Web/Common/GuidExtensions.cs index d02c4a7..0c71da8 100644 --- a/src/Web/Common/GuidExtensions.cs +++ b/src/Web/Common/GuidExtensions.cs @@ -1,30 +1,94 @@ -using System.Buffers.Binary; -using System.Security.Cryptography; - -namespace Hutopy.Web.Common; +namespace Hutopy.Web.Common; +/// +/// Adapted from https://raw.githubusercontent.com/uuidjs/uuid/main/src/v7.ts. +/// to match the uuidv7 generated on the client +/// public static class GuidHelper { - // TODO: Delete when NET9 is release! + private class V7State + { + public long Msecs { get; set; } = long.MinValue; + public int Seq { get; set; } + } + + private static readonly V7State State = new(); + private static readonly Random Random = new(); + public static Guid GenerateUuidV7() { - Span uuidv7 = stackalloc byte[16]; - ulong unixTimeTicks = (ulong)DateTimeOffset.UtcNow.Subtract(DateTimeOffset.UnixEpoch).Ticks; - ulong unixTsMs = (unixTimeTicks & 0x0FFFFFFFFFFFF000) << 4; - ulong unixTsMsVer = unixTsMs | 0b0111UL << 12; - ulong randA = unixTimeTicks & 0x0000000000000FFF; - // merge "unix_ts_ms", "ver" and "rand_a" - ulong hi = unixTsMsVer | randA; - BinaryPrimitives.WriteUInt64BigEndian(uuidv7, hi); - // fill "rand_b" and "var" - RandomNumberGenerator.Fill(uuidv7[8..]); - // set "var" - byte varOctet = uuidv7[8]; - varOctet = (byte)(varOctet & 0b00111111); - varOctet = (byte)(varOctet | 0b10111111); - uuidv7[8] = varOctet; + byte[] randomValues = new byte[16]; + Random.NextBytes(randomValues); + + UpdateV7State( + State, + DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(), + randomValues); + + var values = V7Bytes(randomValues, State.Msecs, State.Seq); + + return new(values); + } + + private static void UpdateV7State(V7State state, long now, byte[] rnds) + { + if (now > state.Msecs) + { + state.Seq = (rnds[6] << 23) | (rnds[7] << 16) | (rnds[8] << 8) | rnds[9]; + state.Msecs = now; + } + else + { + state.Seq = (state.Seq + 1) | 0; + if (state.Seq == 0) + { + state.Msecs++; + } + } + } + + private static byte[] V7Bytes(byte[] rnds, long? msecs = null, int? seq = null, byte[] buf = null, int offset = 0) + { + if (buf == null) + { + buf = new byte[16]; + offset = 0; + } + + // Defaults + msecs ??= DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(); + seq ??= ((rnds[6] & 0x7f) << 24) | (rnds[7] << 16) | (rnds[8] << 8) | rnds[9]; + + // byte 0-5: timestamp (48 bits) + buf[offset++] = (byte)((msecs.Value / 0x10000000000) & 0xff); + buf[offset++] = (byte)((msecs.Value / 0x100000000) & 0xff); + buf[offset++] = (byte)((msecs.Value / 0x1000000) & 0xff); + buf[offset++] = (byte)((msecs.Value / 0x10000) & 0xff); + buf[offset++] = (byte)((msecs.Value / 0x100) & 0xff); + buf[offset++] = (byte)(msecs.Value & 0xff); - var value = Convert.ToHexString(uuidv7); - return Guid.Parse(value); + // byte 6: `version` (4 bits) | sequence bits 28-31 (4 bits) + buf[offset++] = (byte)(0x70 | ((seq.Value >> 28) & 0x0f)); + + // byte 7: sequence bits 20-27 (8 bits) + buf[offset++] = (byte)((seq.Value >> 20) & 0xff); + + // byte 8: `variant` (2 bits) | sequence bits 14-19 (6 bits) + buf[offset++] = (byte)(0x80 | ((seq.Value >> 14) & 0x3f)); + + // byte 9: sequence bits 6-13 (8 bits) + buf[offset++] = (byte)((seq.Value >> 6) & 0xff); + + // byte 10: sequence bits 0-5 (6 bits) | random (2 bits) + buf[offset++] = (byte)(((seq.Value << 2) & 0xff) | (rnds[10] & 0x03)); + + // bytes 11-15: random (40 bits) + buf[offset++] = rnds[11]; + buf[offset++] = rnds[12]; + buf[offset++] = rnds[13]; + buf[offset++] = rnds[14]; + buf[offset++] = rnds[15]; + + return buf; } } From 06fccdee804d9d37967936bbb9959c100f76bccf Mon Sep 17 00:00:00 2001 From: Jonathan Bourdon Date: Sat, 20 Jul 2024 04:35:05 -0400 Subject: [PATCH 128/229] TestData generation is starts in the past now --- src/Web/TestDataSeeder.cs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Web/TestDataSeeder.cs b/src/Web/TestDataSeeder.cs index 84f56b3..c357ade 100644 --- a/src/Web/TestDataSeeder.cs +++ b/src/Web/TestDataSeeder.cs @@ -65,7 +65,7 @@ internal class TestDataSeeder( var contents = new List(); - for (var c = 0; c < contentCount; c++) + for (var c = contentCount; c > 0; c--) { var content = new Content { @@ -80,7 +80,7 @@ internal class TestDataSeeder( contents.Add(content); - currentDate = currentDate.AddSeconds(Random.Shared.Next(100, 100_000)); + currentDate = currentDate.AddSeconds(-Random.Shared.Next(100, 100_000)); } contentContext.SaveChanges(); @@ -93,9 +93,9 @@ internal class TestDataSeeder( var currentDate = content.CreatedAt; var messages = new List(); - for (var m = 0; m < messageCount; m++) + for (var m = messageCount; m > 0; m--) { - currentDate = currentDate.AddSeconds(Random.Shared.Next(100, 100_000)); + currentDate = currentDate.AddSeconds(-Random.Shared.Next(100, 100_000)); var author = Random.Shared.GetItems(_creators, 1)[0]; var message = new Message @@ -120,10 +120,10 @@ internal class TestDataSeeder( var currentDate = parent.CreatedAt; var replies = new List(); - for (var r = 0; r < replyCount; r++) + for (var r = replyCount; r > 0; r--) { - currentDate = currentDate.AddSeconds(Random.Shared.Next(100, 100_000)); - + currentDate = currentDate.AddSeconds(-Random.Shared.Next(100, 100_000)); + var author = Random.Shared.GetItems(_creators, 1)[0]; var message = new Message From f256adadcaf9b340678a5af2441f93e28f57d91d Mon Sep 17 00:00:00 2001 From: Jonathan Bourdon Date: Sat, 20 Jul 2024 04:35:34 -0400 Subject: [PATCH 129/229] Fix some edge cases in the streaming of messages --- .../Features/Messages/Handlers/GetMessages.cs | 22 +++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/src/Web/Features/Messages/Handlers/GetMessages.cs b/src/Web/Features/Messages/Handlers/GetMessages.cs index 188dd7e..242558f 100644 --- a/src/Web/Features/Messages/Handlers/GetMessages.cs +++ b/src/Web/Features/Messages/Handlers/GetMessages.cs @@ -31,12 +31,26 @@ public class GetMessages( .Where(c => c.SubjectId == req.SubjectId) .Where(c => c.ParentId == null); - query = query.OrderByDescending(c => c.CreatedAt); + if (req.LastId.HasValue) + { + var lastMessage = await context + .Messages + .Where(c => c.Id == req.LastId.Value) + .Select(c => new { c.CreatedAt, c.Id }) + .FirstOrDefaultAsync(cancellationToken: ct); - if (req.LastId is not null) - query = query.Where(c => c.Id < req.LastId.Value); + if (lastMessage != null) + { + query = query + .Where(c => c.CreatedAt < lastMessage.CreatedAt + || (c.CreatedAt == lastMessage.CreatedAt && c.Id < lastMessage.Id)); + } + } - query = query.Take(req.PageSize); + query = query + .OrderByDescending(c => c.CreatedAt) + .ThenByDescending(c => c.Id) + .Take(req.PageSize); var messages = await query.ToListAsync(cancellationToken: ct); From 8551398edca5765b592976e7a49326014beac7c6 Mon Sep 17 00:00:00 2001 From: Jonathan Bourdon Date: Mon, 22 Jul 2024 00:31:01 -0400 Subject: [PATCH 130/229] Adds update-databases.sh script --- Hutopy.sln | 1 + update-databases.sh | 17 +++++++++++++++++ 2 files changed, 18 insertions(+) create mode 100644 update-databases.sh diff --git a/Hutopy.sln b/Hutopy.sln index feb84bd..cf13057 100644 --- a/Hutopy.sln +++ b/Hutopy.sln @@ -27,6 +27,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution README.md = README.md start-infrastructure.sh = start-infrastructure.sh azure-pipelines.yml = azure-pipelines.yml + update-databases.sh = update-databases.sh EndProjectSection EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Web", "src\Web\Web.csproj", "{4E4EE20C-F06A-4A1B-851F-C5577796941C}" diff --git a/update-databases.sh b/update-databases.sh new file mode 100644 index 0000000..17a1244 --- /dev/null +++ b/update-databases.sh @@ -0,0 +1,17 @@ +#!/bin/bash + +dotnet ef database update \ + --project src/Web/Web.csproj \ + --startup-project src/Web/Web.csproj \ + --context Hutopy.Web.Features.Messages.Data.MessagingDbContext \ + --configuration Debug \ + --no-build \ + --connection Server=localhost,5432;Database=Hutopy;Uid=sa;Pwd=P@ssword123!; + + dotnet ef database update \ + --project src/Web/Web.csproj \ + --startup-project src/Web/Web.csproj \ + --context Hutopy.Web.Features.Contents.Data.ContentDbContext \ + --configuration Debug \ + --no-build \ + --connection Server=localhost,5432;Database=Hutopy;Uid=sa;Pwd=P@ssword123!; From 0faf5a9a0e10c99337bafab4765bdd55ac6e9b1b Mon Sep 17 00:00:00 2001 From: Jonathan Bourdon Date: Mon, 22 Jul 2024 00:42:27 -0400 Subject: [PATCH 131/229] Adds user Alias. Make StoredDataUrls optionals. --- src/Application/Common/Models/UserModel.cs | 1 + .../Users/Models/StoredDataUrlsModel.cs | 6 +- .../Queries/GetCurrentUser/GetCurrentUser.cs | 1 + .../Users/Queries/GetCurrentUser/UserDto.cs | 1 + .../Identity/ApplicationUser.cs | 5 +- .../Identity/IdentityService.cs | 93 ++- .../Identity/OwnedEntities/StoredDataUrls.cs | 10 +- .../20240721045147_AddAlias.Designer.cs | 563 ++++++++++++++++++ .../Migrations/20240721045147_AddAlias.cs | 28 + ...35_MadeOptional_StoredDataUrls.Designer.cs | 563 ++++++++++++++++++ ...40721063535_MadeOptional_StoredDataUrls.cs | 78 +++ .../ApplicationDbContextModelSnapshot.cs | 17 +- src/Infrastructure/Utils/GenerateJwtToken.cs | 24 +- src/Infrastructure/Utils/KnownClaims.cs | 7 + src/Web/Common/ClaimsPrincipalExtensions.cs | 36 +- src/Web/Controllers/GoogleController.cs | 1 + src/Web/Features/Messages/Data/Message.cs | 18 +- .../Messages/Data/MessagingDbContext.cs | 43 +- .../Features/Messages/Handlers/AddMessage.cs | 24 +- .../Features/Messages/Handlers/AddReply.cs | 28 +- .../Features/Messages/Handlers/GetMessages.cs | 51 +- .../Messages/Handlers/GetMessagesByUser.cs | 19 +- .../Features/Messages/Handlers/GetReplies.cs | 35 +- .../Messages/Handlers/Models/MessageDto.cs | 30 + ....cs => 20240721041322_Initial.Designer.cs} | 13 +- ...6_Initial.cs => 20240721041322_Initial.cs} | 4 +- ...064224_ChangedAuthorDefinition.Designer.cs | 69 +++ .../20240721064224_ChangedAuthorDefinition.cs | 60 ++ .../MessagingDbContextModelSnapshot.cs | 13 +- src/Web/TestDataSeeder.cs | 46 +- tests/Application.FunctionalTests/Testing.cs | 7 +- 31 files changed, 1720 insertions(+), 174 deletions(-) create mode 100644 src/Infrastructure/Migrations/20240721045147_AddAlias.Designer.cs create mode 100644 src/Infrastructure/Migrations/20240721045147_AddAlias.cs create mode 100644 src/Infrastructure/Migrations/20240721063535_MadeOptional_StoredDataUrls.Designer.cs create mode 100644 src/Infrastructure/Migrations/20240721063535_MadeOptional_StoredDataUrls.cs create mode 100644 src/Infrastructure/Utils/KnownClaims.cs create mode 100644 src/Web/Features/Messages/Handlers/Models/MessageDto.cs rename src/Web/Features/Messages/Migrations/{20240718173016_Initial.Designer.cs => 20240721041322_Initial.Designer.cs} (81%) rename src/Web/Features/Messages/Migrations/{20240718173016_Initial.cs => 20240721041322_Initial.cs} (86%) create mode 100644 src/Web/Features/Messages/Migrations/20240721064224_ChangedAuthorDefinition.Designer.cs create mode 100644 src/Web/Features/Messages/Migrations/20240721064224_ChangedAuthorDefinition.cs diff --git a/src/Application/Common/Models/UserModel.cs b/src/Application/Common/Models/UserModel.cs index d7324a1..f67d8a9 100644 --- a/src/Application/Common/Models/UserModel.cs +++ b/src/Application/Common/Models/UserModel.cs @@ -7,6 +7,7 @@ public class UserModel public string Id { get; set; } = string.Empty; public string? CreatorAlias { get; set; } public string UserName { get; set; } = string.Empty; + public string? Alias { get; set; } public string FirstName { get; set; } = string.Empty; public string LastName { get; set; } = string.Empty; public string Occupation { get; set; } = string.Empty; diff --git a/src/Application/Users/Models/StoredDataUrlsModel.cs b/src/Application/Users/Models/StoredDataUrlsModel.cs index 0539508..06eb528 100644 --- a/src/Application/Users/Models/StoredDataUrlsModel.cs +++ b/src/Application/Users/Models/StoredDataUrlsModel.cs @@ -2,7 +2,7 @@ public class StoredDataUrlsModel { - public string BannerPictureUrl { get; set; } = string.Empty; - public string ProfilePictureUrl { get; set; } = string.Empty; - public string WebsiteIconUrl { get; set; } = string.Empty; + public string? BannerPictureUrl { get; set; } + public string? ProfilePictureUrl { get; set; } + public string? WebsiteIconUrl { get; set; } } diff --git a/src/Application/Users/Queries/GetCurrentUser/GetCurrentUser.cs b/src/Application/Users/Queries/GetCurrentUser/GetCurrentUser.cs index 6a90585..4429bed 100644 --- a/src/Application/Users/Queries/GetCurrentUser/GetCurrentUser.cs +++ b/src/Application/Users/Queries/GetCurrentUser/GetCurrentUser.cs @@ -29,6 +29,7 @@ public class GetCurrentUserQueryHandler( var user = new UserDto { Id = currentUserId, + Alias = identityUser.Alias, FirstName = identityUser.FirstName, LastName = identityUser.LastName, UserName = identityUser.UserName, diff --git a/src/Application/Users/Queries/GetCurrentUser/UserDto.cs b/src/Application/Users/Queries/GetCurrentUser/UserDto.cs index 4964a3b..3560de2 100644 --- a/src/Application/Users/Queries/GetCurrentUser/UserDto.cs +++ b/src/Application/Users/Queries/GetCurrentUser/UserDto.cs @@ -5,6 +5,7 @@ namespace Hutopy.Application.Users.Queries.GetCurrentUser; public class UserDto { public Guid Id { get; init; } + public string? Alias { get; init; } public required string FirstName { get; init; } public required string LastName { get; init; } public string? CreatorAlias { get; set; } diff --git a/src/Infrastructure/Identity/ApplicationUser.cs b/src/Infrastructure/Identity/ApplicationUser.cs index 74ad0cf..9b7ebdd 100644 --- a/src/Infrastructure/Identity/ApplicationUser.cs +++ b/src/Infrastructure/Identity/ApplicationUser.cs @@ -5,8 +5,9 @@ namespace Hutopy.Infrastructure.Identity; public class ApplicationUser : IdentityUser { - public string FirstName { get; set; } = string.Empty; - public string LastName { get; set; } = string.Empty; + public string? Alias { get; set; } + public required string FirstName { get; set; } + public required string LastName { get; set; } public string? CreatorAlias { get; set; } public string Occupation { get; set; } = string.Empty; public string BirthDate { get; set; } = string.Empty; diff --git a/src/Infrastructure/Identity/IdentityService.cs b/src/Infrastructure/Identity/IdentityService.cs index 747fff4..beaab6b 100644 --- a/src/Infrastructure/Identity/IdentityService.cs +++ b/src/Infrastructure/Identity/IdentityService.cs @@ -2,8 +2,6 @@ using Google.Apis.Oauth2.v2.Data; using System.Security.Claims; using Hutopy.Application.Common.Interfaces; using Hutopy.Application.Common.Models; -using Hutopy.Application.Users.Models; -using Hutopy.Infrastructure.Identity.OwnedEntities; using Hutopy.Infrastructure.Utils; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; @@ -31,53 +29,52 @@ public class IdentityService( public async Task GetUserByUserNameAsync(string userName) { - var response = await userManager.FindByNameAsync(userName); + var user = await userManager.FindByNameAsync(userName); - if (response == null) return null; + if (user == null) return null; - var userModel = new UserModel() + return new() { - Id = response.Id, - CreatorAlias = response.CreatorAlias, - UserName = response.UserName ?? string.Empty, - FirstName = response.FirstName, - LastName = response.LastName, - Email = response.Email ?? string.Empty, - Occupation = response.Occupation, - PhoneNumber = response.PhoneNumber ?? string.Empty, - BirthDate = response.BirthDate, - Country = response.Country, - City = response.City, - Address = response.Address, - About = response.About, - Description = response.Description, - SocialNetworks = new SocialNetworksModel + Id = user.Id, + CreatorAlias = user.CreatorAlias, + UserName = user.UserName ?? string.Empty, + Alias = user.Alias, + FirstName = user.FirstName, + LastName = user.LastName, + Email = user.Email ?? string.Empty, + Occupation = user.Occupation, + PhoneNumber = user.PhoneNumber ?? string.Empty, + BirthDate = user.BirthDate, + Country = user.Country, + City = user.City, + Address = user.Address, + About = user.About, + Description = user.Description, + SocialNetworks = new() { - FacebookUrl = response.SocialNetworks.FacebookUrl, - InstagramUrl = response.SocialNetworks.InstagramUrl, - XUrl = response.SocialNetworks.XUrl, - LinkedInUrl = response.SocialNetworks.LinkedInUrl, - TikTokUrl = response.SocialNetworks.TikTokUrl, - YoutubeUrl = response.SocialNetworks.YoutubeUrl, - RedditUrl = response.SocialNetworks.RedditUrl, - YourWebsiteUrl = response.SocialNetworks.YourWebsiteUrl, + FacebookUrl = user.SocialNetworks.FacebookUrl, + InstagramUrl = user.SocialNetworks.InstagramUrl, + XUrl = user.SocialNetworks.XUrl, + LinkedInUrl = user.SocialNetworks.LinkedInUrl, + TikTokUrl = user.SocialNetworks.TikTokUrl, + YoutubeUrl = user.SocialNetworks.YoutubeUrl, + RedditUrl = user.SocialNetworks.RedditUrl, + YourWebsiteUrl = user.SocialNetworks.YourWebsiteUrl, }, - ProfileColors = new ProfileColorsModel + ProfileColors = new() { - BannerTop = response.ProfileColors.BannerTop, - BannerBottom = response.ProfileColors.BannerBottom, - Accent = response.ProfileColors.Accent, - Menu = response.ProfileColors.Menu + BannerTop = user.ProfileColors.BannerTop, + BannerBottom = user.ProfileColors.BannerBottom, + Accent = user.ProfileColors.Accent, + Menu = user.ProfileColors.Menu }, - StoredDataUrls = new StoredDataUrlsModel + StoredDataUrls = new() { - ProfilePictureUrl = response.StoredDataUrls.ProfilePictureUrl, - BannerPictureUrl = response.StoredDataUrls.BannerPictureUrl, - WebsiteIconUrl = response.StoredDataUrls.WebsiteIconUrl, + ProfilePictureUrl = user.StoredDataUrls.ProfilePictureUrl, + BannerPictureUrl = user.StoredDataUrls.BannerPictureUrl, + WebsiteIconUrl = user.StoredDataUrls.WebsiteIconUrl, } }; - - return userModel; } public async Task> CreateUserAsync(Userinfo userInfo) @@ -134,7 +131,7 @@ public class IdentityService( applicationUser.Address = userModel.Address; applicationUser.About = userModel.About; applicationUser.Description = userModel.Description; - applicationUser.SocialNetworks = new SocialNetworks + applicationUser.SocialNetworks = new() { FacebookUrl = userModel.SocialNetworks.FacebookUrl, InstagramUrl = userModel.SocialNetworks.InstagramUrl, @@ -145,7 +142,7 @@ public class IdentityService( RedditUrl = userModel.SocialNetworks.RedditUrl, YourWebsiteUrl = userModel.SocialNetworks.YourWebsiteUrl }; - applicationUser.ProfileColors = new ProfileColors + applicationUser.ProfileColors = new() { BannerTop = userModel.ProfileColors.BannerTop, BannerBottom = userModel.ProfileColors.BannerBottom, @@ -192,6 +189,7 @@ public class IdentityService( Id = response.Id, CreatorAlias = response.CreatorAlias, UserName = response.UserName ?? string.Empty, + Alias = response.Alias, FirstName = response.FirstName, LastName = response.LastName, Email = response.Email ?? string.Empty, @@ -203,7 +201,7 @@ public class IdentityService( Address = response.Address, About = response.About, Description = response.Description, - SocialNetworks = new SocialNetworksModel + SocialNetworks = new() { FacebookUrl = response.SocialNetworks.FacebookUrl, InstagramUrl = response.SocialNetworks.InstagramUrl, @@ -214,14 +212,14 @@ public class IdentityService( RedditUrl = response.SocialNetworks.RedditUrl, YourWebsiteUrl = response.SocialNetworks.YourWebsiteUrl, }, - ProfileColors = new ProfileColorsModel + ProfileColors = new() { BannerTop = response.ProfileColors.BannerTop, BannerBottom = response.ProfileColors.BannerBottom, Accent = response.ProfileColors.Accent, Menu = response.ProfileColors.Menu }, - StoredDataUrls = new StoredDataUrlsModel + StoredDataUrls = new() { ProfilePictureUrl = response.StoredDataUrls.ProfilePictureUrl, BannerPictureUrl = response.StoredDataUrls.BannerPictureUrl, @@ -253,7 +251,7 @@ public class IdentityService( Address = response.Address, About = response.About, Description = response.Description, - SocialNetworks = new SocialNetworksModel + SocialNetworks = new() { FacebookUrl = response.SocialNetworks.FacebookUrl, InstagramUrl = response.SocialNetworks.InstagramUrl, @@ -264,14 +262,14 @@ public class IdentityService( RedditUrl = response.SocialNetworks.RedditUrl, YourWebsiteUrl = response.SocialNetworks.YourWebsiteUrl, }, - ProfileColors = new ProfileColorsModel + ProfileColors = new() { BannerTop = response.ProfileColors.BannerTop, BannerBottom = response.ProfileColors.BannerBottom, Accent = response.ProfileColors.Accent, Menu = response.ProfileColors.Menu }, - StoredDataUrls = new StoredDataUrlsModel + StoredDataUrls = new() { ProfilePictureUrl = response.StoredDataUrls.ProfilePictureUrl, BannerPictureUrl = response.StoredDataUrls.BannerPictureUrl, @@ -431,6 +429,7 @@ public class IdentityService( key: jwtOptions.Value.Key, userId: user.Id, email: user.Email, + alias: user.Alias, firstname: user.FirstName, lastname: user.LastName, profilePictureUrl: user.StoredDataUrls.ProfilePictureUrl); diff --git a/src/Infrastructure/Identity/OwnedEntities/StoredDataUrls.cs b/src/Infrastructure/Identity/OwnedEntities/StoredDataUrls.cs index bea6099..53d5346 100644 --- a/src/Infrastructure/Identity/OwnedEntities/StoredDataUrls.cs +++ b/src/Infrastructure/Identity/OwnedEntities/StoredDataUrls.cs @@ -1,8 +1,10 @@ -namespace Hutopy.Infrastructure.Identity.OwnedEntities; +using System.ComponentModel.DataAnnotations; + +namespace Hutopy.Infrastructure.Identity.OwnedEntities; public class StoredDataUrls { - public string BannerPictureUrl { get; set; } = string.Empty; - public string ProfilePictureUrl { get; set; } = string.Empty; - public string WebsiteIconUrl { get; set; } = string.Empty; + [MaxLength(255)] public string? BannerPictureUrl { get; set; } + [MaxLength(255)] public string? ProfilePictureUrl { get; set; } + [MaxLength(255)] public string? WebsiteIconUrl { get; set; } } diff --git a/src/Infrastructure/Migrations/20240721045147_AddAlias.Designer.cs b/src/Infrastructure/Migrations/20240721045147_AddAlias.Designer.cs new file mode 100644 index 0000000..397d04b --- /dev/null +++ b/src/Infrastructure/Migrations/20240721045147_AddAlias.Designer.cs @@ -0,0 +1,563 @@ +// +using System; +using Hutopy.Infrastructure.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Hutopy.Infrastructure.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + [Migration("20240721045147_AddAlias")] + partial class AddAlias + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.4") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("Hutopy.Domain.Entities.FutureCreator", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Created") + .HasColumnType("datetimeoffset"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("EmailAddress") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("FirstName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("LastModified") + .HasColumnType("datetimeoffset"); + + b.Property("LastModifiedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("LastName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumber") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("ReasonToJoin") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("SocialNetworkAccount") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("FutureCreators"); + }); + + modelBuilder.Entity("Hutopy.Domain.Entities.UserTransaction", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Amount") + .HasPrecision(18, 2) + .HasColumnType("decimal(18,2)"); + + b.Property("ApplicationUserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.Property("Created") + .HasColumnType("datetimeoffset"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("Currency") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("IsConfirmed") + .HasColumnType("bit"); + + b.Property("LastModified") + .HasColumnType("datetimeoffset"); + + b.Property("LastModifiedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("Paid") + .HasColumnType("bit"); + + b.Property("StripeBillingDetailEmail") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("StripeBillingDetailName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("StripeChargeId") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("StripeEventId") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("StripePaymentIntent") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("StripePaymentMethod") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("StripeReceiptUrl") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("TipMessage") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationUserId"); + + b.ToTable("UserTransactions"); + }); + + modelBuilder.Entity("Hutopy.Infrastructure.Identity.ApplicationUser", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("About") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("AccessFailedCount") + .HasColumnType("int"); + + b.Property("Address") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Alias") + .HasColumnType("nvarchar(max)"); + + b.Property("BirthDate") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("City") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("nvarchar(max)"); + + b.Property("Country") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("CreatorAlias") + .HasColumnType("nvarchar(max)"); + + b.Property("Description") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("EmailConfirmed") + .HasColumnType("bit"); + + b.Property("FirstName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("LastName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("LockoutEnabled") + .HasColumnType("bit"); + + b.Property("LockoutEnd") + .HasColumnType("datetimeoffset"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("Occupation") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("PasswordHash") + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumber") + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("bit"); + + b.Property("SecurityStamp") + .HasColumnType("nvarchar(max)"); + + b.Property("TwoFactorEnabled") + .HasColumnType("bit"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex") + .HasFilter("[NormalizedUserName] IS NOT NULL"); + + b.ToTable("AspNetUsers", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("nvarchar(max)"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex") + .HasFilter("[NormalizedName] IS NOT NULL"); + + b.ToTable("AspNetRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("nvarchar(max)"); + + b.Property("ClaimValue") + .HasColumnType("nvarchar(max)"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("nvarchar(max)"); + + b.Property("ClaimValue") + .HasColumnType("nvarchar(max)"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("nvarchar(450)"); + + b.Property("ProviderKey") + .HasColumnType("nvarchar(450)"); + + b.Property("ProviderDisplayName") + .HasColumnType("nvarchar(max)"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("nvarchar(450)"); + + b.Property("RoleId") + .HasColumnType("nvarchar(450)"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("nvarchar(450)"); + + b.Property("LoginProvider") + .HasColumnType("nvarchar(450)"); + + b.Property("Name") + .HasColumnType("nvarchar(450)"); + + b.Property("Value") + .HasColumnType("nvarchar(max)"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens", (string)null); + }); + + modelBuilder.Entity("Hutopy.Domain.Entities.UserTransaction", b => + { + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("ApplicationUserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Hutopy.Infrastructure.Identity.ApplicationUser", b => + { + b.OwnsOne("Hutopy.Infrastructure.Identity.OwnedEntities.ProfileColors", "ProfileColors", b1 => + { + b1.Property("ApplicationUserId") + .HasColumnType("nvarchar(450)"); + + b1.Property("Accent") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.Property("BannerBottom") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.Property("BannerTop") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.Property("Menu") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.HasKey("ApplicationUserId"); + + b1.ToTable("ApplicationUser_ProfileColors", (string)null); + + b1.WithOwner() + .HasForeignKey("ApplicationUserId"); + }); + + b.OwnsOne("Hutopy.Infrastructure.Identity.OwnedEntities.SocialNetworks", "SocialNetworks", b1 => + { + b1.Property("ApplicationUserId") + .HasColumnType("nvarchar(450)"); + + b1.Property("FacebookUrl") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.Property("InstagramUrl") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.Property("LinkedInUrl") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.Property("RedditUrl") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.Property("TikTokUrl") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.Property("XUrl") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.Property("YourWebsiteUrl") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.Property("YoutubeUrl") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.HasKey("ApplicationUserId"); + + b1.ToTable("ApplicationUser_SocialNetworks", (string)null); + + b1.WithOwner() + .HasForeignKey("ApplicationUserId"); + }); + + b.OwnsOne("Hutopy.Infrastructure.Identity.OwnedEntities.StoredDataUrls", "StoredDataUrls", b1 => + { + b1.Property("ApplicationUserId") + .HasColumnType("nvarchar(450)"); + + b1.Property("BannerPictureUrl") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.Property("ProfilePictureUrl") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.Property("WebsiteIconUrl") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.HasKey("ApplicationUserId"); + + b1.ToTable("ApplicationUser_StoredDataUrls", (string)null); + + b1.WithOwner() + .HasForeignKey("ApplicationUserId"); + }); + + b.Navigation("ProfileColors") + .IsRequired(); + + b.Navigation("SocialNetworks") + .IsRequired(); + + b.Navigation("StoredDataUrls") + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Infrastructure/Migrations/20240721045147_AddAlias.cs b/src/Infrastructure/Migrations/20240721045147_AddAlias.cs new file mode 100644 index 0000000..9c8ffc9 --- /dev/null +++ b/src/Infrastructure/Migrations/20240721045147_AddAlias.cs @@ -0,0 +1,28 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Hutopy.Infrastructure.Migrations +{ + /// + public partial class AddAlias : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "Alias", + table: "AspNetUsers", + type: "nvarchar(max)", + nullable: true); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "Alias", + table: "AspNetUsers"); + } + } +} diff --git a/src/Infrastructure/Migrations/20240721063535_MadeOptional_StoredDataUrls.Designer.cs b/src/Infrastructure/Migrations/20240721063535_MadeOptional_StoredDataUrls.Designer.cs new file mode 100644 index 0000000..142d953 --- /dev/null +++ b/src/Infrastructure/Migrations/20240721063535_MadeOptional_StoredDataUrls.Designer.cs @@ -0,0 +1,563 @@ +// +using System; +using Hutopy.Infrastructure.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Hutopy.Infrastructure.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + [Migration("20240721063535_MadeOptional_StoredDataUrls")] + partial class MadeOptional_StoredDataUrls + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.4") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("Hutopy.Domain.Entities.FutureCreator", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Created") + .HasColumnType("datetimeoffset"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("EmailAddress") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("FirstName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("LastModified") + .HasColumnType("datetimeoffset"); + + b.Property("LastModifiedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("LastName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumber") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("ReasonToJoin") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("SocialNetworkAccount") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("FutureCreators"); + }); + + modelBuilder.Entity("Hutopy.Domain.Entities.UserTransaction", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Amount") + .HasPrecision(18, 2) + .HasColumnType("decimal(18,2)"); + + b.Property("ApplicationUserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.Property("Created") + .HasColumnType("datetimeoffset"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("Currency") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("IsConfirmed") + .HasColumnType("bit"); + + b.Property("LastModified") + .HasColumnType("datetimeoffset"); + + b.Property("LastModifiedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("Paid") + .HasColumnType("bit"); + + b.Property("StripeBillingDetailEmail") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("StripeBillingDetailName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("StripeChargeId") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("StripeEventId") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("StripePaymentIntent") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("StripePaymentMethod") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("StripeReceiptUrl") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("TipMessage") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationUserId"); + + b.ToTable("UserTransactions"); + }); + + modelBuilder.Entity("Hutopy.Infrastructure.Identity.ApplicationUser", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("About") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("AccessFailedCount") + .HasColumnType("int"); + + b.Property("Address") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Alias") + .HasColumnType("nvarchar(max)"); + + b.Property("BirthDate") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("City") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("nvarchar(max)"); + + b.Property("Country") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("CreatorAlias") + .HasColumnType("nvarchar(max)"); + + b.Property("Description") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("EmailConfirmed") + .HasColumnType("bit"); + + b.Property("FirstName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("LastName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("LockoutEnabled") + .HasColumnType("bit"); + + b.Property("LockoutEnd") + .HasColumnType("datetimeoffset"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("Occupation") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("PasswordHash") + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumber") + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("bit"); + + b.Property("SecurityStamp") + .HasColumnType("nvarchar(max)"); + + b.Property("TwoFactorEnabled") + .HasColumnType("bit"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex") + .HasFilter("[NormalizedUserName] IS NOT NULL"); + + b.ToTable("AspNetUsers", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("nvarchar(max)"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex") + .HasFilter("[NormalizedName] IS NOT NULL"); + + b.ToTable("AspNetRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("nvarchar(max)"); + + b.Property("ClaimValue") + .HasColumnType("nvarchar(max)"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("nvarchar(max)"); + + b.Property("ClaimValue") + .HasColumnType("nvarchar(max)"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("nvarchar(450)"); + + b.Property("ProviderKey") + .HasColumnType("nvarchar(450)"); + + b.Property("ProviderDisplayName") + .HasColumnType("nvarchar(max)"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("nvarchar(450)"); + + b.Property("RoleId") + .HasColumnType("nvarchar(450)"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("nvarchar(450)"); + + b.Property("LoginProvider") + .HasColumnType("nvarchar(450)"); + + b.Property("Name") + .HasColumnType("nvarchar(450)"); + + b.Property("Value") + .HasColumnType("nvarchar(max)"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens", (string)null); + }); + + modelBuilder.Entity("Hutopy.Domain.Entities.UserTransaction", b => + { + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("ApplicationUserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Hutopy.Infrastructure.Identity.ApplicationUser", b => + { + b.OwnsOne("Hutopy.Infrastructure.Identity.OwnedEntities.ProfileColors", "ProfileColors", b1 => + { + b1.Property("ApplicationUserId") + .HasColumnType("nvarchar(450)"); + + b1.Property("Accent") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.Property("BannerBottom") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.Property("BannerTop") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.Property("Menu") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.HasKey("ApplicationUserId"); + + b1.ToTable("ApplicationUser_ProfileColors", (string)null); + + b1.WithOwner() + .HasForeignKey("ApplicationUserId"); + }); + + b.OwnsOne("Hutopy.Infrastructure.Identity.OwnedEntities.SocialNetworks", "SocialNetworks", b1 => + { + b1.Property("ApplicationUserId") + .HasColumnType("nvarchar(450)"); + + b1.Property("FacebookUrl") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.Property("InstagramUrl") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.Property("LinkedInUrl") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.Property("RedditUrl") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.Property("TikTokUrl") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.Property("XUrl") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.Property("YourWebsiteUrl") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.Property("YoutubeUrl") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.HasKey("ApplicationUserId"); + + b1.ToTable("ApplicationUser_SocialNetworks", (string)null); + + b1.WithOwner() + .HasForeignKey("ApplicationUserId"); + }); + + b.OwnsOne("Hutopy.Infrastructure.Identity.OwnedEntities.StoredDataUrls", "StoredDataUrls", b1 => + { + b1.Property("ApplicationUserId") + .HasColumnType("nvarchar(450)"); + + b1.Property("BannerPictureUrl") + .HasMaxLength(255) + .HasColumnType("nvarchar(255)"); + + b1.Property("ProfilePictureUrl") + .HasMaxLength(255) + .HasColumnType("nvarchar(255)"); + + b1.Property("WebsiteIconUrl") + .HasMaxLength(255) + .HasColumnType("nvarchar(255)"); + + b1.HasKey("ApplicationUserId"); + + b1.ToTable("ApplicationUser_StoredDataUrls", (string)null); + + b1.WithOwner() + .HasForeignKey("ApplicationUserId"); + }); + + b.Navigation("ProfileColors") + .IsRequired(); + + b.Navigation("SocialNetworks") + .IsRequired(); + + b.Navigation("StoredDataUrls") + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Infrastructure/Migrations/20240721063535_MadeOptional_StoredDataUrls.cs b/src/Infrastructure/Migrations/20240721063535_MadeOptional_StoredDataUrls.cs new file mode 100644 index 0000000..b3085ae --- /dev/null +++ b/src/Infrastructure/Migrations/20240721063535_MadeOptional_StoredDataUrls.cs @@ -0,0 +1,78 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Hutopy.Infrastructure.Migrations +{ + /// + public partial class MadeOptional_StoredDataUrls : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AlterColumn( + name: "WebsiteIconUrl", + table: "ApplicationUser_StoredDataUrls", + type: "nvarchar(255)", + maxLength: 255, + nullable: true, + oldClrType: typeof(string), + oldType: "nvarchar(max)"); + + migrationBuilder.AlterColumn( + name: "ProfilePictureUrl", + table: "ApplicationUser_StoredDataUrls", + type: "nvarchar(255)", + maxLength: 255, + nullable: true, + oldClrType: typeof(string), + oldType: "nvarchar(max)"); + + migrationBuilder.AlterColumn( + name: "BannerPictureUrl", + table: "ApplicationUser_StoredDataUrls", + type: "nvarchar(255)", + maxLength: 255, + nullable: true, + oldClrType: typeof(string), + oldType: "nvarchar(max)"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.AlterColumn( + name: "WebsiteIconUrl", + table: "ApplicationUser_StoredDataUrls", + type: "nvarchar(max)", + nullable: false, + defaultValue: "", + oldClrType: typeof(string), + oldType: "nvarchar(255)", + oldMaxLength: 255, + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "ProfilePictureUrl", + table: "ApplicationUser_StoredDataUrls", + type: "nvarchar(max)", + nullable: false, + defaultValue: "", + oldClrType: typeof(string), + oldType: "nvarchar(255)", + oldMaxLength: 255, + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "BannerPictureUrl", + table: "ApplicationUser_StoredDataUrls", + type: "nvarchar(max)", + nullable: false, + defaultValue: "", + oldClrType: typeof(string), + oldType: "nvarchar(255)", + oldMaxLength: 255, + oldNullable: true); + } + } +} diff --git a/src/Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs b/src/Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs index 3d3f44a..be95cf4 100644 --- a/src/Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs +++ b/src/Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs @@ -17,7 +17,7 @@ namespace Hutopy.Infrastructure.Migrations { #pragma warning disable 612, 618 modelBuilder - .HasAnnotation("ProductVersion", "8.0.3") + .HasAnnotation("ProductVersion", "8.0.4") .HasAnnotation("Relational:MaxIdentifierLength", 128); SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); @@ -160,6 +160,9 @@ namespace Hutopy.Infrastructure.Migrations .IsRequired() .HasColumnType("nvarchar(max)"); + b.Property("Alias") + .HasColumnType("nvarchar(max)"); + b.Property("BirthDate") .IsRequired() .HasColumnType("nvarchar(max)"); @@ -472,16 +475,16 @@ namespace Hutopy.Infrastructure.Migrations .HasColumnType("nvarchar(450)"); b1.Property("BannerPictureUrl") - .IsRequired() - .HasColumnType("nvarchar(max)"); + .HasMaxLength(255) + .HasColumnType("nvarchar(255)"); b1.Property("ProfilePictureUrl") - .IsRequired() - .HasColumnType("nvarchar(max)"); + .HasMaxLength(255) + .HasColumnType("nvarchar(255)"); b1.Property("WebsiteIconUrl") - .IsRequired() - .HasColumnType("nvarchar(max)"); + .HasMaxLength(255) + .HasColumnType("nvarchar(255)"); b1.HasKey("ApplicationUserId"); diff --git a/src/Infrastructure/Utils/GenerateJwtToken.cs b/src/Infrastructure/Utils/GenerateJwtToken.cs index a5613d6..7992e14 100644 --- a/src/Infrastructure/Utils/GenerateJwtToken.cs +++ b/src/Infrastructure/Utils/GenerateJwtToken.cs @@ -12,10 +12,11 @@ public static class JwtTokenHelper string issuer, string audience, string key, - string? userId, - string? email, - string? firstname, - string? lastname, + string userId, + string email, + string? alias, + string firstname, + string lastname, string? profilePictureUrl) { var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(key)); @@ -25,16 +26,19 @@ public static class JwtTokenHelper { new Claim(JwtRegisteredClaimNames.Sub, userId), new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()), - new Claim(ClaimTypes.NameIdentifier, userId), - new Claim(ClaimTypes.Email, email), - new Claim(ClaimTypes.Name, email), - new Claim(ClaimTypes.GivenName, firstname), - new Claim(ClaimTypes.Surname, lastname), + new Claim(ClaimTypes.NameIdentifier, userId), new Claim(ClaimTypes.Email, email), + new Claim(ClaimTypes.Name, email), new Claim(ClaimTypes.GivenName, firstname), + new Claim(ClaimTypes.Surname, lastname) }); + if (alias is not null) + { + claims.Add(new(KnownClaims.Alias, alias)); + } + if (profilePictureUrl is not null) { - claims.Add(new Claim("portrait-url", profilePictureUrl)); + claims.Add(new(KnownClaims.PortraitUrl, profilePictureUrl)); } var token = new JwtSecurityToken( diff --git a/src/Infrastructure/Utils/KnownClaims.cs b/src/Infrastructure/Utils/KnownClaims.cs new file mode 100644 index 0000000..96b1de9 --- /dev/null +++ b/src/Infrastructure/Utils/KnownClaims.cs @@ -0,0 +1,7 @@ +namespace Hutopy.Infrastructure.Utils; + +public static class KnownClaims +{ + public const string Alias = nameof(Alias); + public const string PortraitUrl = nameof(PortraitUrl); +} diff --git a/src/Web/Common/ClaimsPrincipalExtensions.cs b/src/Web/Common/ClaimsPrincipalExtensions.cs index 3f57da4..d633d6c 100644 --- a/src/Web/Common/ClaimsPrincipalExtensions.cs +++ b/src/Web/Common/ClaimsPrincipalExtensions.cs @@ -1,4 +1,5 @@ using System.Security.Claims; +using Hutopy.Infrastructure.Utils; namespace Hutopy.Web.Common; @@ -6,25 +7,48 @@ public static class ClaimsPrincipalExtensions { public static Guid GetUserId(this ClaimsPrincipal claims) { - return (Guid)claims.GetFirstValue(ClaimTypes.NameIdentifier); + return (Guid)claims.GetRequiredClaim(ClaimTypes.NameIdentifier); } - + + public static string GetName(this ClaimsPrincipal claims) + { + return (string)claims.GetRequiredClaim(ClaimTypes.Name); + } + + public static string? GetAlias(this ClaimsPrincipal claims) + { + return (string?)claims.GetClaim(KnownClaims.Alias); + } + + public static string? GetPortraitUrl(this ClaimsPrincipal claims) + { + return (string?)claims.GetClaim(KnownClaims.PortraitUrl); + } + public static string GetFirstName(this ClaimsPrincipal claims) { - return (string)claims.GetFirstValue(ClaimTypes.GivenName); + return (string)claims.GetRequiredClaim(ClaimTypes.GivenName); } public static string GetLastName(this ClaimsPrincipal claims) { - return (string)claims.GetFirstValue(ClaimTypes.Surname); + return (string)claims.GetRequiredClaim(ClaimTypes.Surname); } public static string GetEmail(this ClaimsPrincipal claims) { - return (string)claims.GetFirstValue(ClaimTypes.Email); + return (string)claims.GetRequiredClaim(ClaimTypes.Email); } - public static object GetFirstValue(this ClaimsPrincipal claims, string key) + public static object? GetClaim(this ClaimsPrincipal claims, string key) + { + var claim = claims.FindFirst(key); + + if (claim is null) return default; + return claims.GetRequiredClaim(key); + } + + public static object GetRequiredClaim(this ClaimsPrincipal claims, string key) { var claim = claims.FindFirst(key); diff --git a/src/Web/Controllers/GoogleController.cs b/src/Web/Controllers/GoogleController.cs index db86eb4..f45006a 100644 --- a/src/Web/Controllers/GoogleController.cs +++ b/src/Web/Controllers/GoogleController.cs @@ -74,6 +74,7 @@ public class GoogleController( jwtOptions.Value.Key, user.Id, user.Email, + user.Alias, user.FirstName, user.LastName, user.StoredDataUrls.ProfilePictureUrl); diff --git a/src/Web/Features/Messages/Data/Message.cs b/src/Web/Features/Messages/Data/Message.cs index 9368718..97dde47 100644 --- a/src/Web/Features/Messages/Data/Message.cs +++ b/src/Web/Features/Messages/Data/Message.cs @@ -1,11 +1,15 @@ -namespace Hutopy.Web.Features.Messages.Data; +using System.ComponentModel.DataAnnotations; + +namespace Hutopy.Web.Features.Messages.Data; public class Message { - public Guid Id { get; init; } - public Guid SubjectId { get; init; } - public Guid CreatedBy { get; init; } - public DateTimeOffset CreatedAt { get; init; } - public Guid? ParentId { get; init; } - public string Value { get; init; } + public Guid Id { get; set; } + public Guid SubjectId { get; set; } + public Guid CreatedBy { get; set; } + [MaxLength(64)] public required string CreatedByName { get; set; } + [MaxLength(256)] public string? CreatedByPortraitUrl { get; set; } + public DateTimeOffset CreatedAt { get; set; } + public Guid? ParentId { get; set; } + public required string Value { get; set; } } diff --git a/src/Web/Features/Messages/Data/MessagingDbContext.cs b/src/Web/Features/Messages/Data/MessagingDbContext.cs index 16fc14a..8cf5bf2 100644 --- a/src/Web/Features/Messages/Data/MessagingDbContext.cs +++ b/src/Web/Features/Messages/Data/MessagingDbContext.cs @@ -1,4 +1,5 @@ -using Microsoft.EntityFrameworkCore; +using Hutopy.Web.Features.Messages.Handlers.Models; +using Microsoft.EntityFrameworkCore; namespace Hutopy.Web.Features.Messages.Data; @@ -9,7 +10,7 @@ public class MessagingDbContext( protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.HasDefaultSchema("Messaging"); - + modelBuilder .Entity() .Property(c => c.CreatedAt) @@ -17,5 +18,41 @@ public class MessagingDbContext( .HasDefaultValueSql("CURRENT_TIMESTAMP"); } - public DbSet Messages { get; set; } + public DbSet Messages { get; set; } + + public async Task> GetMessagesAsync( + Guid subjectId, + Guid? parentId, + Guid? lastId, + int pageSize, + CancellationToken ct = default) + { + var query = Messages + .Where(c => c.SubjectId == subjectId) + .Where(c => c.ParentId == parentId); + + if (lastId.HasValue) + { + var lastMessage = await Messages + .Where(c => c.Id == lastId.Value) + .Select(c => new { c.CreatedAt, c.Id }) + .FirstOrDefaultAsync(cancellationToken: ct); + + if (lastMessage != null) + { + query = query + .Where(c => c.CreatedAt < lastMessage.CreatedAt + || (c.CreatedAt == lastMessage.CreatedAt && c.Id < lastMessage.Id)); + } + } + + var messages = await query + .OrderByDescending(c => c.CreatedAt) + .ThenByDescending(c => c.Id) + .Take(pageSize) + .Select(message => message.ToDto()) + .ToListAsync(cancellationToken: ct); + + return messages; + } } diff --git a/src/Web/Features/Messages/Handlers/AddMessage.cs b/src/Web/Features/Messages/Handlers/AddMessage.cs index fcb6df3..dc7c9e2 100644 --- a/src/Web/Features/Messages/Handlers/AddMessage.cs +++ b/src/Web/Features/Messages/Handlers/AddMessage.cs @@ -1,14 +1,30 @@ using FastEndpoints; +using FluentValidation; using Hutopy.Web.Common; using Hutopy.Web.Features.Messages.Data; namespace Hutopy.Web.Features.Messages.Handlers; -public class AddMessageRequest +public sealed class AddMessageRequest { public Guid? Id { get; set; } - public Guid SubjectId { get; set; } - public string Message { get; set; } + public required Guid SubjectId { get; set; } + public required string Message { get; set; } +} + +internal sealed class AddMessageRequestValidator + : Validator +{ + public AddMessageRequestValidator() + { + RuleFor(r => r.SubjectId) + .NotNull().WithMessage("You must specify a SubjectId") + .NotEmpty().WithMessage("You must specify a non-empty SubjectId"); + + RuleFor(r => r.Message) + .NotNull().WithMessage("You must specify a Message") + .NotEmpty().WithMessage("You must specify a non-empty Message"); + } } public class AddMessage( @@ -30,6 +46,8 @@ public class AddMessage( Id = req.Id ?? GuidHelper.GenerateUuidV7(), SubjectId = req.SubjectId, CreatedBy = User.GetUserId(), + CreatedByName = User.GetAlias() ?? $"{User.GetFirstName()} {User.GetLastName()}", + CreatedByPortraitUrl = User.GetPortraitUrl(), Value = req.Message }; diff --git a/src/Web/Features/Messages/Handlers/AddReply.cs b/src/Web/Features/Messages/Handlers/AddReply.cs index 1ab824d..8b2ea91 100644 --- a/src/Web/Features/Messages/Handlers/AddReply.cs +++ b/src/Web/Features/Messages/Handlers/AddReply.cs @@ -1,16 +1,37 @@ using FastEndpoints; +using FluentValidation; using Hutopy.Web.Common; using Hutopy.Web.Features.Messages.Data; namespace Hutopy.Web.Features.Messages.Handlers; -internal sealed class AddReplyRequest +public sealed class AddReplyRequest { - public required Guid SubjectId { get; set; } + public Guid? Id { get; set; } public required Guid ParentId { get; set; } + public required Guid SubjectId { get; set; } public required string Message { get; set; } } +internal sealed class AddReplyRequestValidator + : Validator +{ + public AddReplyRequestValidator() + { + RuleFor(r => r.ParentId) + .NotNull().WithMessage("You must specify a ParentId") + .NotEmpty().WithMessage("You must specify a non-empty ParentId"); + + RuleFor(r => r.SubjectId) + .NotNull().WithMessage("You must specify a SubjectId") + .NotEmpty().WithMessage("You must specify a non-empty SubjectId"); + + RuleFor(r => r.Message) + .NotNull().WithMessage("You must specify a Message") + .NotEmpty().WithMessage("You must specify a non-empty Message"); + } +} + internal sealed class AddReply( MessagingDbContext context) : Endpoint @@ -28,9 +49,10 @@ internal sealed class AddReply( var message = new Message { Id = GuidHelper.GenerateUuidV7(), - SubjectId = req.SubjectId, + SubjectId = req.SubjectId, ParentId = req.ParentId, CreatedBy = User.GetUserId(), + CreatedByName = User.GetName(), Value = req.Message }; diff --git a/src/Web/Features/Messages/Handlers/GetMessages.cs b/src/Web/Features/Messages/Handlers/GetMessages.cs index 242558f..de98a5e 100644 --- a/src/Web/Features/Messages/Handlers/GetMessages.cs +++ b/src/Web/Features/Messages/Handlers/GetMessages.cs @@ -1,19 +1,24 @@ using FastEndpoints; using Hutopy.Web.Features.Messages.Data; -using Microsoft.EntityFrameworkCore; +using Hutopy.Web.Features.Messages.Handlers.Models; namespace Hutopy.Web.Features.Messages.Handlers; -public class GetMessagesRequest +public sealed class GetMessagesRequest { public Guid SubjectId { get; set; } [BindFrom("page_size")] public int PageSize { get; set; } = 10; [BindFrom("last_id")] public Guid? LastId { get; set; } } +public record struct GetMessagesResponse +{ + public required List Messages { get; init; } +} + public class GetMessages( MessagingDbContext context) - : Endpoint> + : Endpoint { public override void Configure() { @@ -26,34 +31,18 @@ public class GetMessages( GetMessagesRequest req, CancellationToken ct) { - var query = context - .Messages - .Where(c => c.SubjectId == req.SubjectId) - .Where(c => c.ParentId == null); - - if (req.LastId.HasValue) - { - var lastMessage = await context - .Messages - .Where(c => c.Id == req.LastId.Value) - .Select(c => new { c.CreatedAt, c.Id }) - .FirstOrDefaultAsync(cancellationToken: ct); - - if (lastMessage != null) + var messages = await context.GetMessagesAsync( + req.SubjectId, + null, + req.LastId, + req.PageSize, + ct); + + await SendAsync( + new() { - query = query - .Where(c => c.CreatedAt < lastMessage.CreatedAt - || (c.CreatedAt == lastMessage.CreatedAt && c.Id < lastMessage.Id)); - } - } - - query = query - .OrderByDescending(c => c.CreatedAt) - .ThenByDescending(c => c.Id) - .Take(req.PageSize); - - var messages = await query.ToListAsync(cancellationToken: ct); - - await SendAsync(messages, cancellation: ct); + Messages = messages + }, + cancellation: ct); } } diff --git a/src/Web/Features/Messages/Handlers/GetMessagesByUser.cs b/src/Web/Features/Messages/Handlers/GetMessagesByUser.cs index 0b39cef..db611a0 100644 --- a/src/Web/Features/Messages/Handlers/GetMessagesByUser.cs +++ b/src/Web/Features/Messages/Handlers/GetMessagesByUser.cs @@ -1,5 +1,6 @@ using FastEndpoints; using Hutopy.Web.Features.Messages.Data; +using Hutopy.Web.Features.Messages.Handlers.Models; using Microsoft.EntityFrameworkCore; namespace Hutopy.Web.Features.Messages.Handlers; @@ -9,9 +10,14 @@ public class GetMessagesByUserRequest public Guid UserId { get; set; } } +public record struct GetMessagesByUserResponse +{ + public required List Messages { get; init; } +} + public class GetMessagesByUser( MessagingDbContext context) - : Endpoint> + : Endpoint { public override void Configure() { @@ -24,12 +30,19 @@ public class GetMessagesByUser( GetMessagesByUserRequest req, CancellationToken ct) { - var posts = await context + var messages = await context .Messages .Where(c => c.CreatedBy == req.UserId) .Where(c => c.ParentId == null) .ToListAsync(cancellationToken: ct); - await SendAsync(posts, cancellation: ct); + await SendAsync( + new() + { + Messages = messages + .Select(message => message.ToDto()) + .ToList() + }, + cancellation: ct); } } diff --git a/src/Web/Features/Messages/Handlers/GetReplies.cs b/src/Web/Features/Messages/Handlers/GetReplies.cs index 891dbb3..9c39fef 100644 --- a/src/Web/Features/Messages/Handlers/GetReplies.cs +++ b/src/Web/Features/Messages/Handlers/GetReplies.cs @@ -1,6 +1,6 @@ using FastEndpoints; using Hutopy.Web.Features.Messages.Data; -using Microsoft.EntityFrameworkCore; +using Hutopy.Web.Features.Messages.Handlers.Models; namespace Hutopy.Web.Features.Messages.Handlers; @@ -12,9 +12,14 @@ public class GetRepliesRequest [BindFrom("last_id")] public Guid? LastId { get; set; } } +public record struct GetRepliesResponse +{ + public required List Messages { get; init; } +} + public class GetReplies( MessagingDbContext context) - : Endpoint> + : Endpoint { public override void Configure() { @@ -27,20 +32,18 @@ public class GetReplies( GetRepliesRequest req, CancellationToken ct) { - var query = context - .Messages - .Where(c => c.SubjectId == req.SubjectId) - .Where(c => c.ParentId == req.ParentId); + var replies = await context.GetMessagesAsync( + req.SubjectId, + req.ParentId, + req.LastId, + req.PageSize, + ct); - query = query.OrderByDescending(c => c.CreatedAt); - - if (req.LastId is not null) - query = query.Where(c => c.Id < req.LastId.Value); - - query = query.Take(req.PageSize); - - var replies = await query.ToListAsync(cancellationToken: ct); - - await SendAsync(replies, cancellation: ct); + await SendAsync( + new() + { + Messages = replies, + }, + cancellation: ct); } } diff --git a/src/Web/Features/Messages/Handlers/Models/MessageDto.cs b/src/Web/Features/Messages/Handlers/Models/MessageDto.cs new file mode 100644 index 0000000..16b9e78 --- /dev/null +++ b/src/Web/Features/Messages/Handlers/Models/MessageDto.cs @@ -0,0 +1,30 @@ +using Hutopy.Web.Features.Messages.Data; + +namespace Hutopy.Web.Features.Messages.Handlers.Models; + +public record struct MessageDto( + Guid Id, + Guid SubjectId, + Guid CreatedBy, + string CreatedByName, + string? CreatedByPortraitUrl, + DateTimeOffset CreatedAt, + Guid? ParentId, + string Value +); + +public static class MessageExtensions +{ + public static MessageDto ToDto(this Message message) => + new() + { + Id = message.Id, + ParentId = message.ParentId, + CreatedAt = message.CreatedAt, + CreatedBy = message.CreatedBy, + CreatedByName = message.CreatedByName, + CreatedByPortraitUrl = message.CreatedByPortraitUrl, + SubjectId = message.SubjectId, + Value = message.Value + }; +} diff --git a/src/Web/Features/Messages/Migrations/20240718173016_Initial.Designer.cs b/src/Web/Features/Messages/Migrations/20240721041322_Initial.Designer.cs similarity index 81% rename from src/Web/Features/Messages/Migrations/20240718173016_Initial.Designer.cs rename to src/Web/Features/Messages/Migrations/20240721041322_Initial.Designer.cs index 21a45b2..b864487 100644 --- a/src/Web/Features/Messages/Migrations/20240718173016_Initial.Designer.cs +++ b/src/Web/Features/Messages/Migrations/20240721041322_Initial.Designer.cs @@ -9,10 +9,10 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; #nullable disable -namespace Hutopy.Web.Messages.Migrations +namespace Hutopy.Web.Features.Messages.Migrations { [DbContext(typeof(MessagingDbContext))] - [Migration("20240718173016_Initial")] + [Migration("20240721041322_Initial")] partial class Initial { /// @@ -26,7 +26,7 @@ namespace Hutopy.Web.Messages.Migrations NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); - modelBuilder.Entity("Hutopy.Web.Messages.Data.Message", b => + modelBuilder.Entity("Hutopy.Web.Features.Messages.Data.Message", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -40,6 +40,13 @@ namespace Hutopy.Web.Messages.Migrations b.Property("CreatedBy") .HasColumnType("uuid"); + b.Property("CreatedByName") + .IsRequired() + .HasColumnType("text"); + + b.Property("CreatedByPortraitUrl") + .HasColumnType("text"); + b.Property("ParentId") .HasColumnType("uuid"); diff --git a/src/Web/Features/Messages/Migrations/20240718173016_Initial.cs b/src/Web/Features/Messages/Migrations/20240721041322_Initial.cs similarity index 86% rename from src/Web/Features/Messages/Migrations/20240718173016_Initial.cs rename to src/Web/Features/Messages/Migrations/20240721041322_Initial.cs index 6a194da..7287c65 100644 --- a/src/Web/Features/Messages/Migrations/20240718173016_Initial.cs +++ b/src/Web/Features/Messages/Migrations/20240721041322_Initial.cs @@ -3,7 +3,7 @@ using Microsoft.EntityFrameworkCore.Migrations; #nullable disable -namespace Hutopy.Web.Messages.Migrations +namespace Hutopy.Web.Features.Messages.Migrations { /// public partial class Initial : Migration @@ -22,6 +22,8 @@ namespace Hutopy.Web.Messages.Migrations Id = table.Column(type: "uuid", nullable: false), SubjectId = table.Column(type: "uuid", nullable: false), CreatedBy = table.Column(type: "uuid", nullable: false), + CreatedByName = table.Column(type: "text", nullable: false), + CreatedByPortraitUrl = table.Column(type: "text", nullable: true), CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, defaultValueSql: "CURRENT_TIMESTAMP"), ParentId = table.Column(type: "uuid", nullable: true), Value = table.Column(type: "text", nullable: false) diff --git a/src/Web/Features/Messages/Migrations/20240721064224_ChangedAuthorDefinition.Designer.cs b/src/Web/Features/Messages/Migrations/20240721064224_ChangedAuthorDefinition.Designer.cs new file mode 100644 index 0000000..1a92049 --- /dev/null +++ b/src/Web/Features/Messages/Migrations/20240721064224_ChangedAuthorDefinition.Designer.cs @@ -0,0 +1,69 @@ +// +using System; +using Hutopy.Web.Features.Messages.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace Hutopy.Web.Features.Messages.Migrations +{ + [DbContext(typeof(MessagingDbContext))] + [Migration("20240721064224_ChangedAuthorDefinition")] + partial class ChangedAuthorDefinition + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasDefaultSchema("Messaging") + .HasAnnotation("ProductVersion", "8.0.4") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("Hutopy.Web.Features.Messages.Data.Message", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("CURRENT_TIMESTAMP"); + + b.Property("CreatedBy") + .HasColumnType("uuid"); + + b.Property("CreatedByName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("CreatedByPortraitUrl") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("ParentId") + .HasColumnType("uuid"); + + b.Property("SubjectId") + .HasColumnType("uuid"); + + b.Property("Value") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("Messages", "Messaging"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Web/Features/Messages/Migrations/20240721064224_ChangedAuthorDefinition.cs b/src/Web/Features/Messages/Migrations/20240721064224_ChangedAuthorDefinition.cs new file mode 100644 index 0000000..bf04dbe --- /dev/null +++ b/src/Web/Features/Messages/Migrations/20240721064224_ChangedAuthorDefinition.cs @@ -0,0 +1,60 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Hutopy.Web.Features.Messages.Migrations +{ + /// + public partial class ChangedAuthorDefinition : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AlterColumn( + name: "CreatedByPortraitUrl", + schema: "Messaging", + table: "Messages", + type: "character varying(256)", + maxLength: 256, + nullable: true, + oldClrType: typeof(string), + oldType: "text", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "CreatedByName", + schema: "Messaging", + table: "Messages", + type: "character varying(64)", + maxLength: 64, + nullable: false, + oldClrType: typeof(string), + oldType: "text"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.AlterColumn( + name: "CreatedByPortraitUrl", + schema: "Messaging", + table: "Messages", + type: "text", + nullable: true, + oldClrType: typeof(string), + oldType: "character varying(256)", + oldMaxLength: 256, + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "CreatedByName", + schema: "Messaging", + table: "Messages", + type: "text", + nullable: false, + oldClrType: typeof(string), + oldType: "character varying(64)", + oldMaxLength: 64); + } + } +} diff --git a/src/Web/Features/Messages/Migrations/MessagingDbContextModelSnapshot.cs b/src/Web/Features/Messages/Migrations/MessagingDbContextModelSnapshot.cs index c01bd22..111cb88 100644 --- a/src/Web/Features/Messages/Migrations/MessagingDbContextModelSnapshot.cs +++ b/src/Web/Features/Messages/Migrations/MessagingDbContextModelSnapshot.cs @@ -8,7 +8,7 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; #nullable disable -namespace Hutopy.Web.Messages.Migrations +namespace Hutopy.Web.Features.Messages.Migrations { [DbContext(typeof(MessagingDbContext))] partial class MessagingDbContextModelSnapshot : ModelSnapshot @@ -23,7 +23,7 @@ namespace Hutopy.Web.Messages.Migrations NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); - modelBuilder.Entity("Hutopy.Web.Messages.Data.Message", b => + modelBuilder.Entity("Hutopy.Web.Features.Messages.Data.Message", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -37,6 +37,15 @@ namespace Hutopy.Web.Messages.Migrations b.Property("CreatedBy") .HasColumnType("uuid"); + b.Property("CreatedByName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("CreatedByPortraitUrl") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + b.Property("ParentId") .HasColumnType("uuid"); diff --git a/src/Web/TestDataSeeder.cs b/src/Web/TestDataSeeder.cs index c357ade..cb713f9 100644 --- a/src/Web/TestDataSeeder.cs +++ b/src/Web/TestDataSeeder.cs @@ -35,13 +35,13 @@ internal class TestDataSeeder( { if (contentContext.Contents.Any()) return; - _ = await CreateAdministratorAsync("admin"); - _ = await CreateUserAsync("userA"); - _ = await CreateUserAsync("userB"); + _users.Add(await CreateUserAsync("admin", Roles.Administrator)); + _users.Add(await CreateUserAsync("userA")); + _users.Add(await CreateUserAsync("userB")); foreach (var creator in _creators) { - _ = await CreateCreatorAsync(creator); + _users.Add(await CreateCreatorAsync(creator)); var contents = GenerateContent(creator, 100); foreach (var content in contents) @@ -96,15 +96,17 @@ internal class TestDataSeeder( for (var m = messageCount; m > 0; m--) { currentDate = currentDate.AddSeconds(-Random.Shared.Next(100, 100_000)); - var author = Random.Shared.GetItems(_creators, 1)[0]; + var author = Random.Shared.GetItems(_users.ToArray(), 1).First(); var message = new Message { Id = GuidHelper.GenerateUuidV7(), SubjectId = content.Id, - CreatedBy = Guid.Parse(author.Id), CreatedAt = currentDate, - Value = $"Message #{m} from {author.UserName} on {content.Title}" + CreatedBy = Guid.Parse(author.Id), + CreatedByName = author.Alias ?? $"{author.FirstName} {author.LastName}", + CreatedByPortraitUrl = author.StoredDataUrls.ProfilePictureUrl, + Value = $"Message #{m} on {content.Title}" }; messagingContext.Messages.Add(message); @@ -124,7 +126,7 @@ internal class TestDataSeeder( { currentDate = currentDate.AddSeconds(-Random.Shared.Next(100, 100_000)); - var author = Random.Shared.GetItems(_creators, 1)[0]; + var author = Random.Shared.GetItems(_users.ToArray(), 1).First(); var message = new Message { @@ -132,8 +134,10 @@ internal class TestDataSeeder( SubjectId = content.Id, ParentId = parent.Id, CreatedBy = Guid.Parse(author.Id), + CreatedByName = author.Alias ?? $"{author.FirstName} {author.LastName}", + CreatedByPortraitUrl = author.StoredDataUrls.ProfilePictureUrl, CreatedAt = currentDate, - Value = $"Reply {r} to {parent.Value}" + Value = $"Reply {r} to {parent.Value} on {content.Title}" }; messagingContext.Messages.Add(message); @@ -144,31 +148,22 @@ internal class TestDataSeeder( return replies; } - private async Task CreateAdministratorAsync(string name) - { - ArgumentException.ThrowIfNullOrWhiteSpace(name); - - var administrator = new ApplicationUser { UserName = $"{name}@test", Email = $"{name}@test" }; - - await userManager.CreateAsync(administrator, DefaultPassword); - await userManager.AddToRolesAsync(administrator, new[] { Roles.Administrator }); - - return administrator; - } - - private async Task CreateUserAsync(string name) + private async Task CreateUserAsync(string name, params string[] roles) { var user = new ApplicationUser { UserName = $"{name}@test", Email = $"{name}@test", EmailConfirmed = true, + Alias = name, FirstName = $"FirstName of {name}", LastName = $"LastName of {name}" }; await userManager.CreateAsync(user, DefaultPassword); + if (roles.Length > 0) await userManager.AddToRolesAsync(user, roles); + return user; } @@ -180,12 +175,19 @@ internal class TestDataSeeder( } + private readonly List _users = + [ + ]; + + private readonly static ApplicationUser Hutopy = new() { UserName = "hutopy@test", Email = "hutopy@test", EmailConfirmed = true, CreatorAlias = "hutopy", + FirstName = "FirstName of a Brand/Creator", + LastName = "LastName of a Brand/Creator", About = "Page officielle", Description = "Site officiel pour Hutopy. Venez-nous-y retrouver avec tous vos fans!", ProfileColors = new ProfileColors diff --git a/tests/Application.FunctionalTests/Testing.cs b/tests/Application.FunctionalTests/Testing.cs index 8270718..8c31c56 100644 --- a/tests/Application.FunctionalTests/Testing.cs +++ b/tests/Application.FunctionalTests/Testing.cs @@ -65,7 +65,12 @@ public partial class Testing var userManager = scope.ServiceProvider.GetRequiredService(); - var user = new ApplicationUser { UserName = userName, Email = userName }; + var user = new ApplicationUser { + UserName = userName, + Email = userName, + FirstName = "FirstName", + LastName = "LastName" + }; var result = await userManager.CreateAsync(user, password); From 042fd5346334ae97a6720c1043f86122411bdebe Mon Sep 17 00:00:00 2001 From: Jonathan Bourdon Date: Wed, 24 Jul 2024 16:37:34 -0400 Subject: [PATCH 132/229] Change where the MigrationTable are to be created. Improve the update-databases.sh script --- .../Contents/Data/ContentDbContext.cs | 4 +++- .../Messages/Data/MessagingDbContext.cs | 4 +++- src/Web/Program.cs | 16 +++++++++---- update-databases.sh | 23 +++++++++++-------- 4 files changed, 32 insertions(+), 15 deletions(-) diff --git a/src/Web/Features/Contents/Data/ContentDbContext.cs b/src/Web/Features/Contents/Data/ContentDbContext.cs index 657ab6d..9f6b739 100644 --- a/src/Web/Features/Contents/Data/ContentDbContext.cs +++ b/src/Web/Features/Contents/Data/ContentDbContext.cs @@ -6,10 +6,12 @@ public class ContentDbContext( DbContextOptions options) : DbContext(options) { + public const string SchemaName = "Content"; + protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.HasDefaultSchema("Content"); - + modelBuilder .Entity() .Property(c => c.CreatedAt) diff --git a/src/Web/Features/Messages/Data/MessagingDbContext.cs b/src/Web/Features/Messages/Data/MessagingDbContext.cs index 8cf5bf2..2d59e52 100644 --- a/src/Web/Features/Messages/Data/MessagingDbContext.cs +++ b/src/Web/Features/Messages/Data/MessagingDbContext.cs @@ -7,9 +7,11 @@ public class MessagingDbContext( DbContextOptions options) : DbContext(options) { + public const string SchemaName = "Messaging"; + protected override void OnModelCreating(ModelBuilder modelBuilder) { - modelBuilder.HasDefaultSchema("Messaging"); + modelBuilder.HasDefaultSchema(SchemaName); modelBuilder .Entity() diff --git a/src/Web/Program.cs b/src/Web/Program.cs index 759f533..f44349a 100644 --- a/src/Web/Program.cs +++ b/src/Web/Program.cs @@ -6,7 +6,9 @@ using Hutopy.Infrastructure.Data; using Hutopy.Infrastructure.Identity; using Hutopy.Web; using Hutopy.Web.Features.Contents; +using Hutopy.Web.Features.Contents.Data; using Hutopy.Web.Features.Messages; +using Hutopy.Web.Features.Messages.Data; using Microsoft.AspNetCore.HttpOverrides; using Microsoft.EntityFrameworkCore; using NSwag; @@ -73,17 +75,23 @@ builder.Services.AddOpenApiDocument((configure, sp) => In = OpenApiSecurityApiKeyLocation.Header, Description = "Type into the textbox: Bearer {your JWT token}.", }); - + configure.OperationProcessors.Add(new AspNetCoreOperationTagsProcessor()); configure.OperationProcessors.Add(new AspNetCoreOperationSecurityScopeProcessor("JWT")); }); var postgresConnectionString = builder.Configuration.GetConnectionString("PostgresConnection") - ?? throw new InvalidOperationException("Missing ConnectionStrings:PostgresConnection"); + ?? throw new InvalidOperationException("Missing ConnectionStrings:PostgresConnection"); builder.Services.AddFastEndpoints(); -builder.Services.AddContentModule(options => options.UseNpgsql(postgresConnectionString)); -builder.Services.AddMessagingModule(options => options.UseNpgsql(postgresConnectionString)); +builder.Services.AddContentModule(options => + options.UseNpgsql( + postgresConnectionString, + o => o.MigrationsHistoryTable("__EFMigrationsHistory", ContentDbContext.SchemaName))); +builder.Services.AddMessagingModule(options => + options.UseNpgsql( + postgresConnectionString, + o => o.MigrationsHistoryTable("__EFMigrationsHistory", MessagingDbContext.SchemaName))); builder.Services.Configure(builder.Configuration.GetRequiredSection(JwtOptions.SectionName)); diff --git a/update-databases.sh b/update-databases.sh index 17a1244..9f90803 100644 --- a/update-databases.sh +++ b/update-databases.sh @@ -1,17 +1,22 @@ #!/bin/bash +dotnet ef database update \ + --project src/Infrastructure/Infrastructure.csproj \ + --startup-project src/Web/Web.csproj \ + --context Hutopy.Infrastructure.Data.ApplicationDbContext \ + --configuration Debug \ + --no-build + dotnet ef database update \ --project src/Web/Web.csproj \ --startup-project src/Web/Web.csproj \ --context Hutopy.Web.Features.Messages.Data.MessagingDbContext \ --configuration Debug \ - --no-build \ - --connection Server=localhost,5432;Database=Hutopy;Uid=sa;Pwd=P@ssword123!; + --no-build - dotnet ef database update \ - --project src/Web/Web.csproj \ - --startup-project src/Web/Web.csproj \ - --context Hutopy.Web.Features.Contents.Data.ContentDbContext \ - --configuration Debug \ - --no-build \ - --connection Server=localhost,5432;Database=Hutopy;Uid=sa;Pwd=P@ssword123!; +dotnet ef database update \ + --project src/Web/Web.csproj \ + --startup-project src/Web/Web.csproj \ + --context Hutopy.Web.Features.Contents.Data.ContentDbContext \ + --configuration Debug \ + --no-build From bbcc7a8a33ed3537b499a628a42b3e50abca14b1 Mon Sep 17 00:00:00 2001 From: Jonathan Bourdon Date: Wed, 31 Jul 2024 17:38:58 -0400 Subject: [PATCH 133/229] Adds multiple media urls for content --- Directory.Packages.props | 2 +- .../Constants/ContainerNames.cs | 1 + .../Constants/SubDirectoryNames.cs | 2 +- .../Interfaces/IAzureBlobStorageService.cs | 4 +- .../Users/Commands/UploadBannerPicture.cs | 9 +- .../Users/Commands/UploadProfilePicture.cs | 11 +- .../Users/Commands/UploadWebsiteIcon.cs | 29 +++-- .../AzureBlob/AzureBlobStorageService.cs | 80 ++++++------ src/Infrastructure/Infrastructure.csproj | 2 +- .../ApplicationDbContextModelSnapshot.cs | 10 +- src/Web/Endpoints/UpdateMyUser.cs | 6 +- src/Web/Features/Contents/Data/Content.cs | 6 +- .../Contents/Handlers/CreateContent.cs | 114 ++++++++++++++++++ .../Handlers/GetCreatorByAlias.cs | 7 +- .../Features/Contents/Handlers/PostContent.cs | 39 ------ ..._AddMultipleMediaUrlsToContent.Designer.cs | 59 +++++++++ ...725022229_AddMultipleMediaUrlsToContent.cs | 42 +++++++ .../ContentDbContextModelSnapshot.cs | 6 +- src/Web/Web.csproj | 1 + 19 files changed, 319 insertions(+), 111 deletions(-) create mode 100644 src/Web/Features/Contents/Handlers/CreateContent.cs rename src/Web/Features/{Creators => Contents}/Handlers/GetCreatorByAlias.cs (78%) delete mode 100644 src/Web/Features/Contents/Handlers/PostContent.cs create mode 100644 src/Web/Features/Contents/Migrations/20240725022229_AddMultipleMediaUrlsToContent.Designer.cs create mode 100644 src/Web/Features/Contents/Migrations/20240725022229_AddMultipleMediaUrlsToContent.cs diff --git a/Directory.Packages.props b/Directory.Packages.props index cad324b..42adba5 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -8,7 +8,7 @@ - + diff --git a/src/Application/AzureBlobStorage/Constants/ContainerNames.cs b/src/Application/AzureBlobStorage/Constants/ContainerNames.cs index 5bab776..1f49c7e 100644 --- a/src/Application/AzureBlobStorage/Constants/ContainerNames.cs +++ b/src/Application/AzureBlobStorage/Constants/ContainerNames.cs @@ -3,4 +3,5 @@ public static class ContainerNames { public static string Users = "users"; + public static string Creators = "creators"; } diff --git a/src/Application/AzureBlobStorage/Constants/SubDirectoryNames.cs b/src/Application/AzureBlobStorage/Constants/SubDirectoryNames.cs index 6ee43ea..7590b74 100644 --- a/src/Application/AzureBlobStorage/Constants/SubDirectoryNames.cs +++ b/src/Application/AzureBlobStorage/Constants/SubDirectoryNames.cs @@ -3,5 +3,5 @@ public static class SubDirectoryNames { public static string Profile = "profile"; - public static string Posts = "posts"; + public static string Contents = "contents"; } diff --git a/src/Application/Common/Interfaces/IAzureBlobStorageService.cs b/src/Application/Common/Interfaces/IAzureBlobStorageService.cs index a397ce0..e0aa991 100644 --- a/src/Application/Common/Interfaces/IAzureBlobStorageService.cs +++ b/src/Application/Common/Interfaces/IAzureBlobStorageService.cs @@ -2,6 +2,6 @@ public interface IAzureBlobStorageService { - Task UploadFileAsync(string containerName, string blobName, Stream fileStream, string contentType); - Task DownloadFileAsync(string containerName, string blobName); + Task UploadFileAsync(string containerName, string blobName, MemoryStream memoryStream, string contentType, CancellationToken ct = default); + Task DownloadFileAsync(string containerName, string blobName, CancellationToken ct = default); } diff --git a/src/Application/Users/Commands/UploadBannerPicture.cs b/src/Application/Users/Commands/UploadBannerPicture.cs index be7590f..63573fb 100644 --- a/src/Application/Users/Commands/UploadBannerPicture.cs +++ b/src/Application/Users/Commands/UploadBannerPicture.cs @@ -10,7 +10,7 @@ namespace Hutopy.Application.Users.Commands; /// public class UploadBannerPictureCommand : IRequest { - public required Stream BannerPicture { get; init; } + public required MemoryStream BannerPicture { get; init; } public string BannerPictureUrl { get; init; } = string.Empty; } @@ -32,7 +32,12 @@ public class UploadBannerPictureCommandHandler(IHttpContextAccessor contextAcces var blobName = $"{currentUserId}/{SubDirectoryNames.Profile}/{CommonFileNames.BannerPicture}"; - var url = await azureBlobStorageService.UploadFileAsync(ContainerNames.Users, blobName, request.BannerPicture, contentType); + var url = await azureBlobStorageService.UploadFileAsync( + ContainerNames.Users, + blobName, + request.BannerPicture, + contentType, + cancellationToken); await identityService.UpdateCurrentUserBannerPictureUrlAsync(url); diff --git a/src/Application/Users/Commands/UploadProfilePicture.cs b/src/Application/Users/Commands/UploadProfilePicture.cs index 2e017d2..431e014 100644 --- a/src/Application/Users/Commands/UploadProfilePicture.cs +++ b/src/Application/Users/Commands/UploadProfilePicture.cs @@ -10,13 +10,13 @@ namespace Hutopy.Application.Users.Commands; /// public class UploadProfilePictureCommand : IRequest { - public required Stream ProfilePicture { get; init; } + public required MemoryStream ProfilePicture { get; init; } public string ProfilePictureUrl { get; init; } = string.Empty; } public class UploadProfilePictureCommandHandler(IHttpContextAccessor contextAccessor, IIdentityService identityService, IAzureBlobStorageService azureBlobStorageService) : IRequestHandler { - public async Task Handle(UploadProfilePictureCommand request, CancellationToken cancellationToken) + public async Task Handle(UploadProfilePictureCommand request, CancellationToken ct) { // If an url to the picture is provided, use it right away and don't upload anything. if (!string.IsNullOrEmpty(request.ProfilePictureUrl)) @@ -32,7 +32,12 @@ public class UploadProfilePictureCommandHandler(IHttpContextAccessor contextAcce var blobName = $"{currentUserId}/{SubDirectoryNames.Profile}/{CommonFileNames.ProfilePicture}"; - var url = await azureBlobStorageService.UploadFileAsync(ContainerNames.Users, blobName, request.ProfilePicture, contentType); + var url = await azureBlobStorageService.UploadFileAsync( + ContainerNames.Users, + blobName, + request.ProfilePicture, + contentType, + ct); await identityService.UpdateCurrentUserProfilePictureUrlAsync(url); diff --git a/src/Application/Users/Commands/UploadWebsiteIcon.cs b/src/Application/Users/Commands/UploadWebsiteIcon.cs index eaa8cd6..2e74eda 100644 --- a/src/Application/Users/Commands/UploadWebsiteIcon.cs +++ b/src/Application/Users/Commands/UploadWebsiteIcon.cs @@ -10,14 +10,17 @@ namespace Hutopy.Application.Users.Commands; /// public class UploadWebsiteIconCommand : IRequest { - public required Stream WebsiteIcon { get; init; } - + public required MemoryStream WebsiteIcon { get; init; } + public string WebsitePictureUrl { get; init; } = string.Empty; } -public class UploadWebsiteIconCommandHandler(IHttpContextAccessor contextAccessor, IIdentityService identityService, IAzureBlobStorageService azureBlobStorageService) : IRequestHandler +public class UploadWebsiteIconCommandHandler( + IHttpContextAccessor contextAccessor, + IIdentityService identityService, + IAzureBlobStorageService azureBlobStorageService) : IRequestHandler { - public async Task Handle(UploadWebsiteIconCommand request, CancellationToken cancellationToken) + public async Task Handle(UploadWebsiteIconCommand request, CancellationToken ct) { // If an url to the picture is provided, use it right away and don't upload anything. if (!string.IsNullOrEmpty(request.WebsitePictureUrl)) @@ -25,19 +28,23 @@ public class UploadWebsiteIconCommandHandler(IHttpContextAccessor contextAccesso await identityService.UpdateCurrentUserWebsiteIconUrlAsync(request.WebsitePictureUrl); return Results.Ok(request.WebsitePictureUrl); } - + var contentType = contextAccessor.EnsureContentType(); - + var identityUser = await identityService.GetCurrentUserAsync(); var currentUserId = new Guid(identityUser?.Id ?? "").ToString(); - + var blobName = $"{currentUserId}/{SubDirectoryNames.Profile}/{CommonFileNames.WebsiteIcon}"; - - var url = await azureBlobStorageService.UploadFileAsync(ContainerNames.Users, blobName, request.WebsiteIcon, contentType); + + var url = await azureBlobStorageService.UploadFileAsync( + ContainerNames.Users, + blobName, + request.WebsiteIcon, + contentType, + ct); await identityService.UpdateCurrentUserWebsiteIconUrlAsync(url); - + return Results.Ok(request.WebsitePictureUrl); } } - diff --git a/src/Infrastructure/AzureBlob/AzureBlobStorageService.cs b/src/Infrastructure/AzureBlob/AzureBlobStorageService.cs index 8f12630..7887cef 100644 --- a/src/Infrastructure/AzureBlob/AzureBlobStorageService.cs +++ b/src/Infrastructure/AzureBlob/AzureBlobStorageService.cs @@ -11,7 +11,7 @@ public class AzureBlobStorageService : IAzureBlobStorageService { private readonly BlobServiceClient _blobServiceClient; private readonly ILogger _logger; - private readonly long _maxUploadSize = 10 * 1024 * 1024; // 10 MB in bytes + private readonly long _maxUploadSize = 10 * 1024 * 1024; // 10 MB in bytes public AzureBlobStorageService(IConfiguration configuration, ILogger logger) { @@ -25,63 +25,73 @@ public class AzureBlobStorageService : IAzureBlobStorageService /// /// The blob name (path within the container, include the file name). /// The name of the container where the file is stored. - /// The stream. + /// The memory stream containing the image. /// The content type. + /// The cancellation token /// - public async Task UploadFileAsync(string containerName, string blobName, Stream fileStream, string contentType) + public async Task UploadFileAsync(string containerName, string blobName, MemoryStream memoryStream, + string contentType, CancellationToken ct = default) { // Read the file stream into a memory stream to determine the length // WATCH FOR MEMORY USAGE USING THE MEMORY STREAM. - var memoryStream = new MemoryStream(); - await fileStream.CopyToAsync(memoryStream); memoryStream.Position = 0; // Check if the file size exceeds the maximum upload size if (memoryStream.Length > _maxUploadSize) { - _logger.LogInformation($"Blob storage: File size exceeds the maximum allowed size of {_maxUploadSize} bytes."); - throw new InvalidOperationException($"Blob storage: File size exceeds the maximum allowed size of {_maxUploadSize} bytes."); + _logger.LogError( + $"Blob storage: File size exceeds the maximum allowed size of {_maxUploadSize} bytes."); + throw new InvalidOperationException( + $"Blob storage: File size exceeds the maximum allowed size of {_maxUploadSize} bytes."); } - + // Validate content type if (!ContentTypes.IsAllowed(contentType, memoryStream)) { - _logger.LogInformation($"Blob storage: Unsupported file type {contentType}. Only PNG and JPEG are allowed."); + _logger.LogError( + $"Blob storage: Unsupported file type {contentType}. Only PNG and JPEG are allowed."); throw new InvalidOperationException("Unsupported file type. Only PNG and JPEG are allowed."); } - + try { // Get a reference to a container var containerClient = _blobServiceClient.GetBlobContainerClient(containerName); // Create the container if it does not exist - await containerClient.CreateIfNotExistsAsync(); + await containerClient.CreateIfNotExistsAsync( + PublicAccessType.Blob, + cancellationToken: ct); // Get a reference to a blob var blobClient = containerClient.GetBlobClient(blobName); // Define the BlobHttpHeaders to include the content type - var blobHttpHeaders = new BlobHttpHeaders - { - ContentType = contentType - }; + var blobHttpHeaders = new BlobHttpHeaders { ContentType = contentType }; // Upload the file - var response = await blobClient.UploadAsync(memoryStream, new BlobUploadOptions - { - HttpHeaders = blobHttpHeaders - }); + var response = await blobClient.UploadAsync( + memoryStream, + new BlobUploadOptions { HttpHeaders = blobHttpHeaders }, + ct); var fileUri = blobClient.Uri.ToString(); - + _logger.LogInformation( - $"Blob storage: Status [ {response.GetRawResponse().Status.ToString()} ] " + - $"Uploaded [ {blobName} ] to the container [ {containerName} ] " + - $"with contentType [ {contentType} ] " + - $"with a length of [ {memoryStream.Length} bytes ]" + - $"with the uri [ {fileUri} ]" - ); + """ + Blob storage: Status [ {ResponseStatus} ] + Uploaded [ {BlobName} ] to the container [ {ContainerName} ] + with contentType [ {ContentType} ] + with a length of [ {StreamLength} bytes ] + with the uri [ {FileUri} ] + """, + response.GetRawResponse().Status.ToString(), + blobName, + containerName, + contentType, + memoryStream.Length, + fileUri + ); // Return the URI of the uploaded blob return fileUri; @@ -89,7 +99,7 @@ public class AzureBlobStorageService : IAzureBlobStorageService catch (RequestFailedException ex) { _logger.LogError($"Blob storage: Azure Storage request failed: {ex.Message}"); - throw new Exception("Error uploading file to Azure Blob Storage", ex); + throw; } catch (Exception ex) { @@ -99,25 +109,27 @@ public class AzureBlobStorageService : IAzureBlobStorageService } /// - /// Download a file to microsoft azure blob storage. + /// Download a file to microsoft's azure blob storage. /// /// The blob name (path within the container). /// The name of the container where the file is stored. (users) + /// The cancellation token for the request /// - public async Task DownloadFileAsync(string containerName, string blobName) + public async Task DownloadFileAsync(string containerName, string blobName, + CancellationToken ct = default) { try { // Get a reference to a container var containerClient = _blobServiceClient.GetBlobContainerClient(containerName); - + // Get a reference to a blob var blobClient = containerClient.GetBlobClient(blobName); // Download the blob to a stream - BlobDownloadInfo download = await blobClient.DownloadAsync(); + BlobDownloadInfo download = await blobClient.DownloadAsync(ct); MemoryStream memoryStream = new(); - await download.Content.CopyToAsync(memoryStream); + await download.Content.CopyToAsync(memoryStream, ct); memoryStream.Position = 0; // Ensure the stream is at the beginning return memoryStream; @@ -125,12 +137,12 @@ public class AzureBlobStorageService : IAzureBlobStorageService catch (RequestFailedException ex) { _logger.LogError($"Azure Storage request failed: {ex.Message}"); - throw new Exception("Error downloading file from Azure Blob Storage", ex); + throw; } catch (Exception ex) { _logger.LogError($"An error occurred: {ex.Message}"); - throw new ApplicationException("Error downloading file from Azure Blob Storage.", ex); + throw; } } } diff --git a/src/Infrastructure/Infrastructure.csproj b/src/Infrastructure/Infrastructure.csproj index dd3cb64..36b3844 100644 --- a/src/Infrastructure/Infrastructure.csproj +++ b/src/Infrastructure/Infrastructure.csproj @@ -4,7 +4,7 @@ Hutopy.Infrastructure - + diff --git a/src/Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs b/src/Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs index be95cf4..8b4b9ec 100644 --- a/src/Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs +++ b/src/Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs @@ -66,7 +66,7 @@ namespace Hutopy.Infrastructure.Migrations b.HasKey("Id"); - b.ToTable("FutureCreators"); + b.ToTable("FutureCreators", (string)null); }); modelBuilder.Entity("Hutopy.Domain.Entities.UserTransaction", b => @@ -141,7 +141,7 @@ namespace Hutopy.Infrastructure.Migrations b.HasIndex("ApplicationUserId"); - b.ToTable("UserTransactions"); + b.ToTable("UserTransactions", (string)null); }); modelBuilder.Entity("Hutopy.Infrastructure.Identity.ApplicationUser", b => @@ -395,7 +395,7 @@ namespace Hutopy.Infrastructure.Migrations modelBuilder.Entity("Hutopy.Infrastructure.Identity.ApplicationUser", b => { - b.OwnsOne("Hutopy.Infrastructure.Identity.OwnedEntities.ProfileColors", "ProfileColors", b1 => + b.OwnsOne("Hutopy.Infrastructure.Identity.ApplicationUser.ProfileColors#Hutopy.Infrastructure.Identity.OwnedEntities.ProfileColors", "ProfileColors", b1 => { b1.Property("ApplicationUserId") .HasColumnType("nvarchar(450)"); @@ -424,7 +424,7 @@ namespace Hutopy.Infrastructure.Migrations .HasForeignKey("ApplicationUserId"); }); - b.OwnsOne("Hutopy.Infrastructure.Identity.OwnedEntities.SocialNetworks", "SocialNetworks", b1 => + b.OwnsOne("Hutopy.Infrastructure.Identity.ApplicationUser.SocialNetworks#Hutopy.Infrastructure.Identity.OwnedEntities.SocialNetworks", "SocialNetworks", b1 => { b1.Property("ApplicationUserId") .HasColumnType("nvarchar(450)"); @@ -469,7 +469,7 @@ namespace Hutopy.Infrastructure.Migrations .HasForeignKey("ApplicationUserId"); }); - b.OwnsOne("Hutopy.Infrastructure.Identity.OwnedEntities.StoredDataUrls", "StoredDataUrls", b1 => + b.OwnsOne("Hutopy.Infrastructure.Identity.ApplicationUser.StoredDataUrls#Hutopy.Infrastructure.Identity.OwnedEntities.StoredDataUrls", "StoredDataUrls", b1 => { b1.Property("ApplicationUserId") .HasColumnType("nvarchar(450)"); diff --git a/src/Web/Endpoints/UpdateMyUser.cs b/src/Web/Endpoints/UpdateMyUser.cs index b26303a..7399116 100644 --- a/src/Web/Endpoints/UpdateMyUser.cs +++ b/src/Web/Endpoints/UpdateMyUser.cs @@ -19,19 +19,19 @@ public class UpdateMyUser : EndpointGroupBase return await sender.Send(command); } - private static async Task UpdateCurrentUserProfilePicture(ISender sender, Stream stream, string url = "") + private static async Task UpdateCurrentUserProfilePicture(ISender sender, MemoryStream stream, string url = "") { var command = new UploadProfilePictureCommand { ProfilePicture = stream, ProfilePictureUrl = url}; return await sender.Send(command); } - private static async Task UpdateCurrentUserBannerPicture(ISender sender, Stream stream, string url = "") + private static async Task UpdateCurrentUserBannerPicture(ISender sender, MemoryStream stream, string url = "") { var command = new UploadBannerPictureCommand { BannerPicture = stream, BannerPictureUrl = url}; return await sender.Send(command); } - private static async Task UpdateCurrentUserWebsiteIcon(ISender sender, Stream stream, string url = "") + private static async Task UpdateCurrentUserWebsiteIcon(ISender sender, MemoryStream stream, string url = "") { var command = new UploadWebsiteIconCommand { WebsiteIcon = stream, WebsitePictureUrl = url}; return await sender.Send(command); diff --git a/src/Web/Features/Contents/Data/Content.cs b/src/Web/Features/Contents/Data/Content.cs index c5c3dec..08660bb 100644 --- a/src/Web/Features/Contents/Data/Content.cs +++ b/src/Web/Features/Contents/Data/Content.cs @@ -6,7 +6,7 @@ public class Content public Guid CreatedBy { get; init; } public DateTimeOffset CreatedAt { get; init; } - public string? Title { get; init; } - public string? Description { get; init; } - public string? Uri { get; init; } + public string Title { get; set; } + public string Description { get; set; } + public string[]? Urls { get; init; } } diff --git a/src/Web/Features/Contents/Handlers/CreateContent.cs b/src/Web/Features/Contents/Handlers/CreateContent.cs new file mode 100644 index 0000000..9f7c94a --- /dev/null +++ b/src/Web/Features/Contents/Handlers/CreateContent.cs @@ -0,0 +1,114 @@ +using System.Collections.Concurrent; +using FastEndpoints; +using FluentValidation; +using Hutopy.Application.AzureBlobStorage.Constants; +using Hutopy.Application.Common.Interfaces; +using Hutopy.Web.Common; +using Hutopy.Web.Features.Contents.Data; + +namespace Hutopy.Web.Features.Contents.Handlers; + +public record PostContentRequest( + Guid Id, + Guid CreatorId, + string Title, + string Description, + IFormFileCollection Files); + +public sealed class PostContentRequestValidator : Validator +{ + public PostContentRequestValidator() + { + RuleFor(r => r.Id) + .NotNull().WithMessage("You should specify the Id") + .NotEmpty().WithMessage("You should specify a valid/not empty Id"); + + RuleFor(r => r.CreatorId) + .NotNull().WithMessage("You should specify the CreatorId") + .NotEmpty().WithMessage("You should specify a valid/not empty CreatorId"); + + RuleFor(r => r.Title) + .NotNull().WithMessage("You should specify the Title") + .NotEmpty().WithMessage("You should specify a valid/not empty Title"); + + RuleFor(r => r.Description) + .NotNull().WithMessage("You should specify the Description") + .NotEmpty().WithMessage("You should specify a valid/not empty Description"); + } +} + +public sealed class PostContent( + IAzureBlobStorageService blobStorage, + ContentDbContext context) + : Endpoint +{ + public override void Configure() + { + Post("/api/contents"); + Options(o => o.WithTags("Contents")); + AllowFileUploads(); + } + + public override async Task HandleAsync( + PostContentRequest req, + CancellationToken ct) + { + var urls = new ConcurrentBag(); + + await Parallel.ForEachAsync( + req.Files, + ct, + async (file, ict) => + { + try + { + var contentUrl = await SaveFileAsync( + req.CreatorId, + req.Id, + file, + ict); + + urls.Add(contentUrl); + } + catch (Exception ex) + { + Logger.LogError("{ErrorMessage}", ex.Message); + } + }); + + await context.Contents.AddAsync( + new() + { + Id = req.Id, + CreatedBy = User.GetUserId(), + Title = req.Title, + Description = req.Description, + Urls = urls.ToArray() + }, + ct); + + await context.SaveChangesAsync(ct); + + await SendOkAsync(ct); + } + + private async Task SaveFileAsync( + Guid creatorId, + Guid contentId, + IFormFile file, + CancellationToken ct = default) + { + var memoryStream = new MemoryStream(); + await file.CopyToAsync(memoryStream, ct); + + // TODO: I would like us to use ContainerNames.Creators but it seems we are missing configurations @jbourdon + var url = await blobStorage.UploadFileAsync( + ContainerNames.Users, + $"{creatorId}/{SubDirectoryNames.Contents}/{contentId}/{file.FileName}", + memoryStream, + file.ContentType, + ct: ct); + + return url; + } +} diff --git a/src/Web/Features/Creators/Handlers/GetCreatorByAlias.cs b/src/Web/Features/Contents/Handlers/GetCreatorByAlias.cs similarity index 78% rename from src/Web/Features/Creators/Handlers/GetCreatorByAlias.cs rename to src/Web/Features/Contents/Handlers/GetCreatorByAlias.cs index 0c798e9..d5277e2 100644 --- a/src/Web/Features/Creators/Handlers/GetCreatorByAlias.cs +++ b/src/Web/Features/Contents/Handlers/GetCreatorByAlias.cs @@ -3,11 +3,11 @@ using FluentValidation; using Hutopy.Application.Common.Interfaces; using Hutopy.Application.Common.Models; -namespace Hutopy.Web.Features.Creators.Handlers; +namespace Hutopy.Web.Features.Contents.Handlers; public sealed class GetCreatorByAliasRequest { - public string CreatorAlias { get; set; } + public string CreatorAlias { get; init; } } public sealed class GetCreatorByAliasRequestValidator @@ -16,7 +16,8 @@ public sealed class GetCreatorByAliasRequestValidator public GetCreatorByAliasRequestValidator() { RuleFor(r => r.CreatorAlias) - .NotNull().WithMessage("You must specify a creator-alias"); + .NotNull().WithMessage("You should specify the CreatorAlias") + .NotEmpty().WithMessage("You should specify a valid/not empty CreatorAlias"); } } diff --git a/src/Web/Features/Contents/Handlers/PostContent.cs b/src/Web/Features/Contents/Handlers/PostContent.cs deleted file mode 100644 index 71bebd5..0000000 --- a/src/Web/Features/Contents/Handlers/PostContent.cs +++ /dev/null @@ -1,39 +0,0 @@ -using FastEndpoints; -using Hutopy.Web.Common; -using Hutopy.Web.Features.Contents.Data; - -namespace Hutopy.Web.Features.Contents.Handlers; - -public record struct PostContentRequest( - string? Title, - string? Description, - string? Uri); - -public class PostContent( - ContentDbContext context) - : Endpoint -{ - public override void Configure() - { - Post("/api/contents"); - Options( o => o.WithTags("Contents")); - } - - public override async Task HandleAsync( - PostContentRequest req, - CancellationToken ct) - { - await context.Contents.AddAsync( - new Content - { - Id = GuidHelper.GenerateUuidV7(), - CreatedBy = User.GetUserId(), - Title = req.Title, - Description = req.Description, - Uri = req.Uri - }, - ct); - - await context.SaveChangesAsync(ct); - } -} diff --git a/src/Web/Features/Contents/Migrations/20240725022229_AddMultipleMediaUrlsToContent.Designer.cs b/src/Web/Features/Contents/Migrations/20240725022229_AddMultipleMediaUrlsToContent.Designer.cs new file mode 100644 index 0000000..6971bc3 --- /dev/null +++ b/src/Web/Features/Contents/Migrations/20240725022229_AddMultipleMediaUrlsToContent.Designer.cs @@ -0,0 +1,59 @@ +// +using System; +using Hutopy.Web.Features.Contents.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace Hutopy.Web.Features.Contents.Migrations +{ + [DbContext(typeof(ContentDbContext))] + [Migration("20240725022229_AddMultipleMediaUrlsToContent")] + partial class AddMultipleMediaUrlsToContent + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasDefaultSchema("Content") + .HasAnnotation("ProductVersion", "8.0.4") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("Hutopy.Web.Features.Contents.Data.Content", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("CURRENT_TIMESTAMP"); + + b.Property("CreatedBy") + .HasColumnType("uuid"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("Title") + .HasColumnType("text"); + + b.Property("Urls") + .HasColumnType("text[]"); + + b.HasKey("Id"); + + b.ToTable("Contents", "Content"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Web/Features/Contents/Migrations/20240725022229_AddMultipleMediaUrlsToContent.cs b/src/Web/Features/Contents/Migrations/20240725022229_AddMultipleMediaUrlsToContent.cs new file mode 100644 index 0000000..74051db --- /dev/null +++ b/src/Web/Features/Contents/Migrations/20240725022229_AddMultipleMediaUrlsToContent.cs @@ -0,0 +1,42 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Hutopy.Web.Features.Contents.Migrations +{ + /// + public partial class AddMultipleMediaUrlsToContent : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "Uri", + schema: "Content", + table: "Contents"); + + migrationBuilder.AddColumn( + name: "Urls", + schema: "Content", + table: "Contents", + type: "text[]", + nullable: true); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "Urls", + schema: "Content", + table: "Contents"); + + migrationBuilder.AddColumn( + name: "Uri", + schema: "Content", + table: "Contents", + type: "text", + nullable: true); + } + } +} diff --git a/src/Web/Features/Contents/Migrations/ContentDbContextModelSnapshot.cs b/src/Web/Features/Contents/Migrations/ContentDbContextModelSnapshot.cs index e01f3a9..0bff6dd 100644 --- a/src/Web/Features/Contents/Migrations/ContentDbContextModelSnapshot.cs +++ b/src/Web/Features/Contents/Migrations/ContentDbContextModelSnapshot.cs @@ -23,7 +23,7 @@ namespace Hutopy.Web.Contents.Migrations NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); - modelBuilder.Entity("Hutopy.Web.Contents.Data.Content", b => + modelBuilder.Entity("Hutopy.Web.Features.Contents.Data.Content", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -43,8 +43,8 @@ namespace Hutopy.Web.Contents.Migrations b.Property("Title") .HasColumnType("text"); - b.Property("Uri") - .HasColumnType("text"); + b.Property("Urls") + .HasColumnType("text[]"); b.HasKey("Id"); diff --git a/src/Web/Web.csproj b/src/Web/Web.csproj index ead4845..ba72aba 100644 --- a/src/Web/Web.csproj +++ b/src/Web/Web.csproj @@ -12,6 +12,7 @@ + From 2b30e1a03c9893e30c47637e0d4f9e4edf2ebcd6 Mon Sep 17 00:00:00 2001 From: Jonathan Bourdon Date: Wed, 31 Jul 2024 23:29:26 -0400 Subject: [PATCH 134/229] Split creators out of identity --- Directory.Packages.props | 2 +- .../Constants/CommonFileNames.cs | 1 - .../Behaviours/AuthorizationBehaviour.cs | 94 +-- .../Common/Behaviours/LoggingBehaviour.cs | 16 +- .../Common/Behaviours/PerformanceBehaviour.cs | 5 +- .../Interfaces/IAzureBlobStorageService.cs | 3 +- .../Common/Interfaces/IIdentityService.cs | 24 +- src/Application/Common/Interfaces/IUser.cs | 2 +- src/Application/Common/Models/RoleModel.cs | 2 +- src/Application/Common/Models/UserModel.cs | 32 +- .../Commands/ConfirmStripeTransaction.cs | 2 +- .../Commands/CreateSessionCheckoutCommand.cs | 19 +- .../Stripe/Queries/GetMyLastReceipt.cs | 16 +- src/Application/Users/Commands/CreateUser.cs | 4 +- .../Commands/UpdateCurrentUserCommand.cs | 34 +- .../Users/Commands/UploadBannerPicture.cs | 47 -- .../Users/Commands/UploadProfilePicture.cs | 33 +- .../Users/Commands/UploadWebsiteIcon.cs | 50 -- .../Users/Models/ProfileColorsModel.cs | 9 - .../Users/Models/SocialNetworksModel.cs | 13 - .../Users/Models/StoredDataUrlsModel.cs | 8 - .../Queries/GetCurrentUser/GetCurrentUser.cs | 40 +- .../GetCurrentUserProfilePicture.cs | 12 +- .../Users/Queries/GetCurrentUser/UserDto.cs | 31 +- .../Users/Queries/GetUser/GetUser.cs | 46 -- .../Users/Queries/GetUser/GetUserById.cs | 23 + .../Queries/GetUser/GetUserByUserName.cs | 23 + .../Users/Queries/GetUser/UserDto.cs | 30 +- src/Domain/Common/BaseAuditableEntity.cs | 8 +- src/Domain/Entities/UserTransaction.cs | 2 +- .../AzureBlob/AzureBlobStorageService.cs | 17 +- .../Data/ApplicationDbContext.cs | 8 +- .../Data/ApplicationDbContextInitializer.cs | 7 +- .../ApplicationUserConfiguration.cs | 26 - .../AuditableEntityInterceptor.cs | 4 +- src/Infrastructure/DependencyInjection.cs | 5 +- .../Identity/ApplicationRole.cs | 4 +- .../Identity/ApplicationUser.cs | 27 +- .../Identity/ApplicationUserManager.cs | 20 +- .../Identity/IdentityResultExtensions.cs | 3 +- .../Identity/IdentityService.cs | 325 +++------- .../Identity/OwnedEntities/ProfileColors.cs | 9 - .../Identity/OwnedEntities/SocialNetworks.cs | 13 - .../Identity/OwnedEntities/StoredDataUrls.cs | 10 - src/Infrastructure/Identity/RoleService.cs | 6 +- src/Infrastructure/Infrastructure.csproj | 23 +- ...0240418221249_InitialMigration.Designer.cs | 334 ----------- ...0422173330_AddUserTransactions.Designer.cs | 383 ------------ .../20240422173330_AddUserTransactions.cs | 52 -- ...ddIsConfirmedToUserTransaction.Designer.cs | 387 ------------ ...5020920_AddIsConfirmedToUserTransaction.cs | 29 - ...9215538_AddMoreInformationToTransaction.cs | 106 ---- ...000806_AddSocialNetworksToUser.Designer.cs | 469 --------------- .../20240612000806_AddSocialNetworksToUser.cs | 52 -- ...6_AddMissingInformationsToUser.Designer.cs | 497 ---------------- ...0630001806_AddMissingInformationsToUser.cs | 95 --- ...3057_AddMoreInformationsToUser.Designer.cs | 557 ----------------- ...0240630163057_AddMoreInformationsToUser.cs | 77 --- ...701072549_AddPortraitUrlToUser.Designer.cs | 500 ---------------- .../20240701072549_AddPortraitUrlToUser.cs | 28 - ...02055858_AddCreatorAliasTouser.Designer.cs | 560 ----------------- .../20240702055858_AddCreatorAliasTouser.cs | 28 - ...240705010235_RemovePortraitUrl.Designer.cs | 560 ----------------- .../20240705010235_RemovePortraitUrl.cs | 28 - .../20240721045147_AddAlias.Designer.cs | 563 ------------------ .../Migrations/20240721045147_AddAlias.cs | 28 - ...35_MadeOptional_StoredDataUrls.Designer.cs | 563 ------------------ ...40721063535_MadeOptional_StoredDataUrls.cs | 78 --- ....cs => 20240802044736_Initial.Designer.cs} | 190 +++--- ...Migration.cs => 20240802044736_Initial.cs} | 79 ++- .../ApplicationDbContextModelSnapshot.cs | 301 +++------- src/Infrastructure/Stripe/StripeService.cs | 3 - src/Infrastructure/Utils/GenerateJwtToken.cs | 6 +- src/Infrastructure/Utils/KnownClaims.cs | 4 +- src/Web/Controllers/GoogleController.cs | 4 +- src/Web/DependencyInjection.cs | 2 - src/Web/Endpoints/GetMyUser.cs | 3 +- src/Web/Endpoints/UpdateMyUser.cs | 24 +- src/Web/Endpoints/Users.cs | 12 +- .../Contents/Data/ContentDbContext.cs | 39 +- src/Web/Features/Contents/Data/Creator.cs | 48 ++ .../Contents/Handlers/ChangeBanner.cs | 49 ++ .../Contents/Handlers/ChangeColors.cs | 71 +++ .../Contents/Handlers/CreateContent.cs | 6 +- .../Contents/Handlers/CreateCreator.cs | 53 ++ .../Contents/Handlers/GetCreatorByAlias.cs | 31 +- .../Contents/Handlers/GetCreatorById.cs | 47 ++ .../20240718034516_Initial.Designer.cs | 59 -- .../Migrations/20240718034516_Initial.cs | 43 -- ..._AddMultipleMediaUrlsToContent.Designer.cs | 59 -- ...725022229_AddMultipleMediaUrlsToContent.cs | 42 -- .../20240802044656_Initial.Designer.cs | 214 +++++++ .../Migrations/20240802044656_Initial.cs | 78 +++ .../ContentDbContextModelSnapshot.cs | 157 ++++- .../Features/Messages/Handlers/AddMessage.cs | 4 +- .../20240721041322_Initial.Designer.cs | 67 --- .../20240721064224_ChangedAuthorDefinition.cs | 60 -- ....cs => 20240802044717_Initial.Designer.cs} | 4 +- ...2_Initial.cs => 20240802044717_Initial.cs} | 4 +- src/Web/Services/CurrentUser.cs | 7 +- src/Web/TestDataSeeder.cs | 62 +- src/Web/Web.csproj | 5 + tests/Application.FunctionalTests/Testing.cs | 32 +- .../Common/Behaviours/RequestLoggerTests.cs | 4 +- .../Common/Mappings/MappingTests.cs | 2 - 105 files changed, 1497 insertions(+), 7490 deletions(-) delete mode 100644 src/Application/Users/Commands/UploadBannerPicture.cs delete mode 100644 src/Application/Users/Commands/UploadWebsiteIcon.cs delete mode 100644 src/Application/Users/Models/ProfileColorsModel.cs delete mode 100644 src/Application/Users/Models/SocialNetworksModel.cs delete mode 100644 src/Application/Users/Models/StoredDataUrlsModel.cs delete mode 100644 src/Application/Users/Queries/GetUser/GetUser.cs create mode 100644 src/Application/Users/Queries/GetUser/GetUserById.cs create mode 100644 src/Application/Users/Queries/GetUser/GetUserByUserName.cs delete mode 100644 src/Infrastructure/Data/Configurations/ApplicationUserConfiguration.cs delete mode 100644 src/Infrastructure/Identity/OwnedEntities/ProfileColors.cs delete mode 100644 src/Infrastructure/Identity/OwnedEntities/SocialNetworks.cs delete mode 100644 src/Infrastructure/Identity/OwnedEntities/StoredDataUrls.cs delete mode 100644 src/Infrastructure/Migrations/20240418221249_InitialMigration.Designer.cs delete mode 100644 src/Infrastructure/Migrations/20240422173330_AddUserTransactions.Designer.cs delete mode 100644 src/Infrastructure/Migrations/20240422173330_AddUserTransactions.cs delete mode 100644 src/Infrastructure/Migrations/20240425020920_AddIsConfirmedToUserTransaction.Designer.cs delete mode 100644 src/Infrastructure/Migrations/20240425020920_AddIsConfirmedToUserTransaction.cs delete mode 100644 src/Infrastructure/Migrations/20240509215538_AddMoreInformationToTransaction.cs delete mode 100644 src/Infrastructure/Migrations/20240612000806_AddSocialNetworksToUser.Designer.cs delete mode 100644 src/Infrastructure/Migrations/20240612000806_AddSocialNetworksToUser.cs delete mode 100644 src/Infrastructure/Migrations/20240630001806_AddMissingInformationsToUser.Designer.cs delete mode 100644 src/Infrastructure/Migrations/20240630001806_AddMissingInformationsToUser.cs delete mode 100644 src/Infrastructure/Migrations/20240630163057_AddMoreInformationsToUser.Designer.cs delete mode 100644 src/Infrastructure/Migrations/20240630163057_AddMoreInformationsToUser.cs delete mode 100644 src/Infrastructure/Migrations/20240701072549_AddPortraitUrlToUser.Designer.cs delete mode 100644 src/Infrastructure/Migrations/20240701072549_AddPortraitUrlToUser.cs delete mode 100644 src/Infrastructure/Migrations/20240702055858_AddCreatorAliasTouser.Designer.cs delete mode 100644 src/Infrastructure/Migrations/20240702055858_AddCreatorAliasTouser.cs delete mode 100644 src/Infrastructure/Migrations/20240705010235_RemovePortraitUrl.Designer.cs delete mode 100644 src/Infrastructure/Migrations/20240705010235_RemovePortraitUrl.cs delete mode 100644 src/Infrastructure/Migrations/20240721045147_AddAlias.Designer.cs delete mode 100644 src/Infrastructure/Migrations/20240721045147_AddAlias.cs delete mode 100644 src/Infrastructure/Migrations/20240721063535_MadeOptional_StoredDataUrls.Designer.cs delete mode 100644 src/Infrastructure/Migrations/20240721063535_MadeOptional_StoredDataUrls.cs rename src/Infrastructure/Migrations/{20240509215538_AddMoreInformationToTransaction.Designer.cs => 20240802044736_Initial.Designer.cs} (77%) rename src/Infrastructure/Migrations/{20240418221249_InitialMigration.cs => 20240802044736_Initial.cs} (69%) create mode 100644 src/Web/Features/Contents/Data/Creator.cs create mode 100644 src/Web/Features/Contents/Handlers/ChangeBanner.cs create mode 100644 src/Web/Features/Contents/Handlers/ChangeColors.cs create mode 100644 src/Web/Features/Contents/Handlers/CreateCreator.cs create mode 100644 src/Web/Features/Contents/Handlers/GetCreatorById.cs delete mode 100644 src/Web/Features/Contents/Migrations/20240718034516_Initial.Designer.cs delete mode 100644 src/Web/Features/Contents/Migrations/20240718034516_Initial.cs delete mode 100644 src/Web/Features/Contents/Migrations/20240725022229_AddMultipleMediaUrlsToContent.Designer.cs delete mode 100644 src/Web/Features/Contents/Migrations/20240725022229_AddMultipleMediaUrlsToContent.cs create mode 100644 src/Web/Features/Contents/Migrations/20240802044656_Initial.Designer.cs create mode 100644 src/Web/Features/Contents/Migrations/20240802044656_Initial.cs delete mode 100644 src/Web/Features/Messages/Migrations/20240721041322_Initial.Designer.cs delete mode 100644 src/Web/Features/Messages/Migrations/20240721064224_ChangedAuthorDefinition.cs rename src/Web/Features/Messages/Migrations/{20240721064224_ChangedAuthorDefinition.Designer.cs => 20240802044717_Initial.Designer.cs} (95%) rename src/Web/Features/Messages/Migrations/{20240721041322_Initial.cs => 20240802044717_Initial.cs} (93%) diff --git a/Directory.Packages.props b/Directory.Packages.props index 42adba5..00e2212 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -7,7 +7,7 @@ - + diff --git a/src/Application/AzureBlobStorage/Constants/CommonFileNames.cs b/src/Application/AzureBlobStorage/Constants/CommonFileNames.cs index b6d44aa..6a37a08 100644 --- a/src/Application/AzureBlobStorage/Constants/CommonFileNames.cs +++ b/src/Application/AzureBlobStorage/Constants/CommonFileNames.cs @@ -4,5 +4,4 @@ public static class CommonFileNames { public static string ProfilePicture = "profilePicture"; public static string BannerPicture = "bannerPicture"; - public static string WebsiteIcon = "websiteIcon"; } diff --git a/src/Application/Common/Behaviours/AuthorizationBehaviour.cs b/src/Application/Common/Behaviours/AuthorizationBehaviour.cs index 30de73f..8012cce 100644 --- a/src/Application/Common/Behaviours/AuthorizationBehaviour.cs +++ b/src/Application/Common/Behaviours/AuthorizationBehaviour.cs @@ -7,62 +7,74 @@ namespace Hutopy.Application.Common.Behaviours; public class AuthorizationBehaviour( IUser user, - IIdentityService identityService) + IIdentityService identityService) : IPipelineBehavior where TRequest : notnull { - public async Task Handle(TRequest request, RequestHandlerDelegate next, CancellationToken cancellationToken) + public async Task Handle(TRequest request, RequestHandlerDelegate next, + CancellationToken cancellationToken) { - var authorizeAttributes = request.GetType().GetCustomAttributes(); + var authorizeAttributes = request + .GetType() + .GetCustomAttributes() + .ToArray(); - if (authorizeAttributes.Any()) + if (authorizeAttributes.Length == 0) { - // Must be authenticated user - if (user.Id == null) + return await next(); + } + + if (user.Id is null) + { + throw new UnauthorizedAccessException(); + } + + // Role-based authorization + var authorizeAttributesWithRoles = authorizeAttributes + .Where(a => !string.IsNullOrWhiteSpace(a.Roles)) + .ToArray(); + + if (authorizeAttributesWithRoles.Length != 0) + { + var authorized = false; + + foreach (var roles in authorizeAttributesWithRoles.Select(a => a.Roles.Split(','))) { - throw new UnauthorizedAccessException(); - } - - // Role-based authorization - var authorizeAttributesWithRoles = authorizeAttributes.Where(a => !string.IsNullOrWhiteSpace(a.Roles)); - - if (authorizeAttributesWithRoles.Any()) - { - var authorized = false; - - foreach (var roles in authorizeAttributesWithRoles.Select(a => a.Roles.Split(','))) + foreach (var role in roles) { - foreach (var role in roles) + var isInRole = await identityService.IsInRoleAsync(user.Id.Value, role.Trim()); + if (isInRole) { - var isInRole = await identityService.IsInRoleAsync(user.Id, role.Trim()); - if (isInRole) - { - authorized = true; - break; - } + authorized = true; + break; } } - - // Must be a member of at least one role in roles - if (!authorized) - { - throw new ForbiddenAccessException(); - } } - // Policy-based authorization - var authorizeAttributesWithPolicies = authorizeAttributes.Where(a => !string.IsNullOrWhiteSpace(a.Policy)); - if (authorizeAttributesWithPolicies.Any()) + // Must be a member of at least one role in roles + if (!authorized) { - foreach (var policy in authorizeAttributesWithPolicies.Select(a => a.Policy)) - { - var authorized = await identityService.AuthorizeAsync(user.Id, policy); + throw new ForbiddenAccessException(); + } + } - if (!authorized) - { - throw new ForbiddenAccessException(); - } - } + // Policy-based authorization + var authorizeAttributesWithPolicies = authorizeAttributes + .Where(a => !string.IsNullOrWhiteSpace(a.Policy)) + .ToArray(); + + if (authorizeAttributesWithPolicies.Length == 0) + { + return await next(); + } + + foreach (var policy in authorizeAttributesWithPolicies.Select(a => a.Policy)) + { + var authorized = await identityService.AuthorizeAsync(user.Id.Value, policy); + + if (!authorized) + { + throw new ForbiddenAccessException(); } } diff --git a/src/Application/Common/Behaviours/LoggingBehaviour.cs b/src/Application/Common/Behaviours/LoggingBehaviour.cs index 07814ca..def9dca 100644 --- a/src/Application/Common/Behaviours/LoggingBehaviour.cs +++ b/src/Application/Common/Behaviours/LoggingBehaviour.cs @@ -5,9 +5,9 @@ using Microsoft.Extensions.Logging; namespace Hutopy.Application.Common.Behaviours; public class LoggingBehaviour( - ILogger logger, - IUser user, - IIdentityService identityService) + ILogger logger, + IUser user, + IIdentityService identityService) : IRequestPreProcessor where TRequest : notnull { @@ -16,15 +16,15 @@ public class LoggingBehaviour( public async Task Process(TRequest request, CancellationToken cancellationToken) { var requestName = typeof(TRequest).Name; - var userId = user.Id ?? string.Empty; string? userName = string.Empty; - if (!string.IsNullOrEmpty(userId)) + if (user.Id.HasValue) { - userName = await identityService.GetUserNameAsync(userId); + userName = await identityService.GetUserNameAsync(user.Id.Value); } - _logger.LogInformation("Hutopy Request: {Name} {@UserId} {@UserName} {@Request}", - requestName, userId, userName, request); + _logger.LogInformation( + "Hutopy Request: {Name} {@UserId} {@UserName} {@Request}", + requestName, user.Id ?? Guid.Empty, userName, request); } } diff --git a/src/Application/Common/Behaviours/PerformanceBehaviour.cs b/src/Application/Common/Behaviours/PerformanceBehaviour.cs index ada438a..20a82a2 100644 --- a/src/Application/Common/Behaviours/PerformanceBehaviour.cs +++ b/src/Application/Common/Behaviours/PerformanceBehaviour.cs @@ -26,13 +26,12 @@ public class PerformanceBehaviour( if (elapsedMilliseconds <= 500) return response; var requestName = typeof(TRequest).Name; - var userId = user.Id ?? string.Empty; var userName = string.Empty; - if (!string.IsNullOrEmpty(userId)) userName = await identityService.GetUserNameAsync(userId); + if (user.Id.HasValue) userName = await identityService.GetUserNameAsync(user.Id.Value); logger.LogWarning("Hutopy Long Running Request: {Name} ({ElapsedMilliseconds} milliseconds) {@UserId} {@UserName} {@Request}", - requestName, elapsedMilliseconds, userId, userName, request); + requestName, elapsedMilliseconds, user.Id ?? Guid.Empty, userName, request); return response; } diff --git a/src/Application/Common/Interfaces/IAzureBlobStorageService.cs b/src/Application/Common/Interfaces/IAzureBlobStorageService.cs index e0aa991..83537e9 100644 --- a/src/Application/Common/Interfaces/IAzureBlobStorageService.cs +++ b/src/Application/Common/Interfaces/IAzureBlobStorageService.cs @@ -2,6 +2,7 @@ public interface IAzureBlobStorageService { - Task UploadFileAsync(string containerName, string blobName, MemoryStream memoryStream, string contentType, CancellationToken ct = default); + Task UploadFileAsync(string containerName, string blobName, Stream stream, string contentType, + CancellationToken ct = default); Task DownloadFileAsync(string containerName, string blobName, CancellationToken ct = default); } diff --git a/src/Application/Common/Interfaces/IIdentityService.cs b/src/Application/Common/Interfaces/IIdentityService.cs index e780b94..3ebbfb3 100644 --- a/src/Application/Common/Interfaces/IIdentityService.cs +++ b/src/Application/Common/Interfaces/IIdentityService.cs @@ -1,29 +1,27 @@ -using Google.Apis.Oauth2.v2.Data; -using Hutopy.Application.Common.Models; +using Hutopy.Application.Common.Models; namespace Hutopy.Application.Common.Interfaces; public interface IIdentityService { - Task> CreateUserAsync(Userinfo userInfo); - - Task> CreateUserAsync(string email, string userName, string firstName, string lastName, + Task> CreateUserAsync( + string email, + string userName, + string firstName, + string lastName, string password); Task GetCurrentUserAsync(); - Task UpdateCurrentUserBannerPictureUrlAsync(string url); - Task UpdateCurrentUserProfilePictureUrlAsync(string url); - Task UpdateCurrentUserWebsiteIconUrlAsync(string url); - Task> UpdateCurrentUserAsync(UserModel userModel); + Task UpdateCurrentUserPortraitUrlAsync(string url); + Task> UpdateCurrentUserAsync(UserModel userModel); Task> GetCurrentUserRolesAsync(); Task FindUserByIdAsync(string id); - Task FindUserByCreatorAliasAsync(string creatorAlias, CancellationToken cancellationToken); Task FindUserByEmailAsync(string email); Task GetUserByUserNameAsync(string userName); Task LoginAsync(string email, string password); - Task IsInRoleAsync(string userId, string role); - Task AuthorizeAsync(string userId, string policyName); - Task GetUserNameAsync(string userId); + Task IsInRoleAsync(Guid userId, string role); + Task AuthorizeAsync(Guid userId, string policyName); + Task GetUserNameAsync(Guid userId); Task AddRoleAsync(string userId, string role); Task DeleteUserAsync(string userId); diff --git a/src/Application/Common/Interfaces/IUser.cs b/src/Application/Common/Interfaces/IUser.cs index f6112a1..ede555b 100644 --- a/src/Application/Common/Interfaces/IUser.cs +++ b/src/Application/Common/Interfaces/IUser.cs @@ -2,5 +2,5 @@ public interface IUser { - string? Id { get; } + Guid? Id { get; } } diff --git a/src/Application/Common/Models/RoleModel.cs b/src/Application/Common/Models/RoleModel.cs index ed49feb..5c1c786 100644 --- a/src/Application/Common/Models/RoleModel.cs +++ b/src/Application/Common/Models/RoleModel.cs @@ -2,6 +2,6 @@ namespace Hutopy.Application.Common.Models; public class RoleModel { - public string? Id { get; set; } + public Guid Id { get; set; } public string? Name { get; set; } } diff --git a/src/Application/Common/Models/UserModel.cs b/src/Application/Common/Models/UserModel.cs index f67d8a9..b38e4b4 100644 --- a/src/Application/Common/Models/UserModel.cs +++ b/src/Application/Common/Models/UserModel.cs @@ -1,26 +1,16 @@ -using Hutopy.Application.Users.Models; - namespace Hutopy.Application.Common.Models; public class UserModel { - public string Id { get; set; } = string.Empty; - public string? CreatorAlias { get; set; } - public string UserName { get; set; } = string.Empty; - public string? Alias { get; set; } - public string FirstName { get; set; } = string.Empty; - public string LastName { get; set; } = string.Empty; - public string Occupation { get; set; } = string.Empty; - public string Email { get; init; } = string.Empty; - public string PhoneNumber { get; init; } = string.Empty; - public string BirthDate { get; init; } = string.Empty; - public string Country { get; init; } = string.Empty; - public string City { get; init; } = string.Empty; - public string Address { get; init; } = string.Empty; - public string About { get; init; } = string.Empty; - public string Description { get; init; } = string.Empty; - public SocialNetworksModel SocialNetworks { get; init; } = new(); - public ProfileColorsModel ProfileColors { get; init; } = new(); - public StoredDataUrlsModel StoredDataUrls { get; init; } = new(); - public string ProfilePictureUrl { get; set; } = string.Empty; + public Guid Id { get; set; } + public string UserName { get; init; } = null!; + public string? Alias { get; init; } + public string? PortraitUrl { get; init; } + public string? FirstName { get; init; } + public string? LastName { get; init; } + public string? Occupation { get; init; } + public string? Email { get; init; } + public string? PhoneNumber { get; init; } + public string? BirthDate { get; init; } + public string? Address { get; init; } } diff --git a/src/Application/Stripe/Commands/ConfirmStripeTransaction.cs b/src/Application/Stripe/Commands/ConfirmStripeTransaction.cs index 0c74658..e287b45 100644 --- a/src/Application/Stripe/Commands/ConfirmStripeTransaction.cs +++ b/src/Application/Stripe/Commands/ConfirmStripeTransaction.cs @@ -50,7 +50,7 @@ public class ConfirmStripeTransactionCommandHandler( { public async Task Handle(ConfirmStripeTransactionCommand request, CancellationToken cancellationToken) { - var lastTransaction = await dbContext.UserTransactions.OrderBy(x => x.Created).LastAsync(cancellationToken); + var lastTransaction = await dbContext.UserTransactions.OrderBy(x => x.CreatedAt).LastAsync(cancellationToken); var stripeConfirmation = stripeService.ValidateTransaction(request); if (stripeConfirmation.Succeeded) diff --git a/src/Application/Stripe/Commands/CreateSessionCheckoutCommand.cs b/src/Application/Stripe/Commands/CreateSessionCheckoutCommand.cs index 681c4d8..80249d3 100644 --- a/src/Application/Stripe/Commands/CreateSessionCheckoutCommand.cs +++ b/src/Application/Stripe/Commands/CreateSessionCheckoutCommand.cs @@ -2,30 +2,37 @@ using Hutopy.Domain.Entities; namespace Hutopy.Application.Stripe.Commands; + public record CreateSessionCheckoutCommand : IRequest { - public required string CreatorId { get; init; } + public required Guid CreatorId { get; init; } public required int Amount { get; init; } public string Currency { get; init; } = "CAD"; public string TipMessage { get; init; } = string.Empty; } public class CreateSessionCheckoutCommandHandler( - IApplicationDbContext dbContext, + IApplicationDbContext dbContext, IStripeService stripeService - ) +) : IRequestHandler { public async Task Handle(CreateSessionCheckoutCommand request, CancellationToken cancellationToken) { - var stripeSecret = await stripeService.CreateCheckoutSession(request.Amount, request.CreatorId, request.Currency); + var stripeSecret = await stripeService.CreateCheckoutSession( + request.Amount, + request.CreatorId.ToString(), + request.Currency); // ReSharper disable once PossibleLossOfFraction decimal priceInDollars = (request.Amount / 100); - + var userTransaction = new UserTransaction { - Currency = request.Currency, Amount = priceInDollars, TipMessage = request.TipMessage, ApplicationUserId = request.CreatorId + Currency = request.Currency, + Amount = priceInDollars, + TipMessage = request.TipMessage, + ApplicationUserId = request.CreatorId }; await dbContext.UserTransactions.AddAsync(userTransaction, cancellationToken); diff --git a/src/Application/Stripe/Queries/GetMyLastReceipt.cs b/src/Application/Stripe/Queries/GetMyLastReceipt.cs index b8a0602..c4feb05 100644 --- a/src/Application/Stripe/Queries/GetMyLastReceipt.cs +++ b/src/Application/Stripe/Queries/GetMyLastReceipt.cs @@ -4,25 +4,23 @@ namespace Hutopy.Application.Stripe.Queries; public record GetMyLastReceiptQuery : IRequest { + public Guid CreatorId { get; set; } public string Email { get; set; } = string.Empty; - public string CreatorId { get; set; } = string.Empty; }; public class GetMyLastReceiptQueryHandler( IApplicationDbContext dbContext - ) +) : IRequestHandler { public async Task Handle(GetMyLastReceiptQuery request, CancellationToken cancellationToken) { - var lastTransaction = await dbContext.UserTransactions.OrderBy(x => x.Created) - .LastOrDefaultAsync(x => x.ApplicationUserId == request.CreatorId && x.StripeBillingDetailEmail == request.Email, + var lastTransaction = await dbContext.UserTransactions.OrderBy(x => x.CreatedAt) + .LastOrDefaultAsync( + x => x.ApplicationUserId == request.CreatorId && x.StripeBillingDetailEmail == request.Email, cancellationToken); - - var receiptUrl = new MyLastReceiptDto - { - ReceiptUrl = lastTransaction?.StripeReceiptUrl ?? "", - }; + + var receiptUrl = new MyLastReceiptDto { ReceiptUrl = lastTransaction?.StripeReceiptUrl ?? "", }; return receiptUrl; } diff --git a/src/Application/Users/Commands/CreateUser.cs b/src/Application/Users/Commands/CreateUser.cs index 703066c..d84b69b 100644 --- a/src/Application/Users/Commands/CreateUser.cs +++ b/src/Application/Users/Commands/CreateUser.cs @@ -28,8 +28,10 @@ public class CreateUserCommandHandler : IRequestHandler { - public required string FirstName { get; init; } - public required string LastName { get; init; } - public required string Occupation { get; init; } - public required string PhoneNumber { get; init; } - public required string BirthDate { get; init; } - public required string Country { get; init; } - public required string City { get; init; } - public required string Address { get; init; } - public required string About { get; init; } - public required string Description { get; init; } - public required SocialNetworksModel SocialNetworks { get; init; } - public required ProfileColorsModel ProfileColors { get; init; } + public required string? Alias { get; init; } + public required string? FirstName { get; init; } + public required string? LastName { get; init; } + public required string? Occupation { get; init; } + public required string? BirthDate { get; init; } + public required string? Country { get; init; } + public required string? City { get; init; } + public required string? Address { get; init; } - [NotMapped] private class Mapping : Profile { @@ -32,8 +26,11 @@ public class UpdateCurrentUserCommand : IRequest } } -public class UpdateCurrentUserCommandHandler(IApplicationDbContext context, IIdentityService identityService, IMapper mapper) : - IRequestHandler +public class UpdateCurrentUserCommandHandler( + IApplicationDbContext context, + IIdentityService identityService, + IMapper mapper) + : IRequestHandler { public async Task Handle(UpdateCurrentUserCommand request, CancellationToken cancellationToken) { @@ -43,12 +40,11 @@ public class UpdateCurrentUserCommandHandler(IApplicationDbContext context, IIde var userModel = mapper.Map(request); userModel.Id = identityUser.Id; - + var result = await identityService.UpdateCurrentUserAsync(userModel); await context.SaveChangesAsync(cancellationToken); - + return result.Succeeded ? Results.Ok(result.GetValueOrDefault()) : Results.Problem(result.GetErrorsAsString()); } } - diff --git a/src/Application/Users/Commands/UploadBannerPicture.cs b/src/Application/Users/Commands/UploadBannerPicture.cs deleted file mode 100644 index 63573fb..0000000 --- a/src/Application/Users/Commands/UploadBannerPicture.cs +++ /dev/null @@ -1,47 +0,0 @@ -using Hutopy.Application.AzureBlobStorage.Constants; -using Hutopy.Application.Common.Interfaces; -using Hutopy.Application.Utils; -using Microsoft.AspNetCore.Http; - -namespace Hutopy.Application.Users.Commands; - -/// -/// Upload a banner picture. If the user has the url already, set the BannerPictureUrl in the user only without upload. -/// -public class UploadBannerPictureCommand : IRequest -{ - public required MemoryStream BannerPicture { get; init; } - public string BannerPictureUrl { get; init; } = string.Empty; -} - -public class UploadBannerPictureCommandHandler(IHttpContextAccessor contextAccessor, IIdentityService identityService, IAzureBlobStorageService azureBlobStorageService) : IRequestHandler -{ - public async Task Handle(UploadBannerPictureCommand request, CancellationToken cancellationToken) - { - // If an url to the picture is provided, use it right away and don't upload anything. - if (!string.IsNullOrEmpty(request.BannerPictureUrl)) - { - await identityService.UpdateCurrentUserBannerPictureUrlAsync(request.BannerPictureUrl); - return Results.Ok(request.BannerPictureUrl); - } - - var contentType = contextAccessor.EnsureContentType(); - - var identityUser = await identityService.GetCurrentUserAsync(); - var currentUserId = new Guid(identityUser?.Id ?? "").ToString(); - - var blobName = $"{currentUserId}/{SubDirectoryNames.Profile}/{CommonFileNames.BannerPicture}"; - - var url = await azureBlobStorageService.UploadFileAsync( - ContainerNames.Users, - blobName, - request.BannerPicture, - contentType, - cancellationToken); - - await identityService.UpdateCurrentUserBannerPictureUrlAsync(url); - - return Results.Ok(url); - } -} - diff --git a/src/Application/Users/Commands/UploadProfilePicture.cs b/src/Application/Users/Commands/UploadProfilePicture.cs index 431e014..cbf4b00 100644 --- a/src/Application/Users/Commands/UploadProfilePicture.cs +++ b/src/Application/Users/Commands/UploadProfilePicture.cs @@ -10,38 +10,29 @@ namespace Hutopy.Application.Users.Commands; /// public class UploadProfilePictureCommand : IRequest { - public required MemoryStream ProfilePicture { get; init; } - public string ProfilePictureUrl { get; init; } = string.Empty; + public required IFormFile File { get; init; } } -public class UploadProfilePictureCommandHandler(IHttpContextAccessor contextAccessor, IIdentityService identityService, IAzureBlobStorageService azureBlobStorageService) : IRequestHandler +public class UploadProfilePictureCommandHandler( + IHttpContextAccessor contextAccessor, + IIdentityService identityService, + IAzureBlobStorageService azureBlobStorageService) : IRequestHandler { public async Task Handle(UploadProfilePictureCommand request, CancellationToken ct) { - // If an url to the picture is provided, use it right away and don't upload anything. - if (!string.IsNullOrEmpty(request.ProfilePictureUrl)) - { - await identityService.UpdateCurrentUserProfilePictureUrlAsync(request.ProfilePictureUrl); - return Results.Ok(request.ProfilePictureUrl); - } - var contentType = contextAccessor.EnsureContentType(); - + var identityUser = await identityService.GetCurrentUserAsync(); - var currentUserId = new Guid(identityUser?.Id ?? "").ToString(); - - var blobName = $"{currentUserId}/{SubDirectoryNames.Profile}/{CommonFileNames.ProfilePicture}"; - + var url = await azureBlobStorageService.UploadFileAsync( - ContainerNames.Users, - blobName, - request.ProfilePicture, + ContainerNames.Users, + $"{identityUser.Id}/{SubDirectoryNames.Profile}/{CommonFileNames.ProfilePicture}", + request.File.OpenReadStream(), contentType, ct); - await identityService.UpdateCurrentUserProfilePictureUrlAsync(url); - + await identityService.UpdateCurrentUserPortraitUrlAsync(url); + return Results.Ok(url); } } - diff --git a/src/Application/Users/Commands/UploadWebsiteIcon.cs b/src/Application/Users/Commands/UploadWebsiteIcon.cs deleted file mode 100644 index 2e74eda..0000000 --- a/src/Application/Users/Commands/UploadWebsiteIcon.cs +++ /dev/null @@ -1,50 +0,0 @@ -using Hutopy.Application.AzureBlobStorage.Constants; -using Hutopy.Application.Common.Interfaces; -using Hutopy.Application.Utils; -using Microsoft.AspNetCore.Http; - -namespace Hutopy.Application.Users.Commands; - -/// -/// Upload a website icon. If the user has the url already, set the WebsitePictureUrl in the user only without upload. -/// -public class UploadWebsiteIconCommand : IRequest -{ - public required MemoryStream WebsiteIcon { get; init; } - - public string WebsitePictureUrl { get; init; } = string.Empty; -} - -public class UploadWebsiteIconCommandHandler( - IHttpContextAccessor contextAccessor, - IIdentityService identityService, - IAzureBlobStorageService azureBlobStorageService) : IRequestHandler -{ - public async Task Handle(UploadWebsiteIconCommand request, CancellationToken ct) - { - // If an url to the picture is provided, use it right away and don't upload anything. - if (!string.IsNullOrEmpty(request.WebsitePictureUrl)) - { - await identityService.UpdateCurrentUserWebsiteIconUrlAsync(request.WebsitePictureUrl); - return Results.Ok(request.WebsitePictureUrl); - } - - var contentType = contextAccessor.EnsureContentType(); - - var identityUser = await identityService.GetCurrentUserAsync(); - var currentUserId = new Guid(identityUser?.Id ?? "").ToString(); - - var blobName = $"{currentUserId}/{SubDirectoryNames.Profile}/{CommonFileNames.WebsiteIcon}"; - - var url = await azureBlobStorageService.UploadFileAsync( - ContainerNames.Users, - blobName, - request.WebsiteIcon, - contentType, - ct); - - await identityService.UpdateCurrentUserWebsiteIconUrlAsync(url); - - return Results.Ok(request.WebsitePictureUrl); - } -} diff --git a/src/Application/Users/Models/ProfileColorsModel.cs b/src/Application/Users/Models/ProfileColorsModel.cs deleted file mode 100644 index 04baadb..0000000 --- a/src/Application/Users/Models/ProfileColorsModel.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace Hutopy.Application.Users.Models; - -public class ProfileColorsModel -{ - public string BannerTop { get; init; } = String.Empty; - public string BannerBottom { get; init; } = String.Empty; - public string Accent { get; init; } = String.Empty; - public string Menu { get; init; } = String.Empty; -} diff --git a/src/Application/Users/Models/SocialNetworksModel.cs b/src/Application/Users/Models/SocialNetworksModel.cs deleted file mode 100644 index 19a2f02..0000000 --- a/src/Application/Users/Models/SocialNetworksModel.cs +++ /dev/null @@ -1,13 +0,0 @@ -namespace Hutopy.Application.Users.Models; - -public class SocialNetworksModel -{ - public string FacebookUrl { get; init; } = string.Empty; - public string InstagramUrl { get; init; } = string.Empty; - public string XUrl { get; init; } = string.Empty; - public string LinkedInUrl { get; init; } = string.Empty; - public string TikTokUrl { get; init; } = string.Empty; - public string YoutubeUrl { get; init; } = string.Empty; - public string RedditUrl { get; init; } = string.Empty; - public string YourWebsiteUrl { get; init; } = string.Empty; -} diff --git a/src/Application/Users/Models/StoredDataUrlsModel.cs b/src/Application/Users/Models/StoredDataUrlsModel.cs deleted file mode 100644 index 06eb528..0000000 --- a/src/Application/Users/Models/StoredDataUrlsModel.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace Hutopy.Application.Users.Models; - -public class StoredDataUrlsModel -{ - public string? BannerPictureUrl { get; set; } - public string? ProfilePictureUrl { get; set; } - public string? WebsiteIconUrl { get; set; } -} diff --git a/src/Application/Users/Queries/GetCurrentUser/GetCurrentUser.cs b/src/Application/Users/Queries/GetCurrentUser/GetCurrentUser.cs index 4429bed..18e3f8e 100644 --- a/src/Application/Users/Queries/GetCurrentUser/GetCurrentUser.cs +++ b/src/Application/Users/Queries/GetCurrentUser/GetCurrentUser.cs @@ -11,15 +11,16 @@ public class GetCurrentUserQueryHandler( ) : IRequestHandler { - public async Task Handle(GetCurrentUserQuery request, CancellationToken cancellationToken) + public async Task Handle(GetCurrentUserQuery request, CancellationToken cancellationToken) { - var identityUser = await identityService.GetCurrentUserAsync(); - var currentUserId = Guid.Parse(identityUser!.Id!); + var userModel = await identityService.GetCurrentUserAsync(); + if (userModel is null) return null; + var transactions = await context .UserTransactions - .Where(x => x.ApplicationUserId == currentUserId.ToString()) - .OrderBy(x => x.LastModified) + .Where(x => x.ApplicationUserId == userModel.Id) + .OrderBy(x => x.LastModifiedAt) .ProjectTo(mapper.ConfigurationProvider) .Where(x => x.IsConfirmed == true) .ToListAsync(cancellationToken); @@ -28,24 +29,17 @@ public class GetCurrentUserQueryHandler( var user = new UserDto { - Id = currentUserId, - Alias = identityUser.Alias, - FirstName = identityUser.FirstName, - LastName = identityUser.LastName, - UserName = identityUser.UserName, - CreatorAlias= identityUser.CreatorAlias, - Occupation = identityUser.Occupation, - PhoneNumber = identityUser.PhoneNumber, - Email = identityUser.Email, - BirthDate = identityUser.BirthDate, - Country = identityUser.Country, - City = identityUser.City, - Address = identityUser.Address, - About = identityUser.About, - Description = identityUser.Description, - SocialNetworks = identityUser.SocialNetworks, - ProfileColors = identityUser.ProfileColors, - StoredDataUrls = identityUser.StoredDataUrls, + Id = userModel.Id, + Alias = userModel.Alias, + PortraitUrl = userModel.PortraitUrl, + FirstName = userModel.FirstName, + LastName = userModel.LastName, + UserName = userModel.UserName, + Occupation = userModel.Occupation, + PhoneNumber = userModel.PhoneNumber, + Email = userModel.Email, + BirthDate = userModel.BirthDate, + Address = userModel.Address, UserTransactions = transactions, TotalBalance = transactions.Sum(x => x.Amount), UserRoles = roles, diff --git a/src/Application/Users/Queries/GetCurrentUser/GetCurrentUserProfilePicture.cs b/src/Application/Users/Queries/GetCurrentUser/GetCurrentUserProfilePicture.cs index cb4e6b4..f598887 100644 --- a/src/Application/Users/Queries/GetCurrentUser/GetCurrentUserProfilePicture.cs +++ b/src/Application/Users/Queries/GetCurrentUser/GetCurrentUserProfilePicture.cs @@ -8,16 +8,16 @@ public record GetCurrentUserProfilePictureQuery : IRequest; public class GetCurrentUserProfilePictureQueryHandler( IIdentityService identityService, IAzureBlobStorageService azureBlobStorageService - ) +) : IRequestHandler { public async Task Handle(GetCurrentUserProfilePictureQuery request, CancellationToken cancellationToken) { var identityUser = await identityService.GetCurrentUserAsync(); - var currentUserId = new Guid(identityUser?.Id ?? ""); - - var blobName = $"{currentUserId.ToString()}/{SubDirectoryNames.Profile}/{CommonFileNames.ProfilePicture}"; - - return await azureBlobStorageService.DownloadFileAsync(ContainerNames.Users, blobName); + + return await azureBlobStorageService.DownloadFileAsync( + ContainerNames.Users, + $"{identityUser.Id.ToString()}/{SubDirectoryNames.Profile}/{CommonFileNames.ProfilePicture}", + cancellationToken); } } diff --git a/src/Application/Users/Queries/GetCurrentUser/UserDto.cs b/src/Application/Users/Queries/GetCurrentUser/UserDto.cs index 3560de2..689c411 100644 --- a/src/Application/Users/Queries/GetCurrentUser/UserDto.cs +++ b/src/Application/Users/Queries/GetCurrentUser/UserDto.cs @@ -1,28 +1,19 @@ -using Hutopy.Application.Users.Models; - namespace Hutopy.Application.Users.Queries.GetCurrentUser; public class UserDto { public Guid Id { get; init; } - public string? Alias { get; init; } - public required string FirstName { get; init; } - public required string LastName { get; init; } - public string? CreatorAlias { get; set; } - public string UserName { get; init; } = string.Empty; - public string Occupation { get; init; } = string.Empty; - public string Email { get; init; } = string.Empty; - public string PhoneNumber { get; init; } = string.Empty; - public string BirthDate { get; init; } = string.Empty; - public string Country { get; init; } = string.Empty; - public string City { get; init; } = string.Empty; - public string Address { get; init; } = string.Empty; - public string About { get; init; } = string.Empty; - public string Description { get; init; } = string.Empty; - public SocialNetworksModel SocialNetworks { get; init; } = new(); - public ProfileColorsModel ProfileColors { get; init; } = new(); - public StoredDataUrlsModel StoredDataUrls { get; init; } = new(); - public List UserTransactions { get; init; } = []; public IList UserRoles { get; init; } = []; + public string UserName { get; init; } = null!; + public string? Alias { get; init; } + public string? PortraitUrl { get; init; } + public string? FirstName { get; init; } + public string? LastName { get; init; } + public string? Occupation { get; init; } + public string? Email { get; init; } + public string? PhoneNumber { get; init; } + public string? BirthDate { get; init; } + public string? Address { get; init; } + public List UserTransactions { get; init; } = []; public required decimal TotalBalance { get; init; } } diff --git a/src/Application/Users/Queries/GetUser/GetUser.cs b/src/Application/Users/Queries/GetUser/GetUser.cs deleted file mode 100644 index 3b36caa..0000000 --- a/src/Application/Users/Queries/GetUser/GetUser.cs +++ /dev/null @@ -1,46 +0,0 @@ -using Hutopy.Application.Common.Interfaces; -using Hutopy.Application.Common.Models; - -namespace Hutopy.Application.Users.Queries.GetUser; - -public record GetUserQuery : IRequest -{ - public string? UserId { get; set; } = string.Empty; - public string? UserName { get; set; } = string.Empty; -}; - -public class GetUserQueryHandler( - IIdentityService identityService - ) - : IRequestHandler -{ - public async Task Handle(GetUserQuery request, CancellationToken cancellationToken) - { - UserModel? identityUser = null; - - if (request.UserId != string.Empty) - { - identityUser = await identityService.FindUserByIdAsync(request.UserId); - - } - - if (request.UserName != string.Empty) - { - identityUser = await identityService.GetUserByUserNameAsync(request.UserName); - } - - var user = new UserDto - { - Id = identityUser?.Id ?? string.Empty, - FirstName = identityUser?.FirstName ?? string.Empty, - LastName = identityUser?.LastName ?? string.Empty, - UserName = identityUser?.UserName ?? string.Empty, - Occupation = identityUser?.Occupation ?? string.Empty, - SocialNetworks = identityUser?.SocialNetworks ?? new(), - ProfileColors = identityUser?.ProfileColors ?? new(), - StoredDataUrls = identityUser?.StoredDataUrls ?? new(), - }; - - return user; - } -} diff --git a/src/Application/Users/Queries/GetUser/GetUserById.cs b/src/Application/Users/Queries/GetUser/GetUserById.cs new file mode 100644 index 0000000..1128cfc --- /dev/null +++ b/src/Application/Users/Queries/GetUser/GetUserById.cs @@ -0,0 +1,23 @@ +using Hutopy.Application.Common.Interfaces; + +namespace Hutopy.Application.Users.Queries.GetUser; + +public record GetUserByIdQuery : IRequest +{ + public required string UserId { get; init; } +} + +public class GetUserByIdHandler( + IIdentityService identityService + ) + : IRequestHandler +{ + public async Task Handle(GetUserByIdQuery query, CancellationToken cancellationToken) + { + var user = await identityService.FindUserByIdAsync(query.UserId); + + if (user is null) throw new InvalidOperationException(); + + return user.ToDto(); + } +} diff --git a/src/Application/Users/Queries/GetUser/GetUserByUserName.cs b/src/Application/Users/Queries/GetUser/GetUserByUserName.cs new file mode 100644 index 0000000..131ac8b --- /dev/null +++ b/src/Application/Users/Queries/GetUser/GetUserByUserName.cs @@ -0,0 +1,23 @@ +using Hutopy.Application.Common.Interfaces; + +namespace Hutopy.Application.Users.Queries.GetUser; + +public record GetUserByUserNameQuery : IRequest +{ + public required string UserName { get; init; } +}; + +public class GetUserByUserNameQueryHandler( + IIdentityService identityService +) + : IRequestHandler +{ + public async Task Handle(GetUserByUserNameQuery query, CancellationToken cancellationToken) + { + var user = await identityService.GetUserByUserNameAsync(query.UserName); + + if (user is null) throw new InvalidOperationException(); + + return user.ToDto(); + } +} diff --git a/src/Application/Users/Queries/GetUser/UserDto.cs b/src/Application/Users/Queries/GetUser/UserDto.cs index 6c1dc13..86ce3d4 100644 --- a/src/Application/Users/Queries/GetUser/UserDto.cs +++ b/src/Application/Users/Queries/GetUser/UserDto.cs @@ -1,17 +1,25 @@ -using Hutopy.Application.Users.Models; +using Hutopy.Application.Common.Models; namespace Hutopy.Application.Users.Queries.GetUser; public class UserDto { - public required string Id { get; init; } - public required string FirstName { get; init; } - public required string LastName { get; init; } - public string CreatorAlias { get; set; } - public required string UserName { get; init; } = String.Empty; - public required string Occupation { get; init; } = String.Empty; - - public SocialNetworksModel SocialNetworks { get; init; } = new(); - public ProfileColorsModel ProfileColors { get; init; } = new(); - public StoredDataUrlsModel StoredDataUrls { get; init; } = new(); + public required Guid Id { get; init; } + public required string UserName { get; init; } + public string? FirstName { get; init; } + public string? LastName { get; init; } + public string? Occupation { get; init; } +} + +public static class UserDtoExtensions +{ + public static UserDto ToDto(this UserModel model) => + new() + { + Id = model.Id, + FirstName = model.FirstName, + LastName = model.LastName, + UserName = model.UserName, + Occupation = model.Occupation + }; } diff --git a/src/Domain/Common/BaseAuditableEntity.cs b/src/Domain/Common/BaseAuditableEntity.cs index f1da955..617d876 100644 --- a/src/Domain/Common/BaseAuditableEntity.cs +++ b/src/Domain/Common/BaseAuditableEntity.cs @@ -2,11 +2,11 @@ public abstract class BaseAuditableEntity : BaseEntity { - public DateTimeOffset Created { get; set; } + public DateTimeOffset CreatedAt { get; set; } - public string? CreatedBy { get; set; } + public Guid? CreatedBy { get; set; } - public DateTimeOffset LastModified { get; set; } + public DateTimeOffset LastModifiedAt { get; set; } - public string? LastModifiedBy { get; set; } + public Guid? LastModifiedBy { get; set; } } diff --git a/src/Domain/Entities/UserTransaction.cs b/src/Domain/Entities/UserTransaction.cs index 78e32d4..b7df7da 100644 --- a/src/Domain/Entities/UserTransaction.cs +++ b/src/Domain/Entities/UserTransaction.cs @@ -7,7 +7,7 @@ public class UserTransaction : BaseAuditableEntity public string TipMessage { get; set; } = string.Empty; // Foreign key to ApplicationUser - public required string ApplicationUserId { get; set; } + public required Guid ApplicationUserId { get; set; } public bool IsConfirmed { get; set; } public string StripeEventId { get; set; } = string.Empty; public string StripeChargeId { get; set; } = string.Empty; diff --git a/src/Infrastructure/AzureBlob/AzureBlobStorageService.cs b/src/Infrastructure/AzureBlob/AzureBlobStorageService.cs index 7887cef..9fee071 100644 --- a/src/Infrastructure/AzureBlob/AzureBlobStorageService.cs +++ b/src/Infrastructure/AzureBlob/AzureBlobStorageService.cs @@ -23,21 +23,21 @@ public class AzureBlobStorageService : IAzureBlobStorageService /// /// Upload a file to microsoft azure blob storage. /// - /// The blob name (path within the container, include the file name). /// The name of the container where the file is stored. - /// The memory stream containing the image. + /// The blob name (path within the container, include the file name). + /// /// The content type. /// The cancellation token /// - public async Task UploadFileAsync(string containerName, string blobName, MemoryStream memoryStream, + public async Task UploadFileAsync(string containerName, string blobName, Stream stream, string contentType, CancellationToken ct = default) { // Read the file stream into a memory stream to determine the length // WATCH FOR MEMORY USAGE USING THE MEMORY STREAM. - memoryStream.Position = 0; + stream.Position = 0; // Check if the file size exceeds the maximum upload size - if (memoryStream.Length > _maxUploadSize) + if (stream.Length > _maxUploadSize) { _logger.LogError( $"Blob storage: File size exceeds the maximum allowed size of {_maxUploadSize} bytes."); @@ -46,7 +46,7 @@ public class AzureBlobStorageService : IAzureBlobStorageService } // Validate content type - if (!ContentTypes.IsAllowed(contentType, memoryStream)) + if (!ContentTypes.IsAllowed(contentType, stream)) { _logger.LogError( $"Blob storage: Unsupported file type {contentType}. Only PNG and JPEG are allowed."); @@ -71,7 +71,7 @@ public class AzureBlobStorageService : IAzureBlobStorageService // Upload the file var response = await blobClient.UploadAsync( - memoryStream, + stream, new BlobUploadOptions { HttpHeaders = blobHttpHeaders }, ct); @@ -89,7 +89,7 @@ public class AzureBlobStorageService : IAzureBlobStorageService blobName, containerName, contentType, - memoryStream.Length, + stream.Length, fileUri ); @@ -128,6 +128,7 @@ public class AzureBlobStorageService : IAzureBlobStorageService // Download the blob to a stream BlobDownloadInfo download = await blobClient.DownloadAsync(ct); + MemoryStream memoryStream = new(); await download.Content.CopyToAsync(memoryStream, ct); memoryStream.Position = 0; // Ensure the stream is at the beginning diff --git a/src/Infrastructure/Data/ApplicationDbContext.cs b/src/Infrastructure/Data/ApplicationDbContext.cs index 21b06a4..a8a5d4f 100644 --- a/src/Infrastructure/Data/ApplicationDbContext.cs +++ b/src/Infrastructure/Data/ApplicationDbContext.cs @@ -7,13 +7,9 @@ using Microsoft.EntityFrameworkCore; namespace Hutopy.Infrastructure.Data { - public class ApplicationDbContext : IdentityDbContext, IApplicationDbContext + public class ApplicationDbContext(DbContextOptions options) + : IdentityDbContext(options), IApplicationDbContext { - public ApplicationDbContext(DbContextOptions options) - : base(options) - { - } - public DbSet FutureCreators => Set(); public DbSet UserTransactions => Set(); diff --git a/src/Infrastructure/Data/ApplicationDbContextInitializer.cs b/src/Infrastructure/Data/ApplicationDbContextInitializer.cs index ef35783..ff313b4 100644 --- a/src/Infrastructure/Data/ApplicationDbContextInitializer.cs +++ b/src/Infrastructure/Data/ApplicationDbContextInitializer.cs @@ -1,4 +1,5 @@ using Hutopy.Domain.Constants; +using Hutopy.Infrastructure.Identity; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Identity; using Microsoft.EntityFrameworkCore; @@ -24,7 +25,7 @@ public static class InitializerExtensions public class ApplicationDbContextInitializer( ILogger logger, ApplicationDbContext context, - RoleManager roleManager) + RoleManager roleManager) { public async Task InitialiseAsync() { @@ -54,13 +55,13 @@ public class ApplicationDbContextInitializer( private async Task TrySeedAsync() { - var administratorRole = new IdentityRole(Roles.Administrator); + var administratorRole = new ApplicationRole(Roles.Administrator); if (roleManager.Roles.All(r => r.Name != administratorRole.Name)) { await roleManager.CreateAsync(administratorRole); } - var roleCreator = new IdentityRole(Roles.Creator); + var roleCreator = new ApplicationRole(Roles.Creator); if (roleManager.Roles.All(r => r.Name != roleCreator.Name)) { await roleManager.CreateAsync(roleCreator); diff --git a/src/Infrastructure/Data/Configurations/ApplicationUserConfiguration.cs b/src/Infrastructure/Data/Configurations/ApplicationUserConfiguration.cs deleted file mode 100644 index b3a3735..0000000 --- a/src/Infrastructure/Data/Configurations/ApplicationUserConfiguration.cs +++ /dev/null @@ -1,26 +0,0 @@ -using Hutopy.Infrastructure.Identity; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Metadata.Builders; - -namespace Hutopy.Infrastructure.Data.Configurations; - -public class ApplicationUserConfiguration : IEntityTypeConfiguration -{ - public void Configure(EntityTypeBuilder builder) - { - // Relationship between ApplicationUser and SocialNetworks - builder - .OwnsOne(u => u.SocialNetworks) - .ToTable($"{nameof(ApplicationUser)}_SocialNetworks"); - - // Relationship between ApplicationUser and ProfileColors - builder - .OwnsOne(u => u.ProfileColors) - .ToTable($"{nameof(ApplicationUser)}_ProfileColors"); - - // Relationship between ApplicationUser and StoredDataUrls - builder - .OwnsOne(u => u.StoredDataUrls) - .ToTable($"{nameof(ApplicationUser)}_StoredDataUrls"); - } -} diff --git a/src/Infrastructure/Data/Interceptors/AuditableEntityInterceptor.cs b/src/Infrastructure/Data/Interceptors/AuditableEntityInterceptor.cs index f38d7b5..b1d7157 100644 --- a/src/Infrastructure/Data/Interceptors/AuditableEntityInterceptor.cs +++ b/src/Infrastructure/Data/Interceptors/AuditableEntityInterceptor.cs @@ -36,10 +36,10 @@ public class AuditableEntityInterceptor( if (entry.State == EntityState.Added) { entry.Entity.CreatedBy = user.Id; - entry.Entity.Created = utcNow; + entry.Entity.CreatedAt = utcNow; } entry.Entity.LastModifiedBy = user.Id; - entry.Entity.LastModified = utcNow; + entry.Entity.LastModifiedAt = utcNow; } } } diff --git a/src/Infrastructure/DependencyInjection.cs b/src/Infrastructure/DependencyInjection.cs index c4abf71..f7c3525 100644 --- a/src/Infrastructure/DependencyInjection.cs +++ b/src/Infrastructure/DependencyInjection.cs @@ -1,5 +1,4 @@ -using System; -using Hutopy.Application.Common.Interfaces; +using Hutopy.Application.Common.Interfaces; using Hutopy.Domain.Constants; using Hutopy.Infrastructure.AzureBlob; using Hutopy.Infrastructure.Data; @@ -45,7 +44,7 @@ public static class DependencyInjection services .AddIdentityCore() .AddUserManager() - .AddRoles() + .AddRoles() .AddEntityFrameworkStores() .AddApiEndpoints() .AddSignInManager>() diff --git a/src/Infrastructure/Identity/ApplicationRole.cs b/src/Infrastructure/Identity/ApplicationRole.cs index eba9904..4f90614 100644 --- a/src/Infrastructure/Identity/ApplicationRole.cs +++ b/src/Infrastructure/Identity/ApplicationRole.cs @@ -2,6 +2,8 @@ namespace Hutopy.Infrastructure.Identity; -public class ApplicationRole : IdentityRole +public class ApplicationRole : IdentityRole { + public ApplicationRole() { } + public ApplicationRole(string roleName) : base(roleName) { } } diff --git a/src/Infrastructure/Identity/ApplicationUser.cs b/src/Infrastructure/Identity/ApplicationUser.cs index 9b7ebdd..7d52e10 100644 --- a/src/Infrastructure/Identity/ApplicationUser.cs +++ b/src/Infrastructure/Identity/ApplicationUser.cs @@ -1,22 +1,15 @@ -using Hutopy.Infrastructure.Identity.OwnedEntities; +using System.ComponentModel.DataAnnotations; using Microsoft.AspNetCore.Identity; namespace Hutopy.Infrastructure.Identity; -public class ApplicationUser : IdentityUser -{ - public string? Alias { get; set; } - public required string FirstName { get; set; } - public required string LastName { get; set; } - public string? CreatorAlias { get; set; } - public string Occupation { get; set; } = string.Empty; - public string BirthDate { get; set; } = string.Empty; - public string Country { get; set; } = string.Empty; - public string City { get; set; } = string.Empty; - public string Address { get; set; } = string.Empty; - public string About { get; set; } = string.Empty; - public string Description { get; set; } = string.Empty; - public SocialNetworks SocialNetworks { get; set; } = new(); - public ProfileColors ProfileColors { get; set; } = new(); - public StoredDataUrls StoredDataUrls { get; set; } = new(); +public class ApplicationUser : IdentityUser +{ + [MaxLength(255)] public string? Alias { get; set; } + [MaxLength(255)] public string? FirstName { get; set; } + [MaxLength(255)] public string? LastName { get; set; } + [MaxLength(255)] public string? Occupation { get; set; } + [MaxLength(255)] public string? BirthDate { get; set; } + [MaxLength(255)] public string? Address { get; set; } + [MaxLength(255)] public string? PortraitUrl { get; set; } } diff --git a/src/Infrastructure/Identity/ApplicationUserManager.cs b/src/Infrastructure/Identity/ApplicationUserManager.cs index 8125aae..1799bbc 100644 --- a/src/Infrastructure/Identity/ApplicationUserManager.cs +++ b/src/Infrastructure/Identity/ApplicationUserManager.cs @@ -1,9 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Identity; -using Microsoft.EntityFrameworkCore; +using Microsoft.AspNetCore.Identity; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; @@ -30,17 +25,4 @@ public sealed class ApplicationUserManager( services, logger) { - public async Task FindByCreatorAliasAsync(string creatorAlias, - CancellationToken cancellationToken = default) - { - ArgumentException.ThrowIfNullOrEmpty(creatorAlias); - ThrowIfDisposed(); - - var user = await Users.SingleOrDefaultAsync(u => EF.Functions.Like( - creatorAlias, - u.CreatorAlias), - cancellationToken: cancellationToken); - - return user; - } } diff --git a/src/Infrastructure/Identity/IdentityResultExtensions.cs b/src/Infrastructure/Identity/IdentityResultExtensions.cs index 0902e4f..630c372 100644 --- a/src/Infrastructure/Identity/IdentityResultExtensions.cs +++ b/src/Infrastructure/Identity/IdentityResultExtensions.cs @@ -1,5 +1,4 @@ -using System.Linq; -using Hutopy.Application.Common.Models; +using Hutopy.Application.Common.Models; using Microsoft.AspNetCore.Identity; namespace Hutopy.Infrastructure.Identity; diff --git a/src/Infrastructure/Identity/IdentityService.cs b/src/Infrastructure/Identity/IdentityService.cs index beaab6b..f853d1f 100644 --- a/src/Infrastructure/Identity/IdentityService.cs +++ b/src/Infrastructure/Identity/IdentityService.cs @@ -17,67 +17,39 @@ public class IdentityService( IAuthorizationService authorizationService, IHttpContextAccessor contextAccessor, IOptionsSnapshot jwtOptions - ) +) : IIdentityService { - public async Task GetUserNameAsync(string userId) + public async Task GetUserNameAsync(Guid userId) { - var user = await userManager.FindByIdAsync(userId); + var user = await userManager.FindByIdAsync(userId.ToString()); return user?.UserName; } - + public async Task GetUserByUserNameAsync(string userName) { var user = await userManager.FindByNameAsync(userName); - + if (user == null) return null; return new() { Id = user.Id, - CreatorAlias = user.CreatorAlias, - UserName = user.UserName ?? string.Empty, + UserName = user.UserName!, + PhoneNumber = user.PhoneNumber, + Email = user.Email, Alias = user.Alias, FirstName = user.FirstName, LastName = user.LastName, - Email = user.Email ?? string.Empty, Occupation = user.Occupation, - PhoneNumber = user.PhoneNumber ?? string.Empty, BirthDate = user.BirthDate, - Country = user.Country, - City = user.City, Address = user.Address, - About = user.About, - Description = user.Description, - SocialNetworks = new() - { - FacebookUrl = user.SocialNetworks.FacebookUrl, - InstagramUrl = user.SocialNetworks.InstagramUrl, - XUrl = user.SocialNetworks.XUrl, - LinkedInUrl = user.SocialNetworks.LinkedInUrl, - TikTokUrl = user.SocialNetworks.TikTokUrl, - YoutubeUrl = user.SocialNetworks.YoutubeUrl, - RedditUrl = user.SocialNetworks.RedditUrl, - YourWebsiteUrl = user.SocialNetworks.YourWebsiteUrl, - }, - ProfileColors = new() - { - BannerTop = user.ProfileColors.BannerTop, - BannerBottom = user.ProfileColors.BannerBottom, - Accent = user.ProfileColors.Accent, - Menu = user.ProfileColors.Menu - }, - StoredDataUrls = new() - { - ProfilePictureUrl = user.StoredDataUrls.ProfilePictureUrl, - BannerPictureUrl = user.StoredDataUrls.BannerPictureUrl, - WebsiteIconUrl = user.StoredDataUrls.WebsiteIconUrl, - } + PortraitUrl = user.PortraitUrl }; } - - public async Task> CreateUserAsync(Userinfo userInfo) + + public async Task> CreateUserAsync(Userinfo userInfo) { var applicationUser = new ApplicationUser { @@ -86,80 +58,83 @@ public class IdentityService( FirstName = userInfo.GivenName, LastName = userInfo.FamilyName }; - + var password = Guid.NewGuid().ToString("N")[..32]; var identityResult = await userManager.CreateAsync(applicationUser, password); var applicationResult = identityResult.ToApplicationResult(); - var result = new Result(applicationUser.Id, applicationResult.Succeeded, applicationResult.Errors); - + var result = new Result(applicationUser.Id, applicationResult.Succeeded, applicationResult.Errors); + return result; } - - public async Task> CreateUserAsync(string email, string userName, string firstName, string lastName, string password) + + public async Task> CreateUserAsync(string email, string userName, string firstName, string lastName, + string password) { var applicationUser = new ApplicationUser { - UserName = userName, - Email = email, - FirstName = firstName, - LastName = lastName + UserName = userName, Email = email, FirstName = firstName, LastName = lastName }; var response = await userManager.CreateAsync(applicationUser, password); - - var result = new Result(applicationUser.Id, response.Succeeded, response.ToApplicationResult().Errors); + + var result = new Result(applicationUser.Id, response.Succeeded, response.ToApplicationResult().Errors); return result; } - public async Task> UpdateCurrentUserAsync(UserModel userModel) + public async Task> UpdateCurrentUserAsync(UserModel userModel) { - var applicationUser = await userManager.FindByIdAsync(userModel.Id); + var applicationUser = await userManager.FindByIdAsync(userModel.Id.ToString()); - if (applicationUser is null) return Result.Failure("", new[] { "User not found." }); + if (applicationUser is null) return Result.Failure(Guid.Empty, new[] { "User not found." }); + applicationUser.Id = userModel.Id; + applicationUser.Email = userModel.Email; + applicationUser.PhoneNumber = userModel.PhoneNumber; + applicationUser.Alias = userModel.Alias; applicationUser.FirstName = userModel.FirstName; applicationUser.LastName = userModel.LastName; applicationUser.Occupation = userModel.Occupation; - applicationUser.PhoneNumber = userModel.PhoneNumber; applicationUser.BirthDate = userModel.BirthDate; - applicationUser.Country = userModel.Country; - applicationUser.City = userModel.City; applicationUser.Address = userModel.Address; - applicationUser.About = userModel.About; - applicationUser.Description = userModel.Description; - applicationUser.SocialNetworks = new() - { - FacebookUrl = userModel.SocialNetworks.FacebookUrl, - InstagramUrl = userModel.SocialNetworks.InstagramUrl, - XUrl = userModel.SocialNetworks.XUrl, - LinkedInUrl = userModel.SocialNetworks.LinkedInUrl, - TikTokUrl = userModel.SocialNetworks.TikTokUrl, - YoutubeUrl = userModel.SocialNetworks.YoutubeUrl, - RedditUrl = userModel.SocialNetworks.RedditUrl, - YourWebsiteUrl = userModel.SocialNetworks.YourWebsiteUrl - }; - applicationUser.ProfileColors = new() - { - BannerTop = userModel.ProfileColors.BannerTop, - BannerBottom = userModel.ProfileColors.BannerBottom, - Accent = userModel.ProfileColors.Accent, - Menu = userModel.ProfileColors.Menu - }; + applicationUser.PortraitUrl = userModel.PortraitUrl; var response = await userManager.UpdateAsync(applicationUser); var applicationResult = response.ToApplicationResult(); - var result = new Result(userModel.Id, applicationResult.Succeeded, + var result = new Result( + userModel.Id, + applicationResult.Succeeded, applicationResult.Errors); - + return result; } - + + + private static UserModel BuildModelFrom(ApplicationUser response) + { + var userModel = new UserModel + { + Id = response.Id, + UserName = response.UserName ?? string.Empty, + PhoneNumber = response.PhoneNumber ?? string.Empty, + Email = response.Email ?? string.Empty, + PortraitUrl = response.PortraitUrl, + Alias = response.Alias, + FirstName = response.FirstName, + LastName = response.LastName, + Occupation = response.Occupation, + BirthDate = response.BirthDate, + Address = response.Address, + }; + + return userModel; + } + public async Task FindUserByIdAsync(string id) { var user = await userManager.FindByIdAsync(id); @@ -170,64 +145,6 @@ public class IdentityService( return userModel; } - - public async Task FindUserByCreatorAliasAsync(string creatorAlias, CancellationToken cancellationToken = default) - { - var user = await userManager.FindByCreatorAliasAsync(creatorAlias, cancellationToken); - - if (user == null) return null; - - var userModel = BuildModelFrom(user); - - return userModel; - } - - private static UserModel BuildModelFrom(ApplicationUser response) - { - var userModel = new UserModel - { - Id = response.Id, - CreatorAlias = response.CreatorAlias, - UserName = response.UserName ?? string.Empty, - Alias = response.Alias, - FirstName = response.FirstName, - LastName = response.LastName, - Email = response.Email ?? string.Empty, - Occupation = response.Occupation, - PhoneNumber = response.PhoneNumber ?? string.Empty, - BirthDate = response.BirthDate, - Country = response.Country, - City = response.City, - Address = response.Address, - About = response.About, - Description = response.Description, - SocialNetworks = new() - { - FacebookUrl = response.SocialNetworks.FacebookUrl, - InstagramUrl = response.SocialNetworks.InstagramUrl, - XUrl = response.SocialNetworks.XUrl, - LinkedInUrl = response.SocialNetworks.LinkedInUrl, - TikTokUrl = response.SocialNetworks.TikTokUrl, - YoutubeUrl = response.SocialNetworks.YoutubeUrl, - RedditUrl = response.SocialNetworks.RedditUrl, - YourWebsiteUrl = response.SocialNetworks.YourWebsiteUrl, - }, - ProfileColors = new() - { - BannerTop = response.ProfileColors.BannerTop, - BannerBottom = response.ProfileColors.BannerBottom, - Accent = response.ProfileColors.Accent, - Menu = response.ProfileColors.Menu - }, - StoredDataUrls = new() - { - ProfilePictureUrl = response.StoredDataUrls.ProfilePictureUrl, - BannerPictureUrl = response.StoredDataUrls.BannerPictureUrl, - WebsiteIconUrl = response.StoredDataUrls.WebsiteIconUrl, - } - }; - return userModel; - } public async Task FindUserByEmailAsync(string email) { @@ -235,51 +152,9 @@ public class IdentityService( if (response == null) return null; - var userModel = new UserModel - { - Id = response.Id, - CreatorAlias = response.CreatorAlias, - UserName = response.UserName ?? string.Empty, - FirstName = response.FirstName, - LastName = response.LastName, - Email = response.Email ?? string.Empty, - Occupation = response.Occupation, - PhoneNumber = response.PhoneNumber ?? string.Empty, - BirthDate = response.BirthDate, - Country = response.Country, - City = response.City, - Address = response.Address, - About = response.About, - Description = response.Description, - SocialNetworks = new() - { - FacebookUrl = response.SocialNetworks.FacebookUrl, - InstagramUrl = response.SocialNetworks.InstagramUrl, - XUrl = response.SocialNetworks.XUrl, - LinkedInUrl = response.SocialNetworks.LinkedInUrl, - TikTokUrl = response.SocialNetworks.TikTokUrl, - YoutubeUrl = response.SocialNetworks.YoutubeUrl, - RedditUrl = response.SocialNetworks.RedditUrl, - YourWebsiteUrl = response.SocialNetworks.YourWebsiteUrl, - }, - ProfileColors = new() - { - BannerTop = response.ProfileColors.BannerTop, - BannerBottom = response.ProfileColors.BannerBottom, - Accent = response.ProfileColors.Accent, - Menu = response.ProfileColors.Menu - }, - StoredDataUrls = new() - { - ProfilePictureUrl = response.StoredDataUrls.ProfilePictureUrl, - BannerPictureUrl = response.StoredDataUrls.BannerPictureUrl, - WebsiteIconUrl = response.StoredDataUrls.WebsiteIconUrl, - } - }; - - return userModel; + return BuildModelFrom(response); } - + public async Task GetCurrentUserAsync() { var currentUserId = contextAccessor.HttpContext?.User.FindFirst(ClaimTypes.NameIdentifier)?.Value; @@ -291,69 +166,38 @@ public class IdentityService( return await FindUserByIdAsync(currentUserId); } - public async Task UpdateCurrentUserBannerPictureUrlAsync(string url) + public async Task UpdateCurrentUserPortraitUrlAsync(string url) { var userModel = await GetCurrentUserAsync(); - if (userModel is null) return Result.Failure(new[] { "User not found." }); - var applicationUser = await userManager.FindByIdAsync(userModel.Id); - if (applicationUser is null) return Result.Failure(new[] { "ApplicationUser not found." }); + var applicationUser = await userManager.FindByIdAsync(userModel.Id.ToString()); + if (applicationUser is null) return Result.Failure(["ApplicationUser not found."]); + + applicationUser.PortraitUrl = url; - applicationUser.StoredDataUrls.BannerPictureUrl = url; - var response = await userManager.UpdateAsync(applicationUser); return response.ToApplicationResult(); } - public async Task UpdateCurrentUserProfilePictureUrlAsync(string url) + public async Task IsInRoleAsync(Guid userId, string role) { - var userModel = await GetCurrentUserAsync(); - if (userModel is null) return Result.Failure(new[] { "User not found." }); - - var applicationUser = await userManager.FindByIdAsync(userModel.Id); - if (applicationUser is null) return Result.Failure(new[] { "ApplicationUser not found." }); - - applicationUser.StoredDataUrls.ProfilePictureUrl = url; - - var response = await userManager.UpdateAsync(applicationUser); - - return response.ToApplicationResult(); - } - - public async Task UpdateCurrentUserWebsiteIconUrlAsync(string url) - { - var userModel = await GetCurrentUserAsync(); - if (userModel is null) return Result.Failure(new[] { "User not found." }); - - var applicationUser = await userManager.FindByIdAsync(userModel.Id); - if (applicationUser is null) return Result.Failure(new[] { "ApplicationUser not found." }); - - applicationUser.StoredDataUrls.WebsiteIconUrl = url; - - var response = await userManager.UpdateAsync(applicationUser); - - return response.ToApplicationResult(); - } - - public async Task IsInRoleAsync(string userId, string role) - { - var user = await userManager.FindByIdAsync(userId); + var user = await userManager.FindByIdAsync(userId.ToString()); return user != null && await userManager.IsInRoleAsync(user, role); } - + public async Task CurrentUserIsInRoleAsync(string role) { var currentUserModel = await GetCurrentUserAsync(); - var currentUser = await userManager.FindByIdAsync(currentUserModel?.Id ?? ""); + var currentUser = await userManager.FindByIdAsync(currentUserModel.Id.ToString()); return currentUser != null && await userManager.IsInRoleAsync(currentUser, role); } - public async Task AuthorizeAsync(string userId, string policyName) + public async Task AuthorizeAsync(Guid userId, string policyName) { - var user = await userManager.FindByIdAsync(userId); + var user = await userManager.FindByIdAsync(userId.ToString()); if (user == null) { @@ -380,44 +224,45 @@ public class IdentityService( return result.ToApplicationResult(); } - + public async Task AddRoleAsync(string userId, string role) { var hasAdminAccess = await CurrentUserIsInRoleAsync("Administrator"); - - if (!hasAdminAccess) return Result.Failure(new []{"Only administrator can assign new roles to a user."}); + + if (!hasAdminAccess) return Result.Failure(new[] { "Only administrator can assign new roles to a user." }); var user = await userManager.FindByIdAsync(userId); - - if (user is null) return Result.Failure(new []{"User not found."}); - + + if (user is null) return Result.Failure(new[] { "User not found." }); + var result = await userManager.AddToRoleAsync(user, role); return result.ToApplicationResult(); } - + public async Task> GetCurrentUserRolesAsync() { var currentUserModel = await GetCurrentUserAsync(); - - var currentUser = await userManager.FindByIdAsync(currentUserModel?.Id ?? ""); - - if (currentUser is null) return []; + + var currentUser = await userManager.FindByIdAsync(currentUserModel.Id.ToString()); + + if (currentUser is null) return []; var userRoles = await userManager.GetRolesAsync(currentUser); return userRoles; } - + public async Task LoginAsync(string userName, string password) { - var result = await signInManager.PasswordSignInAsync(userName, password, isPersistent: false, lockoutOnFailure: false); - + var result = + await signInManager.PasswordSignInAsync(userName, password, isPersistent: false, lockoutOnFailure: false); + if (!result.Succeeded) { return null; } - + var user = await GetUserByUserNameAsync(userName); if (user is null) throw new InvalidOperationException(); @@ -427,12 +272,12 @@ public class IdentityService( issuer: jwtOptions.Value.Issuer, audience: jwtOptions.Value.Audience, key: jwtOptions.Value.Key, - userId: user.Id, + userId: user.Id.ToString(), email: user.Email, alias: user.Alias, firstname: user.FirstName, lastname: user.LastName, - profilePictureUrl: user.StoredDataUrls.ProfilePictureUrl); + portraitUrl: user.PortraitUrl); return token; } diff --git a/src/Infrastructure/Identity/OwnedEntities/ProfileColors.cs b/src/Infrastructure/Identity/OwnedEntities/ProfileColors.cs deleted file mode 100644 index 3783044..0000000 --- a/src/Infrastructure/Identity/OwnedEntities/ProfileColors.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace Hutopy.Infrastructure.Identity.OwnedEntities; - -public class ProfileColors -{ - public string BannerTop { get; init; } = string.Empty; - public string BannerBottom { get; init; } = string.Empty; - public string Accent { get; init; } = string.Empty; - public string Menu { get; init; } = string.Empty; -} diff --git a/src/Infrastructure/Identity/OwnedEntities/SocialNetworks.cs b/src/Infrastructure/Identity/OwnedEntities/SocialNetworks.cs deleted file mode 100644 index a03e139..0000000 --- a/src/Infrastructure/Identity/OwnedEntities/SocialNetworks.cs +++ /dev/null @@ -1,13 +0,0 @@ -namespace Hutopy.Infrastructure.Identity.OwnedEntities; - -public class SocialNetworks -{ - public string FacebookUrl { get; init; } = string.Empty; - public string InstagramUrl { get; init; } = string.Empty; - public string XUrl { get; init; } = string.Empty; - public string LinkedInUrl { get; init; } = string.Empty; - public string TikTokUrl { get; init; } = string.Empty; - public string YoutubeUrl { get; init; } = string.Empty; - public string RedditUrl { get; init; } = string.Empty; - public string YourWebsiteUrl { get; init; } = string.Empty; -} diff --git a/src/Infrastructure/Identity/OwnedEntities/StoredDataUrls.cs b/src/Infrastructure/Identity/OwnedEntities/StoredDataUrls.cs deleted file mode 100644 index 53d5346..0000000 --- a/src/Infrastructure/Identity/OwnedEntities/StoredDataUrls.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.ComponentModel.DataAnnotations; - -namespace Hutopy.Infrastructure.Identity.OwnedEntities; - -public class StoredDataUrls -{ - [MaxLength(255)] public string? BannerPictureUrl { get; set; } - [MaxLength(255)] public string? ProfilePictureUrl { get; set; } - [MaxLength(255)] public string? WebsiteIconUrl { get; set; } -} diff --git a/src/Infrastructure/Identity/RoleService.cs b/src/Infrastructure/Identity/RoleService.cs index 59fc22b..ef8749a 100644 --- a/src/Infrastructure/Identity/RoleService.cs +++ b/src/Infrastructure/Identity/RoleService.cs @@ -1,6 +1,4 @@ -using System; -using System.Threading.Tasks; -using Hutopy.Application.Common.Interfaces; +using Hutopy.Application.Common.Interfaces; using Hutopy.Application.Common.Models; using Microsoft.AspNetCore.Identity; @@ -13,7 +11,7 @@ public class RoleService( { public async Task CreateRoleAsync(string roleName) { - var role = new ApplicationRole { Name = roleName, Id = Guid.NewGuid().ToString()}; + var role = new ApplicationRole { Name = roleName, Id = Guid.NewGuid()}; var result = await roleManager.CreateAsync(role); return result.ToApplicationResult(); diff --git a/src/Infrastructure/Infrastructure.csproj b/src/Infrastructure/Infrastructure.csproj index 36b3844..93b2a22 100644 --- a/src/Infrastructure/Infrastructure.csproj +++ b/src/Infrastructure/Infrastructure.csproj @@ -4,21 +4,24 @@ Hutopy.Infrastructure - - - - + + + + runtime; build; native; contentfiles; analyzers; buildtransitive all - - - - - + + + + + - + + + + diff --git a/src/Infrastructure/Migrations/20240418221249_InitialMigration.Designer.cs b/src/Infrastructure/Migrations/20240418221249_InitialMigration.Designer.cs deleted file mode 100644 index e1c834e..0000000 --- a/src/Infrastructure/Migrations/20240418221249_InitialMigration.Designer.cs +++ /dev/null @@ -1,334 +0,0 @@ -// -using System; -using Hutopy.Infrastructure.Data; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -#nullable disable - -namespace Hutopy.Infrastructure.Migrations -{ - [DbContext(typeof(ApplicationDbContext))] - [Migration("20240418221249_InitialMigration")] - partial class InitialMigration - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "8.0.3") - .HasAnnotation("Relational:MaxIdentifierLength", 128); - - SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); - - modelBuilder.Entity("Hutopy.Domain.Entities.FutureCreator", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uniqueidentifier"); - - b.Property("Created") - .HasColumnType("datetimeoffset"); - - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("EmailAddress") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("FirstName") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("LastModified") - .HasColumnType("datetimeoffset"); - - b.Property("LastModifiedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("LastName") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("PhoneNumber") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("ReasonToJoin") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("SocialNetworkAccount") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.ToTable("FutureCreators"); - }); - - modelBuilder.Entity("Hutopy.Infrastructure.Identity.ApplicationUser", b => - { - b.Property("Id") - .HasColumnType("nvarchar(450)"); - - b.Property("AccessFailedCount") - .HasColumnType("int"); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnType("nvarchar(max)"); - - b.Property("Email") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("EmailConfirmed") - .HasColumnType("bit"); - - b.Property("FirstName") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("LastName") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("LockoutEnabled") - .HasColumnType("bit"); - - b.Property("LockoutEnd") - .HasColumnType("datetimeoffset"); - - b.Property("NormalizedEmail") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("NormalizedUserName") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("PasswordHash") - .HasColumnType("nvarchar(max)"); - - b.Property("PhoneNumber") - .HasColumnType("nvarchar(max)"); - - b.Property("PhoneNumberConfirmed") - .HasColumnType("bit"); - - b.Property("SecurityStamp") - .HasColumnType("nvarchar(max)"); - - b.Property("TwoFactorEnabled") - .HasColumnType("bit"); - - b.Property("UserName") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.HasKey("Id"); - - b.HasIndex("NormalizedEmail") - .HasDatabaseName("EmailIndex"); - - b.HasIndex("NormalizedUserName") - .IsUnique() - .HasDatabaseName("UserNameIndex") - .HasFilter("[NormalizedUserName] IS NOT NULL"); - - b.ToTable("AspNetUsers", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => - { - b.Property("Id") - .HasColumnType("nvarchar(450)"); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnType("nvarchar(max)"); - - b.Property("Name") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("NormalizedName") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.HasKey("Id"); - - b.HasIndex("NormalizedName") - .IsUnique() - .HasDatabaseName("RoleNameIndex") - .HasFilter("[NormalizedName] IS NOT NULL"); - - b.ToTable("AspNetRoles", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ClaimType") - .HasColumnType("nvarchar(max)"); - - b.Property("ClaimValue") - .HasColumnType("nvarchar(max)"); - - b.Property("RoleId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("Id"); - - b.HasIndex("RoleId"); - - b.ToTable("AspNetRoleClaims", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ClaimType") - .HasColumnType("nvarchar(max)"); - - b.Property("ClaimValue") - .HasColumnType("nvarchar(max)"); - - b.Property("UserId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("AspNetUserClaims", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => - { - b.Property("LoginProvider") - .HasColumnType("nvarchar(450)"); - - b.Property("ProviderKey") - .HasColumnType("nvarchar(450)"); - - b.Property("ProviderDisplayName") - .HasColumnType("nvarchar(max)"); - - b.Property("UserId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("LoginProvider", "ProviderKey"); - - b.HasIndex("UserId"); - - b.ToTable("AspNetUserLogins", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => - { - b.Property("UserId") - .HasColumnType("nvarchar(450)"); - - b.Property("RoleId") - .HasColumnType("nvarchar(450)"); - - b.HasKey("UserId", "RoleId"); - - b.HasIndex("RoleId"); - - b.ToTable("AspNetUserRoles", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => - { - b.Property("UserId") - .HasColumnType("nvarchar(450)"); - - b.Property("LoginProvider") - .HasColumnType("nvarchar(450)"); - - b.Property("Name") - .HasColumnType("nvarchar(450)"); - - b.Property("Value") - .HasColumnType("nvarchar(max)"); - - b.HasKey("UserId", "LoginProvider", "Name"); - - b.ToTable("AspNetUserTokens", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) - .WithMany() - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => - { - b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => - { - b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) - .WithMany() - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => - { - b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Infrastructure/Migrations/20240422173330_AddUserTransactions.Designer.cs b/src/Infrastructure/Migrations/20240422173330_AddUserTransactions.Designer.cs deleted file mode 100644 index cc634ad..0000000 --- a/src/Infrastructure/Migrations/20240422173330_AddUserTransactions.Designer.cs +++ /dev/null @@ -1,383 +0,0 @@ -// -using System; -using Hutopy.Infrastructure.Data; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -#nullable disable - -namespace Hutopy.Infrastructure.Migrations -{ - [DbContext(typeof(ApplicationDbContext))] - [Migration("20240422173330_AddUserTransactions")] - partial class AddUserTransactions - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "8.0.3") - .HasAnnotation("Relational:MaxIdentifierLength", 128); - - SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); - - modelBuilder.Entity("Hutopy.Domain.Entities.FutureCreator", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uniqueidentifier"); - - b.Property("Created") - .HasColumnType("datetimeoffset"); - - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("EmailAddress") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("FirstName") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("LastModified") - .HasColumnType("datetimeoffset"); - - b.Property("LastModifiedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("LastName") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("PhoneNumber") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("ReasonToJoin") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("SocialNetworkAccount") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.ToTable("FutureCreators"); - }); - - modelBuilder.Entity("Hutopy.Domain.Entities.UserTransaction", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uniqueidentifier"); - - b.Property("Amount") - .HasColumnType("decimal(18,2)"); - - b.Property("ApplicationUserId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.Property("Created") - .HasColumnType("datetimeoffset"); - - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("Currency") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("LastModified") - .HasColumnType("datetimeoffset"); - - b.Property("LastModifiedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("TipMessage") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.HasIndex("ApplicationUserId"); - - b.ToTable("UserTransactions"); - }); - - modelBuilder.Entity("Hutopy.Infrastructure.Identity.ApplicationUser", b => - { - b.Property("Id") - .HasColumnType("nvarchar(450)"); - - b.Property("AccessFailedCount") - .HasColumnType("int"); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnType("nvarchar(max)"); - - b.Property("Email") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("EmailConfirmed") - .HasColumnType("bit"); - - b.Property("FirstName") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("LastName") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("LockoutEnabled") - .HasColumnType("bit"); - - b.Property("LockoutEnd") - .HasColumnType("datetimeoffset"); - - b.Property("NormalizedEmail") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("NormalizedUserName") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("PasswordHash") - .HasColumnType("nvarchar(max)"); - - b.Property("PhoneNumber") - .HasColumnType("nvarchar(max)"); - - b.Property("PhoneNumberConfirmed") - .HasColumnType("bit"); - - b.Property("SecurityStamp") - .HasColumnType("nvarchar(max)"); - - b.Property("TwoFactorEnabled") - .HasColumnType("bit"); - - b.Property("UserName") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.HasKey("Id"); - - b.HasIndex("NormalizedEmail") - .HasDatabaseName("EmailIndex"); - - b.HasIndex("NormalizedUserName") - .IsUnique() - .HasDatabaseName("UserNameIndex") - .HasFilter("[NormalizedUserName] IS NOT NULL"); - - b.ToTable("AspNetUsers", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => - { - b.Property("Id") - .HasColumnType("nvarchar(450)"); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnType("nvarchar(max)"); - - b.Property("Name") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("NormalizedName") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.HasKey("Id"); - - b.HasIndex("NormalizedName") - .IsUnique() - .HasDatabaseName("RoleNameIndex") - .HasFilter("[NormalizedName] IS NOT NULL"); - - b.ToTable("AspNetRoles", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ClaimType") - .HasColumnType("nvarchar(max)"); - - b.Property("ClaimValue") - .HasColumnType("nvarchar(max)"); - - b.Property("RoleId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("Id"); - - b.HasIndex("RoleId"); - - b.ToTable("AspNetRoleClaims", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ClaimType") - .HasColumnType("nvarchar(max)"); - - b.Property("ClaimValue") - .HasColumnType("nvarchar(max)"); - - b.Property("UserId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("AspNetUserClaims", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => - { - b.Property("LoginProvider") - .HasColumnType("nvarchar(450)"); - - b.Property("ProviderKey") - .HasColumnType("nvarchar(450)"); - - b.Property("ProviderDisplayName") - .HasColumnType("nvarchar(max)"); - - b.Property("UserId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("LoginProvider", "ProviderKey"); - - b.HasIndex("UserId"); - - b.ToTable("AspNetUserLogins", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => - { - b.Property("UserId") - .HasColumnType("nvarchar(450)"); - - b.Property("RoleId") - .HasColumnType("nvarchar(450)"); - - b.HasKey("UserId", "RoleId"); - - b.HasIndex("RoleId"); - - b.ToTable("AspNetUserRoles", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => - { - b.Property("UserId") - .HasColumnType("nvarchar(450)"); - - b.Property("LoginProvider") - .HasColumnType("nvarchar(450)"); - - b.Property("Name") - .HasColumnType("nvarchar(450)"); - - b.Property("Value") - .HasColumnType("nvarchar(max)"); - - b.HasKey("UserId", "LoginProvider", "Name"); - - b.ToTable("AspNetUserTokens", (string)null); - }); - - modelBuilder.Entity("Hutopy.Domain.Entities.UserTransaction", b => - { - b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) - .WithMany() - .HasForeignKey("ApplicationUserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) - .WithMany() - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => - { - b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => - { - b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) - .WithMany() - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => - { - b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Infrastructure/Migrations/20240422173330_AddUserTransactions.cs b/src/Infrastructure/Migrations/20240422173330_AddUserTransactions.cs deleted file mode 100644 index f60e3fc..0000000 --- a/src/Infrastructure/Migrations/20240422173330_AddUserTransactions.cs +++ /dev/null @@ -1,52 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace Hutopy.Infrastructure.Migrations -{ - /// - public partial class AddUserTransactions : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.CreateTable( - name: "UserTransactions", - columns: table => new - { - Id = table.Column(type: "uniqueidentifier", nullable: false), - Amount = table.Column(type: "decimal(18,2)", nullable: false), - Currency = table.Column(type: "nvarchar(max)", nullable: false), - TipMessage = table.Column(type: "nvarchar(max)", nullable: false), - ApplicationUserId = table.Column(type: "nvarchar(450)", nullable: false), - Created = table.Column(type: "datetimeoffset", nullable: false), - CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), - LastModified = table.Column(type: "datetimeoffset", nullable: false), - LastModifiedBy = table.Column(type: "nvarchar(max)", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_UserTransactions", x => x.Id); - table.ForeignKey( - name: "FK_UserTransactions_AspNetUsers_ApplicationUserId", - column: x => x.ApplicationUserId, - principalTable: "AspNetUsers", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateIndex( - name: "IX_UserTransactions_ApplicationUserId", - table: "UserTransactions", - column: "ApplicationUserId"); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "UserTransactions"); - } - } -} diff --git a/src/Infrastructure/Migrations/20240425020920_AddIsConfirmedToUserTransaction.Designer.cs b/src/Infrastructure/Migrations/20240425020920_AddIsConfirmedToUserTransaction.Designer.cs deleted file mode 100644 index 80ac05b..0000000 --- a/src/Infrastructure/Migrations/20240425020920_AddIsConfirmedToUserTransaction.Designer.cs +++ /dev/null @@ -1,387 +0,0 @@ -// -using System; -using Hutopy.Infrastructure.Data; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -#nullable disable - -namespace Hutopy.Infrastructure.Migrations -{ - [DbContext(typeof(ApplicationDbContext))] - [Migration("20240425020920_AddIsConfirmedToUserTransaction")] - partial class AddIsConfirmedToUserTransaction - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "8.0.3") - .HasAnnotation("Relational:MaxIdentifierLength", 128); - - SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); - - modelBuilder.Entity("Hutopy.Domain.Entities.FutureCreator", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uniqueidentifier"); - - b.Property("Created") - .HasColumnType("datetimeoffset"); - - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("EmailAddress") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("FirstName") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("LastModified") - .HasColumnType("datetimeoffset"); - - b.Property("LastModifiedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("LastName") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("PhoneNumber") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("ReasonToJoin") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("SocialNetworkAccount") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.ToTable("FutureCreators"); - }); - - modelBuilder.Entity("Hutopy.Domain.Entities.UserTransaction", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uniqueidentifier"); - - b.Property("Amount") - .HasPrecision(18, 2) - .HasColumnType("decimal(18,2)"); - - b.Property("ApplicationUserId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.Property("Created") - .HasColumnType("datetimeoffset"); - - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("Currency") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("IsConfirmed") - .HasColumnType("bit"); - - b.Property("LastModified") - .HasColumnType("datetimeoffset"); - - b.Property("LastModifiedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("TipMessage") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.HasIndex("ApplicationUserId"); - - b.ToTable("UserTransactions"); - }); - - modelBuilder.Entity("Hutopy.Infrastructure.Identity.ApplicationUser", b => - { - b.Property("Id") - .HasColumnType("nvarchar(450)"); - - b.Property("AccessFailedCount") - .HasColumnType("int"); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnType("nvarchar(max)"); - - b.Property("Email") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("EmailConfirmed") - .HasColumnType("bit"); - - b.Property("FirstName") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("LastName") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("LockoutEnabled") - .HasColumnType("bit"); - - b.Property("LockoutEnd") - .HasColumnType("datetimeoffset"); - - b.Property("NormalizedEmail") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("NormalizedUserName") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("PasswordHash") - .HasColumnType("nvarchar(max)"); - - b.Property("PhoneNumber") - .HasColumnType("nvarchar(max)"); - - b.Property("PhoneNumberConfirmed") - .HasColumnType("bit"); - - b.Property("SecurityStamp") - .HasColumnType("nvarchar(max)"); - - b.Property("TwoFactorEnabled") - .HasColumnType("bit"); - - b.Property("UserName") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.HasKey("Id"); - - b.HasIndex("NormalizedEmail") - .HasDatabaseName("EmailIndex"); - - b.HasIndex("NormalizedUserName") - .IsUnique() - .HasDatabaseName("UserNameIndex") - .HasFilter("[NormalizedUserName] IS NOT NULL"); - - b.ToTable("AspNetUsers", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => - { - b.Property("Id") - .HasColumnType("nvarchar(450)"); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnType("nvarchar(max)"); - - b.Property("Name") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("NormalizedName") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.HasKey("Id"); - - b.HasIndex("NormalizedName") - .IsUnique() - .HasDatabaseName("RoleNameIndex") - .HasFilter("[NormalizedName] IS NOT NULL"); - - b.ToTable("AspNetRoles", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ClaimType") - .HasColumnType("nvarchar(max)"); - - b.Property("ClaimValue") - .HasColumnType("nvarchar(max)"); - - b.Property("RoleId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("Id"); - - b.HasIndex("RoleId"); - - b.ToTable("AspNetRoleClaims", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ClaimType") - .HasColumnType("nvarchar(max)"); - - b.Property("ClaimValue") - .HasColumnType("nvarchar(max)"); - - b.Property("UserId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("AspNetUserClaims", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => - { - b.Property("LoginProvider") - .HasColumnType("nvarchar(450)"); - - b.Property("ProviderKey") - .HasColumnType("nvarchar(450)"); - - b.Property("ProviderDisplayName") - .HasColumnType("nvarchar(max)"); - - b.Property("UserId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("LoginProvider", "ProviderKey"); - - b.HasIndex("UserId"); - - b.ToTable("AspNetUserLogins", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => - { - b.Property("UserId") - .HasColumnType("nvarchar(450)"); - - b.Property("RoleId") - .HasColumnType("nvarchar(450)"); - - b.HasKey("UserId", "RoleId"); - - b.HasIndex("RoleId"); - - b.ToTable("AspNetUserRoles", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => - { - b.Property("UserId") - .HasColumnType("nvarchar(450)"); - - b.Property("LoginProvider") - .HasColumnType("nvarchar(450)"); - - b.Property("Name") - .HasColumnType("nvarchar(450)"); - - b.Property("Value") - .HasColumnType("nvarchar(max)"); - - b.HasKey("UserId", "LoginProvider", "Name"); - - b.ToTable("AspNetUserTokens", (string)null); - }); - - modelBuilder.Entity("Hutopy.Domain.Entities.UserTransaction", b => - { - b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) - .WithMany() - .HasForeignKey("ApplicationUserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) - .WithMany() - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => - { - b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => - { - b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) - .WithMany() - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => - { - b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Infrastructure/Migrations/20240425020920_AddIsConfirmedToUserTransaction.cs b/src/Infrastructure/Migrations/20240425020920_AddIsConfirmedToUserTransaction.cs deleted file mode 100644 index 39ded1c..0000000 --- a/src/Infrastructure/Migrations/20240425020920_AddIsConfirmedToUserTransaction.cs +++ /dev/null @@ -1,29 +0,0 @@ -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace Hutopy.Infrastructure.Migrations -{ - /// - public partial class AddIsConfirmedToUserTransaction : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.AddColumn( - name: "IsConfirmed", - table: "UserTransactions", - type: "bit", - nullable: false, - defaultValue: false); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropColumn( - name: "IsConfirmed", - table: "UserTransactions"); - } - } -} diff --git a/src/Infrastructure/Migrations/20240509215538_AddMoreInformationToTransaction.cs b/src/Infrastructure/Migrations/20240509215538_AddMoreInformationToTransaction.cs deleted file mode 100644 index d91d3cf..0000000 --- a/src/Infrastructure/Migrations/20240509215538_AddMoreInformationToTransaction.cs +++ /dev/null @@ -1,106 +0,0 @@ -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace Hutopy.Infrastructure.Migrations -{ - /// - public partial class AddMoreInformationToTransaction : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.AddColumn( - name: "Paid", - table: "UserTransactions", - type: "bit", - nullable: false, - defaultValue: false); - - migrationBuilder.AddColumn( - name: "StripeBillingDetailEmail", - table: "UserTransactions", - type: "nvarchar(max)", - nullable: false, - defaultValue: ""); - - migrationBuilder.AddColumn( - name: "StripeBillingDetailName", - table: "UserTransactions", - type: "nvarchar(max)", - nullable: false, - defaultValue: ""); - - migrationBuilder.AddColumn( - name: "StripeChargeId", - table: "UserTransactions", - type: "nvarchar(max)", - nullable: false, - defaultValue: ""); - - migrationBuilder.AddColumn( - name: "StripeEventId", - table: "UserTransactions", - type: "nvarchar(max)", - nullable: false, - defaultValue: ""); - - migrationBuilder.AddColumn( - name: "StripePaymentIntent", - table: "UserTransactions", - type: "nvarchar(max)", - nullable: false, - defaultValue: ""); - - migrationBuilder.AddColumn( - name: "StripePaymentMethod", - table: "UserTransactions", - type: "nvarchar(max)", - nullable: false, - defaultValue: ""); - - migrationBuilder.AddColumn( - name: "StripeReceiptUrl", - table: "UserTransactions", - type: "nvarchar(max)", - nullable: false, - defaultValue: ""); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropColumn( - name: "Paid", - table: "UserTransactions"); - - migrationBuilder.DropColumn( - name: "StripeBillingDetailEmail", - table: "UserTransactions"); - - migrationBuilder.DropColumn( - name: "StripeBillingDetailName", - table: "UserTransactions"); - - migrationBuilder.DropColumn( - name: "StripeChargeId", - table: "UserTransactions"); - - migrationBuilder.DropColumn( - name: "StripeEventId", - table: "UserTransactions"); - - migrationBuilder.DropColumn( - name: "StripePaymentIntent", - table: "UserTransactions"); - - migrationBuilder.DropColumn( - name: "StripePaymentMethod", - table: "UserTransactions"); - - migrationBuilder.DropColumn( - name: "StripeReceiptUrl", - table: "UserTransactions"); - } - } -} diff --git a/src/Infrastructure/Migrations/20240612000806_AddSocialNetworksToUser.Designer.cs b/src/Infrastructure/Migrations/20240612000806_AddSocialNetworksToUser.Designer.cs deleted file mode 100644 index 2c074bc..0000000 --- a/src/Infrastructure/Migrations/20240612000806_AddSocialNetworksToUser.Designer.cs +++ /dev/null @@ -1,469 +0,0 @@ -// -using System; -using Hutopy.Infrastructure.Data; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -#nullable disable - -namespace Hutopy.Infrastructure.Migrations -{ - [DbContext(typeof(ApplicationDbContext))] - [Migration("20240612000806_AddSocialNetworksToUser")] - partial class AddSocialNetworksToUser - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "8.0.3") - .HasAnnotation("Relational:MaxIdentifierLength", 128); - - SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); - - modelBuilder.Entity("Hutopy.Domain.Entities.FutureCreator", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uniqueidentifier"); - - b.Property("Created") - .HasColumnType("datetimeoffset"); - - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("EmailAddress") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("FirstName") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("LastModified") - .HasColumnType("datetimeoffset"); - - b.Property("LastModifiedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("LastName") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("PhoneNumber") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("ReasonToJoin") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("SocialNetworkAccount") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.ToTable("FutureCreators"); - }); - - modelBuilder.Entity("Hutopy.Domain.Entities.UserTransaction", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uniqueidentifier"); - - b.Property("Amount") - .HasPrecision(18, 2) - .HasColumnType("decimal(18,2)"); - - b.Property("ApplicationUserId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.Property("Created") - .HasColumnType("datetimeoffset"); - - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("Currency") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("IsConfirmed") - .HasColumnType("bit"); - - b.Property("LastModified") - .HasColumnType("datetimeoffset"); - - b.Property("LastModifiedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("Paid") - .HasColumnType("bit"); - - b.Property("StripeBillingDetailEmail") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("StripeBillingDetailName") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("StripeChargeId") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("StripeEventId") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("StripePaymentIntent") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("StripePaymentMethod") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("StripeReceiptUrl") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("TipMessage") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.HasIndex("ApplicationUserId"); - - b.ToTable("UserTransactions"); - }); - - modelBuilder.Entity("Hutopy.Infrastructure.Identity.ApplicationUser", b => - { - b.Property("Id") - .HasColumnType("nvarchar(450)"); - - b.Property("AccessFailedCount") - .HasColumnType("int"); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnType("nvarchar(max)"); - - b.Property("Email") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("EmailConfirmed") - .HasColumnType("bit"); - - b.Property("FirstName") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("LastName") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("LockoutEnabled") - .HasColumnType("bit"); - - b.Property("LockoutEnd") - .HasColumnType("datetimeoffset"); - - b.Property("NormalizedEmail") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("NormalizedUserName") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("PasswordHash") - .HasColumnType("nvarchar(max)"); - - b.Property("PhoneNumber") - .HasColumnType("nvarchar(max)"); - - b.Property("PhoneNumberConfirmed") - .HasColumnType("bit"); - - b.Property("SecurityStamp") - .HasColumnType("nvarchar(max)"); - - b.Property("TwoFactorEnabled") - .HasColumnType("bit"); - - b.Property("UserName") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.HasKey("Id"); - - b.HasIndex("NormalizedEmail") - .HasDatabaseName("EmailIndex"); - - b.HasIndex("NormalizedUserName") - .IsUnique() - .HasDatabaseName("UserNameIndex") - .HasFilter("[NormalizedUserName] IS NOT NULL"); - - b.ToTable("AspNetUsers", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => - { - b.Property("Id") - .HasColumnType("nvarchar(450)"); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnType("nvarchar(max)"); - - b.Property("Name") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("NormalizedName") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.HasKey("Id"); - - b.HasIndex("NormalizedName") - .IsUnique() - .HasDatabaseName("RoleNameIndex") - .HasFilter("[NormalizedName] IS NOT NULL"); - - b.ToTable("AspNetRoles", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ClaimType") - .HasColumnType("nvarchar(max)"); - - b.Property("ClaimValue") - .HasColumnType("nvarchar(max)"); - - b.Property("RoleId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("Id"); - - b.HasIndex("RoleId"); - - b.ToTable("AspNetRoleClaims", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ClaimType") - .HasColumnType("nvarchar(max)"); - - b.Property("ClaimValue") - .HasColumnType("nvarchar(max)"); - - b.Property("UserId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("AspNetUserClaims", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => - { - b.Property("LoginProvider") - .HasColumnType("nvarchar(450)"); - - b.Property("ProviderKey") - .HasColumnType("nvarchar(450)"); - - b.Property("ProviderDisplayName") - .HasColumnType("nvarchar(max)"); - - b.Property("UserId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("LoginProvider", "ProviderKey"); - - b.HasIndex("UserId"); - - b.ToTable("AspNetUserLogins", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => - { - b.Property("UserId") - .HasColumnType("nvarchar(450)"); - - b.Property("RoleId") - .HasColumnType("nvarchar(450)"); - - b.HasKey("UserId", "RoleId"); - - b.HasIndex("RoleId"); - - b.ToTable("AspNetUserRoles", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => - { - b.Property("UserId") - .HasColumnType("nvarchar(450)"); - - b.Property("LoginProvider") - .HasColumnType("nvarchar(450)"); - - b.Property("Name") - .HasColumnType("nvarchar(450)"); - - b.Property("Value") - .HasColumnType("nvarchar(max)"); - - b.HasKey("UserId", "LoginProvider", "Name"); - - b.ToTable("AspNetUserTokens", (string)null); - }); - - modelBuilder.Entity("Hutopy.Domain.Entities.UserTransaction", b => - { - b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) - .WithMany() - .HasForeignKey("ApplicationUserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Hutopy.Infrastructure.Identity.ApplicationUser", b => - { - b.OwnsOne("Hutopy.Infrastructure.Identity.OwnedEntities.SocialNetworks", "SocialNetworks", b1 => - { - b1.Property("ApplicationUserId") - .HasColumnType("nvarchar(450)"); - - b1.Property("FacebookUrl") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.Property("InstagramUrl") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.Property("LinkedInUrl") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.Property("RedditUrl") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.Property("TikTokUrl") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.Property("XUrl") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.Property("YourWebsiteUrl") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.Property("YoutubeUrl") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.HasKey("ApplicationUserId"); - - b1.ToTable("ApplicationUser_SocialNetworks", (string)null); - - b1.WithOwner() - .HasForeignKey("ApplicationUserId"); - }); - - b.Navigation("SocialNetworks") - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) - .WithMany() - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => - { - b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => - { - b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) - .WithMany() - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => - { - b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Infrastructure/Migrations/20240612000806_AddSocialNetworksToUser.cs b/src/Infrastructure/Migrations/20240612000806_AddSocialNetworksToUser.cs deleted file mode 100644 index 14dfa81..0000000 --- a/src/Infrastructure/Migrations/20240612000806_AddSocialNetworksToUser.cs +++ /dev/null @@ -1,52 +0,0 @@ -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace Hutopy.Infrastructure.Migrations -{ - /// - public partial class AddSocialNetworksToUser : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.CreateTable( - name: "ApplicationUser_SocialNetworks", - columns: table => new - { - ApplicationUserId = table.Column(type: "nvarchar(450)", nullable: false), - FacebookUrl = table.Column(type: "nvarchar(max)", nullable: false), - InstagramUrl = table.Column(type: "nvarchar(max)", nullable: false), - XUrl = table.Column(type: "nvarchar(max)", nullable: false), - LinkedInUrl = table.Column(type: "nvarchar(max)", nullable: false), - TikTokUrl = table.Column(type: "nvarchar(max)", nullable: false), - YoutubeUrl = table.Column(type: "nvarchar(max)", nullable: false), - RedditUrl = table.Column(type: "nvarchar(max)", nullable: false), - YourWebsiteUrl = table.Column(type: "nvarchar(max)", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_ApplicationUser_SocialNetworks", x => x.ApplicationUserId); - table.ForeignKey( - name: "FK_ApplicationUser_SocialNetworks_AspNetUsers_ApplicationUserId", - column: x => x.ApplicationUserId, - principalTable: "AspNetUsers", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.Sql(@" - INSERT INTO ApplicationUser_SocialNetworks (ApplicationUserId, FacebookUrl, InstagramUrl, XUrl, LinkedInUrl, TikTokUrl, YoutubeUrl, RedditUrl, YourWebsiteUrl) - SELECT Id, '', '', '', '', '', '', '', '' - FROM AspNetUsers - "); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "ApplicationUser_SocialNetworks"); - } - } -} diff --git a/src/Infrastructure/Migrations/20240630001806_AddMissingInformationsToUser.Designer.cs b/src/Infrastructure/Migrations/20240630001806_AddMissingInformationsToUser.Designer.cs deleted file mode 100644 index 2a9623e..0000000 --- a/src/Infrastructure/Migrations/20240630001806_AddMissingInformationsToUser.Designer.cs +++ /dev/null @@ -1,497 +0,0 @@ -// -using System; -using Hutopy.Infrastructure.Data; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -#nullable disable - -namespace Hutopy.Infrastructure.Migrations -{ - [DbContext(typeof(ApplicationDbContext))] - [Migration("20240630001806_AddMissingInformationsToUser")] - partial class AddMissingInformationsToUser - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "8.0.3") - .HasAnnotation("Relational:MaxIdentifierLength", 128); - - SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); - - modelBuilder.Entity("Hutopy.Domain.Entities.FutureCreator", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uniqueidentifier"); - - b.Property("Created") - .HasColumnType("datetimeoffset"); - - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("EmailAddress") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("FirstName") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("LastModified") - .HasColumnType("datetimeoffset"); - - b.Property("LastModifiedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("LastName") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("PhoneNumber") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("ReasonToJoin") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("SocialNetworkAccount") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.ToTable("FutureCreators"); - }); - - modelBuilder.Entity("Hutopy.Domain.Entities.UserTransaction", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uniqueidentifier"); - - b.Property("Amount") - .HasPrecision(18, 2) - .HasColumnType("decimal(18,2)"); - - b.Property("ApplicationUserId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.Property("Created") - .HasColumnType("datetimeoffset"); - - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("Currency") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("IsConfirmed") - .HasColumnType("bit"); - - b.Property("LastModified") - .HasColumnType("datetimeoffset"); - - b.Property("LastModifiedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("Paid") - .HasColumnType("bit"); - - b.Property("StripeBillingDetailEmail") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("StripeBillingDetailName") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("StripeChargeId") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("StripeEventId") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("StripePaymentIntent") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("StripePaymentMethod") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("StripeReceiptUrl") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("TipMessage") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.HasIndex("ApplicationUserId"); - - b.ToTable("UserTransactions"); - }); - - modelBuilder.Entity("Hutopy.Infrastructure.Identity.ApplicationUser", b => - { - b.Property("Id") - .HasColumnType("nvarchar(450)"); - - b.Property("About") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("AccessFailedCount") - .HasColumnType("int"); - - b.Property("Address") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("BirthDate") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("City") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnType("nvarchar(max)"); - - b.Property("Country") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("Description") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("Email") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("EmailConfirmed") - .HasColumnType("bit"); - - b.Property("FirstName") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("LastName") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("LockoutEnabled") - .HasColumnType("bit"); - - b.Property("LockoutEnd") - .HasColumnType("datetimeoffset"); - - b.Property("NormalizedEmail") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("NormalizedUserName") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("Occupation") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("PasswordHash") - .HasColumnType("nvarchar(max)"); - - b.Property("PhoneNumber") - .HasColumnType("nvarchar(max)"); - - b.Property("PhoneNumberConfirmed") - .HasColumnType("bit"); - - b.Property("SecurityStamp") - .HasColumnType("nvarchar(max)"); - - b.Property("TwoFactorEnabled") - .HasColumnType("bit"); - - b.Property("UserName") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.HasKey("Id"); - - b.HasIndex("NormalizedEmail") - .HasDatabaseName("EmailIndex"); - - b.HasIndex("NormalizedUserName") - .IsUnique() - .HasDatabaseName("UserNameIndex") - .HasFilter("[NormalizedUserName] IS NOT NULL"); - - b.ToTable("AspNetUsers", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => - { - b.Property("Id") - .HasColumnType("nvarchar(450)"); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnType("nvarchar(max)"); - - b.Property("Name") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("NormalizedName") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.HasKey("Id"); - - b.HasIndex("NormalizedName") - .IsUnique() - .HasDatabaseName("RoleNameIndex") - .HasFilter("[NormalizedName] IS NOT NULL"); - - b.ToTable("AspNetRoles", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ClaimType") - .HasColumnType("nvarchar(max)"); - - b.Property("ClaimValue") - .HasColumnType("nvarchar(max)"); - - b.Property("RoleId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("Id"); - - b.HasIndex("RoleId"); - - b.ToTable("AspNetRoleClaims", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ClaimType") - .HasColumnType("nvarchar(max)"); - - b.Property("ClaimValue") - .HasColumnType("nvarchar(max)"); - - b.Property("UserId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("AspNetUserClaims", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => - { - b.Property("LoginProvider") - .HasColumnType("nvarchar(450)"); - - b.Property("ProviderKey") - .HasColumnType("nvarchar(450)"); - - b.Property("ProviderDisplayName") - .HasColumnType("nvarchar(max)"); - - b.Property("UserId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("LoginProvider", "ProviderKey"); - - b.HasIndex("UserId"); - - b.ToTable("AspNetUserLogins", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => - { - b.Property("UserId") - .HasColumnType("nvarchar(450)"); - - b.Property("RoleId") - .HasColumnType("nvarchar(450)"); - - b.HasKey("UserId", "RoleId"); - - b.HasIndex("RoleId"); - - b.ToTable("AspNetUserRoles", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => - { - b.Property("UserId") - .HasColumnType("nvarchar(450)"); - - b.Property("LoginProvider") - .HasColumnType("nvarchar(450)"); - - b.Property("Name") - .HasColumnType("nvarchar(450)"); - - b.Property("Value") - .HasColumnType("nvarchar(max)"); - - b.HasKey("UserId", "LoginProvider", "Name"); - - b.ToTable("AspNetUserTokens", (string)null); - }); - - modelBuilder.Entity("Hutopy.Domain.Entities.UserTransaction", b => - { - b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) - .WithMany() - .HasForeignKey("ApplicationUserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Hutopy.Infrastructure.Identity.ApplicationUser", b => - { - b.OwnsOne("Hutopy.Infrastructure.Identity.OwnedEntities.SocialNetworks", "SocialNetworks", b1 => - { - b1.Property("ApplicationUserId") - .HasColumnType("nvarchar(450)"); - - b1.Property("FacebookUrl") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.Property("InstagramUrl") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.Property("LinkedInUrl") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.Property("RedditUrl") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.Property("TikTokUrl") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.Property("XUrl") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.Property("YourWebsiteUrl") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.Property("YoutubeUrl") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.HasKey("ApplicationUserId"); - - b1.ToTable("ApplicationUser_SocialNetworks", (string)null); - - b1.WithOwner() - .HasForeignKey("ApplicationUserId"); - }); - - b.Navigation("SocialNetworks") - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) - .WithMany() - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => - { - b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => - { - b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) - .WithMany() - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => - { - b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Infrastructure/Migrations/20240630001806_AddMissingInformationsToUser.cs b/src/Infrastructure/Migrations/20240630001806_AddMissingInformationsToUser.cs deleted file mode 100644 index cd1a612..0000000 --- a/src/Infrastructure/Migrations/20240630001806_AddMissingInformationsToUser.cs +++ /dev/null @@ -1,95 +0,0 @@ -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace Hutopy.Infrastructure.Migrations -{ - /// - public partial class AddMissingInformationsToUser : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.AddColumn( - name: "About", - table: "AspNetUsers", - type: "nvarchar(max)", - nullable: false, - defaultValue: ""); - - migrationBuilder.AddColumn( - name: "Address", - table: "AspNetUsers", - type: "nvarchar(max)", - nullable: false, - defaultValue: ""); - - migrationBuilder.AddColumn( - name: "BirthDate", - table: "AspNetUsers", - type: "nvarchar(max)", - nullable: false, - defaultValue: ""); - - migrationBuilder.AddColumn( - name: "City", - table: "AspNetUsers", - type: "nvarchar(max)", - nullable: false, - defaultValue: ""); - - migrationBuilder.AddColumn( - name: "Country", - table: "AspNetUsers", - type: "nvarchar(max)", - nullable: false, - defaultValue: ""); - - migrationBuilder.AddColumn( - name: "Description", - table: "AspNetUsers", - type: "nvarchar(max)", - nullable: false, - defaultValue: ""); - - migrationBuilder.AddColumn( - name: "Occupation", - table: "AspNetUsers", - type: "nvarchar(max)", - nullable: false, - defaultValue: ""); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropColumn( - name: "About", - table: "AspNetUsers"); - - migrationBuilder.DropColumn( - name: "Address", - table: "AspNetUsers"); - - migrationBuilder.DropColumn( - name: "BirthDate", - table: "AspNetUsers"); - - migrationBuilder.DropColumn( - name: "City", - table: "AspNetUsers"); - - migrationBuilder.DropColumn( - name: "Country", - table: "AspNetUsers"); - - migrationBuilder.DropColumn( - name: "Description", - table: "AspNetUsers"); - - migrationBuilder.DropColumn( - name: "Occupation", - table: "AspNetUsers"); - } - } -} diff --git a/src/Infrastructure/Migrations/20240630163057_AddMoreInformationsToUser.Designer.cs b/src/Infrastructure/Migrations/20240630163057_AddMoreInformationsToUser.Designer.cs deleted file mode 100644 index af10f04..0000000 --- a/src/Infrastructure/Migrations/20240630163057_AddMoreInformationsToUser.Designer.cs +++ /dev/null @@ -1,557 +0,0 @@ -// -using System; -using Hutopy.Infrastructure.Data; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -#nullable disable - -namespace Hutopy.Infrastructure.Migrations -{ - [DbContext(typeof(ApplicationDbContext))] - [Migration("20240630163057_AddMoreInformationsToUser")] - partial class AddMoreInformationsToUser - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "8.0.3") - .HasAnnotation("Relational:MaxIdentifierLength", 128); - - SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); - - modelBuilder.Entity("Hutopy.Domain.Entities.FutureCreator", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uniqueidentifier"); - - b.Property("Created") - .HasColumnType("datetimeoffset"); - - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("EmailAddress") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("FirstName") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("LastModified") - .HasColumnType("datetimeoffset"); - - b.Property("LastModifiedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("LastName") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("PhoneNumber") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("ReasonToJoin") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("SocialNetworkAccount") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.ToTable("FutureCreators"); - }); - - modelBuilder.Entity("Hutopy.Domain.Entities.UserTransaction", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uniqueidentifier"); - - b.Property("Amount") - .HasPrecision(18, 2) - .HasColumnType("decimal(18,2)"); - - b.Property("ApplicationUserId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.Property("Created") - .HasColumnType("datetimeoffset"); - - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("Currency") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("IsConfirmed") - .HasColumnType("bit"); - - b.Property("LastModified") - .HasColumnType("datetimeoffset"); - - b.Property("LastModifiedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("Paid") - .HasColumnType("bit"); - - b.Property("StripeBillingDetailEmail") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("StripeBillingDetailName") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("StripeChargeId") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("StripeEventId") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("StripePaymentIntent") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("StripePaymentMethod") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("StripeReceiptUrl") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("TipMessage") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.HasIndex("ApplicationUserId"); - - b.ToTable("UserTransactions"); - }); - - modelBuilder.Entity("Hutopy.Infrastructure.Identity.ApplicationUser", b => - { - b.Property("Id") - .HasColumnType("nvarchar(450)"); - - b.Property("About") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("AccessFailedCount") - .HasColumnType("int"); - - b.Property("Address") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("BirthDate") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("City") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnType("nvarchar(max)"); - - b.Property("Country") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("Description") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("Email") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("EmailConfirmed") - .HasColumnType("bit"); - - b.Property("FirstName") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("LastName") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("LockoutEnabled") - .HasColumnType("bit"); - - b.Property("LockoutEnd") - .HasColumnType("datetimeoffset"); - - b.Property("NormalizedEmail") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("NormalizedUserName") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("Occupation") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("PasswordHash") - .HasColumnType("nvarchar(max)"); - - b.Property("PhoneNumber") - .HasColumnType("nvarchar(max)"); - - b.Property("PhoneNumberConfirmed") - .HasColumnType("bit"); - - b.Property("SecurityStamp") - .HasColumnType("nvarchar(max)"); - - b.Property("TwoFactorEnabled") - .HasColumnType("bit"); - - b.Property("UserName") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.HasKey("Id"); - - b.HasIndex("NormalizedEmail") - .HasDatabaseName("EmailIndex"); - - b.HasIndex("NormalizedUserName") - .IsUnique() - .HasDatabaseName("UserNameIndex") - .HasFilter("[NormalizedUserName] IS NOT NULL"); - - b.ToTable("AspNetUsers", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => - { - b.Property("Id") - .HasColumnType("nvarchar(450)"); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnType("nvarchar(max)"); - - b.Property("Name") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("NormalizedName") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.HasKey("Id"); - - b.HasIndex("NormalizedName") - .IsUnique() - .HasDatabaseName("RoleNameIndex") - .HasFilter("[NormalizedName] IS NOT NULL"); - - b.ToTable("AspNetRoles", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ClaimType") - .HasColumnType("nvarchar(max)"); - - b.Property("ClaimValue") - .HasColumnType("nvarchar(max)"); - - b.Property("RoleId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("Id"); - - b.HasIndex("RoleId"); - - b.ToTable("AspNetRoleClaims", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ClaimType") - .HasColumnType("nvarchar(max)"); - - b.Property("ClaimValue") - .HasColumnType("nvarchar(max)"); - - b.Property("UserId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("AspNetUserClaims", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => - { - b.Property("LoginProvider") - .HasColumnType("nvarchar(450)"); - - b.Property("ProviderKey") - .HasColumnType("nvarchar(450)"); - - b.Property("ProviderDisplayName") - .HasColumnType("nvarchar(max)"); - - b.Property("UserId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("LoginProvider", "ProviderKey"); - - b.HasIndex("UserId"); - - b.ToTable("AspNetUserLogins", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => - { - b.Property("UserId") - .HasColumnType("nvarchar(450)"); - - b.Property("RoleId") - .HasColumnType("nvarchar(450)"); - - b.HasKey("UserId", "RoleId"); - - b.HasIndex("RoleId"); - - b.ToTable("AspNetUserRoles", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => - { - b.Property("UserId") - .HasColumnType("nvarchar(450)"); - - b.Property("LoginProvider") - .HasColumnType("nvarchar(450)"); - - b.Property("Name") - .HasColumnType("nvarchar(450)"); - - b.Property("Value") - .HasColumnType("nvarchar(max)"); - - b.HasKey("UserId", "LoginProvider", "Name"); - - b.ToTable("AspNetUserTokens", (string)null); - }); - - modelBuilder.Entity("Hutopy.Domain.Entities.UserTransaction", b => - { - b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) - .WithMany() - .HasForeignKey("ApplicationUserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Hutopy.Infrastructure.Identity.ApplicationUser", b => - { - b.OwnsOne("Hutopy.Infrastructure.Identity.OwnedEntities.ProfileColors", "ProfileColors", b1 => - { - b1.Property("ApplicationUserId") - .HasColumnType("nvarchar(450)"); - - b1.Property("Accent") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.Property("BannerBottom") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.Property("BannerTop") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.Property("Menu") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.HasKey("ApplicationUserId"); - - b1.ToTable("ApplicationUser_ProfileColors", (string)null); - - b1.WithOwner() - .HasForeignKey("ApplicationUserId"); - }); - - b.OwnsOne("Hutopy.Infrastructure.Identity.OwnedEntities.SocialNetworks", "SocialNetworks", b1 => - { - b1.Property("ApplicationUserId") - .HasColumnType("nvarchar(450)"); - - b1.Property("FacebookUrl") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.Property("InstagramUrl") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.Property("LinkedInUrl") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.Property("RedditUrl") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.Property("TikTokUrl") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.Property("XUrl") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.Property("YourWebsiteUrl") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.Property("YoutubeUrl") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.HasKey("ApplicationUserId"); - - b1.ToTable("ApplicationUser_SocialNetworks", (string)null); - - b1.WithOwner() - .HasForeignKey("ApplicationUserId"); - }); - - b.OwnsOne("Hutopy.Infrastructure.Identity.OwnedEntities.StoredDataUrls", "StoredDataUrls", b1 => - { - b1.Property("ApplicationUserId") - .HasColumnType("nvarchar(450)"); - - b1.Property("BannerPictureUrl") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.Property("ProfilePictureUrl") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.Property("WebsiteIconUrl") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.HasKey("ApplicationUserId"); - - b1.ToTable("ApplicationUser_StoredDataUrls", (string)null); - - b1.WithOwner() - .HasForeignKey("ApplicationUserId"); - }); - - b.Navigation("ProfileColors") - .IsRequired(); - - b.Navigation("SocialNetworks") - .IsRequired(); - - b.Navigation("StoredDataUrls") - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) - .WithMany() - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => - { - b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => - { - b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) - .WithMany() - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => - { - b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Infrastructure/Migrations/20240630163057_AddMoreInformationsToUser.cs b/src/Infrastructure/Migrations/20240630163057_AddMoreInformationsToUser.cs deleted file mode 100644 index 85e7b7e..0000000 --- a/src/Infrastructure/Migrations/20240630163057_AddMoreInformationsToUser.cs +++ /dev/null @@ -1,77 +0,0 @@ -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace Hutopy.Infrastructure.Migrations -{ - /// - public partial class AddMoreInformationsToUser : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.CreateTable( - name: "ApplicationUser_ProfileColors", - columns: table => new - { - ApplicationUserId = table.Column(type: "nvarchar(450)", nullable: false), - BannerTop = table.Column(type: "nvarchar(max)", nullable: false), - BannerBottom = table.Column(type: "nvarchar(max)", nullable: false), - Accent = table.Column(type: "nvarchar(max)", nullable: false), - Menu = table.Column(type: "nvarchar(max)", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_ApplicationUser_ProfileColors", x => x.ApplicationUserId); - table.ForeignKey( - name: "FK_ApplicationUser_ProfileColors_AspNetUsers_ApplicationUserId", - column: x => x.ApplicationUserId, - principalTable: "AspNetUsers", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.Sql(@" - INSERT INTO ApplicationUser_ProfileColors (ApplicationUserId, BannerTop, BannerBottom, Accent, Menu) - SELECT Id, '', '', '', '' - FROM AspNetUsers - "); - - migrationBuilder.CreateTable( - name: "ApplicationUser_StoredDataUrls", - columns: table => new - { - ApplicationUserId = table.Column(type: "nvarchar(450)", nullable: false), - BannerPictureUrl = table.Column(type: "nvarchar(max)", nullable: false), - ProfilePictureUrl = table.Column(type: "nvarchar(max)", nullable: false), - WebsiteIconUrl = table.Column(type: "nvarchar(max)", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_ApplicationUser_StoredDataUrls", x => x.ApplicationUserId); - table.ForeignKey( - name: "FK_ApplicationUser_StoredDataUrls_AspNetUsers_ApplicationUserId", - column: x => x.ApplicationUserId, - principalTable: "AspNetUsers", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.Sql(@" - INSERT INTO ApplicationUser_StoredDataUrls (ApplicationUserId, BannerPictureUrl, ProfilePictureUrl, WebsiteIconUrl) - SELECT Id, '', '', '' - FROM AspNetUsers - "); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "ApplicationUser_ProfileColors"); - - migrationBuilder.DropTable( - name: "ApplicationUser_StoredDataUrls"); - } - } -} diff --git a/src/Infrastructure/Migrations/20240701072549_AddPortraitUrlToUser.Designer.cs b/src/Infrastructure/Migrations/20240701072549_AddPortraitUrlToUser.Designer.cs deleted file mode 100644 index 2ce61d4..0000000 --- a/src/Infrastructure/Migrations/20240701072549_AddPortraitUrlToUser.Designer.cs +++ /dev/null @@ -1,500 +0,0 @@ -// -using System; -using Hutopy.Infrastructure.Data; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -#nullable disable - -namespace Hutopy.Infrastructure.Migrations -{ - [DbContext(typeof(ApplicationDbContext))] - [Migration("20240701072549_AddPortraitUrlToUser")] - partial class AddPortraitUrlToUser - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "8.0.3") - .HasAnnotation("Relational:MaxIdentifierLength", 128); - - SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); - - modelBuilder.Entity("Hutopy.Domain.Entities.FutureCreator", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uniqueidentifier"); - - b.Property("Created") - .HasColumnType("datetimeoffset"); - - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("EmailAddress") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("FirstName") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("LastModified") - .HasColumnType("datetimeoffset"); - - b.Property("LastModifiedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("LastName") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("PhoneNumber") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("ReasonToJoin") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("SocialNetworkAccount") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.ToTable("FutureCreators"); - }); - - modelBuilder.Entity("Hutopy.Domain.Entities.UserTransaction", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uniqueidentifier"); - - b.Property("Amount") - .HasPrecision(18, 2) - .HasColumnType("decimal(18,2)"); - - b.Property("ApplicationUserId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.Property("Created") - .HasColumnType("datetimeoffset"); - - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("Currency") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("IsConfirmed") - .HasColumnType("bit"); - - b.Property("LastModified") - .HasColumnType("datetimeoffset"); - - b.Property("LastModifiedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("Paid") - .HasColumnType("bit"); - - b.Property("StripeBillingDetailEmail") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("StripeBillingDetailName") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("StripeChargeId") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("StripeEventId") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("StripePaymentIntent") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("StripePaymentMethod") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("StripeReceiptUrl") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("TipMessage") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.HasIndex("ApplicationUserId"); - - b.ToTable("UserTransactions"); - }); - - modelBuilder.Entity("Hutopy.Infrastructure.Identity.ApplicationUser", b => - { - b.Property("Id") - .HasColumnType("nvarchar(450)"); - - b.Property("About") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("AccessFailedCount") - .HasColumnType("int"); - - b.Property("Address") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("BirthDate") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("City") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnType("nvarchar(max)"); - - b.Property("Country") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("Description") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("Email") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("EmailConfirmed") - .HasColumnType("bit"); - - b.Property("FirstName") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("LastName") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("LockoutEnabled") - .HasColumnType("bit"); - - b.Property("LockoutEnd") - .HasColumnType("datetimeoffset"); - - b.Property("NormalizedEmail") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("NormalizedUserName") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("Occupation") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("PasswordHash") - .HasColumnType("nvarchar(max)"); - - b.Property("PhoneNumber") - .HasColumnType("nvarchar(max)"); - - b.Property("PhoneNumberConfirmed") - .HasColumnType("bit"); - - b.Property("PortraitUrl") - .HasColumnType("nvarchar(max)"); - - b.Property("SecurityStamp") - .HasColumnType("nvarchar(max)"); - - b.Property("TwoFactorEnabled") - .HasColumnType("bit"); - - b.Property("UserName") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.HasKey("Id"); - - b.HasIndex("NormalizedEmail") - .HasDatabaseName("EmailIndex"); - - b.HasIndex("NormalizedUserName") - .IsUnique() - .HasDatabaseName("UserNameIndex") - .HasFilter("[NormalizedUserName] IS NOT NULL"); - - b.ToTable("AspNetUsers", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => - { - b.Property("Id") - .HasColumnType("nvarchar(450)"); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnType("nvarchar(max)"); - - b.Property("Name") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("NormalizedName") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.HasKey("Id"); - - b.HasIndex("NormalizedName") - .IsUnique() - .HasDatabaseName("RoleNameIndex") - .HasFilter("[NormalizedName] IS NOT NULL"); - - b.ToTable("AspNetRoles", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ClaimType") - .HasColumnType("nvarchar(max)"); - - b.Property("ClaimValue") - .HasColumnType("nvarchar(max)"); - - b.Property("RoleId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("Id"); - - b.HasIndex("RoleId"); - - b.ToTable("AspNetRoleClaims", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ClaimType") - .HasColumnType("nvarchar(max)"); - - b.Property("ClaimValue") - .HasColumnType("nvarchar(max)"); - - b.Property("UserId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("AspNetUserClaims", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => - { - b.Property("LoginProvider") - .HasColumnType("nvarchar(450)"); - - b.Property("ProviderKey") - .HasColumnType("nvarchar(450)"); - - b.Property("ProviderDisplayName") - .HasColumnType("nvarchar(max)"); - - b.Property("UserId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("LoginProvider", "ProviderKey"); - - b.HasIndex("UserId"); - - b.ToTable("AspNetUserLogins", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => - { - b.Property("UserId") - .HasColumnType("nvarchar(450)"); - - b.Property("RoleId") - .HasColumnType("nvarchar(450)"); - - b.HasKey("UserId", "RoleId"); - - b.HasIndex("RoleId"); - - b.ToTable("AspNetUserRoles", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => - { - b.Property("UserId") - .HasColumnType("nvarchar(450)"); - - b.Property("LoginProvider") - .HasColumnType("nvarchar(450)"); - - b.Property("Name") - .HasColumnType("nvarchar(450)"); - - b.Property("Value") - .HasColumnType("nvarchar(max)"); - - b.HasKey("UserId", "LoginProvider", "Name"); - - b.ToTable("AspNetUserTokens", (string)null); - }); - - modelBuilder.Entity("Hutopy.Domain.Entities.UserTransaction", b => - { - b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) - .WithMany() - .HasForeignKey("ApplicationUserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Hutopy.Infrastructure.Identity.ApplicationUser", b => - { - b.OwnsOne("Hutopy.Infrastructure.Identity.OwnedEntities.SocialNetworks", "SocialNetworks", b1 => - { - b1.Property("ApplicationUserId") - .HasColumnType("nvarchar(450)"); - - b1.Property("FacebookUrl") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.Property("InstagramUrl") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.Property("LinkedInUrl") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.Property("RedditUrl") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.Property("TikTokUrl") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.Property("XUrl") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.Property("YourWebsiteUrl") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.Property("YoutubeUrl") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.HasKey("ApplicationUserId"); - - b1.ToTable("ApplicationUser_SocialNetworks", (string)null); - - b1.WithOwner() - .HasForeignKey("ApplicationUserId"); - }); - - b.Navigation("SocialNetworks") - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) - .WithMany() - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => - { - b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => - { - b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) - .WithMany() - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => - { - b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Infrastructure/Migrations/20240701072549_AddPortraitUrlToUser.cs b/src/Infrastructure/Migrations/20240701072549_AddPortraitUrlToUser.cs deleted file mode 100644 index a279865..0000000 --- a/src/Infrastructure/Migrations/20240701072549_AddPortraitUrlToUser.cs +++ /dev/null @@ -1,28 +0,0 @@ -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace Hutopy.Infrastructure.Migrations -{ - /// - public partial class AddPortraitUrlToUser : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.AddColumn( - name: "PortraitUrl", - table: "AspNetUsers", - type: "nvarchar(max)", - nullable: true); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropColumn( - name: "PortraitUrl", - table: "AspNetUsers"); - } - } -} diff --git a/src/Infrastructure/Migrations/20240702055858_AddCreatorAliasTouser.Designer.cs b/src/Infrastructure/Migrations/20240702055858_AddCreatorAliasTouser.Designer.cs deleted file mode 100644 index 47946f4..0000000 --- a/src/Infrastructure/Migrations/20240702055858_AddCreatorAliasTouser.Designer.cs +++ /dev/null @@ -1,560 +0,0 @@ -// -using System; -using Hutopy.Infrastructure.Data; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -#nullable disable - -namespace Hutopy.Infrastructure.Migrations -{ - [DbContext(typeof(ApplicationDbContext))] - [Migration("20240702055858_AddCreatorAliasTouser")] - partial class AddCreatorAliasTouser - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "8.0.3") - .HasAnnotation("Relational:MaxIdentifierLength", 128); - - SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); - - modelBuilder.Entity("Hutopy.Domain.Entities.FutureCreator", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uniqueidentifier"); - - b.Property("Created") - .HasColumnType("datetimeoffset"); - - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("EmailAddress") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("FirstName") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("LastModified") - .HasColumnType("datetimeoffset"); - - b.Property("LastModifiedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("LastName") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("PhoneNumber") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("ReasonToJoin") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("SocialNetworkAccount") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.ToTable("FutureCreators"); - }); - - modelBuilder.Entity("Hutopy.Domain.Entities.UserTransaction", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uniqueidentifier"); - - b.Property("Amount") - .HasPrecision(18, 2) - .HasColumnType("decimal(18,2)"); - - b.Property("ApplicationUserId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.Property("Created") - .HasColumnType("datetimeoffset"); - - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("Currency") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("IsConfirmed") - .HasColumnType("bit"); - - b.Property("LastModified") - .HasColumnType("datetimeoffset"); - - b.Property("LastModifiedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("Paid") - .HasColumnType("bit"); - - b.Property("StripeBillingDetailEmail") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("StripeBillingDetailName") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("StripeChargeId") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("StripeEventId") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("StripePaymentIntent") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("StripePaymentMethod") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("StripeReceiptUrl") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("TipMessage") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.HasIndex("ApplicationUserId"); - - b.ToTable("UserTransactions"); - }); - - modelBuilder.Entity("Hutopy.Infrastructure.Identity.ApplicationUser", b => - { - b.Property("Id") - .HasColumnType("nvarchar(450)"); - - b.Property("About") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("AccessFailedCount") - .HasColumnType("int"); - - b.Property("Address") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("BirthDate") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("City") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnType("nvarchar(max)"); - - b.Property("Country") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("CreatorAlias") - .HasColumnType("nvarchar(max)"); - - b.Property("Description") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("Email") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("EmailConfirmed") - .HasColumnType("bit"); - - b.Property("FirstName") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("LastName") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("LockoutEnabled") - .HasColumnType("bit"); - - b.Property("LockoutEnd") - .HasColumnType("datetimeoffset"); - - b.Property("NormalizedEmail") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("NormalizedUserName") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("Occupation") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("PasswordHash") - .HasColumnType("nvarchar(max)"); - - b.Property("PhoneNumber") - .HasColumnType("nvarchar(max)"); - - b.Property("PhoneNumberConfirmed") - .HasColumnType("bit"); - - b.Property("SecurityStamp") - .HasColumnType("nvarchar(max)"); - - b.Property("TwoFactorEnabled") - .HasColumnType("bit"); - - b.Property("UserName") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.HasKey("Id"); - - b.HasIndex("NormalizedEmail") - .HasDatabaseName("EmailIndex"); - - b.HasIndex("NormalizedUserName") - .IsUnique() - .HasDatabaseName("UserNameIndex") - .HasFilter("[NormalizedUserName] IS NOT NULL"); - - b.ToTable("AspNetUsers", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => - { - b.Property("Id") - .HasColumnType("nvarchar(450)"); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnType("nvarchar(max)"); - - b.Property("Name") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("NormalizedName") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.HasKey("Id"); - - b.HasIndex("NormalizedName") - .IsUnique() - .HasDatabaseName("RoleNameIndex") - .HasFilter("[NormalizedName] IS NOT NULL"); - - b.ToTable("AspNetRoles", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ClaimType") - .HasColumnType("nvarchar(max)"); - - b.Property("ClaimValue") - .HasColumnType("nvarchar(max)"); - - b.Property("RoleId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("Id"); - - b.HasIndex("RoleId"); - - b.ToTable("AspNetRoleClaims", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ClaimType") - .HasColumnType("nvarchar(max)"); - - b.Property("ClaimValue") - .HasColumnType("nvarchar(max)"); - - b.Property("UserId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("AspNetUserClaims", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => - { - b.Property("LoginProvider") - .HasColumnType("nvarchar(450)"); - - b.Property("ProviderKey") - .HasColumnType("nvarchar(450)"); - - b.Property("ProviderDisplayName") - .HasColumnType("nvarchar(max)"); - - b.Property("UserId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("LoginProvider", "ProviderKey"); - - b.HasIndex("UserId"); - - b.ToTable("AspNetUserLogins", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => - { - b.Property("UserId") - .HasColumnType("nvarchar(450)"); - - b.Property("RoleId") - .HasColumnType("nvarchar(450)"); - - b.HasKey("UserId", "RoleId"); - - b.HasIndex("RoleId"); - - b.ToTable("AspNetUserRoles", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => - { - b.Property("UserId") - .HasColumnType("nvarchar(450)"); - - b.Property("LoginProvider") - .HasColumnType("nvarchar(450)"); - - b.Property("Name") - .HasColumnType("nvarchar(450)"); - - b.Property("Value") - .HasColumnType("nvarchar(max)"); - - b.HasKey("UserId", "LoginProvider", "Name"); - - b.ToTable("AspNetUserTokens", (string)null); - }); - - modelBuilder.Entity("Hutopy.Domain.Entities.UserTransaction", b => - { - b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) - .WithMany() - .HasForeignKey("ApplicationUserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Hutopy.Infrastructure.Identity.ApplicationUser", b => - { - b.OwnsOne("Hutopy.Infrastructure.Identity.OwnedEntities.ProfileColors", "ProfileColors", b1 => - { - b1.Property("ApplicationUserId") - .HasColumnType("nvarchar(450)"); - - b1.Property("Accent") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.Property("BannerBottom") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.Property("BannerTop") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.Property("Menu") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.HasKey("ApplicationUserId"); - - b1.ToTable("ApplicationUser_ProfileColors", (string)null); - - b1.WithOwner() - .HasForeignKey("ApplicationUserId"); - }); - - b.OwnsOne("Hutopy.Infrastructure.Identity.OwnedEntities.SocialNetworks", "SocialNetworks", b1 => - { - b1.Property("ApplicationUserId") - .HasColumnType("nvarchar(450)"); - - b1.Property("FacebookUrl") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.Property("InstagramUrl") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.Property("LinkedInUrl") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.Property("RedditUrl") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.Property("TikTokUrl") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.Property("XUrl") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.Property("YourWebsiteUrl") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.Property("YoutubeUrl") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.HasKey("ApplicationUserId"); - - b1.ToTable("ApplicationUser_SocialNetworks", (string)null); - - b1.WithOwner() - .HasForeignKey("ApplicationUserId"); - }); - - b.OwnsOne("Hutopy.Infrastructure.Identity.OwnedEntities.StoredDataUrls", "StoredDataUrls", b1 => - { - b1.Property("ApplicationUserId") - .HasColumnType("nvarchar(450)"); - - b1.Property("BannerPictureUrl") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.Property("ProfilePictureUrl") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.Property("WebsiteIconUrl") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.HasKey("ApplicationUserId"); - - b1.ToTable("ApplicationUser_StoredDataUrls", (string)null); - - b1.WithOwner() - .HasForeignKey("ApplicationUserId"); - }); - - b.Navigation("ProfileColors") - .IsRequired(); - - b.Navigation("SocialNetworks") - .IsRequired(); - - b.Navigation("StoredDataUrls") - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) - .WithMany() - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => - { - b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => - { - b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) - .WithMany() - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => - { - b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Infrastructure/Migrations/20240702055858_AddCreatorAliasTouser.cs b/src/Infrastructure/Migrations/20240702055858_AddCreatorAliasTouser.cs deleted file mode 100644 index 456b236..0000000 --- a/src/Infrastructure/Migrations/20240702055858_AddCreatorAliasTouser.cs +++ /dev/null @@ -1,28 +0,0 @@ -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace Hutopy.Infrastructure.Migrations -{ - /// - public partial class AddCreatorAliasTouser : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.AddColumn( - name: "CreatorAlias", - table: "AspNetUsers", - type: "nvarchar(max)", - nullable: true); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropColumn( - name: "CreatorAlias", - table: "AspNetUsers"); - } - } -} diff --git a/src/Infrastructure/Migrations/20240705010235_RemovePortraitUrl.Designer.cs b/src/Infrastructure/Migrations/20240705010235_RemovePortraitUrl.Designer.cs deleted file mode 100644 index 1df55e6..0000000 --- a/src/Infrastructure/Migrations/20240705010235_RemovePortraitUrl.Designer.cs +++ /dev/null @@ -1,560 +0,0 @@ -// -using System; -using Hutopy.Infrastructure.Data; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -#nullable disable - -namespace Hutopy.Infrastructure.Migrations -{ - [DbContext(typeof(ApplicationDbContext))] - [Migration("20240705010235_RemovePortraitUrl")] - partial class RemovePortraitUrl - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "8.0.3") - .HasAnnotation("Relational:MaxIdentifierLength", 128); - - SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); - - modelBuilder.Entity("Hutopy.Domain.Entities.FutureCreator", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uniqueidentifier"); - - b.Property("Created") - .HasColumnType("datetimeoffset"); - - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("EmailAddress") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("FirstName") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("LastModified") - .HasColumnType("datetimeoffset"); - - b.Property("LastModifiedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("LastName") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("PhoneNumber") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("ReasonToJoin") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("SocialNetworkAccount") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.ToTable("FutureCreators"); - }); - - modelBuilder.Entity("Hutopy.Domain.Entities.UserTransaction", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uniqueidentifier"); - - b.Property("Amount") - .HasPrecision(18, 2) - .HasColumnType("decimal(18,2)"); - - b.Property("ApplicationUserId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.Property("Created") - .HasColumnType("datetimeoffset"); - - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("Currency") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("IsConfirmed") - .HasColumnType("bit"); - - b.Property("LastModified") - .HasColumnType("datetimeoffset"); - - b.Property("LastModifiedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("Paid") - .HasColumnType("bit"); - - b.Property("StripeBillingDetailEmail") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("StripeBillingDetailName") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("StripeChargeId") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("StripeEventId") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("StripePaymentIntent") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("StripePaymentMethod") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("StripeReceiptUrl") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("TipMessage") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.HasIndex("ApplicationUserId"); - - b.ToTable("UserTransactions"); - }); - - modelBuilder.Entity("Hutopy.Infrastructure.Identity.ApplicationUser", b => - { - b.Property("Id") - .HasColumnType("nvarchar(450)"); - - b.Property("About") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("AccessFailedCount") - .HasColumnType("int"); - - b.Property("Address") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("BirthDate") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("City") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnType("nvarchar(max)"); - - b.Property("Country") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("CreatorAlias") - .HasColumnType("nvarchar(max)"); - - b.Property("Description") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("Email") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("EmailConfirmed") - .HasColumnType("bit"); - - b.Property("FirstName") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("LastName") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("LockoutEnabled") - .HasColumnType("bit"); - - b.Property("LockoutEnd") - .HasColumnType("datetimeoffset"); - - b.Property("NormalizedEmail") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("NormalizedUserName") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("Occupation") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("PasswordHash") - .HasColumnType("nvarchar(max)"); - - b.Property("PhoneNumber") - .HasColumnType("nvarchar(max)"); - - b.Property("PhoneNumberConfirmed") - .HasColumnType("bit"); - - b.Property("SecurityStamp") - .HasColumnType("nvarchar(max)"); - - b.Property("TwoFactorEnabled") - .HasColumnType("bit"); - - b.Property("UserName") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.HasKey("Id"); - - b.HasIndex("NormalizedEmail") - .HasDatabaseName("EmailIndex"); - - b.HasIndex("NormalizedUserName") - .IsUnique() - .HasDatabaseName("UserNameIndex") - .HasFilter("[NormalizedUserName] IS NOT NULL"); - - b.ToTable("AspNetUsers", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => - { - b.Property("Id") - .HasColumnType("nvarchar(450)"); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnType("nvarchar(max)"); - - b.Property("Name") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("NormalizedName") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.HasKey("Id"); - - b.HasIndex("NormalizedName") - .IsUnique() - .HasDatabaseName("RoleNameIndex") - .HasFilter("[NormalizedName] IS NOT NULL"); - - b.ToTable("AspNetRoles", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ClaimType") - .HasColumnType("nvarchar(max)"); - - b.Property("ClaimValue") - .HasColumnType("nvarchar(max)"); - - b.Property("RoleId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("Id"); - - b.HasIndex("RoleId"); - - b.ToTable("AspNetRoleClaims", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ClaimType") - .HasColumnType("nvarchar(max)"); - - b.Property("ClaimValue") - .HasColumnType("nvarchar(max)"); - - b.Property("UserId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("AspNetUserClaims", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => - { - b.Property("LoginProvider") - .HasColumnType("nvarchar(450)"); - - b.Property("ProviderKey") - .HasColumnType("nvarchar(450)"); - - b.Property("ProviderDisplayName") - .HasColumnType("nvarchar(max)"); - - b.Property("UserId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("LoginProvider", "ProviderKey"); - - b.HasIndex("UserId"); - - b.ToTable("AspNetUserLogins", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => - { - b.Property("UserId") - .HasColumnType("nvarchar(450)"); - - b.Property("RoleId") - .HasColumnType("nvarchar(450)"); - - b.HasKey("UserId", "RoleId"); - - b.HasIndex("RoleId"); - - b.ToTable("AspNetUserRoles", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => - { - b.Property("UserId") - .HasColumnType("nvarchar(450)"); - - b.Property("LoginProvider") - .HasColumnType("nvarchar(450)"); - - b.Property("Name") - .HasColumnType("nvarchar(450)"); - - b.Property("Value") - .HasColumnType("nvarchar(max)"); - - b.HasKey("UserId", "LoginProvider", "Name"); - - b.ToTable("AspNetUserTokens", (string)null); - }); - - modelBuilder.Entity("Hutopy.Domain.Entities.UserTransaction", b => - { - b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) - .WithMany() - .HasForeignKey("ApplicationUserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Hutopy.Infrastructure.Identity.ApplicationUser", b => - { - b.OwnsOne("Hutopy.Infrastructure.Identity.OwnedEntities.ProfileColors", "ProfileColors", b1 => - { - b1.Property("ApplicationUserId") - .HasColumnType("nvarchar(450)"); - - b1.Property("Accent") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.Property("BannerBottom") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.Property("BannerTop") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.Property("Menu") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.HasKey("ApplicationUserId"); - - b1.ToTable("ApplicationUser_ProfileColors", (string)null); - - b1.WithOwner() - .HasForeignKey("ApplicationUserId"); - }); - - b.OwnsOne("Hutopy.Infrastructure.Identity.OwnedEntities.SocialNetworks", "SocialNetworks", b1 => - { - b1.Property("ApplicationUserId") - .HasColumnType("nvarchar(450)"); - - b1.Property("FacebookUrl") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.Property("InstagramUrl") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.Property("LinkedInUrl") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.Property("RedditUrl") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.Property("TikTokUrl") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.Property("XUrl") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.Property("YourWebsiteUrl") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.Property("YoutubeUrl") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.HasKey("ApplicationUserId"); - - b1.ToTable("ApplicationUser_SocialNetworks", (string)null); - - b1.WithOwner() - .HasForeignKey("ApplicationUserId"); - }); - - b.OwnsOne("Hutopy.Infrastructure.Identity.OwnedEntities.StoredDataUrls", "StoredDataUrls", b1 => - { - b1.Property("ApplicationUserId") - .HasColumnType("nvarchar(450)"); - - b1.Property("BannerPictureUrl") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.Property("ProfilePictureUrl") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.Property("WebsiteIconUrl") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.HasKey("ApplicationUserId"); - - b1.ToTable("ApplicationUser_StoredDataUrls", (string)null); - - b1.WithOwner() - .HasForeignKey("ApplicationUserId"); - }); - - b.Navigation("ProfileColors") - .IsRequired(); - - b.Navigation("SocialNetworks") - .IsRequired(); - - b.Navigation("StoredDataUrls") - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) - .WithMany() - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => - { - b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => - { - b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) - .WithMany() - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => - { - b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Infrastructure/Migrations/20240705010235_RemovePortraitUrl.cs b/src/Infrastructure/Migrations/20240705010235_RemovePortraitUrl.cs deleted file mode 100644 index e504870..0000000 --- a/src/Infrastructure/Migrations/20240705010235_RemovePortraitUrl.cs +++ /dev/null @@ -1,28 +0,0 @@ -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace Hutopy.Infrastructure.Migrations -{ - /// - public partial class RemovePortraitUrl : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropColumn( - name: "PortraitUrl", - table: "AspNetUsers"); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.AddColumn( - name: "PortraitUrl", - table: "AspNetUsers", - type: "nvarchar(max)", - nullable: true); - } - } -} diff --git a/src/Infrastructure/Migrations/20240721045147_AddAlias.Designer.cs b/src/Infrastructure/Migrations/20240721045147_AddAlias.Designer.cs deleted file mode 100644 index 397d04b..0000000 --- a/src/Infrastructure/Migrations/20240721045147_AddAlias.Designer.cs +++ /dev/null @@ -1,563 +0,0 @@ -// -using System; -using Hutopy.Infrastructure.Data; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -#nullable disable - -namespace Hutopy.Infrastructure.Migrations -{ - [DbContext(typeof(ApplicationDbContext))] - [Migration("20240721045147_AddAlias")] - partial class AddAlias - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "8.0.4") - .HasAnnotation("Relational:MaxIdentifierLength", 128); - - SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); - - modelBuilder.Entity("Hutopy.Domain.Entities.FutureCreator", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uniqueidentifier"); - - b.Property("Created") - .HasColumnType("datetimeoffset"); - - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("EmailAddress") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("FirstName") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("LastModified") - .HasColumnType("datetimeoffset"); - - b.Property("LastModifiedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("LastName") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("PhoneNumber") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("ReasonToJoin") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("SocialNetworkAccount") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.ToTable("FutureCreators"); - }); - - modelBuilder.Entity("Hutopy.Domain.Entities.UserTransaction", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uniqueidentifier"); - - b.Property("Amount") - .HasPrecision(18, 2) - .HasColumnType("decimal(18,2)"); - - b.Property("ApplicationUserId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.Property("Created") - .HasColumnType("datetimeoffset"); - - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("Currency") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("IsConfirmed") - .HasColumnType("bit"); - - b.Property("LastModified") - .HasColumnType("datetimeoffset"); - - b.Property("LastModifiedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("Paid") - .HasColumnType("bit"); - - b.Property("StripeBillingDetailEmail") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("StripeBillingDetailName") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("StripeChargeId") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("StripeEventId") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("StripePaymentIntent") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("StripePaymentMethod") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("StripeReceiptUrl") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("TipMessage") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.HasIndex("ApplicationUserId"); - - b.ToTable("UserTransactions"); - }); - - modelBuilder.Entity("Hutopy.Infrastructure.Identity.ApplicationUser", b => - { - b.Property("Id") - .HasColumnType("nvarchar(450)"); - - b.Property("About") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("AccessFailedCount") - .HasColumnType("int"); - - b.Property("Address") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("Alias") - .HasColumnType("nvarchar(max)"); - - b.Property("BirthDate") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("City") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnType("nvarchar(max)"); - - b.Property("Country") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("CreatorAlias") - .HasColumnType("nvarchar(max)"); - - b.Property("Description") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("Email") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("EmailConfirmed") - .HasColumnType("bit"); - - b.Property("FirstName") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("LastName") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("LockoutEnabled") - .HasColumnType("bit"); - - b.Property("LockoutEnd") - .HasColumnType("datetimeoffset"); - - b.Property("NormalizedEmail") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("NormalizedUserName") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("Occupation") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("PasswordHash") - .HasColumnType("nvarchar(max)"); - - b.Property("PhoneNumber") - .HasColumnType("nvarchar(max)"); - - b.Property("PhoneNumberConfirmed") - .HasColumnType("bit"); - - b.Property("SecurityStamp") - .HasColumnType("nvarchar(max)"); - - b.Property("TwoFactorEnabled") - .HasColumnType("bit"); - - b.Property("UserName") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.HasKey("Id"); - - b.HasIndex("NormalizedEmail") - .HasDatabaseName("EmailIndex"); - - b.HasIndex("NormalizedUserName") - .IsUnique() - .HasDatabaseName("UserNameIndex") - .HasFilter("[NormalizedUserName] IS NOT NULL"); - - b.ToTable("AspNetUsers", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => - { - b.Property("Id") - .HasColumnType("nvarchar(450)"); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnType("nvarchar(max)"); - - b.Property("Name") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("NormalizedName") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.HasKey("Id"); - - b.HasIndex("NormalizedName") - .IsUnique() - .HasDatabaseName("RoleNameIndex") - .HasFilter("[NormalizedName] IS NOT NULL"); - - b.ToTable("AspNetRoles", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ClaimType") - .HasColumnType("nvarchar(max)"); - - b.Property("ClaimValue") - .HasColumnType("nvarchar(max)"); - - b.Property("RoleId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("Id"); - - b.HasIndex("RoleId"); - - b.ToTable("AspNetRoleClaims", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ClaimType") - .HasColumnType("nvarchar(max)"); - - b.Property("ClaimValue") - .HasColumnType("nvarchar(max)"); - - b.Property("UserId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("AspNetUserClaims", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => - { - b.Property("LoginProvider") - .HasColumnType("nvarchar(450)"); - - b.Property("ProviderKey") - .HasColumnType("nvarchar(450)"); - - b.Property("ProviderDisplayName") - .HasColumnType("nvarchar(max)"); - - b.Property("UserId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("LoginProvider", "ProviderKey"); - - b.HasIndex("UserId"); - - b.ToTable("AspNetUserLogins", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => - { - b.Property("UserId") - .HasColumnType("nvarchar(450)"); - - b.Property("RoleId") - .HasColumnType("nvarchar(450)"); - - b.HasKey("UserId", "RoleId"); - - b.HasIndex("RoleId"); - - b.ToTable("AspNetUserRoles", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => - { - b.Property("UserId") - .HasColumnType("nvarchar(450)"); - - b.Property("LoginProvider") - .HasColumnType("nvarchar(450)"); - - b.Property("Name") - .HasColumnType("nvarchar(450)"); - - b.Property("Value") - .HasColumnType("nvarchar(max)"); - - b.HasKey("UserId", "LoginProvider", "Name"); - - b.ToTable("AspNetUserTokens", (string)null); - }); - - modelBuilder.Entity("Hutopy.Domain.Entities.UserTransaction", b => - { - b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) - .WithMany() - .HasForeignKey("ApplicationUserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Hutopy.Infrastructure.Identity.ApplicationUser", b => - { - b.OwnsOne("Hutopy.Infrastructure.Identity.OwnedEntities.ProfileColors", "ProfileColors", b1 => - { - b1.Property("ApplicationUserId") - .HasColumnType("nvarchar(450)"); - - b1.Property("Accent") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.Property("BannerBottom") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.Property("BannerTop") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.Property("Menu") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.HasKey("ApplicationUserId"); - - b1.ToTable("ApplicationUser_ProfileColors", (string)null); - - b1.WithOwner() - .HasForeignKey("ApplicationUserId"); - }); - - b.OwnsOne("Hutopy.Infrastructure.Identity.OwnedEntities.SocialNetworks", "SocialNetworks", b1 => - { - b1.Property("ApplicationUserId") - .HasColumnType("nvarchar(450)"); - - b1.Property("FacebookUrl") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.Property("InstagramUrl") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.Property("LinkedInUrl") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.Property("RedditUrl") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.Property("TikTokUrl") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.Property("XUrl") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.Property("YourWebsiteUrl") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.Property("YoutubeUrl") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.HasKey("ApplicationUserId"); - - b1.ToTable("ApplicationUser_SocialNetworks", (string)null); - - b1.WithOwner() - .HasForeignKey("ApplicationUserId"); - }); - - b.OwnsOne("Hutopy.Infrastructure.Identity.OwnedEntities.StoredDataUrls", "StoredDataUrls", b1 => - { - b1.Property("ApplicationUserId") - .HasColumnType("nvarchar(450)"); - - b1.Property("BannerPictureUrl") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.Property("ProfilePictureUrl") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.Property("WebsiteIconUrl") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.HasKey("ApplicationUserId"); - - b1.ToTable("ApplicationUser_StoredDataUrls", (string)null); - - b1.WithOwner() - .HasForeignKey("ApplicationUserId"); - }); - - b.Navigation("ProfileColors") - .IsRequired(); - - b.Navigation("SocialNetworks") - .IsRequired(); - - b.Navigation("StoredDataUrls") - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) - .WithMany() - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => - { - b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => - { - b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) - .WithMany() - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => - { - b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Infrastructure/Migrations/20240721045147_AddAlias.cs b/src/Infrastructure/Migrations/20240721045147_AddAlias.cs deleted file mode 100644 index 9c8ffc9..0000000 --- a/src/Infrastructure/Migrations/20240721045147_AddAlias.cs +++ /dev/null @@ -1,28 +0,0 @@ -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace Hutopy.Infrastructure.Migrations -{ - /// - public partial class AddAlias : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.AddColumn( - name: "Alias", - table: "AspNetUsers", - type: "nvarchar(max)", - nullable: true); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropColumn( - name: "Alias", - table: "AspNetUsers"); - } - } -} diff --git a/src/Infrastructure/Migrations/20240721063535_MadeOptional_StoredDataUrls.Designer.cs b/src/Infrastructure/Migrations/20240721063535_MadeOptional_StoredDataUrls.Designer.cs deleted file mode 100644 index 142d953..0000000 --- a/src/Infrastructure/Migrations/20240721063535_MadeOptional_StoredDataUrls.Designer.cs +++ /dev/null @@ -1,563 +0,0 @@ -// -using System; -using Hutopy.Infrastructure.Data; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -#nullable disable - -namespace Hutopy.Infrastructure.Migrations -{ - [DbContext(typeof(ApplicationDbContext))] - [Migration("20240721063535_MadeOptional_StoredDataUrls")] - partial class MadeOptional_StoredDataUrls - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "8.0.4") - .HasAnnotation("Relational:MaxIdentifierLength", 128); - - SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); - - modelBuilder.Entity("Hutopy.Domain.Entities.FutureCreator", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uniqueidentifier"); - - b.Property("Created") - .HasColumnType("datetimeoffset"); - - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("EmailAddress") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("FirstName") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("LastModified") - .HasColumnType("datetimeoffset"); - - b.Property("LastModifiedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("LastName") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("PhoneNumber") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("ReasonToJoin") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("SocialNetworkAccount") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.ToTable("FutureCreators"); - }); - - modelBuilder.Entity("Hutopy.Domain.Entities.UserTransaction", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uniqueidentifier"); - - b.Property("Amount") - .HasPrecision(18, 2) - .HasColumnType("decimal(18,2)"); - - b.Property("ApplicationUserId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.Property("Created") - .HasColumnType("datetimeoffset"); - - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("Currency") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("IsConfirmed") - .HasColumnType("bit"); - - b.Property("LastModified") - .HasColumnType("datetimeoffset"); - - b.Property("LastModifiedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("Paid") - .HasColumnType("bit"); - - b.Property("StripeBillingDetailEmail") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("StripeBillingDetailName") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("StripeChargeId") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("StripeEventId") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("StripePaymentIntent") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("StripePaymentMethod") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("StripeReceiptUrl") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("TipMessage") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.HasIndex("ApplicationUserId"); - - b.ToTable("UserTransactions"); - }); - - modelBuilder.Entity("Hutopy.Infrastructure.Identity.ApplicationUser", b => - { - b.Property("Id") - .HasColumnType("nvarchar(450)"); - - b.Property("About") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("AccessFailedCount") - .HasColumnType("int"); - - b.Property("Address") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("Alias") - .HasColumnType("nvarchar(max)"); - - b.Property("BirthDate") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("City") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnType("nvarchar(max)"); - - b.Property("Country") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("CreatorAlias") - .HasColumnType("nvarchar(max)"); - - b.Property("Description") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("Email") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("EmailConfirmed") - .HasColumnType("bit"); - - b.Property("FirstName") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("LastName") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("LockoutEnabled") - .HasColumnType("bit"); - - b.Property("LockoutEnd") - .HasColumnType("datetimeoffset"); - - b.Property("NormalizedEmail") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("NormalizedUserName") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("Occupation") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("PasswordHash") - .HasColumnType("nvarchar(max)"); - - b.Property("PhoneNumber") - .HasColumnType("nvarchar(max)"); - - b.Property("PhoneNumberConfirmed") - .HasColumnType("bit"); - - b.Property("SecurityStamp") - .HasColumnType("nvarchar(max)"); - - b.Property("TwoFactorEnabled") - .HasColumnType("bit"); - - b.Property("UserName") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.HasKey("Id"); - - b.HasIndex("NormalizedEmail") - .HasDatabaseName("EmailIndex"); - - b.HasIndex("NormalizedUserName") - .IsUnique() - .HasDatabaseName("UserNameIndex") - .HasFilter("[NormalizedUserName] IS NOT NULL"); - - b.ToTable("AspNetUsers", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => - { - b.Property("Id") - .HasColumnType("nvarchar(450)"); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnType("nvarchar(max)"); - - b.Property("Name") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("NormalizedName") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.HasKey("Id"); - - b.HasIndex("NormalizedName") - .IsUnique() - .HasDatabaseName("RoleNameIndex") - .HasFilter("[NormalizedName] IS NOT NULL"); - - b.ToTable("AspNetRoles", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ClaimType") - .HasColumnType("nvarchar(max)"); - - b.Property("ClaimValue") - .HasColumnType("nvarchar(max)"); - - b.Property("RoleId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("Id"); - - b.HasIndex("RoleId"); - - b.ToTable("AspNetRoleClaims", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ClaimType") - .HasColumnType("nvarchar(max)"); - - b.Property("ClaimValue") - .HasColumnType("nvarchar(max)"); - - b.Property("UserId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("AspNetUserClaims", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => - { - b.Property("LoginProvider") - .HasColumnType("nvarchar(450)"); - - b.Property("ProviderKey") - .HasColumnType("nvarchar(450)"); - - b.Property("ProviderDisplayName") - .HasColumnType("nvarchar(max)"); - - b.Property("UserId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("LoginProvider", "ProviderKey"); - - b.HasIndex("UserId"); - - b.ToTable("AspNetUserLogins", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => - { - b.Property("UserId") - .HasColumnType("nvarchar(450)"); - - b.Property("RoleId") - .HasColumnType("nvarchar(450)"); - - b.HasKey("UserId", "RoleId"); - - b.HasIndex("RoleId"); - - b.ToTable("AspNetUserRoles", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => - { - b.Property("UserId") - .HasColumnType("nvarchar(450)"); - - b.Property("LoginProvider") - .HasColumnType("nvarchar(450)"); - - b.Property("Name") - .HasColumnType("nvarchar(450)"); - - b.Property("Value") - .HasColumnType("nvarchar(max)"); - - b.HasKey("UserId", "LoginProvider", "Name"); - - b.ToTable("AspNetUserTokens", (string)null); - }); - - modelBuilder.Entity("Hutopy.Domain.Entities.UserTransaction", b => - { - b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) - .WithMany() - .HasForeignKey("ApplicationUserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Hutopy.Infrastructure.Identity.ApplicationUser", b => - { - b.OwnsOne("Hutopy.Infrastructure.Identity.OwnedEntities.ProfileColors", "ProfileColors", b1 => - { - b1.Property("ApplicationUserId") - .HasColumnType("nvarchar(450)"); - - b1.Property("Accent") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.Property("BannerBottom") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.Property("BannerTop") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.Property("Menu") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.HasKey("ApplicationUserId"); - - b1.ToTable("ApplicationUser_ProfileColors", (string)null); - - b1.WithOwner() - .HasForeignKey("ApplicationUserId"); - }); - - b.OwnsOne("Hutopy.Infrastructure.Identity.OwnedEntities.SocialNetworks", "SocialNetworks", b1 => - { - b1.Property("ApplicationUserId") - .HasColumnType("nvarchar(450)"); - - b1.Property("FacebookUrl") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.Property("InstagramUrl") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.Property("LinkedInUrl") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.Property("RedditUrl") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.Property("TikTokUrl") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.Property("XUrl") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.Property("YourWebsiteUrl") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.Property("YoutubeUrl") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.HasKey("ApplicationUserId"); - - b1.ToTable("ApplicationUser_SocialNetworks", (string)null); - - b1.WithOwner() - .HasForeignKey("ApplicationUserId"); - }); - - b.OwnsOne("Hutopy.Infrastructure.Identity.OwnedEntities.StoredDataUrls", "StoredDataUrls", b1 => - { - b1.Property("ApplicationUserId") - .HasColumnType("nvarchar(450)"); - - b1.Property("BannerPictureUrl") - .HasMaxLength(255) - .HasColumnType("nvarchar(255)"); - - b1.Property("ProfilePictureUrl") - .HasMaxLength(255) - .HasColumnType("nvarchar(255)"); - - b1.Property("WebsiteIconUrl") - .HasMaxLength(255) - .HasColumnType("nvarchar(255)"); - - b1.HasKey("ApplicationUserId"); - - b1.ToTable("ApplicationUser_StoredDataUrls", (string)null); - - b1.WithOwner() - .HasForeignKey("ApplicationUserId"); - }); - - b.Navigation("ProfileColors") - .IsRequired(); - - b.Navigation("SocialNetworks") - .IsRequired(); - - b.Navigation("StoredDataUrls") - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) - .WithMany() - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => - { - b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => - { - b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) - .WithMany() - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => - { - b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Infrastructure/Migrations/20240721063535_MadeOptional_StoredDataUrls.cs b/src/Infrastructure/Migrations/20240721063535_MadeOptional_StoredDataUrls.cs deleted file mode 100644 index b3085ae..0000000 --- a/src/Infrastructure/Migrations/20240721063535_MadeOptional_StoredDataUrls.cs +++ /dev/null @@ -1,78 +0,0 @@ -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace Hutopy.Infrastructure.Migrations -{ - /// - public partial class MadeOptional_StoredDataUrls : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.AlterColumn( - name: "WebsiteIconUrl", - table: "ApplicationUser_StoredDataUrls", - type: "nvarchar(255)", - maxLength: 255, - nullable: true, - oldClrType: typeof(string), - oldType: "nvarchar(max)"); - - migrationBuilder.AlterColumn( - name: "ProfilePictureUrl", - table: "ApplicationUser_StoredDataUrls", - type: "nvarchar(255)", - maxLength: 255, - nullable: true, - oldClrType: typeof(string), - oldType: "nvarchar(max)"); - - migrationBuilder.AlterColumn( - name: "BannerPictureUrl", - table: "ApplicationUser_StoredDataUrls", - type: "nvarchar(255)", - maxLength: 255, - nullable: true, - oldClrType: typeof(string), - oldType: "nvarchar(max)"); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.AlterColumn( - name: "WebsiteIconUrl", - table: "ApplicationUser_StoredDataUrls", - type: "nvarchar(max)", - nullable: false, - defaultValue: "", - oldClrType: typeof(string), - oldType: "nvarchar(255)", - oldMaxLength: 255, - oldNullable: true); - - migrationBuilder.AlterColumn( - name: "ProfilePictureUrl", - table: "ApplicationUser_StoredDataUrls", - type: "nvarchar(max)", - nullable: false, - defaultValue: "", - oldClrType: typeof(string), - oldType: "nvarchar(255)", - oldMaxLength: 255, - oldNullable: true); - - migrationBuilder.AlterColumn( - name: "BannerPictureUrl", - table: "ApplicationUser_StoredDataUrls", - type: "nvarchar(max)", - nullable: false, - defaultValue: "", - oldClrType: typeof(string), - oldType: "nvarchar(255)", - oldMaxLength: 255, - oldNullable: true); - } - } -} diff --git a/src/Infrastructure/Migrations/20240509215538_AddMoreInformationToTransaction.Designer.cs b/src/Infrastructure/Migrations/20240802044736_Initial.Designer.cs similarity index 77% rename from src/Infrastructure/Migrations/20240509215538_AddMoreInformationToTransaction.Designer.cs rename to src/Infrastructure/Migrations/20240802044736_Initial.Designer.cs index f8c9e81..ad817a1 100644 --- a/src/Infrastructure/Migrations/20240509215538_AddMoreInformationToTransaction.Designer.cs +++ b/src/Infrastructure/Migrations/20240802044736_Initial.Designer.cs @@ -12,15 +12,15 @@ using Microsoft.EntityFrameworkCore.Storage.ValueConversion; namespace Hutopy.Infrastructure.Migrations { [DbContext(typeof(ApplicationDbContext))] - [Migration("20240509215538_AddMoreInformationToTransaction")] - partial class AddMoreInformationToTransaction + [Migration("20240802044736_Initial")] + partial class Initial { /// protected override void BuildTargetModel(ModelBuilder modelBuilder) { #pragma warning disable 612, 618 modelBuilder - .HasAnnotation("ProductVersion", "8.0.3") + .HasAnnotation("ProductVersion", "8.0.4") .HasAnnotation("Relational:MaxIdentifierLength", 128); SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); @@ -31,11 +31,11 @@ namespace Hutopy.Infrastructure.Migrations .ValueGeneratedOnAdd() .HasColumnType("uniqueidentifier"); - b.Property("Created") + b.Property("CreatedAt") .HasColumnType("datetimeoffset"); - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); + b.Property("CreatedBy") + .HasColumnType("uniqueidentifier"); b.Property("EmailAddress") .IsRequired() @@ -45,11 +45,11 @@ namespace Hutopy.Infrastructure.Migrations .IsRequired() .HasColumnType("nvarchar(max)"); - b.Property("LastModified") + b.Property("LastModifiedAt") .HasColumnType("datetimeoffset"); - b.Property("LastModifiedBy") - .HasColumnType("nvarchar(max)"); + b.Property("LastModifiedBy") + .HasColumnType("uniqueidentifier"); b.Property("LastName") .IsRequired() @@ -82,15 +82,14 @@ namespace Hutopy.Infrastructure.Migrations .HasPrecision(18, 2) .HasColumnType("decimal(18,2)"); - b.Property("ApplicationUserId") - .IsRequired() - .HasColumnType("nvarchar(450)"); + b.Property("ApplicationUserId") + .HasColumnType("uniqueidentifier"); - b.Property("Created") + b.Property("CreatedAt") .HasColumnType("datetimeoffset"); - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); + b.Property("CreatedBy") + .HasColumnType("uniqueidentifier"); b.Property("Currency") .IsRequired() @@ -99,11 +98,11 @@ namespace Hutopy.Infrastructure.Migrations b.Property("IsConfirmed") .HasColumnType("bit"); - b.Property("LastModified") + b.Property("LastModifiedAt") .HasColumnType("datetimeoffset"); - b.Property("LastModifiedBy") - .HasColumnType("nvarchar(max)"); + b.Property("LastModifiedBy") + .HasColumnType("uniqueidentifier"); b.Property("Paid") .HasColumnType("bit"); @@ -147,18 +146,67 @@ namespace Hutopy.Infrastructure.Migrations b.ToTable("UserTransactions"); }); - modelBuilder.Entity("Hutopy.Infrastructure.Identity.ApplicationUser", b => + modelBuilder.Entity("Hutopy.Infrastructure.Identity.ApplicationRole", b => { - b.Property("Id") - .HasColumnType("nvarchar(450)"); - - b.Property("AccessFailedCount") - .HasColumnType("int"); + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); b.Property("ConcurrencyStamp") .IsConcurrencyToken() .HasColumnType("nvarchar(max)"); + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex") + .HasFilter("[NormalizedName] IS NOT NULL"); + + b.ToTable("AspNetRoles", (string)null); + }); + + modelBuilder.Entity("Hutopy.Infrastructure.Identity.ApplicationUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("AccessFailedCount") + .HasColumnType("int"); + + b.Property("Address") + .HasMaxLength(255) + .HasColumnType("nvarchar(255)"); + + b.Property("Alias") + .HasMaxLength(255) + .HasColumnType("nvarchar(255)"); + + b.Property("BirthDate") + .HasMaxLength(255) + .HasColumnType("nvarchar(255)"); + + b.Property("City") + .HasMaxLength(255) + .HasColumnType("nvarchar(255)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("nvarchar(max)"); + + b.Property("Country") + .HasMaxLength(255) + .HasColumnType("nvarchar(255)"); + b.Property("Email") .HasMaxLength(256) .HasColumnType("nvarchar(256)"); @@ -167,12 +215,12 @@ namespace Hutopy.Infrastructure.Migrations .HasColumnType("bit"); b.Property("FirstName") - .IsRequired() - .HasColumnType("nvarchar(max)"); + .HasMaxLength(255) + .HasColumnType("nvarchar(255)"); b.Property("LastName") - .IsRequired() - .HasColumnType("nvarchar(max)"); + .HasMaxLength(255) + .HasColumnType("nvarchar(255)"); b.Property("LockoutEnabled") .HasColumnType("bit"); @@ -188,6 +236,10 @@ namespace Hutopy.Infrastructure.Migrations .HasMaxLength(256) .HasColumnType("nvarchar(256)"); + b.Property("Occupation") + .HasMaxLength(255) + .HasColumnType("nvarchar(255)"); + b.Property("PasswordHash") .HasColumnType("nvarchar(max)"); @@ -197,6 +249,10 @@ namespace Hutopy.Infrastructure.Migrations b.Property("PhoneNumberConfirmed") .HasColumnType("bit"); + b.Property("PortraitUrl") + .HasMaxLength(255) + .HasColumnType("nvarchar(255)"); + b.Property("SecurityStamp") .HasColumnType("nvarchar(max)"); @@ -220,34 +276,7 @@ namespace Hutopy.Infrastructure.Migrations b.ToTable("AspNetUsers", (string)null); }); - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => - { - b.Property("Id") - .HasColumnType("nvarchar(450)"); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnType("nvarchar(max)"); - - b.Property("Name") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("NormalizedName") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.HasKey("Id"); - - b.HasIndex("NormalizedName") - .IsUnique() - .HasDatabaseName("RoleNameIndex") - .HasFilter("[NormalizedName] IS NOT NULL"); - - b.ToTable("AspNetRoles", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -261,9 +290,8 @@ namespace Hutopy.Infrastructure.Migrations b.Property("ClaimValue") .HasColumnType("nvarchar(max)"); - b.Property("RoleId") - .IsRequired() - .HasColumnType("nvarchar(450)"); + b.Property("RoleId") + .HasColumnType("uniqueidentifier"); b.HasKey("Id"); @@ -272,7 +300,7 @@ namespace Hutopy.Infrastructure.Migrations b.ToTable("AspNetRoleClaims", (string)null); }); - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -286,9 +314,8 @@ namespace Hutopy.Infrastructure.Migrations b.Property("ClaimValue") .HasColumnType("nvarchar(max)"); - b.Property("UserId") - .IsRequired() - .HasColumnType("nvarchar(450)"); + b.Property("UserId") + .HasColumnType("uniqueidentifier"); b.HasKey("Id"); @@ -297,7 +324,7 @@ namespace Hutopy.Infrastructure.Migrations b.ToTable("AspNetUserClaims", (string)null); }); - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => { b.Property("LoginProvider") .HasColumnType("nvarchar(450)"); @@ -308,9 +335,8 @@ namespace Hutopy.Infrastructure.Migrations b.Property("ProviderDisplayName") .HasColumnType("nvarchar(max)"); - b.Property("UserId") - .IsRequired() - .HasColumnType("nvarchar(450)"); + b.Property("UserId") + .HasColumnType("uniqueidentifier"); b.HasKey("LoginProvider", "ProviderKey"); @@ -319,13 +345,13 @@ namespace Hutopy.Infrastructure.Migrations b.ToTable("AspNetUserLogins", (string)null); }); - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => { - b.Property("UserId") - .HasColumnType("nvarchar(450)"); + b.Property("UserId") + .HasColumnType("uniqueidentifier"); - b.Property("RoleId") - .HasColumnType("nvarchar(450)"); + b.Property("RoleId") + .HasColumnType("uniqueidentifier"); b.HasKey("UserId", "RoleId"); @@ -334,10 +360,10 @@ namespace Hutopy.Infrastructure.Migrations b.ToTable("AspNetUserRoles", (string)null); }); - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => { - b.Property("UserId") - .HasColumnType("nvarchar(450)"); + b.Property("UserId") + .HasColumnType("uniqueidentifier"); b.Property("LoginProvider") .HasColumnType("nvarchar(450)"); @@ -362,16 +388,16 @@ namespace Hutopy.Infrastructure.Migrations .IsRequired(); }); - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationRole", null) .WithMany() .HasForeignKey("RoleId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); }); - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => { b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) .WithMany() @@ -380,7 +406,7 @@ namespace Hutopy.Infrastructure.Migrations .IsRequired(); }); - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => { b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) .WithMany() @@ -389,9 +415,9 @@ namespace Hutopy.Infrastructure.Migrations .IsRequired(); }); - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationRole", null) .WithMany() .HasForeignKey("RoleId") .OnDelete(DeleteBehavior.Cascade) @@ -404,7 +430,7 @@ namespace Hutopy.Infrastructure.Migrations .IsRequired(); }); - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => { b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) .WithMany() diff --git a/src/Infrastructure/Migrations/20240418221249_InitialMigration.cs b/src/Infrastructure/Migrations/20240802044736_Initial.cs similarity index 69% rename from src/Infrastructure/Migrations/20240418221249_InitialMigration.cs rename to src/Infrastructure/Migrations/20240802044736_Initial.cs index ae91d8e..5b50f9c 100644 --- a/src/Infrastructure/Migrations/20240418221249_InitialMigration.cs +++ b/src/Infrastructure/Migrations/20240802044736_Initial.cs @@ -6,7 +6,7 @@ using Microsoft.EntityFrameworkCore.Migrations; namespace Hutopy.Infrastructure.Migrations { /// - public partial class InitialMigration : Migration + public partial class Initial : Migration { /// protected override void Up(MigrationBuilder migrationBuilder) @@ -15,7 +15,7 @@ namespace Hutopy.Infrastructure.Migrations name: "AspNetRoles", columns: table => new { - Id = table.Column(type: "nvarchar(450)", nullable: false), + Id = table.Column(type: "uniqueidentifier", nullable: false), Name = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), NormalizedName = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), ConcurrencyStamp = table.Column(type: "nvarchar(max)", nullable: true) @@ -29,9 +29,16 @@ namespace Hutopy.Infrastructure.Migrations name: "AspNetUsers", columns: table => new { - Id = table.Column(type: "nvarchar(450)", nullable: false), - FirstName = table.Column(type: "nvarchar(max)", nullable: false), - LastName = table.Column(type: "nvarchar(max)", nullable: false), + Id = table.Column(type: "uniqueidentifier", nullable: false), + Alias = table.Column(type: "nvarchar(255)", maxLength: 255, nullable: true), + FirstName = table.Column(type: "nvarchar(255)", maxLength: 255, nullable: true), + LastName = table.Column(type: "nvarchar(255)", maxLength: 255, nullable: true), + Occupation = table.Column(type: "nvarchar(255)", maxLength: 255, nullable: true), + BirthDate = table.Column(type: "nvarchar(255)", maxLength: 255, nullable: true), + Country = table.Column(type: "nvarchar(255)", maxLength: 255, nullable: true), + City = table.Column(type: "nvarchar(255)", maxLength: 255, nullable: true), + Address = table.Column(type: "nvarchar(255)", maxLength: 255, nullable: true), + PortraitUrl = table.Column(type: "nvarchar(255)", maxLength: 255, nullable: true), UserName = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), NormalizedUserName = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), Email = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), @@ -63,10 +70,10 @@ namespace Hutopy.Infrastructure.Migrations PhoneNumber = table.Column(type: "nvarchar(max)", nullable: false), SocialNetworkAccount = table.Column(type: "nvarchar(max)", nullable: false), ReasonToJoin = table.Column(type: "nvarchar(max)", nullable: false), - Created = table.Column(type: "datetimeoffset", nullable: false), - CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), - LastModified = table.Column(type: "datetimeoffset", nullable: false), - LastModifiedBy = table.Column(type: "nvarchar(max)", nullable: true) + CreatedAt = table.Column(type: "datetimeoffset", nullable: false), + CreatedBy = table.Column(type: "uniqueidentifier", nullable: true), + LastModifiedAt = table.Column(type: "datetimeoffset", nullable: false), + LastModifiedBy = table.Column(type: "uniqueidentifier", nullable: true) }, constraints: table => { @@ -79,7 +86,7 @@ namespace Hutopy.Infrastructure.Migrations { Id = table.Column(type: "int", nullable: false) .Annotation("SqlServer:Identity", "1, 1"), - RoleId = table.Column(type: "nvarchar(450)", nullable: false), + RoleId = table.Column(type: "uniqueidentifier", nullable: false), ClaimType = table.Column(type: "nvarchar(max)", nullable: true), ClaimValue = table.Column(type: "nvarchar(max)", nullable: true) }, @@ -100,7 +107,7 @@ namespace Hutopy.Infrastructure.Migrations { Id = table.Column(type: "int", nullable: false) .Annotation("SqlServer:Identity", "1, 1"), - UserId = table.Column(type: "nvarchar(450)", nullable: false), + UserId = table.Column(type: "uniqueidentifier", nullable: false), ClaimType = table.Column(type: "nvarchar(max)", nullable: true), ClaimValue = table.Column(type: "nvarchar(max)", nullable: true) }, @@ -122,7 +129,7 @@ namespace Hutopy.Infrastructure.Migrations LoginProvider = table.Column(type: "nvarchar(450)", nullable: false), ProviderKey = table.Column(type: "nvarchar(450)", nullable: false), ProviderDisplayName = table.Column(type: "nvarchar(max)", nullable: true), - UserId = table.Column(type: "nvarchar(450)", nullable: false) + UserId = table.Column(type: "uniqueidentifier", nullable: false) }, constraints: table => { @@ -139,8 +146,8 @@ namespace Hutopy.Infrastructure.Migrations name: "AspNetUserRoles", columns: table => new { - UserId = table.Column(type: "nvarchar(450)", nullable: false), - RoleId = table.Column(type: "nvarchar(450)", nullable: false) + UserId = table.Column(type: "uniqueidentifier", nullable: false), + RoleId = table.Column(type: "uniqueidentifier", nullable: false) }, constraints: table => { @@ -163,7 +170,7 @@ namespace Hutopy.Infrastructure.Migrations name: "AspNetUserTokens", columns: table => new { - UserId = table.Column(type: "nvarchar(450)", nullable: false), + UserId = table.Column(type: "uniqueidentifier", nullable: false), LoginProvider = table.Column(type: "nvarchar(450)", nullable: false), Name = table.Column(type: "nvarchar(450)", nullable: false), Value = table.Column(type: "nvarchar(max)", nullable: true) @@ -179,6 +186,40 @@ namespace Hutopy.Infrastructure.Migrations onDelete: ReferentialAction.Cascade); }); + migrationBuilder.CreateTable( + name: "UserTransactions", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + Amount = table.Column(type: "decimal(18,2)", precision: 18, scale: 2, nullable: false), + Currency = table.Column(type: "nvarchar(max)", nullable: false), + TipMessage = table.Column(type: "nvarchar(max)", nullable: false), + ApplicationUserId = table.Column(type: "uniqueidentifier", nullable: false), + IsConfirmed = table.Column(type: "bit", nullable: false), + StripeEventId = table.Column(type: "nvarchar(max)", nullable: false), + StripeChargeId = table.Column(type: "nvarchar(max)", nullable: false), + StripePaymentIntent = table.Column(type: "nvarchar(max)", nullable: false), + StripePaymentMethod = table.Column(type: "nvarchar(max)", nullable: false), + StripeReceiptUrl = table.Column(type: "nvarchar(max)", nullable: false), + StripeBillingDetailEmail = table.Column(type: "nvarchar(max)", nullable: false), + StripeBillingDetailName = table.Column(type: "nvarchar(max)", nullable: false), + Paid = table.Column(type: "bit", nullable: false), + CreatedAt = table.Column(type: "datetimeoffset", nullable: false), + CreatedBy = table.Column(type: "uniqueidentifier", nullable: true), + LastModifiedAt = table.Column(type: "datetimeoffset", nullable: false), + LastModifiedBy = table.Column(type: "uniqueidentifier", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_UserTransactions", x => x.Id); + table.ForeignKey( + name: "FK_UserTransactions_AspNetUsers_ApplicationUserId", + column: x => x.ApplicationUserId, + principalTable: "AspNetUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + migrationBuilder.CreateIndex( name: "IX_AspNetRoleClaims_RoleId", table: "AspNetRoleClaims", @@ -217,6 +258,11 @@ namespace Hutopy.Infrastructure.Migrations column: "NormalizedUserName", unique: true, filter: "[NormalizedUserName] IS NOT NULL"); + + migrationBuilder.CreateIndex( + name: "IX_UserTransactions_ApplicationUserId", + table: "UserTransactions", + column: "ApplicationUserId"); } /// @@ -240,6 +286,9 @@ namespace Hutopy.Infrastructure.Migrations migrationBuilder.DropTable( name: "FutureCreators"); + migrationBuilder.DropTable( + name: "UserTransactions"); + migrationBuilder.DropTable( name: "AspNetRoles"); diff --git a/src/Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs b/src/Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs index 8b4b9ec..7e0e9ed 100644 --- a/src/Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs +++ b/src/Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs @@ -28,11 +28,11 @@ namespace Hutopy.Infrastructure.Migrations .ValueGeneratedOnAdd() .HasColumnType("uniqueidentifier"); - b.Property("Created") + b.Property("CreatedAt") .HasColumnType("datetimeoffset"); - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); + b.Property("CreatedBy") + .HasColumnType("uniqueidentifier"); b.Property("EmailAddress") .IsRequired() @@ -42,11 +42,11 @@ namespace Hutopy.Infrastructure.Migrations .IsRequired() .HasColumnType("nvarchar(max)"); - b.Property("LastModified") + b.Property("LastModifiedAt") .HasColumnType("datetimeoffset"); - b.Property("LastModifiedBy") - .HasColumnType("nvarchar(max)"); + b.Property("LastModifiedBy") + .HasColumnType("uniqueidentifier"); b.Property("LastName") .IsRequired() @@ -66,7 +66,7 @@ namespace Hutopy.Infrastructure.Migrations b.HasKey("Id"); - b.ToTable("FutureCreators", (string)null); + b.ToTable("FutureCreators"); }); modelBuilder.Entity("Hutopy.Domain.Entities.UserTransaction", b => @@ -79,15 +79,14 @@ namespace Hutopy.Infrastructure.Migrations .HasPrecision(18, 2) .HasColumnType("decimal(18,2)"); - b.Property("ApplicationUserId") - .IsRequired() - .HasColumnType("nvarchar(450)"); + b.Property("ApplicationUserId") + .HasColumnType("uniqueidentifier"); - b.Property("Created") + b.Property("CreatedAt") .HasColumnType("datetimeoffset"); - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); + b.Property("CreatedBy") + .HasColumnType("uniqueidentifier"); b.Property("Currency") .IsRequired() @@ -96,11 +95,11 @@ namespace Hutopy.Infrastructure.Migrations b.Property("IsConfirmed") .HasColumnType("bit"); - b.Property("LastModified") + b.Property("LastModifiedAt") .HasColumnType("datetimeoffset"); - b.Property("LastModifiedBy") - .HasColumnType("nvarchar(max)"); + b.Property("LastModifiedBy") + .HasColumnType("uniqueidentifier"); b.Property("Paid") .HasColumnType("bit"); @@ -141,50 +140,69 @@ namespace Hutopy.Infrastructure.Migrations b.HasIndex("ApplicationUserId"); - b.ToTable("UserTransactions", (string)null); + b.ToTable("UserTransactions"); + }); + + modelBuilder.Entity("Hutopy.Infrastructure.Identity.ApplicationRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("nvarchar(max)"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex") + .HasFilter("[NormalizedName] IS NOT NULL"); + + b.ToTable("AspNetRoles", (string)null); }); modelBuilder.Entity("Hutopy.Infrastructure.Identity.ApplicationUser", b => { - b.Property("Id") - .HasColumnType("nvarchar(450)"); - - b.Property("About") - .IsRequired() - .HasColumnType("nvarchar(max)"); + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); b.Property("AccessFailedCount") .HasColumnType("int"); b.Property("Address") - .IsRequired() - .HasColumnType("nvarchar(max)"); + .HasMaxLength(255) + .HasColumnType("nvarchar(255)"); b.Property("Alias") - .HasColumnType("nvarchar(max)"); + .HasMaxLength(255) + .HasColumnType("nvarchar(255)"); b.Property("BirthDate") - .IsRequired() - .HasColumnType("nvarchar(max)"); + .HasMaxLength(255) + .HasColumnType("nvarchar(255)"); b.Property("City") - .IsRequired() - .HasColumnType("nvarchar(max)"); + .HasMaxLength(255) + .HasColumnType("nvarchar(255)"); b.Property("ConcurrencyStamp") .IsConcurrencyToken() .HasColumnType("nvarchar(max)"); b.Property("Country") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("CreatorAlias") - .HasColumnType("nvarchar(max)"); - - b.Property("Description") - .IsRequired() - .HasColumnType("nvarchar(max)"); + .HasMaxLength(255) + .HasColumnType("nvarchar(255)"); b.Property("Email") .HasMaxLength(256) @@ -194,12 +212,12 @@ namespace Hutopy.Infrastructure.Migrations .HasColumnType("bit"); b.Property("FirstName") - .IsRequired() - .HasColumnType("nvarchar(max)"); + .HasMaxLength(255) + .HasColumnType("nvarchar(255)"); b.Property("LastName") - .IsRequired() - .HasColumnType("nvarchar(max)"); + .HasMaxLength(255) + .HasColumnType("nvarchar(255)"); b.Property("LockoutEnabled") .HasColumnType("bit"); @@ -216,8 +234,8 @@ namespace Hutopy.Infrastructure.Migrations .HasColumnType("nvarchar(256)"); b.Property("Occupation") - .IsRequired() - .HasColumnType("nvarchar(max)"); + .HasMaxLength(255) + .HasColumnType("nvarchar(255)"); b.Property("PasswordHash") .HasColumnType("nvarchar(max)"); @@ -228,6 +246,10 @@ namespace Hutopy.Infrastructure.Migrations b.Property("PhoneNumberConfirmed") .HasColumnType("bit"); + b.Property("PortraitUrl") + .HasMaxLength(255) + .HasColumnType("nvarchar(255)"); + b.Property("SecurityStamp") .HasColumnType("nvarchar(max)"); @@ -251,34 +273,7 @@ namespace Hutopy.Infrastructure.Migrations b.ToTable("AspNetUsers", (string)null); }); - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => - { - b.Property("Id") - .HasColumnType("nvarchar(450)"); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnType("nvarchar(max)"); - - b.Property("Name") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("NormalizedName") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.HasKey("Id"); - - b.HasIndex("NormalizedName") - .IsUnique() - .HasDatabaseName("RoleNameIndex") - .HasFilter("[NormalizedName] IS NOT NULL"); - - b.ToTable("AspNetRoles", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -292,9 +287,8 @@ namespace Hutopy.Infrastructure.Migrations b.Property("ClaimValue") .HasColumnType("nvarchar(max)"); - b.Property("RoleId") - .IsRequired() - .HasColumnType("nvarchar(450)"); + b.Property("RoleId") + .HasColumnType("uniqueidentifier"); b.HasKey("Id"); @@ -303,7 +297,7 @@ namespace Hutopy.Infrastructure.Migrations b.ToTable("AspNetRoleClaims", (string)null); }); - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -317,9 +311,8 @@ namespace Hutopy.Infrastructure.Migrations b.Property("ClaimValue") .HasColumnType("nvarchar(max)"); - b.Property("UserId") - .IsRequired() - .HasColumnType("nvarchar(450)"); + b.Property("UserId") + .HasColumnType("uniqueidentifier"); b.HasKey("Id"); @@ -328,7 +321,7 @@ namespace Hutopy.Infrastructure.Migrations b.ToTable("AspNetUserClaims", (string)null); }); - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => { b.Property("LoginProvider") .HasColumnType("nvarchar(450)"); @@ -339,9 +332,8 @@ namespace Hutopy.Infrastructure.Migrations b.Property("ProviderDisplayName") .HasColumnType("nvarchar(max)"); - b.Property("UserId") - .IsRequired() - .HasColumnType("nvarchar(450)"); + b.Property("UserId") + .HasColumnType("uniqueidentifier"); b.HasKey("LoginProvider", "ProviderKey"); @@ -350,13 +342,13 @@ namespace Hutopy.Infrastructure.Migrations b.ToTable("AspNetUserLogins", (string)null); }); - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => { - b.Property("UserId") - .HasColumnType("nvarchar(450)"); + b.Property("UserId") + .HasColumnType("uniqueidentifier"); - b.Property("RoleId") - .HasColumnType("nvarchar(450)"); + b.Property("RoleId") + .HasColumnType("uniqueidentifier"); b.HasKey("UserId", "RoleId"); @@ -365,10 +357,10 @@ namespace Hutopy.Infrastructure.Migrations b.ToTable("AspNetUserRoles", (string)null); }); - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => { - b.Property("UserId") - .HasColumnType("nvarchar(450)"); + b.Property("UserId") + .HasColumnType("uniqueidentifier"); b.Property("LoginProvider") .HasColumnType("nvarchar(450)"); @@ -393,127 +385,16 @@ namespace Hutopy.Infrastructure.Migrations .IsRequired(); }); - modelBuilder.Entity("Hutopy.Infrastructure.Identity.ApplicationUser", b => + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => { - b.OwnsOne("Hutopy.Infrastructure.Identity.ApplicationUser.ProfileColors#Hutopy.Infrastructure.Identity.OwnedEntities.ProfileColors", "ProfileColors", b1 => - { - b1.Property("ApplicationUserId") - .HasColumnType("nvarchar(450)"); - - b1.Property("Accent") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.Property("BannerBottom") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.Property("BannerTop") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.Property("Menu") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.HasKey("ApplicationUserId"); - - b1.ToTable("ApplicationUser_ProfileColors", (string)null); - - b1.WithOwner() - .HasForeignKey("ApplicationUserId"); - }); - - b.OwnsOne("Hutopy.Infrastructure.Identity.ApplicationUser.SocialNetworks#Hutopy.Infrastructure.Identity.OwnedEntities.SocialNetworks", "SocialNetworks", b1 => - { - b1.Property("ApplicationUserId") - .HasColumnType("nvarchar(450)"); - - b1.Property("FacebookUrl") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.Property("InstagramUrl") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.Property("LinkedInUrl") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.Property("RedditUrl") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.Property("TikTokUrl") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.Property("XUrl") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.Property("YourWebsiteUrl") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.Property("YoutubeUrl") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.HasKey("ApplicationUserId"); - - b1.ToTable("ApplicationUser_SocialNetworks", (string)null); - - b1.WithOwner() - .HasForeignKey("ApplicationUserId"); - }); - - b.OwnsOne("Hutopy.Infrastructure.Identity.ApplicationUser.StoredDataUrls#Hutopy.Infrastructure.Identity.OwnedEntities.StoredDataUrls", "StoredDataUrls", b1 => - { - b1.Property("ApplicationUserId") - .HasColumnType("nvarchar(450)"); - - b1.Property("BannerPictureUrl") - .HasMaxLength(255) - .HasColumnType("nvarchar(255)"); - - b1.Property("ProfilePictureUrl") - .HasMaxLength(255) - .HasColumnType("nvarchar(255)"); - - b1.Property("WebsiteIconUrl") - .HasMaxLength(255) - .HasColumnType("nvarchar(255)"); - - b1.HasKey("ApplicationUserId"); - - b1.ToTable("ApplicationUser_StoredDataUrls", (string)null); - - b1.WithOwner() - .HasForeignKey("ApplicationUserId"); - }); - - b.Navigation("ProfileColors") - .IsRequired(); - - b.Navigation("SocialNetworks") - .IsRequired(); - - b.Navigation("StoredDataUrls") - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationRole", null) .WithMany() .HasForeignKey("RoleId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); }); - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => { b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) .WithMany() @@ -522,7 +403,7 @@ namespace Hutopy.Infrastructure.Migrations .IsRequired(); }); - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => { b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) .WithMany() @@ -531,9 +412,9 @@ namespace Hutopy.Infrastructure.Migrations .IsRequired(); }); - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationRole", null) .WithMany() .HasForeignKey("RoleId") .OnDelete(DeleteBehavior.Cascade) @@ -546,7 +427,7 @@ namespace Hutopy.Infrastructure.Migrations .IsRequired(); }); - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => { b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) .WithMany() diff --git a/src/Infrastructure/Stripe/StripeService.cs b/src/Infrastructure/Stripe/StripeService.cs index 3f4e366..7b78fff 100644 --- a/src/Infrastructure/Stripe/StripeService.cs +++ b/src/Infrastructure/Stripe/StripeService.cs @@ -1,6 +1,3 @@ -using System; -using System.Collections.Generic; -using System.Threading.Tasks; using Stripe; using Stripe.Checkout; using Hutopy.Application.Common.Interfaces; diff --git a/src/Infrastructure/Utils/GenerateJwtToken.cs b/src/Infrastructure/Utils/GenerateJwtToken.cs index 7992e14..d2120b8 100644 --- a/src/Infrastructure/Utils/GenerateJwtToken.cs +++ b/src/Infrastructure/Utils/GenerateJwtToken.cs @@ -17,7 +17,7 @@ public static class JwtTokenHelper string? alias, string firstname, string lastname, - string? profilePictureUrl) + string? portraitUrl) { var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(key)); var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256); @@ -36,9 +36,9 @@ public static class JwtTokenHelper claims.Add(new(KnownClaims.Alias, alias)); } - if (profilePictureUrl is not null) + if (portraitUrl is not null) { - claims.Add(new(KnownClaims.PortraitUrl, profilePictureUrl)); + claims.Add(new(KnownClaims.PortraitUrl, portraitUrl)); } var token = new JwtSecurityToken( diff --git a/src/Infrastructure/Utils/KnownClaims.cs b/src/Infrastructure/Utils/KnownClaims.cs index 96b1de9..21d44e2 100644 --- a/src/Infrastructure/Utils/KnownClaims.cs +++ b/src/Infrastructure/Utils/KnownClaims.cs @@ -2,6 +2,6 @@ namespace Hutopy.Infrastructure.Utils; public static class KnownClaims { - public const string Alias = nameof(Alias); - public const string PortraitUrl = nameof(PortraitUrl); + public const string Alias = "alias"; + public const string PortraitUrl = "portraitUrl"; } diff --git a/src/Web/Controllers/GoogleController.cs b/src/Web/Controllers/GoogleController.cs index f45006a..1030f43 100644 --- a/src/Web/Controllers/GoogleController.cs +++ b/src/Web/Controllers/GoogleController.cs @@ -72,12 +72,12 @@ public class GoogleController( jwtOptions.Value.Issuer, jwtOptions.Value.Audience, jwtOptions.Value.Key, - user.Id, + user.Id.ToString(), user.Email, user.Alias, user.FirstName, user.LastName, - user.StoredDataUrls.ProfilePictureUrl); + user.PortraitUrl); return Ok(new { accessToken = token, email }); } diff --git a/src/Web/DependencyInjection.cs b/src/Web/DependencyInjection.cs index 2a76f33..e1ca536 100644 --- a/src/Web/DependencyInjection.cs +++ b/src/Web/DependencyInjection.cs @@ -9,8 +9,6 @@ using Microsoft.AspNetCore.Authentication.Google; using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Mvc; using Microsoft.IdentityModel.Tokens; -using NSwag; -using NSwag.Generation.Processors.Security; namespace Hutopy.Web; diff --git a/src/Web/Endpoints/GetMyUser.cs b/src/Web/Endpoints/GetMyUser.cs index 444cbe9..4d88e2b 100644 --- a/src/Web/Endpoints/GetMyUser.cs +++ b/src/Web/Endpoints/GetMyUser.cs @@ -1,5 +1,4 @@ -using Hutopy.Application.Users.Queries; -using Hutopy.Application.Users.Queries.GetCurrentUser; +using Hutopy.Application.Users.Queries.GetCurrentUser; namespace Hutopy.Web.Endpoints; diff --git a/src/Web/Endpoints/UpdateMyUser.cs b/src/Web/Endpoints/UpdateMyUser.cs index 7399116..3416dfd 100644 --- a/src/Web/Endpoints/UpdateMyUser.cs +++ b/src/Web/Endpoints/UpdateMyUser.cs @@ -9,31 +9,19 @@ public class UpdateMyUser : EndpointGroupBase app.MapGroup(this) .RequireAuthorization() .MapPost(UpdateCurrentUserProfilePicture, "/profile-picture") - .MapPost(UpdateCurrentUserBannerPicture, "/banner-picture") - .MapPost(UpdateCurrentUserWebsiteIcon, "/website-icon") .MapPatch("/profile", UpdateCurrentUser); } - + private static async Task UpdateCurrentUser(ISender sender, UpdateCurrentUserCommand command) { return await sender.Send(command); } - - private static async Task UpdateCurrentUserProfilePicture(ISender sender, MemoryStream stream, string url = "") + + private static async Task UpdateCurrentUserProfilePicture( + ISender sender, + IFormFile formFile) { - var command = new UploadProfilePictureCommand { ProfilePicture = stream, ProfilePictureUrl = url}; - return await sender.Send(command); - } - - private static async Task UpdateCurrentUserBannerPicture(ISender sender, MemoryStream stream, string url = "") - { - var command = new UploadBannerPictureCommand { BannerPicture = stream, BannerPictureUrl = url}; - return await sender.Send(command); - } - - private static async Task UpdateCurrentUserWebsiteIcon(ISender sender, MemoryStream stream, string url = "") - { - var command = new UploadWebsiteIconCommand { WebsiteIcon = stream, WebsitePictureUrl = url}; + var command = new UploadProfilePictureCommand { File = formFile }; return await sender.Send(command); } } diff --git a/src/Web/Endpoints/Users.cs b/src/Web/Endpoints/Users.cs index bbdeb4c..4757789 100644 --- a/src/Web/Endpoints/Users.cs +++ b/src/Web/Endpoints/Users.cs @@ -10,7 +10,8 @@ public class Users : EndpointGroupBase app.MapGroup(this) .MapPost(CreateUser) .MapPost(Login, "/login") - .MapGet(GetUser); + .MapGet(GetUserById, "/id") + .MapGet(GetUserByUserName, "/user-name"); } private static async Task CreateUser(ISender sender, CreateUserCommand command) @@ -18,7 +19,14 @@ public class Users : EndpointGroupBase return await sender.Send(command); } - private static async Task GetUser(ISender sender, [AsParameters] GetUserQuery query) + private static async Task GetUserById(ISender sender, + [AsParameters] GetUserByIdQuery query) + { + return await sender.Send(query); + } + + private static async Task GetUserByUserName(ISender sender, + [AsParameters] GetUserByUserNameQuery query) { return await sender.Send(query); } diff --git a/src/Web/Features/Contents/Data/ContentDbContext.cs b/src/Web/Features/Contents/Data/ContentDbContext.cs index 9f6b739..1215d7f 100644 --- a/src/Web/Features/Contents/Data/ContentDbContext.cs +++ b/src/Web/Features/Contents/Data/ContentDbContext.cs @@ -7,17 +7,50 @@ public class ContentDbContext( : DbContext(options) { public const string SchemaName = "Content"; - + protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.HasDefaultSchema("Content"); - + modelBuilder .Entity() .Property(c => c.CreatedAt) .ValueGeneratedOnAdd() .HasDefaultValueSql("CURRENT_TIMESTAMP"); + + modelBuilder + .Entity() + .OwnsOne(x => x.About); + + modelBuilder + .Entity() + .OwnsOne(x => x.SocialNetworks); + + modelBuilder + .Entity() + .OwnsOne(x => x.ProfileColors); + + modelBuilder + .Entity() + .OwnsOne(x => x.StoredDataUrls); } - public DbSet Contents { get; set; } + public DbSet Contents { get; init; } = null!; + public DbSet Creators { get; init; } = null!; + + + public async Task FindByCreatorAliasAsync( + string creatorAlias, + CancellationToken cancellationToken = default) + { + ArgumentException.ThrowIfNullOrEmpty(creatorAlias); + + var user = await Creators.SingleOrDefaultAsync(creator => + EF.Functions.Like( + creatorAlias, + creator.Name), + cancellationToken: cancellationToken); + + return user; + } } diff --git a/src/Web/Features/Contents/Data/Creator.cs b/src/Web/Features/Contents/Data/Creator.cs new file mode 100644 index 0000000..85a835b --- /dev/null +++ b/src/Web/Features/Contents/Data/Creator.cs @@ -0,0 +1,48 @@ +using System.ComponentModel.DataAnnotations; + +namespace Hutopy.Web.Features.Contents.Data; + +public class Creator +{ + public Guid Id { get; set; } + public Guid CreatedBy { get; init; } + public DateTimeOffset CreatedAt { get; init; } + [MaxLength(255)] public string Name { get; set; } = null!; + + public About About { get; set; } = new(); + public SocialNetworks SocialNetworks { get; set; } = new(); + public ProfileColors ProfileColors { get; set; } = new(); + public StoredDataUrls StoredDataUrls { get; set; } = new(); +} + +public class About +{ + [MaxLength(255)] public string? Title { get; set; } + [MaxLength(255)] public string? Description { get; set; } +} + +public class ProfileColors +{ + [MaxLength(9)] public string? BannerTop { get; set; } + [MaxLength(9)] public string? BannerBottom { get; set; } + [MaxLength(9)] public string? Accent { get; set; } + [MaxLength(9)] public string? Menu { get; set; } +} + +public class SocialNetworks +{ + [MaxLength(255)] public string? FacebookUrl { get; set; } + [MaxLength(255)] public string? InstagramUrl { get; set; } + [MaxLength(255)] public string? XUrl { get; set; } + [MaxLength(255)] public string? LinkedInUrl { get; set; } + [MaxLength(255)] public string? TikTokUrl { get; set; } + [MaxLength(255)] public string? YoutubeUrl { get; set; } + [MaxLength(255)] public string? RedditUrl { get; set; } + [MaxLength(255)] public string? WebsiteUrl { get; set; } +} + +public class StoredDataUrls +{ + [MaxLength(255)] public string? BannerPictureUrl { get; set; } + [MaxLength(255)] public string? ProfilePictureUrl { get; set; } +} diff --git a/src/Web/Features/Contents/Handlers/ChangeBanner.cs b/src/Web/Features/Contents/Handlers/ChangeBanner.cs new file mode 100644 index 0000000..8601ff4 --- /dev/null +++ b/src/Web/Features/Contents/Handlers/ChangeBanner.cs @@ -0,0 +1,49 @@ +using FastEndpoints; +using Hutopy.Application.AzureBlobStorage.Constants; +using Hutopy.Application.Common.Interfaces; +using Hutopy.Application.Utils; +using Hutopy.Web.Features.Contents.Data; +using Microsoft.EntityFrameworkCore; + +namespace Hutopy.Web.Features.Contents.Handlers; + +public record ChangeBannerRequest( + Guid CreatorId, + IFormFile File); + +public class ChangeBannerHandler( + IHttpContextAccessor contextAccessor, + ContentDbContext context, + IAzureBlobStorageService azureBlobStorageService) + : Endpoint +{ + public override void Configure() + { + Post("/api/creators/{CreatorId}/banner"); + Options(o => o.WithTags("Contents")); + AllowFileUploads(); + } + + public override async Task HandleAsync(ChangeBannerRequest request, CancellationToken ct) + { + var creator = await context + .Creators + .Include(c => c.StoredDataUrls) + .SingleAsync( + c => c.Id == request.CreatorId, + cancellationToken: ct); + + var contentType = contextAccessor.EnsureContentType(); + + var blobUrl = await azureBlobStorageService.UploadFileAsync( + ContainerNames.Users, + $"{request.CreatorId}/{SubDirectoryNames.Profile}/{CommonFileNames.BannerPicture}", + request.File.OpenReadStream(), + contentType, + ct); + + await context.SaveChangesAsync(ct); + + await SendOkAsync(blobUrl, ct); + } +} diff --git a/src/Web/Features/Contents/Handlers/ChangeColors.cs b/src/Web/Features/Contents/Handlers/ChangeColors.cs new file mode 100644 index 0000000..76a003f --- /dev/null +++ b/src/Web/Features/Contents/Handlers/ChangeColors.cs @@ -0,0 +1,71 @@ +using FastEndpoints; +using FluentValidation; +using Hutopy.Web.Features.Contents.Data; +using Microsoft.EntityFrameworkCore; + +namespace Hutopy.Web.Features.Contents.Handlers; + +public record ChangeColorsRequest( + Guid CreatorId, + string? BannerTop, + string? BannerBottom, + string? Accent, + string? Menu); + +public sealed class ChangeColorsRequestValidator + : Validator +{ + public ChangeColorsRequestValidator() + { + RuleFor(x => x.BannerTop) + .MinimumLength(4).WithMessage("The minimum value should be in the format #444") + .MinimumLength(9).WithMessage("The maximum value should be in the format #11223344") + .Must(x => x.StartsWith('#')).WithMessage("The format should be a valid html color and start with #"); + + RuleFor(x => x.BannerBottom) + .MinimumLength(4).WithMessage("The minimum value should be in the format #444") + .MinimumLength(9).WithMessage("The maximum value should be in the format #11223344") + .Must(x => x.StartsWith('#')).WithMessage("The format should be a valid html color and start with #"); + + RuleFor(x => x.Accent) + .MinimumLength(4).WithMessage("The minimum value should be in the format #444") + .MinimumLength(9).WithMessage("The maximum value should be in the format #11223344") + .Must(x => x.StartsWith('#')).WithMessage("The format should be a valid html color and start with #"); + + RuleFor(x => x.Menu) + .MinimumLength(4).WithMessage("The minimum value should be in the format #444") + .MinimumLength(9).WithMessage("The maximum value should be in the format #11223344") + .Must(x => x.StartsWith('#')).WithMessage("The format should be a valid html color and start with #"); + } +} + +public class ChangeColorsHandler( + ContentDbContext context) + : Endpoint +{ + public override void Configure() + { + Post("/api/creators/{CreatorId}/colors"); + Options(o => o.WithTags("Contents")); + AllowFileUploads(); + } + + public override async Task HandleAsync(ChangeColorsRequest request, CancellationToken ct) + { + var creator = await context + .Creators + .Include(c => c.ProfileColors) + .SingleAsync( + c => c.Id == request.CreatorId, + cancellationToken: ct); + + creator.ProfileColors.BannerTop = request.BannerTop; + creator.ProfileColors.BannerBottom = request.BannerBottom; + creator.ProfileColors.Accent = request.Accent; + creator.ProfileColors.Menu = request.Menu; + + await context.SaveChangesAsync(ct); + + await SendOkAsync(ct); + } +} diff --git a/src/Web/Features/Contents/Handlers/CreateContent.cs b/src/Web/Features/Contents/Handlers/CreateContent.cs index 9f7c94a..836dbe1 100644 --- a/src/Web/Features/Contents/Handlers/CreateContent.cs +++ b/src/Web/Features/Contents/Handlers/CreateContent.cs @@ -53,6 +53,7 @@ public sealed class PostContent( PostContentRequest req, CancellationToken ct) { + var urls = new ConcurrentBag(); await Parallel.ForEachAsync( @@ -98,14 +99,11 @@ public sealed class PostContent( IFormFile file, CancellationToken ct = default) { - var memoryStream = new MemoryStream(); - await file.CopyToAsync(memoryStream, ct); - // TODO: I would like us to use ContainerNames.Creators but it seems we are missing configurations @jbourdon var url = await blobStorage.UploadFileAsync( ContainerNames.Users, $"{creatorId}/{SubDirectoryNames.Contents}/{contentId}/{file.FileName}", - memoryStream, + file.OpenReadStream(), file.ContentType, ct: ct); diff --git a/src/Web/Features/Contents/Handlers/CreateCreator.cs b/src/Web/Features/Contents/Handlers/CreateCreator.cs new file mode 100644 index 0000000..f68e96b --- /dev/null +++ b/src/Web/Features/Contents/Handlers/CreateCreator.cs @@ -0,0 +1,53 @@ +using FastEndpoints; +using FluentValidation; +using Hutopy.Web.Common; +using Hutopy.Web.Features.Contents.Data; + +namespace Hutopy.Web.Features.Contents.Handlers; + +public record CreateCreatorRequest( + Guid CreatorId, + string Name); + +public sealed class CreateCreatorRequestValidator : Validator +{ + public CreateCreatorRequestValidator() + { + RuleFor(r => r.CreatorId) + .NotNull().WithMessage("You should specify the CreatorId") + .NotEmpty().WithMessage("You should specify a valid/not empty CreatorId"); + + RuleFor(r => r.Name) + .NotNull().WithMessage("You should specify the Name") + .NotEmpty().WithMessage("You should specify a valid/not empty Name"); + } +} + +public sealed class CreateCreatorHandler( + ContentDbContext context) + : Endpoint +{ + public override void Configure() + { + Post("/api/creators"); + Options(o => o.WithTags("Contents")); + } + + public override async Task HandleAsync( + CreateCreatorRequest req, + CancellationToken ct) + { + await context.Creators.AddAsync( + new() + { + Id = req.CreatorId, + CreatedBy = User.GetUserId(), + Name = req.Name + }, + ct); + + await context.SaveChangesAsync(ct); + + await SendOkAsync(ct); + } +} diff --git a/src/Web/Features/Contents/Handlers/GetCreatorByAlias.cs b/src/Web/Features/Contents/Handlers/GetCreatorByAlias.cs index d5277e2..6204558 100644 --- a/src/Web/Features/Contents/Handlers/GetCreatorByAlias.cs +++ b/src/Web/Features/Contents/Handlers/GetCreatorByAlias.cs @@ -1,13 +1,13 @@ using FastEndpoints; using FluentValidation; -using Hutopy.Application.Common.Interfaces; -using Hutopy.Application.Common.Models; +using Hutopy.Web.Features.Contents.Data; +using Microsoft.EntityFrameworkCore; namespace Hutopy.Web.Features.Contents.Handlers; public sealed class GetCreatorByAliasRequest { - public string CreatorAlias { get; init; } + public required string Name { get; set; } } public sealed class GetCreatorByAliasRequestValidator @@ -15,20 +15,20 @@ public sealed class GetCreatorByAliasRequestValidator { public GetCreatorByAliasRequestValidator() { - RuleFor(r => r.CreatorAlias) - .NotNull().WithMessage("You should specify the CreatorAlias") - .NotEmpty().WithMessage("You should specify a valid/not empty CreatorAlias"); + RuleFor(r => r.Name) + .NotNull().WithMessage("You should specify the Name") + .NotEmpty().WithMessage("You should specify a valid/not empty Name"); } } -public class GetCreatorByAlias( - IIdentityService identityService) - : Endpoint +public class GetCreatorByAliasHandler( + ContentDbContext context) + : Endpoint { public override void Configure() { + Get("/api/creators/@{Name}"); Options((o => o.WithTags("Creators"))); - Get("/api/creators/@{CreatorAlias}"); AllowAnonymous(); } @@ -36,10 +36,13 @@ public class GetCreatorByAlias( GetCreatorByAliasRequest req, CancellationToken ct) { - var user = await identityService.FindUserByCreatorAliasAsync( - req.CreatorAlias, - ct); + var creator = await context + .Creators + .SingleOrDefaultAsync( + c => EF.Functions.Like(c.Name, req.Name), + cancellationToken: ct); - await SendAsync(user, cancellation: ct); + if (creator is null) await SendNotFoundAsync(ct); + else await SendAsync(creator, cancellation: ct); } } diff --git a/src/Web/Features/Contents/Handlers/GetCreatorById.cs b/src/Web/Features/Contents/Handlers/GetCreatorById.cs new file mode 100644 index 0000000..a5ed6ad --- /dev/null +++ b/src/Web/Features/Contents/Handlers/GetCreatorById.cs @@ -0,0 +1,47 @@ +using FastEndpoints; +using FluentValidation; +using Hutopy.Web.Features.Contents.Data; + +namespace Hutopy.Web.Features.Contents.Handlers; + +public sealed class GetCreatorByIdRequest +{ + public required Guid CreatorId { get; set; } +} + +public sealed class GetCreatorByIdRequestValidator + : Validator +{ + public GetCreatorByIdRequestValidator() + { + RuleFor(r => r.CreatorId) + .NotNull().WithMessage("You should specify the CreatorId") + .NotEmpty().WithMessage("You should specify a valid/not empty CreatorId"); + } +} + +public class GetCreatorByIdHandler( + ContentDbContext context) + : Endpoint +{ + public override void Configure() + { + Get("/api/creators/{CreatorId}"); + Options((o => o.WithTags("Creators"))); + AllowAnonymous(); + } + + public override async Task HandleAsync( + GetCreatorByIdRequest req, + CancellationToken ct) + { + var creator = await context + .Creators + .FindAsync( + [req.CreatorId], + cancellationToken: ct); + + if (creator is null) await SendNotFoundAsync(ct); + else await SendAsync(creator, cancellation: ct); + } +} diff --git a/src/Web/Features/Contents/Migrations/20240718034516_Initial.Designer.cs b/src/Web/Features/Contents/Migrations/20240718034516_Initial.Designer.cs deleted file mode 100644 index 4ea464a..0000000 --- a/src/Web/Features/Contents/Migrations/20240718034516_Initial.Designer.cs +++ /dev/null @@ -1,59 +0,0 @@ -// -using System; -using Hutopy.Web.Features.Contents.Data; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; - -#nullable disable - -namespace Hutopy.Web.Contents.Migrations -{ - [DbContext(typeof(ContentDbContext))] - [Migration("20240718034516_Initial")] - partial class Initial - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasDefaultSchema("Content") - .HasAnnotation("ProductVersion", "8.0.4") - .HasAnnotation("Relational:MaxIdentifierLength", 63); - - NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); - - modelBuilder.Entity("Hutopy.Web.Contents.Data.Content", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid"); - - b.Property("CreatedAt") - .ValueGeneratedOnAdd() - .HasColumnType("timestamp with time zone") - .HasDefaultValueSql("CURRENT_TIMESTAMP"); - - b.Property("CreatedBy") - .HasColumnType("uuid"); - - b.Property("Description") - .HasColumnType("text"); - - b.Property("Title") - .HasColumnType("text"); - - b.Property("Uri") - .HasColumnType("text"); - - b.HasKey("Id"); - - b.ToTable("Contents", "Content"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Web/Features/Contents/Migrations/20240718034516_Initial.cs b/src/Web/Features/Contents/Migrations/20240718034516_Initial.cs deleted file mode 100644 index d2ed5d8..0000000 --- a/src/Web/Features/Contents/Migrations/20240718034516_Initial.cs +++ /dev/null @@ -1,43 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace Hutopy.Web.Contents.Migrations -{ - /// - public partial class Initial : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.EnsureSchema( - name: "Content"); - - migrationBuilder.CreateTable( - name: "Contents", - schema: "Content", - columns: table => new - { - Id = table.Column(type: "uuid", nullable: false), - CreatedBy = table.Column(type: "uuid", nullable: false), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, defaultValueSql: "CURRENT_TIMESTAMP"), - Title = table.Column(type: "text", nullable: true), - Description = table.Column(type: "text", nullable: true), - Uri = table.Column(type: "text", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_Contents", x => x.Id); - }); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "Contents", - schema: "Content"); - } - } -} diff --git a/src/Web/Features/Contents/Migrations/20240725022229_AddMultipleMediaUrlsToContent.Designer.cs b/src/Web/Features/Contents/Migrations/20240725022229_AddMultipleMediaUrlsToContent.Designer.cs deleted file mode 100644 index 6971bc3..0000000 --- a/src/Web/Features/Contents/Migrations/20240725022229_AddMultipleMediaUrlsToContent.Designer.cs +++ /dev/null @@ -1,59 +0,0 @@ -// -using System; -using Hutopy.Web.Features.Contents.Data; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; - -#nullable disable - -namespace Hutopy.Web.Features.Contents.Migrations -{ - [DbContext(typeof(ContentDbContext))] - [Migration("20240725022229_AddMultipleMediaUrlsToContent")] - partial class AddMultipleMediaUrlsToContent - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasDefaultSchema("Content") - .HasAnnotation("ProductVersion", "8.0.4") - .HasAnnotation("Relational:MaxIdentifierLength", 63); - - NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); - - modelBuilder.Entity("Hutopy.Web.Features.Contents.Data.Content", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid"); - - b.Property("CreatedAt") - .ValueGeneratedOnAdd() - .HasColumnType("timestamp with time zone") - .HasDefaultValueSql("CURRENT_TIMESTAMP"); - - b.Property("CreatedBy") - .HasColumnType("uuid"); - - b.Property("Description") - .HasColumnType("text"); - - b.Property("Title") - .HasColumnType("text"); - - b.Property("Urls") - .HasColumnType("text[]"); - - b.HasKey("Id"); - - b.ToTable("Contents", "Content"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Web/Features/Contents/Migrations/20240725022229_AddMultipleMediaUrlsToContent.cs b/src/Web/Features/Contents/Migrations/20240725022229_AddMultipleMediaUrlsToContent.cs deleted file mode 100644 index 74051db..0000000 --- a/src/Web/Features/Contents/Migrations/20240725022229_AddMultipleMediaUrlsToContent.cs +++ /dev/null @@ -1,42 +0,0 @@ -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace Hutopy.Web.Features.Contents.Migrations -{ - /// - public partial class AddMultipleMediaUrlsToContent : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropColumn( - name: "Uri", - schema: "Content", - table: "Contents"); - - migrationBuilder.AddColumn( - name: "Urls", - schema: "Content", - table: "Contents", - type: "text[]", - nullable: true); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropColumn( - name: "Urls", - schema: "Content", - table: "Contents"); - - migrationBuilder.AddColumn( - name: "Uri", - schema: "Content", - table: "Contents", - type: "text", - nullable: true); - } - } -} diff --git a/src/Web/Features/Contents/Migrations/20240802044656_Initial.Designer.cs b/src/Web/Features/Contents/Migrations/20240802044656_Initial.Designer.cs new file mode 100644 index 0000000..f14eda2 --- /dev/null +++ b/src/Web/Features/Contents/Migrations/20240802044656_Initial.Designer.cs @@ -0,0 +1,214 @@ +// +using System; +using Hutopy.Web.Features.Contents.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace Hutopy.Web.Features.Contents.Migrations +{ + [DbContext(typeof(ContentDbContext))] + [Migration("20240802044656_Initial")] + partial class Initial + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasDefaultSchema("Content") + .HasAnnotation("ProductVersion", "8.0.4") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("Hutopy.Web.Features.Contents.Data.Content", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("CURRENT_TIMESTAMP"); + + b.Property("CreatedBy") + .HasColumnType("uuid"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text"); + + b.Property("Title") + .IsRequired() + .HasColumnType("text"); + + b.Property("Urls") + .HasColumnType("text[]"); + + b.HasKey("Id"); + + b.ToTable("Contents", "Content"); + }); + + modelBuilder.Entity("Hutopy.Web.Features.Contents.Data.Creator", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("uuid"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.HasKey("Id"); + + b.ToTable("Creators", "Content"); + }); + + modelBuilder.Entity("Hutopy.Web.Features.Contents.Data.Creator", b => + { + b.OwnsOne("Hutopy.Web.Features.Contents.Data.About", "About", b1 => + { + b1.Property("CreatorId") + .HasColumnType("uuid"); + + b1.Property("Description") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.Property("Title") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.HasKey("CreatorId"); + + b1.ToTable("Creators", "Content"); + + b1.WithOwner() + .HasForeignKey("CreatorId"); + }); + + b.OwnsOne("Hutopy.Web.Features.Contents.Data.ProfileColors", "ProfileColors", b1 => + { + b1.Property("CreatorId") + .HasColumnType("uuid"); + + b1.Property("Accent") + .HasMaxLength(9) + .HasColumnType("character varying(9)"); + + b1.Property("BannerBottom") + .HasMaxLength(9) + .HasColumnType("character varying(9)"); + + b1.Property("BannerTop") + .HasMaxLength(9) + .HasColumnType("character varying(9)"); + + b1.Property("Menu") + .HasMaxLength(9) + .HasColumnType("character varying(9)"); + + b1.HasKey("CreatorId"); + + b1.ToTable("Creators", "Content"); + + b1.WithOwner() + .HasForeignKey("CreatorId"); + }); + + b.OwnsOne("Hutopy.Web.Features.Contents.Data.SocialNetworks", "SocialNetworks", b1 => + { + b1.Property("CreatorId") + .HasColumnType("uuid"); + + b1.Property("FacebookUrl") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.Property("InstagramUrl") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.Property("LinkedInUrl") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.Property("RedditUrl") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.Property("TikTokUrl") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.Property("WebsiteUrl") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.Property("XUrl") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.Property("YoutubeUrl") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.HasKey("CreatorId"); + + b1.ToTable("Creators", "Content"); + + b1.WithOwner() + .HasForeignKey("CreatorId"); + }); + + b.OwnsOne("Hutopy.Web.Features.Contents.Data.StoredDataUrls", "StoredDataUrls", b1 => + { + b1.Property("CreatorId") + .HasColumnType("uuid"); + + b1.Property("BannerPictureUrl") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.Property("ProfilePictureUrl") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.HasKey("CreatorId"); + + b1.ToTable("Creators", "Content"); + + b1.WithOwner() + .HasForeignKey("CreatorId"); + }); + + b.Navigation("About") + .IsRequired(); + + b.Navigation("ProfileColors") + .IsRequired(); + + b.Navigation("SocialNetworks") + .IsRequired(); + + b.Navigation("StoredDataUrls") + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Web/Features/Contents/Migrations/20240802044656_Initial.cs b/src/Web/Features/Contents/Migrations/20240802044656_Initial.cs new file mode 100644 index 0000000..465ecbb --- /dev/null +++ b/src/Web/Features/Contents/Migrations/20240802044656_Initial.cs @@ -0,0 +1,78 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Hutopy.Web.Features.Contents.Migrations +{ + /// + public partial class Initial : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.EnsureSchema( + name: "Content"); + + migrationBuilder.CreateTable( + name: "Contents", + schema: "Content", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + CreatedBy = table.Column(type: "uuid", nullable: false), + CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, defaultValueSql: "CURRENT_TIMESTAMP"), + Title = table.Column(type: "text", nullable: false), + Description = table.Column(type: "text", nullable: false), + Urls = table.Column(type: "text[]", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Contents", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "Creators", + schema: "Content", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + CreatedBy = table.Column(type: "uuid", nullable: false), + CreatedAt = table.Column(type: "timestamp with time zone", nullable: false), + Name = table.Column(type: "character varying(255)", maxLength: 255, nullable: false), + About_Title = table.Column(type: "character varying(255)", maxLength: 255, nullable: true), + About_Description = table.Column(type: "character varying(255)", maxLength: 255, nullable: true), + SocialNetworks_FacebookUrl = table.Column(type: "character varying(255)", maxLength: 255, nullable: true), + SocialNetworks_InstagramUrl = table.Column(type: "character varying(255)", maxLength: 255, nullable: true), + SocialNetworks_XUrl = table.Column(type: "character varying(255)", maxLength: 255, nullable: true), + SocialNetworks_LinkedInUrl = table.Column(type: "character varying(255)", maxLength: 255, nullable: true), + SocialNetworks_TikTokUrl = table.Column(type: "character varying(255)", maxLength: 255, nullable: true), + SocialNetworks_YoutubeUrl = table.Column(type: "character varying(255)", maxLength: 255, nullable: true), + SocialNetworks_RedditUrl = table.Column(type: "character varying(255)", maxLength: 255, nullable: true), + SocialNetworks_WebsiteUrl = table.Column(type: "character varying(255)", maxLength: 255, nullable: true), + ProfileColors_BannerTop = table.Column(type: "character varying(9)", maxLength: 9, nullable: true), + ProfileColors_BannerBottom = table.Column(type: "character varying(9)", maxLength: 9, nullable: true), + ProfileColors_Accent = table.Column(type: "character varying(9)", maxLength: 9, nullable: true), + ProfileColors_Menu = table.Column(type: "character varying(9)", maxLength: 9, nullable: true), + StoredDataUrls_BannerPictureUrl = table.Column(type: "character varying(255)", maxLength: 255, nullable: true), + StoredDataUrls_ProfilePictureUrl = table.Column(type: "character varying(255)", maxLength: 255, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Creators", x => x.Id); + }); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "Contents", + schema: "Content"); + + migrationBuilder.DropTable( + name: "Creators", + schema: "Content"); + } + } +} diff --git a/src/Web/Features/Contents/Migrations/ContentDbContextModelSnapshot.cs b/src/Web/Features/Contents/Migrations/ContentDbContextModelSnapshot.cs index 0bff6dd..920ea8b 100644 --- a/src/Web/Features/Contents/Migrations/ContentDbContextModelSnapshot.cs +++ b/src/Web/Features/Contents/Migrations/ContentDbContextModelSnapshot.cs @@ -8,7 +8,7 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; #nullable disable -namespace Hutopy.Web.Contents.Migrations +namespace Hutopy.Web.Features.Contents.Migrations { [DbContext(typeof(ContentDbContext))] partial class ContentDbContextModelSnapshot : ModelSnapshot @@ -38,9 +38,11 @@ namespace Hutopy.Web.Contents.Migrations .HasColumnType("uuid"); b.Property("Description") + .IsRequired() .HasColumnType("text"); b.Property("Title") + .IsRequired() .HasColumnType("text"); b.Property("Urls") @@ -50,6 +52,159 @@ namespace Hutopy.Web.Contents.Migrations b.ToTable("Contents", "Content"); }); + + modelBuilder.Entity("Hutopy.Web.Features.Contents.Data.Creator", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("uuid"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.HasKey("Id"); + + b.ToTable("Creators", "Content"); + }); + + modelBuilder.Entity("Hutopy.Web.Features.Contents.Data.Creator", b => + { + b.OwnsOne("Hutopy.Web.Features.Contents.Data.About", "About", b1 => + { + b1.Property("CreatorId") + .HasColumnType("uuid"); + + b1.Property("Description") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.Property("Title") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.HasKey("CreatorId"); + + b1.ToTable("Creators", "Content"); + + b1.WithOwner() + .HasForeignKey("CreatorId"); + }); + + b.OwnsOne("Hutopy.Web.Features.Contents.Data.ProfileColors", "ProfileColors", b1 => + { + b1.Property("CreatorId") + .HasColumnType("uuid"); + + b1.Property("Accent") + .HasMaxLength(9) + .HasColumnType("character varying(9)"); + + b1.Property("BannerBottom") + .HasMaxLength(9) + .HasColumnType("character varying(9)"); + + b1.Property("BannerTop") + .HasMaxLength(9) + .HasColumnType("character varying(9)"); + + b1.Property("Menu") + .HasMaxLength(9) + .HasColumnType("character varying(9)"); + + b1.HasKey("CreatorId"); + + b1.ToTable("Creators", "Content"); + + b1.WithOwner() + .HasForeignKey("CreatorId"); + }); + + b.OwnsOne("Hutopy.Web.Features.Contents.Data.SocialNetworks", "SocialNetworks", b1 => + { + b1.Property("CreatorId") + .HasColumnType("uuid"); + + b1.Property("FacebookUrl") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.Property("InstagramUrl") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.Property("LinkedInUrl") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.Property("RedditUrl") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.Property("TikTokUrl") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.Property("WebsiteUrl") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.Property("XUrl") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.Property("YoutubeUrl") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.HasKey("CreatorId"); + + b1.ToTable("Creators", "Content"); + + b1.WithOwner() + .HasForeignKey("CreatorId"); + }); + + b.OwnsOne("Hutopy.Web.Features.Contents.Data.StoredDataUrls", "StoredDataUrls", b1 => + { + b1.Property("CreatorId") + .HasColumnType("uuid"); + + b1.Property("BannerPictureUrl") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.Property("ProfilePictureUrl") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.HasKey("CreatorId"); + + b1.ToTable("Creators", "Content"); + + b1.WithOwner() + .HasForeignKey("CreatorId"); + }); + + b.Navigation("About") + .IsRequired(); + + b.Navigation("ProfileColors") + .IsRequired(); + + b.Navigation("SocialNetworks") + .IsRequired(); + + b.Navigation("StoredDataUrls") + .IsRequired(); + }); #pragma warning restore 612, 618 } } diff --git a/src/Web/Features/Messages/Handlers/AddMessage.cs b/src/Web/Features/Messages/Handlers/AddMessage.cs index dc7c9e2..81c12b8 100644 --- a/src/Web/Features/Messages/Handlers/AddMessage.cs +++ b/src/Web/Features/Messages/Handlers/AddMessage.cs @@ -49,8 +49,8 @@ public class AddMessage( CreatedByName = User.GetAlias() ?? $"{User.GetFirstName()} {User.GetLastName()}", CreatedByPortraitUrl = User.GetPortraitUrl(), Value = req.Message - }; - + }; + await context.Messages.AddAsync(message, ct); await context.SaveChangesAsync(ct); diff --git a/src/Web/Features/Messages/Migrations/20240721041322_Initial.Designer.cs b/src/Web/Features/Messages/Migrations/20240721041322_Initial.Designer.cs deleted file mode 100644 index b864487..0000000 --- a/src/Web/Features/Messages/Migrations/20240721041322_Initial.Designer.cs +++ /dev/null @@ -1,67 +0,0 @@ -// -using System; -using Hutopy.Web.Features.Messages.Data; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; - -#nullable disable - -namespace Hutopy.Web.Features.Messages.Migrations -{ - [DbContext(typeof(MessagingDbContext))] - [Migration("20240721041322_Initial")] - partial class Initial - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasDefaultSchema("Messaging") - .HasAnnotation("ProductVersion", "8.0.4") - .HasAnnotation("Relational:MaxIdentifierLength", 63); - - NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); - - modelBuilder.Entity("Hutopy.Web.Features.Messages.Data.Message", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid"); - - b.Property("CreatedAt") - .ValueGeneratedOnAdd() - .HasColumnType("timestamp with time zone") - .HasDefaultValueSql("CURRENT_TIMESTAMP"); - - b.Property("CreatedBy") - .HasColumnType("uuid"); - - b.Property("CreatedByName") - .IsRequired() - .HasColumnType("text"); - - b.Property("CreatedByPortraitUrl") - .HasColumnType("text"); - - b.Property("ParentId") - .HasColumnType("uuid"); - - b.Property("SubjectId") - .HasColumnType("uuid"); - - b.Property("Value") - .IsRequired() - .HasColumnType("text"); - - b.HasKey("Id"); - - b.ToTable("Messages", "Messaging"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Web/Features/Messages/Migrations/20240721064224_ChangedAuthorDefinition.cs b/src/Web/Features/Messages/Migrations/20240721064224_ChangedAuthorDefinition.cs deleted file mode 100644 index bf04dbe..0000000 --- a/src/Web/Features/Messages/Migrations/20240721064224_ChangedAuthorDefinition.cs +++ /dev/null @@ -1,60 +0,0 @@ -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace Hutopy.Web.Features.Messages.Migrations -{ - /// - public partial class ChangedAuthorDefinition : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.AlterColumn( - name: "CreatedByPortraitUrl", - schema: "Messaging", - table: "Messages", - type: "character varying(256)", - maxLength: 256, - nullable: true, - oldClrType: typeof(string), - oldType: "text", - oldNullable: true); - - migrationBuilder.AlterColumn( - name: "CreatedByName", - schema: "Messaging", - table: "Messages", - type: "character varying(64)", - maxLength: 64, - nullable: false, - oldClrType: typeof(string), - oldType: "text"); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.AlterColumn( - name: "CreatedByPortraitUrl", - schema: "Messaging", - table: "Messages", - type: "text", - nullable: true, - oldClrType: typeof(string), - oldType: "character varying(256)", - oldMaxLength: 256, - oldNullable: true); - - migrationBuilder.AlterColumn( - name: "CreatedByName", - schema: "Messaging", - table: "Messages", - type: "text", - nullable: false, - oldClrType: typeof(string), - oldType: "character varying(64)", - oldMaxLength: 64); - } - } -} diff --git a/src/Web/Features/Messages/Migrations/20240721064224_ChangedAuthorDefinition.Designer.cs b/src/Web/Features/Messages/Migrations/20240802044717_Initial.Designer.cs similarity index 95% rename from src/Web/Features/Messages/Migrations/20240721064224_ChangedAuthorDefinition.Designer.cs rename to src/Web/Features/Messages/Migrations/20240802044717_Initial.Designer.cs index 1a92049..63d787f 100644 --- a/src/Web/Features/Messages/Migrations/20240721064224_ChangedAuthorDefinition.Designer.cs +++ b/src/Web/Features/Messages/Migrations/20240802044717_Initial.Designer.cs @@ -12,8 +12,8 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; namespace Hutopy.Web.Features.Messages.Migrations { [DbContext(typeof(MessagingDbContext))] - [Migration("20240721064224_ChangedAuthorDefinition")] - partial class ChangedAuthorDefinition + [Migration("20240802044717_Initial")] + partial class Initial { /// protected override void BuildTargetModel(ModelBuilder modelBuilder) diff --git a/src/Web/Features/Messages/Migrations/20240721041322_Initial.cs b/src/Web/Features/Messages/Migrations/20240802044717_Initial.cs similarity index 93% rename from src/Web/Features/Messages/Migrations/20240721041322_Initial.cs rename to src/Web/Features/Messages/Migrations/20240802044717_Initial.cs index 7287c65..fa9c144 100644 --- a/src/Web/Features/Messages/Migrations/20240721041322_Initial.cs +++ b/src/Web/Features/Messages/Migrations/20240802044717_Initial.cs @@ -22,8 +22,8 @@ namespace Hutopy.Web.Features.Messages.Migrations Id = table.Column(type: "uuid", nullable: false), SubjectId = table.Column(type: "uuid", nullable: false), CreatedBy = table.Column(type: "uuid", nullable: false), - CreatedByName = table.Column(type: "text", nullable: false), - CreatedByPortraitUrl = table.Column(type: "text", nullable: true), + CreatedByName = table.Column(type: "character varying(64)", maxLength: 64, nullable: false), + CreatedByPortraitUrl = table.Column(type: "character varying(256)", maxLength: 256, nullable: true), CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, defaultValueSql: "CURRENT_TIMESTAMP"), ParentId = table.Column(type: "uuid", nullable: true), Value = table.Column(type: "text", nullable: false) diff --git a/src/Web/Services/CurrentUser.cs b/src/Web/Services/CurrentUser.cs index 50a502a..29003d5 100644 --- a/src/Web/Services/CurrentUser.cs +++ b/src/Web/Services/CurrentUser.cs @@ -1,6 +1,5 @@ -using System.Security.Claims; - -using Hutopy.Application.Common.Interfaces; +using Hutopy.Application.Common.Interfaces; +using Hutopy.Web.Common; namespace Hutopy.Web.Services; @@ -8,5 +7,5 @@ public class CurrentUser( IHttpContextAccessor httpContextAccessor) : IUser { - public string? Id => httpContextAccessor.HttpContext?.User?.FindFirstValue(ClaimTypes.NameIdentifier); + public Guid? Id => httpContextAccessor.HttpContext?.User.GetUserId(); } diff --git a/src/Web/TestDataSeeder.cs b/src/Web/TestDataSeeder.cs index cb713f9..fb87568 100644 --- a/src/Web/TestDataSeeder.cs +++ b/src/Web/TestDataSeeder.cs @@ -1,6 +1,5 @@ using Hutopy.Domain.Constants; using Hutopy.Infrastructure.Identity; -using Hutopy.Infrastructure.Identity.OwnedEntities; using Hutopy.Web.Common; using Hutopy.Web.Features.Contents.Data; using Hutopy.Web.Features.Messages.Data; @@ -38,10 +37,14 @@ internal class TestDataSeeder( _users.Add(await CreateUserAsync("admin", Roles.Administrator)); _users.Add(await CreateUserAsync("userA")); _users.Add(await CreateUserAsync("userB")); - + foreach (var creator in _creators) { - _users.Add(await CreateCreatorAsync(creator)); + var creatorUser = await CreateUserAsync(creator.Name, Roles.Creator); + + creator.Id = creatorUser.Id; + + await contentContext.Creators.AddAsync(creator); var contents = GenerateContent(creator, 100); foreach (var content in contents) @@ -59,7 +62,7 @@ internal class TestDataSeeder( } } - private List GenerateContent(ApplicationUser user, int contentCount) + private List GenerateContent(Creator creator, int contentCount) { var currentDate = DateTimeOffset.UtcNow; @@ -70,10 +73,10 @@ internal class TestDataSeeder( var content = new Content { Id = GuidHelper.GenerateUuidV7(), - CreatedBy = Guid.Parse(user.Id), + CreatedBy = creator.Id, CreatedAt = currentDate, - Title = $"Title {user.UserName}-{c}", - Description = $"Description {user.UserName}-{c}" + Title = $"Title {creator.Name}-{c}", + Description = $"Description {creator.Name}-{c}" }; contentContext.Contents.Add(content); @@ -103,9 +106,9 @@ internal class TestDataSeeder( Id = GuidHelper.GenerateUuidV7(), SubjectId = content.Id, CreatedAt = currentDate, - CreatedBy = Guid.Parse(author.Id), + CreatedBy = author.Id, CreatedByName = author.Alias ?? $"{author.FirstName} {author.LastName}", - CreatedByPortraitUrl = author.StoredDataUrls.ProfilePictureUrl, + CreatedByPortraitUrl = author.PortraitUrl, Value = $"Message #{m} on {content.Title}" }; @@ -133,9 +136,9 @@ internal class TestDataSeeder( Id = GuidHelper.GenerateUuidV7(), SubjectId = content.Id, ParentId = parent.Id, - CreatedBy = Guid.Parse(author.Id), + CreatedBy = author.Id, CreatedByName = author.Alias ?? $"{author.FirstName} {author.LastName}", - CreatedByPortraitUrl = author.StoredDataUrls.ProfilePictureUrl, + CreatedByPortraitUrl = author.PortraitUrl, CreatedAt = currentDate, Value = $"Reply {r} to {parent.Value} on {content.Title}" }; @@ -167,49 +170,38 @@ internal class TestDataSeeder( return user; } - private async Task CreateCreatorAsync(ApplicationUser creator) - { - await userManager.CreateAsync(creator, DefaultPassword); - await userManager.AddToRolesAsync(creator, new[] { Roles.Creator }); - return creator; - } - - private readonly List _users = [ ]; - - private readonly static ApplicationUser Hutopy = new() + private readonly static Creator HutopyCreator = new() { - UserName = "hutopy@test", - Email = "hutopy@test", - EmailConfirmed = true, - CreatorAlias = "hutopy", - FirstName = "FirstName of a Brand/Creator", - LastName = "LastName of a Brand/Creator", - About = "Page officielle", - Description = "Site officiel pour Hutopy. Venez-nous-y retrouver avec tous vos fans!", - ProfileColors = new ProfileColors + Name = "hutopy", + About = new() { - BannerTop = "A30E79", BannerBottom = "6B0065", Accent = "23393B", Menu = "53B93B", + Title = "Page officielle", + Description = "Site officiel pour Hutopy. Venez-nous-y retrouver avec tous vos fans!", + }, + ProfileColors = new() + { + BannerTop = "#A30E79", BannerBottom = "#6B0065", Accent = "#23393B", Menu = "#53B93B", }, SocialNetworks = - new SocialNetworks + new() { XUrl = "https://twitter.com/Hutopyinc", FacebookUrl = "https://www.facebook.com/Hutopy", InstagramUrl = "https://www.instagram.com/hutopy.inc/" }, - StoredDataUrls = new StoredDataUrls + StoredDataUrls = new() { BannerPictureUrl = "/images/usersmedia/HutopyProfile/banners/banner01.png", ProfilePictureUrl = "/images/usersmedia/HutopyProfile/profilepictures/profileHutopyProfile01.png" } }; - private readonly ApplicationUser[] _creators = + private readonly Creator[] _creators = [ - Hutopy + HutopyCreator ]; } diff --git a/src/Web/Web.csproj b/src/Web/Web.csproj index ba72aba..605e476 100644 --- a/src/Web/Web.csproj +++ b/src/Web/Web.csproj @@ -32,4 +32,9 @@ + + + + + diff --git a/tests/Application.FunctionalTests/Testing.cs b/tests/Application.FunctionalTests/Testing.cs index 8c31c56..74cd4d0 100644 --- a/tests/Application.FunctionalTests/Testing.cs +++ b/tests/Application.FunctionalTests/Testing.cs @@ -14,7 +14,7 @@ public partial class Testing private static ITestDatabase _database; private static CustomWebApplicationFactory _factory = null!; private static IServiceScopeFactory _scopeFactory = null!; - private static string? _userId; + private static Guid _userId; [OneTimeSetUp] public async Task RunBeforeAnyTests() @@ -44,32 +44,36 @@ public partial class Testing await mediator.Send(request); } - public static string? GetUserId() + public static Guid GetUserId() { return _userId; } - public static async Task RunAsDefaultUserAsync() + public static async Task RunAsDefaultUserAsync() { - return await RunAsUserAsync("test@local", "Testing1234!", Array.Empty()); + return await RunAsUserAsync( + "test@local", + "Testing1234!", + []); } - public static async Task RunAsAdministratorAsync() + public static async Task RunAsAdministratorAsync() { - return await RunAsUserAsync("administrator@local", "Administrator1234!", new[] { Roles.Administrator }); + return await RunAsUserAsync( + "administrator@local", + "Administrator1234!", + [Roles.Administrator]); } - public static async Task RunAsUserAsync(string userName, string password, string[] roles) + public static async Task RunAsUserAsync(string userName, string password, string[] roles) { using var scope = _scopeFactory.CreateScope(); var userManager = scope.ServiceProvider.GetRequiredService(); - var user = new ApplicationUser { - UserName = userName, - Email = userName, - FirstName = "FirstName", - LastName = "LastName" + var user = new ApplicationUser + { + UserName = userName, Email = userName, FirstName = "FirstName", LastName = "LastName" }; var result = await userManager.CreateAsync(user, password); @@ -104,11 +108,11 @@ public partial class Testing { await _database.ResetAsync(); } - catch (Exception) + catch (Exception) { } - _userId = null; + _userId = Guid.Empty; } public static async Task FindAsync(params object[] keyValues) diff --git a/tests/Application.UnitTests/Common/Behaviours/RequestLoggerTests.cs b/tests/Application.UnitTests/Common/Behaviours/RequestLoggerTests.cs index 28b4f49..a6fc766 100644 --- a/tests/Application.UnitTests/Common/Behaviours/RequestLoggerTests.cs +++ b/tests/Application.UnitTests/Common/Behaviours/RequestLoggerTests.cs @@ -1,6 +1,4 @@ -using Hutopy.Application.Common.Behaviours; -using Hutopy.Application.Common.Interfaces; -using Microsoft.Extensions.Logging; +using Hutopy.Application.Common.Interfaces; using Moq; using NUnit.Framework; diff --git a/tests/Application.UnitTests/Common/Mappings/MappingTests.cs b/tests/Application.UnitTests/Common/Mappings/MappingTests.cs index fcd2b2a..e95ed50 100644 --- a/tests/Application.UnitTests/Common/Mappings/MappingTests.cs +++ b/tests/Application.UnitTests/Common/Mappings/MappingTests.cs @@ -2,8 +2,6 @@ using System.Runtime.CompilerServices; using AutoMapper; using Hutopy.Application.Common.Interfaces; -using Hutopy.Application.Common.Models; -using Hutopy.Domain.Entities; using NUnit.Framework; namespace Hutopy.Application.UnitTests.Common.Mappings; From 0340904847c9b778616b49af44581913b2fa9c05 Mon Sep 17 00:00:00 2001 From: Jonathan Bourdon Date: Sat, 3 Aug 2024 22:56:12 -0400 Subject: [PATCH 135/229] Hold on Subscriptions --- .../Contents/Data/ContentDbContext.cs | 17 +++++----- .../Features/Contents/Data/Subscription.cs | 9 ++++++ .../Contents/Handlers/GetCreatorByAlias.cs | 2 +- .../Contents/Handlers/GetCreatorById.cs | 2 +- .../Contents/Handlers/GetSubscriptions.cs | 31 +++++++++++++++++++ .../Handlers/SubscripbeFromCreator.cs | 21 +++++++++++++ .../Contents/Handlers/SubscripbeToCreator.cs | 30 ++++++++++++++++++ 7 files changed, 103 insertions(+), 9 deletions(-) create mode 100644 src/Web/Features/Contents/Data/Subscription.cs create mode 100644 src/Web/Features/Contents/Handlers/GetSubscriptions.cs create mode 100644 src/Web/Features/Contents/Handlers/SubscripbeFromCreator.cs create mode 100644 src/Web/Features/Contents/Handlers/SubscripbeToCreator.cs diff --git a/src/Web/Features/Contents/Data/ContentDbContext.cs b/src/Web/Features/Contents/Data/ContentDbContext.cs index 1215d7f..4dd5476 100644 --- a/src/Web/Features/Contents/Data/ContentDbContext.cs +++ b/src/Web/Features/Contents/Data/ContentDbContext.cs @@ -8,6 +8,10 @@ public class ContentDbContext( { public const string SchemaName = "Content"; + public DbSet Contents => Set(); + public DbSet Creators => Set(); + public DbSet Subscriptions => Set(); + protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.HasDefaultSchema("Content"); @@ -24,21 +28,20 @@ public class ContentDbContext( modelBuilder .Entity() - .OwnsOne(x => x.SocialNetworks); + .OwnsOne(x => x.SocialNetworks) + .ToTable(nameof(SocialNetworks)); modelBuilder .Entity() - .OwnsOne(x => x.ProfileColors); + .OwnsOne(x => x.ProfileColors) + .ToTable(nameof(ProfileColors)); modelBuilder .Entity() - .OwnsOne(x => x.StoredDataUrls); + .OwnsOne(x => x.StoredDataUrls) + .ToTable(nameof(StoredDataUrls)); } - public DbSet Contents { get; init; } = null!; - public DbSet Creators { get; init; } = null!; - - public async Task FindByCreatorAliasAsync( string creatorAlias, CancellationToken cancellationToken = default) diff --git a/src/Web/Features/Contents/Data/Subscription.cs b/src/Web/Features/Contents/Data/Subscription.cs new file mode 100644 index 0000000..d3a0cbd --- /dev/null +++ b/src/Web/Features/Contents/Data/Subscription.cs @@ -0,0 +1,9 @@ +namespace Hutopy.Web.Features.Contents.Data; + +public class Subscription +{ + public Guid Id { get; init; } + public Guid CreatorId { get; init; } + public Guid CreatedBy { get; init; } + public DateTimeOffset CreatedAt { get; init; } +} diff --git a/src/Web/Features/Contents/Handlers/GetCreatorByAlias.cs b/src/Web/Features/Contents/Handlers/GetCreatorByAlias.cs index 6204558..df15cac 100644 --- a/src/Web/Features/Contents/Handlers/GetCreatorByAlias.cs +++ b/src/Web/Features/Contents/Handlers/GetCreatorByAlias.cs @@ -28,7 +28,7 @@ public class GetCreatorByAliasHandler( public override void Configure() { Get("/api/creators/@{Name}"); - Options((o => o.WithTags("Creators"))); + Options((o => o.WithTags("Contents"))); AllowAnonymous(); } diff --git a/src/Web/Features/Contents/Handlers/GetCreatorById.cs b/src/Web/Features/Contents/Handlers/GetCreatorById.cs index a5ed6ad..0022515 100644 --- a/src/Web/Features/Contents/Handlers/GetCreatorById.cs +++ b/src/Web/Features/Contents/Handlers/GetCreatorById.cs @@ -27,7 +27,7 @@ public class GetCreatorByIdHandler( public override void Configure() { Get("/api/creators/{CreatorId}"); - Options((o => o.WithTags("Creators"))); + Options((o => o.WithTags("Contents"))); AllowAnonymous(); } diff --git a/src/Web/Features/Contents/Handlers/GetSubscriptions.cs b/src/Web/Features/Contents/Handlers/GetSubscriptions.cs new file mode 100644 index 0000000..d175102 --- /dev/null +++ b/src/Web/Features/Contents/Handlers/GetSubscriptions.cs @@ -0,0 +1,31 @@ +using FastEndpoints; +using Hutopy.Web.Common; +using Hutopy.Web.Features.Contents.Data; +using Microsoft.EntityFrameworkCore; + +namespace Hutopy.Web.Features.Contents.Handlers; + +public class GetSubscriptionsHandler( + ContentDbContext context) + : EndpointWithoutRequest +{ + public override void Configure() + { + Get("/api/subscriptions"); + Options((o => o.WithTags("Creators"))); + } + + public override async Task HandleAsync( + CancellationToken ct) + { + var userId = HttpContext.User.GetUserId(); + + await context + .Subscriptions + .Where(s => s.CreatedBy == userId) + .Include(s => s.Creator) + .ToListAsync(cancellationToken: ct); + + await SendOkAsync(ct); + } +} diff --git a/src/Web/Features/Contents/Handlers/SubscripbeFromCreator.cs b/src/Web/Features/Contents/Handlers/SubscripbeFromCreator.cs new file mode 100644 index 0000000..5c8787c --- /dev/null +++ b/src/Web/Features/Contents/Handlers/SubscripbeFromCreator.cs @@ -0,0 +1,21 @@ +using FastEndpoints; + +namespace Hutopy.Web.Features.Contents.Handlers; + +public record UnsubscribeFromCreatorRequest( + Guid CreatorId); + +public class UnsubscribeFromCreatorHandler + : Endpoint +{ public override void Configure() + { + Post(""); + } + + public override async Task HandleAsync( + UnsubscribeFromCreatorRequest req, + CancellationToken ct) + { + return base.HandleAsync(req, ct); + } +} diff --git a/src/Web/Features/Contents/Handlers/SubscripbeToCreator.cs b/src/Web/Features/Contents/Handlers/SubscripbeToCreator.cs new file mode 100644 index 0000000..7b4ce45 --- /dev/null +++ b/src/Web/Features/Contents/Handlers/SubscripbeToCreator.cs @@ -0,0 +1,30 @@ +using FastEndpoints; +using Hutopy.Web.Common; +using Hutopy.Web.Features.Contents.Data; + +namespace Hutopy.Web.Features.Contents.Handlers; + +public record SubscribeToCreatorRequest( + Guid CreatorId); + +public sealed class SubscribeToCreatorHandler( + ContentDbContext context) + : Endpoint +{ + public override void Configure() + { + Post("/api/creators/{CreatorId}/subscribe"); + Options((o => o.WithTags("Creators"))); + } + + public override async Task HandleAsync( + UnsubscribeFromCreatorRequest req, + CancellationToken ct) + { + await context.Subscriptions.AddAsync( + new() { CreatedBy = HttpContext.User.GetUserId(), CreatorId = req.CreatorId }, + ct); + + await SendOkAsync(ct); + } +} From e560dfccc1bc544c8080ab1606944d6212f070f4 Mon Sep 17 00:00:00 2001 From: Jonathan Bourdon Date: Sat, 3 Aug 2024 23:23:37 -0400 Subject: [PATCH 136/229] Add a Creator property on Content --- src/Web/Features/Contents/Data/Content.cs | 9 +++++--- .../Contents/Data/ContentDbContext.cs | 21 ++++++------------- .../Features/Contents/Handlers/GetContent.cs | 2 +- ...tentsByUser.cs => GetContentsByCreator.cs} | 10 ++++----- 4 files changed, 18 insertions(+), 24 deletions(-) rename src/Web/Features/Contents/Handlers/{GetContentsByUser.cs => GetContentsByCreator.cs} (80%) diff --git a/src/Web/Features/Contents/Data/Content.cs b/src/Web/Features/Contents/Data/Content.cs index 08660bb..dff459a 100644 --- a/src/Web/Features/Contents/Data/Content.cs +++ b/src/Web/Features/Contents/Data/Content.cs @@ -1,12 +1,15 @@ -namespace Hutopy.Web.Features.Contents.Data; +using System.ComponentModel.DataAnnotations; + +namespace Hutopy.Web.Features.Contents.Data; public class Content { public Guid Id { get; init; } public Guid CreatedBy { get; init; } + public Creator? Creator { get; set; } public DateTimeOffset CreatedAt { get; init; } - public string Title { get; set; } - public string Description { get; set; } + [MaxLength(128)] public required string Title { get; set; } + [MaxLength(2048)] public required string Description { get; set; } public string[]? Urls { get; init; } } diff --git a/src/Web/Features/Contents/Data/ContentDbContext.cs b/src/Web/Features/Contents/Data/ContentDbContext.cs index 4dd5476..e01321b 100644 --- a/src/Web/Features/Contents/Data/ContentDbContext.cs +++ b/src/Web/Features/Contents/Data/ContentDbContext.cs @@ -21,6 +21,12 @@ public class ContentDbContext( .Property(c => c.CreatedAt) .ValueGeneratedOnAdd() .HasDefaultValueSql("CURRENT_TIMESTAMP"); + + modelBuilder + .Entity() + .HasOne(c => c.Creator) + .WithMany() + .HasForeignKey(c => c.CreatedBy); modelBuilder .Entity() @@ -41,19 +47,4 @@ public class ContentDbContext( .OwnsOne(x => x.StoredDataUrls) .ToTable(nameof(StoredDataUrls)); } - - public async Task FindByCreatorAliasAsync( - string creatorAlias, - CancellationToken cancellationToken = default) - { - ArgumentException.ThrowIfNullOrEmpty(creatorAlias); - - var user = await Creators.SingleOrDefaultAsync(creator => - EF.Functions.Like( - creatorAlias, - creator.Name), - cancellationToken: cancellationToken); - - return user; - } } diff --git a/src/Web/Features/Contents/Handlers/GetContent.cs b/src/Web/Features/Contents/Handlers/GetContent.cs index 95dd16a..7e79021 100644 --- a/src/Web/Features/Contents/Handlers/GetContent.cs +++ b/src/Web/Features/Contents/Handlers/GetContent.cs @@ -26,7 +26,7 @@ public class GetContent( { var content = await context .Contents - .FirstOrDefaultAsync( + .SingleOrDefaultAsync( c => c.Id == req.ContentId, cancellationToken: ct); diff --git a/src/Web/Features/Contents/Handlers/GetContentsByUser.cs b/src/Web/Features/Contents/Handlers/GetContentsByCreator.cs similarity index 80% rename from src/Web/Features/Contents/Handlers/GetContentsByUser.cs rename to src/Web/Features/Contents/Handlers/GetContentsByCreator.cs index f17214e..3ec2e83 100644 --- a/src/Web/Features/Contents/Handlers/GetContentsByUser.cs +++ b/src/Web/Features/Contents/Handlers/GetContentsByCreator.cs @@ -4,26 +4,26 @@ using Microsoft.EntityFrameworkCore; namespace Hutopy.Web.Features.Contents.Handlers; -public sealed class GetContentsByUserRequest +public sealed class GetContentsByCreatorRequest { public Guid UserId { get; set; } [BindFrom("page_size")] public int PageSize { get; set; } = 10; [BindFrom("last_id")] public Guid? LastId { get; set; } } -public class GetContentsByUser( +public class GetContentsByCreatorHandler( ContentDbContext context) - : Endpoint> + : Endpoint> { public override void Configure() { - Get("/api/contents/user/{UserId:guid}"); + Get("/api/contents/creator/{UserId:guid}"); Options(o => o.WithTags("Contents")); AllowAnonymous(); } public override async Task HandleAsync( - GetContentsByUserRequest req, + GetContentsByCreatorRequest req, CancellationToken ct) { var query = context From 19ae599bd04cddb3cc21fe237e3f39a062eeb662 Mon Sep 17 00:00:00 2001 From: Jonathan Bourdon Date: Sun, 4 Aug 2024 03:24:50 -0400 Subject: [PATCH 137/229] Improves update-databases.sh --- update-databases.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/update-databases.sh b/update-databases.sh index 9f90803..2203b11 100644 --- a/update-databases.sh +++ b/update-databases.sh @@ -1,5 +1,7 @@ #!/bin/bash +dotnet build + dotnet ef database update \ --project src/Infrastructure/Infrastructure.csproj \ --startup-project src/Web/Web.csproj \ @@ -9,14 +11,12 @@ dotnet ef database update \ dotnet ef database update \ --project src/Web/Web.csproj \ - --startup-project src/Web/Web.csproj \ --context Hutopy.Web.Features.Messages.Data.MessagingDbContext \ --configuration Debug \ --no-build dotnet ef database update \ --project src/Web/Web.csproj \ - --startup-project src/Web/Web.csproj \ --context Hutopy.Web.Features.Contents.Data.ContentDbContext \ --configuration Debug \ --no-build From 303619cc188bbde14688bc8355782eca947642cc Mon Sep 17 00:00:00 2001 From: Jonathan Bourdon Date: Sun, 4 Aug 2024 03:25:01 -0400 Subject: [PATCH 138/229] Updates the web.http --- src/Web/Web.http | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/Web/Web.http b/src/Web/Web.http index 5dfb87a..bc91375 100644 --- a/src/Web/Web.http +++ b/src/Web/Web.http @@ -1,6 +1,6 @@ # For more info on HTTP files go to https://aka.ms/vs/httpfile -@Email=administrator@localhost -@Password=Administrator1! +@Email=userA@test +@Password=Test123# @auth_token= # POST Users Register @@ -37,19 +37,26 @@ Content-Type: application/json } ### - # GET GetMyUser GET {{base_url}}/api/GetMyUser Authorization: Bearer {{auth_token}} ### - # GET /api/posts GET {{base_url}}/api/messages/00000001-0000-0000-0000-000000000001 ### +# GET /api/subscriptions +GET {{base_url}}/api/subscriptions +Authorization: Bearer {{auth_token}} +### +# POST /api/creators/{CreatorId}/subscribe +POST {{base_url}}/api/creators/74d60ff6-bdd3-4347-acd8-08dcb43b3ea4/subscribe +Authorization: Bearer {{auth_token}} + +### # GET /api/posts/by-user GET {{base_url}}/api/messages/by-user/325C69E8-DBC4-4CEE-B56E-C3C90AEE7963 Authorization: Bearer {{auth_token}} \ No newline at end of file From 68ef947e26cd250835ad0559a11cf2b596924053 Mon Sep 17 00:00:00 2001 From: Jonathan Bourdon Date: Sun, 4 Aug 2024 03:27:21 -0400 Subject: [PATCH 139/229] Adds subscriptions --- .../Contents/Data/ContentDbContext.cs | 12 +- .../Features/Contents/Data/Subscription.cs | 4 +- .../Contents/Handlers/GetSubscriptions.cs | 12 +- .../Handlers/Models/SubscriptionModel.cs | 6 + .../Contents/Handlers/SubscribeToCreator.cs | 54 +++++ .../Handlers/SubscripbeFromCreator.cs | 21 -- .../Contents/Handlers/SubscripbeToCreator.cs | 30 --- .../Handlers/UnsubscribeFromCreator.cs | 42 ++++ .../Migrations/20240802044656_Initial.cs | 78 ------- ....cs => 20240804071117_Initial.Designer.cs} | 56 ++++- .../Migrations/20240804071117_Initial.cs | 191 ++++++++++++++++++ .../ContentDbContextModelSnapshot.cs | 54 ++++- 12 files changed, 413 insertions(+), 147 deletions(-) create mode 100644 src/Web/Features/Contents/Handlers/Models/SubscriptionModel.cs create mode 100644 src/Web/Features/Contents/Handlers/SubscribeToCreator.cs delete mode 100644 src/Web/Features/Contents/Handlers/SubscripbeFromCreator.cs delete mode 100644 src/Web/Features/Contents/Handlers/SubscripbeToCreator.cs create mode 100644 src/Web/Features/Contents/Handlers/UnsubscribeFromCreator.cs delete mode 100644 src/Web/Features/Contents/Migrations/20240802044656_Initial.cs rename src/Web/Features/Contents/Migrations/{20240802044656_Initial.Designer.cs => 20240804071117_Initial.Designer.cs} (79%) create mode 100644 src/Web/Features/Contents/Migrations/20240804071117_Initial.cs diff --git a/src/Web/Features/Contents/Data/ContentDbContext.cs b/src/Web/Features/Contents/Data/ContentDbContext.cs index e01321b..29860e4 100644 --- a/src/Web/Features/Contents/Data/ContentDbContext.cs +++ b/src/Web/Features/Contents/Data/ContentDbContext.cs @@ -21,13 +21,23 @@ public class ContentDbContext( .Property(c => c.CreatedAt) .ValueGeneratedOnAdd() .HasDefaultValueSql("CURRENT_TIMESTAMP"); - + modelBuilder .Entity() .HasOne(c => c.Creator) .WithMany() .HasForeignKey(c => c.CreatedBy); + modelBuilder + .Entity() + .HasOne(c => c.Creator) + .WithMany() + .HasForeignKey(c => c.CreatorId); + + modelBuilder + .Entity() + .HasKey(s => new { s.CreatedBy, s.CreatorId }); + modelBuilder .Entity() .OwnsOne(x => x.About); diff --git a/src/Web/Features/Contents/Data/Subscription.cs b/src/Web/Features/Contents/Data/Subscription.cs index d3a0cbd..4875fd9 100644 --- a/src/Web/Features/Contents/Data/Subscription.cs +++ b/src/Web/Features/Contents/Data/Subscription.cs @@ -2,8 +2,8 @@ public class Subscription { - public Guid Id { get; init; } - public Guid CreatorId { get; init; } public Guid CreatedBy { get; init; } public DateTimeOffset CreatedAt { get; init; } + public Guid CreatorId { get; init; } + public Creator? Creator { get; set; } } diff --git a/src/Web/Features/Contents/Handlers/GetSubscriptions.cs b/src/Web/Features/Contents/Handlers/GetSubscriptions.cs index d175102..1f5690c 100644 --- a/src/Web/Features/Contents/Handlers/GetSubscriptions.cs +++ b/src/Web/Features/Contents/Handlers/GetSubscriptions.cs @@ -1,13 +1,14 @@ using FastEndpoints; using Hutopy.Web.Common; using Hutopy.Web.Features.Contents.Data; +using Hutopy.Web.Features.Contents.Handlers.Models; using Microsoft.EntityFrameworkCore; namespace Hutopy.Web.Features.Contents.Handlers; public class GetSubscriptionsHandler( ContentDbContext context) - : EndpointWithoutRequest + : EndpointWithoutRequest> { public override void Configure() { @@ -20,12 +21,15 @@ public class GetSubscriptionsHandler( { var userId = HttpContext.User.GetUserId(); - await context + var subscriptions = await context .Subscriptions .Where(s => s.CreatedBy == userId) - .Include(s => s.Creator) + .Select(s => new SubscriptionModel( + s.CreatorId, + s.Creator!.Name, + s.Creator.StoredDataUrls.ProfilePictureUrl)) .ToListAsync(cancellationToken: ct); - await SendOkAsync(ct); + await SendOkAsync(subscriptions, ct); } } diff --git a/src/Web/Features/Contents/Handlers/Models/SubscriptionModel.cs b/src/Web/Features/Contents/Handlers/Models/SubscriptionModel.cs new file mode 100644 index 0000000..7c3df21 --- /dev/null +++ b/src/Web/Features/Contents/Handlers/Models/SubscriptionModel.cs @@ -0,0 +1,6 @@ +namespace Hutopy.Web.Features.Contents.Handlers.Models; + +public record SubscriptionModel( + Guid CreatorId, + string CreatorName, + string? CreatorPortraitUrl); diff --git a/src/Web/Features/Contents/Handlers/SubscribeToCreator.cs b/src/Web/Features/Contents/Handlers/SubscribeToCreator.cs new file mode 100644 index 0000000..eb20946 --- /dev/null +++ b/src/Web/Features/Contents/Handlers/SubscribeToCreator.cs @@ -0,0 +1,54 @@ +using FastEndpoints; +using Hutopy.Web.Common; +using Hutopy.Web.Features.Contents.Data; +using Hutopy.Web.Features.Contents.Handlers.Models; +using Microsoft.EntityFrameworkCore; + +namespace Hutopy.Web.Features.Contents.Handlers; + +public sealed class SubscribeToCreatorRequest +{ + public Guid CreatorId { get; set; } +} + +public sealed class SubscribeToCreatorHandler( + ContentDbContext context) + : Endpoint +{ + public override void Configure() + { + Post("/api/creators/{CreatorId}/subscribe"); + Options((o => o.WithTags("Creators"))); + Description(x => x.Accepts("*/*")); + } + + public override async Task HandleAsync( + SubscribeToCreatorRequest req, + CancellationToken ct) + { + await context.Subscriptions.AddAsync( + new() { CreatedBy = HttpContext.User.GetUserId(), CreatorId = req.CreatorId }, + ct); + + await context.SaveChangesAsync(ct); + + var creator = await context + .Creators + .Where(c => c.Id == req.CreatorId) + .Select(c => new SubscriptionModel( + req.CreatorId, + c.Name, + c.StoredDataUrls.ProfilePictureUrl + )) + .FirstOrDefaultAsync(cancellationToken: ct); + + if (creator is null) + { + await SendNotFoundAsync(ct); + } + else + { + await SendOkAsync(creator, ct); + } + } +} diff --git a/src/Web/Features/Contents/Handlers/SubscripbeFromCreator.cs b/src/Web/Features/Contents/Handlers/SubscripbeFromCreator.cs deleted file mode 100644 index 5c8787c..0000000 --- a/src/Web/Features/Contents/Handlers/SubscripbeFromCreator.cs +++ /dev/null @@ -1,21 +0,0 @@ -using FastEndpoints; - -namespace Hutopy.Web.Features.Contents.Handlers; - -public record UnsubscribeFromCreatorRequest( - Guid CreatorId); - -public class UnsubscribeFromCreatorHandler - : Endpoint -{ public override void Configure() - { - Post(""); - } - - public override async Task HandleAsync( - UnsubscribeFromCreatorRequest req, - CancellationToken ct) - { - return base.HandleAsync(req, ct); - } -} diff --git a/src/Web/Features/Contents/Handlers/SubscripbeToCreator.cs b/src/Web/Features/Contents/Handlers/SubscripbeToCreator.cs deleted file mode 100644 index 7b4ce45..0000000 --- a/src/Web/Features/Contents/Handlers/SubscripbeToCreator.cs +++ /dev/null @@ -1,30 +0,0 @@ -using FastEndpoints; -using Hutopy.Web.Common; -using Hutopy.Web.Features.Contents.Data; - -namespace Hutopy.Web.Features.Contents.Handlers; - -public record SubscribeToCreatorRequest( - Guid CreatorId); - -public sealed class SubscribeToCreatorHandler( - ContentDbContext context) - : Endpoint -{ - public override void Configure() - { - Post("/api/creators/{CreatorId}/subscribe"); - Options((o => o.WithTags("Creators"))); - } - - public override async Task HandleAsync( - UnsubscribeFromCreatorRequest req, - CancellationToken ct) - { - await context.Subscriptions.AddAsync( - new() { CreatedBy = HttpContext.User.GetUserId(), CreatorId = req.CreatorId }, - ct); - - await SendOkAsync(ct); - } -} diff --git a/src/Web/Features/Contents/Handlers/UnsubscribeFromCreator.cs b/src/Web/Features/Contents/Handlers/UnsubscribeFromCreator.cs new file mode 100644 index 0000000..87c4855 --- /dev/null +++ b/src/Web/Features/Contents/Handlers/UnsubscribeFromCreator.cs @@ -0,0 +1,42 @@ +using FastEndpoints; +using Hutopy.Web.Common; +using Hutopy.Web.Features.Contents.Data; + +namespace Hutopy.Web.Features.Contents.Handlers; + +public sealed class UnsubscribeFromCreatorRequest +{ + public Guid CreatorId { get; set; } +} + +public class UnsubscribeFromCreatorHandler( + ContentDbContext context) + : Endpoint +{ + public override void Configure() + { + Post("/api/creators/{CreatorId}/unsubscribe"); + Options((o => o.WithTags("Creators"))); + Description(x => x.Accepts("*/*")); + } + + public override async Task HandleAsync( + UnsubscribeFromCreatorRequest req, + CancellationToken ct) + { + var subscription = new Subscription { CreatorId = req.CreatorId, CreatedBy = HttpContext.User.GetUserId() }; + + context.Subscriptions.Attach(subscription); + context.Subscriptions.Remove(subscription); + + try + { + await context.SaveChangesAsync(ct); + await SendOkAsync(ct); + } + catch (Exception) + { + await SendNotFoundAsync(ct); + } + } +} diff --git a/src/Web/Features/Contents/Migrations/20240802044656_Initial.cs b/src/Web/Features/Contents/Migrations/20240802044656_Initial.cs deleted file mode 100644 index 465ecbb..0000000 --- a/src/Web/Features/Contents/Migrations/20240802044656_Initial.cs +++ /dev/null @@ -1,78 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace Hutopy.Web.Features.Contents.Migrations -{ - /// - public partial class Initial : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.EnsureSchema( - name: "Content"); - - migrationBuilder.CreateTable( - name: "Contents", - schema: "Content", - columns: table => new - { - Id = table.Column(type: "uuid", nullable: false), - CreatedBy = table.Column(type: "uuid", nullable: false), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, defaultValueSql: "CURRENT_TIMESTAMP"), - Title = table.Column(type: "text", nullable: false), - Description = table.Column(type: "text", nullable: false), - Urls = table.Column(type: "text[]", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_Contents", x => x.Id); - }); - - migrationBuilder.CreateTable( - name: "Creators", - schema: "Content", - columns: table => new - { - Id = table.Column(type: "uuid", nullable: false), - CreatedBy = table.Column(type: "uuid", nullable: false), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false), - Name = table.Column(type: "character varying(255)", maxLength: 255, nullable: false), - About_Title = table.Column(type: "character varying(255)", maxLength: 255, nullable: true), - About_Description = table.Column(type: "character varying(255)", maxLength: 255, nullable: true), - SocialNetworks_FacebookUrl = table.Column(type: "character varying(255)", maxLength: 255, nullable: true), - SocialNetworks_InstagramUrl = table.Column(type: "character varying(255)", maxLength: 255, nullable: true), - SocialNetworks_XUrl = table.Column(type: "character varying(255)", maxLength: 255, nullable: true), - SocialNetworks_LinkedInUrl = table.Column(type: "character varying(255)", maxLength: 255, nullable: true), - SocialNetworks_TikTokUrl = table.Column(type: "character varying(255)", maxLength: 255, nullable: true), - SocialNetworks_YoutubeUrl = table.Column(type: "character varying(255)", maxLength: 255, nullable: true), - SocialNetworks_RedditUrl = table.Column(type: "character varying(255)", maxLength: 255, nullable: true), - SocialNetworks_WebsiteUrl = table.Column(type: "character varying(255)", maxLength: 255, nullable: true), - ProfileColors_BannerTop = table.Column(type: "character varying(9)", maxLength: 9, nullable: true), - ProfileColors_BannerBottom = table.Column(type: "character varying(9)", maxLength: 9, nullable: true), - ProfileColors_Accent = table.Column(type: "character varying(9)", maxLength: 9, nullable: true), - ProfileColors_Menu = table.Column(type: "character varying(9)", maxLength: 9, nullable: true), - StoredDataUrls_BannerPictureUrl = table.Column(type: "character varying(255)", maxLength: 255, nullable: true), - StoredDataUrls_ProfilePictureUrl = table.Column(type: "character varying(255)", maxLength: 255, nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_Creators", x => x.Id); - }); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "Contents", - schema: "Content"); - - migrationBuilder.DropTable( - name: "Creators", - schema: "Content"); - } - } -} diff --git a/src/Web/Features/Contents/Migrations/20240802044656_Initial.Designer.cs b/src/Web/Features/Contents/Migrations/20240804071117_Initial.Designer.cs similarity index 79% rename from src/Web/Features/Contents/Migrations/20240802044656_Initial.Designer.cs rename to src/Web/Features/Contents/Migrations/20240804071117_Initial.Designer.cs index f14eda2..2239cb6 100644 --- a/src/Web/Features/Contents/Migrations/20240802044656_Initial.Designer.cs +++ b/src/Web/Features/Contents/Migrations/20240804071117_Initial.Designer.cs @@ -12,7 +12,7 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; namespace Hutopy.Web.Features.Contents.Migrations { [DbContext(typeof(ContentDbContext))] - [Migration("20240802044656_Initial")] + [Migration("20240804071117_Initial")] partial class Initial { /// @@ -42,17 +42,21 @@ namespace Hutopy.Web.Features.Contents.Migrations b.Property("Description") .IsRequired() - .HasColumnType("text"); + .HasMaxLength(2048) + .HasColumnType("character varying(2048)"); b.Property("Title") .IsRequired() - .HasColumnType("text"); + .HasMaxLength(128) + .HasColumnType("character varying(128)"); b.Property("Urls") .HasColumnType("text[]"); b.HasKey("Id"); + b.HasIndex("CreatedBy"); + b.ToTable("Contents", "Content"); }); @@ -78,6 +82,35 @@ namespace Hutopy.Web.Features.Contents.Migrations b.ToTable("Creators", "Content"); }); + modelBuilder.Entity("Hutopy.Web.Features.Contents.Data.Subscription", b => + { + b.Property("CreatedBy") + .HasColumnType("uuid"); + + b.Property("CreatorId") + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("CreatedBy", "CreatorId"); + + b.HasIndex("CreatorId"); + + b.ToTable("Subscriptions", "Content"); + }); + + modelBuilder.Entity("Hutopy.Web.Features.Contents.Data.Content", b => + { + b.HasOne("Hutopy.Web.Features.Contents.Data.Creator", "Creator") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Creator"); + }); + modelBuilder.Entity("Hutopy.Web.Features.Contents.Data.Creator", b => { b.OwnsOne("Hutopy.Web.Features.Contents.Data.About", "About", b1 => @@ -124,7 +157,7 @@ namespace Hutopy.Web.Features.Contents.Migrations b1.HasKey("CreatorId"); - b1.ToTable("Creators", "Content"); + b1.ToTable("ProfileColors", "Content"); b1.WithOwner() .HasForeignKey("CreatorId"); @@ -169,7 +202,7 @@ namespace Hutopy.Web.Features.Contents.Migrations b1.HasKey("CreatorId"); - b1.ToTable("Creators", "Content"); + b1.ToTable("SocialNetworks", "Content"); b1.WithOwner() .HasForeignKey("CreatorId"); @@ -190,7 +223,7 @@ namespace Hutopy.Web.Features.Contents.Migrations b1.HasKey("CreatorId"); - b1.ToTable("Creators", "Content"); + b1.ToTable("StoredDataUrls", "Content"); b1.WithOwner() .HasForeignKey("CreatorId"); @@ -208,6 +241,17 @@ namespace Hutopy.Web.Features.Contents.Migrations b.Navigation("StoredDataUrls") .IsRequired(); }); + + modelBuilder.Entity("Hutopy.Web.Features.Contents.Data.Subscription", b => + { + b.HasOne("Hutopy.Web.Features.Contents.Data.Creator", "Creator") + .WithMany() + .HasForeignKey("CreatorId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Creator"); + }); #pragma warning restore 612, 618 } } diff --git a/src/Web/Features/Contents/Migrations/20240804071117_Initial.cs b/src/Web/Features/Contents/Migrations/20240804071117_Initial.cs new file mode 100644 index 0000000..f4db5f5 --- /dev/null +++ b/src/Web/Features/Contents/Migrations/20240804071117_Initial.cs @@ -0,0 +1,191 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Hutopy.Web.Features.Contents.Migrations +{ + /// + public partial class Initial : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.EnsureSchema( + name: "Content"); + + migrationBuilder.CreateTable( + name: "Creators", + schema: "Content", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + CreatedBy = table.Column(type: "uuid", nullable: false), + CreatedAt = table.Column(type: "timestamp with time zone", nullable: false), + Name = table.Column(type: "character varying(255)", maxLength: 255, nullable: false), + About_Title = table.Column(type: "character varying(255)", maxLength: 255, nullable: true), + About_Description = table.Column(type: "character varying(255)", maxLength: 255, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Creators", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "Contents", + schema: "Content", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + CreatedBy = table.Column(type: "uuid", nullable: false), + CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, defaultValueSql: "CURRENT_TIMESTAMP"), + Title = table.Column(type: "character varying(128)", maxLength: 128, nullable: false), + Description = table.Column(type: "character varying(2048)", maxLength: 2048, nullable: false), + Urls = table.Column(type: "text[]", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Contents", x => x.Id); + table.ForeignKey( + name: "FK_Contents_Creators_CreatedBy", + column: x => x.CreatedBy, + principalSchema: "Content", + principalTable: "Creators", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "ProfileColors", + schema: "Content", + columns: table => new + { + CreatorId = table.Column(type: "uuid", nullable: false), + BannerTop = table.Column(type: "character varying(9)", maxLength: 9, nullable: true), + BannerBottom = table.Column(type: "character varying(9)", maxLength: 9, nullable: true), + Accent = table.Column(type: "character varying(9)", maxLength: 9, nullable: true), + Menu = table.Column(type: "character varying(9)", maxLength: 9, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_ProfileColors", x => x.CreatorId); + table.ForeignKey( + name: "FK_ProfileColors_Creators_CreatorId", + column: x => x.CreatorId, + principalSchema: "Content", + principalTable: "Creators", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "SocialNetworks", + schema: "Content", + columns: table => new + { + CreatorId = table.Column(type: "uuid", nullable: false), + FacebookUrl = table.Column(type: "character varying(255)", maxLength: 255, nullable: true), + InstagramUrl = table.Column(type: "character varying(255)", maxLength: 255, nullable: true), + XUrl = table.Column(type: "character varying(255)", maxLength: 255, nullable: true), + LinkedInUrl = table.Column(type: "character varying(255)", maxLength: 255, nullable: true), + TikTokUrl = table.Column(type: "character varying(255)", maxLength: 255, nullable: true), + YoutubeUrl = table.Column(type: "character varying(255)", maxLength: 255, nullable: true), + RedditUrl = table.Column(type: "character varying(255)", maxLength: 255, nullable: true), + WebsiteUrl = table.Column(type: "character varying(255)", maxLength: 255, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_SocialNetworks", x => x.CreatorId); + table.ForeignKey( + name: "FK_SocialNetworks_Creators_CreatorId", + column: x => x.CreatorId, + principalSchema: "Content", + principalTable: "Creators", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "StoredDataUrls", + schema: "Content", + columns: table => new + { + CreatorId = table.Column(type: "uuid", nullable: false), + BannerPictureUrl = table.Column(type: "character varying(255)", maxLength: 255, nullable: true), + ProfilePictureUrl = table.Column(type: "character varying(255)", maxLength: 255, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_StoredDataUrls", x => x.CreatorId); + table.ForeignKey( + name: "FK_StoredDataUrls_Creators_CreatorId", + column: x => x.CreatorId, + principalSchema: "Content", + principalTable: "Creators", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "Subscriptions", + schema: "Content", + columns: table => new + { + CreatedBy = table.Column(type: "uuid", nullable: false), + CreatorId = table.Column(type: "uuid", nullable: false), + CreatedAt = table.Column(type: "timestamp with time zone", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Subscriptions", x => new { x.CreatedBy, x.CreatorId }); + table.ForeignKey( + name: "FK_Subscriptions_Creators_CreatorId", + column: x => x.CreatorId, + principalSchema: "Content", + principalTable: "Creators", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "IX_Contents_CreatedBy", + schema: "Content", + table: "Contents", + column: "CreatedBy"); + + migrationBuilder.CreateIndex( + name: "IX_Subscriptions_CreatorId", + schema: "Content", + table: "Subscriptions", + column: "CreatorId"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "Contents", + schema: "Content"); + + migrationBuilder.DropTable( + name: "ProfileColors", + schema: "Content"); + + migrationBuilder.DropTable( + name: "SocialNetworks", + schema: "Content"); + + migrationBuilder.DropTable( + name: "StoredDataUrls", + schema: "Content"); + + migrationBuilder.DropTable( + name: "Subscriptions", + schema: "Content"); + + migrationBuilder.DropTable( + name: "Creators", + schema: "Content"); + } + } +} diff --git a/src/Web/Features/Contents/Migrations/ContentDbContextModelSnapshot.cs b/src/Web/Features/Contents/Migrations/ContentDbContextModelSnapshot.cs index 920ea8b..cd39fe1 100644 --- a/src/Web/Features/Contents/Migrations/ContentDbContextModelSnapshot.cs +++ b/src/Web/Features/Contents/Migrations/ContentDbContextModelSnapshot.cs @@ -39,17 +39,21 @@ namespace Hutopy.Web.Features.Contents.Migrations b.Property("Description") .IsRequired() - .HasColumnType("text"); + .HasMaxLength(2048) + .HasColumnType("character varying(2048)"); b.Property("Title") .IsRequired() - .HasColumnType("text"); + .HasMaxLength(128) + .HasColumnType("character varying(128)"); b.Property("Urls") .HasColumnType("text[]"); b.HasKey("Id"); + b.HasIndex("CreatedBy"); + b.ToTable("Contents", "Content"); }); @@ -75,6 +79,35 @@ namespace Hutopy.Web.Features.Contents.Migrations b.ToTable("Creators", "Content"); }); + modelBuilder.Entity("Hutopy.Web.Features.Contents.Data.Subscription", b => + { + b.Property("CreatedBy") + .HasColumnType("uuid"); + + b.Property("CreatorId") + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("CreatedBy", "CreatorId"); + + b.HasIndex("CreatorId"); + + b.ToTable("Subscriptions", "Content"); + }); + + modelBuilder.Entity("Hutopy.Web.Features.Contents.Data.Content", b => + { + b.HasOne("Hutopy.Web.Features.Contents.Data.Creator", "Creator") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Creator"); + }); + modelBuilder.Entity("Hutopy.Web.Features.Contents.Data.Creator", b => { b.OwnsOne("Hutopy.Web.Features.Contents.Data.About", "About", b1 => @@ -121,7 +154,7 @@ namespace Hutopy.Web.Features.Contents.Migrations b1.HasKey("CreatorId"); - b1.ToTable("Creators", "Content"); + b1.ToTable("ProfileColors", "Content"); b1.WithOwner() .HasForeignKey("CreatorId"); @@ -166,7 +199,7 @@ namespace Hutopy.Web.Features.Contents.Migrations b1.HasKey("CreatorId"); - b1.ToTable("Creators", "Content"); + b1.ToTable("SocialNetworks", "Content"); b1.WithOwner() .HasForeignKey("CreatorId"); @@ -187,7 +220,7 @@ namespace Hutopy.Web.Features.Contents.Migrations b1.HasKey("CreatorId"); - b1.ToTable("Creators", "Content"); + b1.ToTable("StoredDataUrls", "Content"); b1.WithOwner() .HasForeignKey("CreatorId"); @@ -205,6 +238,17 @@ namespace Hutopy.Web.Features.Contents.Migrations b.Navigation("StoredDataUrls") .IsRequired(); }); + + modelBuilder.Entity("Hutopy.Web.Features.Contents.Data.Subscription", b => + { + b.HasOne("Hutopy.Web.Features.Contents.Data.Creator", "Creator") + .WithMany() + .HasForeignKey("CreatorId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Creator"); + }); #pragma warning restore 612, 618 } } From 2276128c4e028f52abc074717b336bd7938c09c9 Mon Sep 17 00:00:00 2001 From: Jonathan Bourdon Date: Sun, 4 Aug 2024 04:05:36 -0400 Subject: [PATCH 140/229] Adds arps as creator --- src/Web/Features/Contents/Data/Creator.cs | 2 +- .../Contents/Handlers/GetCreatorByAlias.cs | 6 ++- src/Web/TestDataSeeder.cs | 53 +++++++++++++++---- 3 files changed, 49 insertions(+), 12 deletions(-) diff --git a/src/Web/Features/Contents/Data/Creator.cs b/src/Web/Features/Contents/Data/Creator.cs index 85a835b..67803d0 100644 --- a/src/Web/Features/Contents/Data/Creator.cs +++ b/src/Web/Features/Contents/Data/Creator.cs @@ -5,7 +5,7 @@ namespace Hutopy.Web.Features.Contents.Data; public class Creator { public Guid Id { get; set; } - public Guid CreatedBy { get; init; } + public Guid CreatedBy { get; set; } public DateTimeOffset CreatedAt { get; init; } [MaxLength(255)] public string Name { get; set; } = null!; diff --git a/src/Web/Features/Contents/Handlers/GetCreatorByAlias.cs b/src/Web/Features/Contents/Handlers/GetCreatorByAlias.cs index df15cac..be4359a 100644 --- a/src/Web/Features/Contents/Handlers/GetCreatorByAlias.cs +++ b/src/Web/Features/Contents/Handlers/GetCreatorByAlias.cs @@ -36,12 +36,16 @@ public class GetCreatorByAliasHandler( GetCreatorByAliasRequest req, CancellationToken ct) { + var creatorName = req.Name.ToLower(); + var creator = await context .Creators .SingleOrDefaultAsync( - c => EF.Functions.Like(c.Name, req.Name), + c => EF.Functions.Like(c.Name, creatorName), cancellationToken: ct); + var creators = await context.Creators.ToListAsync(cancellationToken: ct); + if (creator is null) await SendNotFoundAsync(ct); else await SendAsync(creator, cancellation: ct); } diff --git a/src/Web/TestDataSeeder.cs b/src/Web/TestDataSeeder.cs index fb87568..0fad50c 100644 --- a/src/Web/TestDataSeeder.cs +++ b/src/Web/TestDataSeeder.cs @@ -34,16 +34,20 @@ internal class TestDataSeeder( { if (contentContext.Contents.Any()) return; - _users.Add(await CreateUserAsync("admin", Roles.Administrator)); - _users.Add(await CreateUserAsync("userA")); - _users.Add(await CreateUserAsync("userB")); - + _users.Add(await CreateUserAsync("admin", null, Roles.Administrator)); + _users.Add(await CreateUserAsync("userA", null)); + _users.Add(await CreateUserAsync("userB", null)); + foreach (var creator in _creators) { - var creatorUser = await CreateUserAsync(creator.Name, Roles.Creator); - + var creatorUser = await CreateUserAsync( + creator.Name, + creator.StoredDataUrls.ProfilePictureUrl, + Roles.Creator); + creator.Id = creatorUser.Id; - + creator.CreatedBy = creator.Id; + await contentContext.Creators.AddAsync(creator); var contents = GenerateContent(creator, 100); @@ -151,7 +155,7 @@ internal class TestDataSeeder( return replies; } - private async Task CreateUserAsync(string name, params string[] roles) + private async Task CreateUserAsync(string name, string? portraitUrl, params string[] roles) { var user = new ApplicationUser { @@ -160,7 +164,8 @@ internal class TestDataSeeder( EmailConfirmed = true, Alias = name, FirstName = $"FirstName of {name}", - LastName = $"LastName of {name}" + LastName = $"LastName of {name}", + PortraitUrl = portraitUrl }; await userManager.CreateAsync(user, DefaultPassword); @@ -200,8 +205,36 @@ internal class TestDataSeeder( } }; + private readonly static Creator ArpsCreator = new() + { + Name = "Arps", + About = + new() + { + Title = "Page officielle", + Description = "Site officiel pour Arps. Venez-nous-y retrouver avec tous vos fans!", + }, + ProfileColors = + new() { BannerTop = "#231F20", BannerBottom = "#231F20", Accent = "#272526", Menu = "#FFFFFF" }, + SocialNetworks = new() + { + FacebookUrl = "https://www.facebook.com/arps.company", + InstagramUrl = "https://www.instagram.com/arps.co/", + YoutubeUrl = "https://www.youtube.com/channel/UCgnT_psydUXohYm5Yz_wFUg", + TikTokUrl = "https://www.tiktok.com/@arps.co", + LinkedInUrl = "https://www.linkedin.com/in/mickael-simard-96079a90/", + WebsiteUrl = "https://www.arps.ca/" + }, + StoredDataUrls = new() + { + BannerPictureUrl = "/images/usersmedia/ARPS/banners/bannerARPS01.png", + ProfilePictureUrl = "/images/usersmedia/ARPS/profilepictures/profileARPS.png" + } + }; + private readonly Creator[] _creators = [ - HutopyCreator + HutopyCreator, + ArpsCreator ]; } From 0cd913b2741af99786b64d75f27673694f9b23b5 Mon Sep 17 00:00:00 2001 From: Jonathan Bourdon Date: Sun, 4 Aug 2024 04:07:53 -0400 Subject: [PATCH 141/229] Reduce the amount of data generated during test --- src/Web/TestDataSeeder.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Web/TestDataSeeder.cs b/src/Web/TestDataSeeder.cs index 0fad50c..e32cc38 100644 --- a/src/Web/TestDataSeeder.cs +++ b/src/Web/TestDataSeeder.cs @@ -50,12 +50,12 @@ internal class TestDataSeeder( await contentContext.Creators.AddAsync(creator); - var contents = GenerateContent(creator, 100); + var contents = GenerateContent(creator, 10); foreach (var content in contents) { - var messages = GenerateMessages(content, 100); + var messages = GenerateMessages(content, 10); + var parentMessages = messages.Where((_, index) => index % 2 == 0).ToList(); - foreach (var parentMessage in parentMessages) { _ = GenerateReplies(content, parentMessage, 10); From 7ec668a822a41d9d8c670b1f1afa2acffdc2945c Mon Sep 17 00:00:00 2001 From: Jonathan Bourdon Date: Sun, 4 Aug 2024 04:35:08 -0400 Subject: [PATCH 142/229] Adds subscriber count --- .../Contents/Handlers/GetCreatorByAlias.cs | 37 +++++++++++++++---- .../Contents/Handlers/Models/CreatorModel.cs | 16 ++++++++ src/Web/TestDataSeeder.cs | 32 +++++++++++++++- 3 files changed, 76 insertions(+), 9 deletions(-) create mode 100644 src/Web/Features/Contents/Handlers/Models/CreatorModel.cs diff --git a/src/Web/Features/Contents/Handlers/GetCreatorByAlias.cs b/src/Web/Features/Contents/Handlers/GetCreatorByAlias.cs index be4359a..cc3a677 100644 --- a/src/Web/Features/Contents/Handlers/GetCreatorByAlias.cs +++ b/src/Web/Features/Contents/Handlers/GetCreatorByAlias.cs @@ -1,6 +1,7 @@ using FastEndpoints; using FluentValidation; using Hutopy.Web.Features.Contents.Data; +using Hutopy.Web.Features.Contents.Handlers.Models; using Microsoft.EntityFrameworkCore; namespace Hutopy.Web.Features.Contents.Handlers; @@ -23,7 +24,7 @@ public sealed class GetCreatorByAliasRequestValidator public class GetCreatorByAliasHandler( ContentDbContext context) - : Endpoint + : Endpoint { public override void Configure() { @@ -37,16 +38,36 @@ public class GetCreatorByAliasHandler( CancellationToken ct) { var creatorName = req.Name.ToLower(); - + var creator = await context .Creators - .SingleOrDefaultAsync( - c => EF.Functions.Like(c.Name, creatorName), + .Where(c => EF.Functions.Like(c.Name, creatorName)) + .FirstOrDefaultAsync(ct); + + if (creator is null) + { + await SendNotFoundAsync(ct); + } + else + { + var subscriberCount = await context.Subscriptions.CountAsync( + s => s.CreatorId == creator.Id, cancellationToken: ct); - var creators = await context.Creators.ToListAsync(cancellationToken: ct); - - if (creator is null) await SendNotFoundAsync(ct); - else await SendAsync(creator, cancellation: ct); + var model = new CreatorModel + { + Id = creator.Id, + CreatedBy = creator.CreatedBy, + CreatedAt = creator.CreatedAt, + Name = creator.Name, + About = creator.About, + SocialNetworks = creator.SocialNetworks, + ProfileColors = creator.ProfileColors, + StoredDataUrls = creator.StoredDataUrls, + SubscriberCount = subscriberCount, + }; + + await SendAsync(model, cancellation: ct); + } } } diff --git a/src/Web/Features/Contents/Handlers/Models/CreatorModel.cs b/src/Web/Features/Contents/Handlers/Models/CreatorModel.cs new file mode 100644 index 0000000..90492e5 --- /dev/null +++ b/src/Web/Features/Contents/Handlers/Models/CreatorModel.cs @@ -0,0 +1,16 @@ +using Hutopy.Web.Features.Contents.Data; + +namespace Hutopy.Web.Features.Contents.Handlers.Models; + +public class CreatorModel +{ + public Guid Id { get; set; } + public Guid CreatedBy { get; set; } + public DateTimeOffset CreatedAt { get; set; } + public string Name { get; set; } + public About About { get; set; } + public SocialNetworks SocialNetworks { get; set; } + public ProfileColors ProfileColors { get; set; } + public StoredDataUrls StoredDataUrls { get; set; } + public int SubscriberCount { get; set; } +} diff --git a/src/Web/TestDataSeeder.cs b/src/Web/TestDataSeeder.cs index e32cc38..89b91dc 100644 --- a/src/Web/TestDataSeeder.cs +++ b/src/Web/TestDataSeeder.cs @@ -232,9 +232,39 @@ internal class TestDataSeeder( } }; + private readonly static Creator ChloeCreator = new() + { + Name = "chloeprofile", + About = new() + { + Title = "Page officielle", + Description = "𝐿𝑎 𝑐𝑟𝑒́𝑎𝑡𝑖𝑣𝑖𝑡𝑒́ 𝑐’𝑒𝑠𝑡 𝑙’𝑖𝑛𝑡𝑒𝑙𝑙𝑖𝑔𝑒𝑛𝑐𝑒 𝑞𝑢𝑖 𝑠’𝑎𝑚𝑢𝑠𝑒!", + }, + ProfileColors = new() + { + BannerTop = "#231F20", + BannerBottom = "#272526", + Accent = "#231F20", + Menu = "#231F20", + }, + SocialNetworks = + new() + { + FacebookUrl = "https://www.facebook.com/chloegestionmedias", + InstagramUrl = "https://www.instagram.com/chloe.photo_gms", + + }, + StoredDataUrls = new() + { + BannerPictureUrl = "/images/usersmedia/chloebeaugrand/banners/bannerChloeBeaugrand01.png", + ProfilePictureUrl = "/images/usersmedia/chloebeaugrand/profilepictures/profileChloeBeaugrand01.png" + } + }; + private readonly Creator[] _creators = [ HutopyCreator, - ArpsCreator + ArpsCreator, + ChloeCreator ]; } From 7c5f3d72ef23bb83006c1b7dddbb624cb4d0006d Mon Sep 17 00:00:00 2001 From: Jonathan Bourdon Date: Sun, 4 Aug 2024 04:45:53 -0400 Subject: [PATCH 143/229] Fix some errors in test data --- src/Web/TestDataSeeder.cs | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/src/Web/TestDataSeeder.cs b/src/Web/TestDataSeeder.cs index 89b91dc..e873fea 100644 --- a/src/Web/TestDataSeeder.cs +++ b/src/Web/TestDataSeeder.cs @@ -41,8 +41,8 @@ internal class TestDataSeeder( foreach (var creator in _creators) { var creatorUser = await CreateUserAsync( - creator.Name, - creator.StoredDataUrls.ProfilePictureUrl, + creator.Name, + creator.StoredDataUrls.ProfilePictureUrl, Roles.Creator); creator.Id = creatorUser.Id; @@ -54,7 +54,7 @@ internal class TestDataSeeder( foreach (var content in contents) { var messages = GenerateMessages(content, 10); - + var parentMessages = messages.Where((_, index) => index % 2 == 0).ToList(); foreach (var parentMessage in parentMessages) { @@ -207,7 +207,7 @@ internal class TestDataSeeder( private readonly static Creator ArpsCreator = new() { - Name = "Arps", + Name = "arps", About = new() { @@ -234,7 +234,7 @@ internal class TestDataSeeder( private readonly static Creator ChloeCreator = new() { - Name = "chloeprofile", + Name = "chloe", About = new() { Title = "Page officielle", @@ -242,17 +242,13 @@ internal class TestDataSeeder( }, ProfileColors = new() { - BannerTop = "#231F20", - BannerBottom = "#272526", - Accent = "#231F20", - Menu = "#231F20", + BannerTop = "#231F20", BannerBottom = "#272526", Accent = "#231F20", Menu = "#231F20", }, SocialNetworks = new() { FacebookUrl = "https://www.facebook.com/chloegestionmedias", InstagramUrl = "https://www.instagram.com/chloe.photo_gms", - }, StoredDataUrls = new() { @@ -260,7 +256,7 @@ internal class TestDataSeeder( ProfilePictureUrl = "/images/usersmedia/chloebeaugrand/profilepictures/profileChloeBeaugrand01.png" } }; - + private readonly Creator[] _creators = [ HutopyCreator, From 143774340f8f757ab26db9f238eedb3ac653ed26 Mon Sep 17 00:00:00 2001 From: PascalMarchesseault <97350299+PascalMarchesseault@users.noreply.github.com> Date: Sun, 4 Aug 2024 21:19:12 -0400 Subject: [PATCH 144/229] Added Creator informations in DataSeeder --- src/Web/TestDataSeeder.cs | 90 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 87 insertions(+), 3 deletions(-) diff --git a/src/Web/TestDataSeeder.cs b/src/Web/TestDataSeeder.cs index e873fea..6bd5a16 100644 --- a/src/Web/TestDataSeeder.cs +++ b/src/Web/TestDataSeeder.cs @@ -232,9 +232,9 @@ internal class TestDataSeeder( } }; - private readonly static Creator ChloeCreator = new() + private readonly static Creator ChloeBeaugrandCreator = new() { - Name = "chloe", + Name = "chloebeaugrand", About = new() { Title = "Page officielle", @@ -256,11 +256,95 @@ internal class TestDataSeeder( ProfilePictureUrl = "/images/usersmedia/chloebeaugrand/profilepictures/profileChloeBeaugrand01.png" } }; + + private readonly static Creator GuillaumeMCreator = new() + { + Name = "guillaumem", + About = new() + { + Title = "Page officielle", + Description = "Mettre en lumière le côté humain des entrepreneurs. Chaque service, chaque produit est porteur d’une histoire, d’une passion, d’une vision unique. Mon objectif est de faire rayonner cette unicité, de créer des connexions authentiques entre ces entrepreneurs et leurs clients potentiels. Parce que derrière chaque entreprise, il y a des personnes inspirantes qui méritent d’être entendues et comprises. Et toi, quel est ton objectif pour cette année?", + }, + ProfileColors = new() + { + BannerTop = "#0BAAB2", BannerBottom = "#006D77", Accent = "#CC6F91", Menu = "#CC6F91", + }, + SocialNetworks = + new() + { + FacebookUrl = "https://www.facebook.com/GuillaumeMousseau222", + InstagramUrl = "https://www.instagram.com/guillaumeaime/", + TikTokUrl = "https://www.tiktok.com/@guillaumeaime" + }, + StoredDataUrls = new() + { + BannerPictureUrl = "/images/usersmedia/guillaumeMousseau/banners/bannerGuillaumeMousseau01.png", + ProfilePictureUrl = "/images/usersmedia/guillaumeMousseau/profilepictures/profileGuillaumeMousseau01.png" + } + }; + + private readonly static Creator LeffetCreator = new() + { + Name = "leffet", + About = new() + { + Title = "Page officielle", + Description = "Mettre en lumière le côté humain des entrepreneurs. Chaque service, chaque produit est porteur d’une histoire, d’une passion, d’une vision unique. Mon objectif est de faire rayonner cette unicité, de créer des connexions authentiques entre ces entrepreneurs et leurs clients potentiels. Parce que derrière chaque entreprise, il y a des personnes inspirantes qui méritent d’être entendues et comprises. Et toi, quel est ton objectif pour cette année?", + }, + ProfileColors = new() + { + BannerTop = "#CC6F91", BannerBottom = "#FBC702", Accent = "#FBC702", Menu = "#FBC702", + }, + SocialNetworks = + new() + { + FacebookUrl = "https://www.facebook.com/Hutopy", + InstagramUrl = "https://www.instagram.com/guillaumeaime/", + WebsiteUrl = "https://fondationleffet.ca/" + }, + StoredDataUrls = new() + { + BannerPictureUrl = "/images/usersmedia/leffet/banners/banner02.png", + ProfilePictureUrl = "/images/usersmedia/leffet/profilepictures/leffetProfile01.png" + } + }; + + private readonly static Creator MathieuCaron = new() + { + Name = "mathieucaron", + About = new() + { + Title = "Page officielle", + Description = "Mettre en lumière le côté humain des entrepreneurs. Chaque service, chaque produit est porteur d’une histoire, d’une passion, d’une vision unique. Mon objectif est de faire rayonner cette unicité, de créer des connexions authentiques entre ces entrepreneurs et leurs clients potentiels. Parce que derrière chaque entreprise, il y a des personnes inspirantes qui méritent d’être entendues et comprises. Et toi, quel est ton objectif pour cette année?", + }, + ProfileColors = new() + { + BannerTop = "#101B49", BannerBottom = "#698FE7", Accent = "#1D1D1B", Menu = "#1D1D1B", + }, + SocialNetworks = + new() + { + FacebookUrl = "https://www.facebook.com/MathieuCaronPro/", + YoutubeUrl = "https://www.youtube.com/@lesinterviewsatypiquesdema4692", + + }, + StoredDataUrls = new() + { + BannerPictureUrl = "/images/usersmedia/mathieuCaron/banners/bannerMathieuCaron01.png", + ProfilePictureUrl = "/images/usersmedia/mathieuCaron/profilepictures/profileMathieuCaron01.png" + } + }; private readonly Creator[] _creators = [ HutopyCreator, ArpsCreator, - ChloeCreator + ChloeBeaugrandCreator, + GuillaumeMCreator, + LeffetCreator, + MathieuCaron + + + ]; } From e617b5ffd3aae3208e03b07e5aa372e9b071b71e Mon Sep 17 00:00:00 2001 From: Jonathan Bourdon Date: Sun, 4 Aug 2024 21:52:09 -0400 Subject: [PATCH 145/229] Changed all MaxLength to be 64, 128, 256, or 2048 probably we need to review this --- src/Web/Features/Contents/Data/Creator.cs | 2 +- ....cs => 20240805012309_Initial.Designer.cs} | 6 ++--- ...7_Initial.cs => 20240805012309_Initial.cs} | 2 +- .../ContentDbContextModelSnapshot.cs | 4 +-- src/Web/Features/Messages/Data/Message.cs | 4 +-- ....cs => 20240805012343_Initial.Designer.cs} | 10 +++---- ...7_Initial.cs => 20240805012343_Initial.cs} | 4 +-- .../MessagingDbContextModelSnapshot.cs | 8 +++--- src/Web/TestDataSeeder.cs | 26 ++++++++++--------- 9 files changed, 34 insertions(+), 32 deletions(-) rename src/Web/Features/Contents/Migrations/{20240804071117_Initial.Designer.cs => 20240805012309_Initial.Designer.cs} (98%) rename src/Web/Features/Contents/Migrations/{20240804071117_Initial.cs => 20240805012309_Initial.cs} (99%) rename src/Web/Features/Messages/Migrations/{20240802044717_Initial.Designer.cs => 20240805012343_Initial.Designer.cs} (89%) rename src/Web/Features/Messages/Migrations/{20240802044717_Initial.cs => 20240805012343_Initial.cs} (93%) diff --git a/src/Web/Features/Contents/Data/Creator.cs b/src/Web/Features/Contents/Data/Creator.cs index 67803d0..d0b0b37 100644 --- a/src/Web/Features/Contents/Data/Creator.cs +++ b/src/Web/Features/Contents/Data/Creator.cs @@ -18,7 +18,7 @@ public class Creator public class About { [MaxLength(255)] public string? Title { get; set; } - [MaxLength(255)] public string? Description { get; set; } + [MaxLength(2048)] public string? Description { get; set; } } public class ProfileColors diff --git a/src/Web/Features/Contents/Migrations/20240804071117_Initial.Designer.cs b/src/Web/Features/Contents/Migrations/20240805012309_Initial.Designer.cs similarity index 98% rename from src/Web/Features/Contents/Migrations/20240804071117_Initial.Designer.cs rename to src/Web/Features/Contents/Migrations/20240805012309_Initial.Designer.cs index 2239cb6..25a08d7 100644 --- a/src/Web/Features/Contents/Migrations/20240804071117_Initial.Designer.cs +++ b/src/Web/Features/Contents/Migrations/20240805012309_Initial.Designer.cs @@ -12,7 +12,7 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; namespace Hutopy.Web.Features.Contents.Migrations { [DbContext(typeof(ContentDbContext))] - [Migration("20240804071117_Initial")] + [Migration("20240805012309_Initial")] partial class Initial { /// @@ -119,8 +119,8 @@ namespace Hutopy.Web.Features.Contents.Migrations .HasColumnType("uuid"); b1.Property("Description") - .HasMaxLength(255) - .HasColumnType("character varying(255)"); + .HasMaxLength(2048) + .HasColumnType("character varying(2048)"); b1.Property("Title") .HasMaxLength(255) diff --git a/src/Web/Features/Contents/Migrations/20240804071117_Initial.cs b/src/Web/Features/Contents/Migrations/20240805012309_Initial.cs similarity index 99% rename from src/Web/Features/Contents/Migrations/20240804071117_Initial.cs rename to src/Web/Features/Contents/Migrations/20240805012309_Initial.cs index f4db5f5..bb3198d 100644 --- a/src/Web/Features/Contents/Migrations/20240804071117_Initial.cs +++ b/src/Web/Features/Contents/Migrations/20240805012309_Initial.cs @@ -24,7 +24,7 @@ namespace Hutopy.Web.Features.Contents.Migrations CreatedAt = table.Column(type: "timestamp with time zone", nullable: false), Name = table.Column(type: "character varying(255)", maxLength: 255, nullable: false), About_Title = table.Column(type: "character varying(255)", maxLength: 255, nullable: true), - About_Description = table.Column(type: "character varying(255)", maxLength: 255, nullable: true) + About_Description = table.Column(type: "character varying(2048)", maxLength: 2048, nullable: true) }, constraints: table => { diff --git a/src/Web/Features/Contents/Migrations/ContentDbContextModelSnapshot.cs b/src/Web/Features/Contents/Migrations/ContentDbContextModelSnapshot.cs index cd39fe1..2904a21 100644 --- a/src/Web/Features/Contents/Migrations/ContentDbContextModelSnapshot.cs +++ b/src/Web/Features/Contents/Migrations/ContentDbContextModelSnapshot.cs @@ -116,8 +116,8 @@ namespace Hutopy.Web.Features.Contents.Migrations .HasColumnType("uuid"); b1.Property("Description") - .HasMaxLength(255) - .HasColumnType("character varying(255)"); + .HasMaxLength(2048) + .HasColumnType("character varying(2048)"); b1.Property("Title") .HasMaxLength(255) diff --git a/src/Web/Features/Messages/Data/Message.cs b/src/Web/Features/Messages/Data/Message.cs index 97dde47..83af411 100644 --- a/src/Web/Features/Messages/Data/Message.cs +++ b/src/Web/Features/Messages/Data/Message.cs @@ -7,8 +7,8 @@ public class Message public Guid Id { get; set; } public Guid SubjectId { get; set; } public Guid CreatedBy { get; set; } - [MaxLength(64)] public required string CreatedByName { get; set; } - [MaxLength(256)] public string? CreatedByPortraitUrl { get; set; } + [MaxLength(255)] public required string CreatedByName { get; set; } + [MaxLength(255)] public string? CreatedByPortraitUrl { get; set; } public DateTimeOffset CreatedAt { get; set; } public Guid? ParentId { get; set; } public required string Value { get; set; } diff --git a/src/Web/Features/Messages/Migrations/20240802044717_Initial.Designer.cs b/src/Web/Features/Messages/Migrations/20240805012343_Initial.Designer.cs similarity index 89% rename from src/Web/Features/Messages/Migrations/20240802044717_Initial.Designer.cs rename to src/Web/Features/Messages/Migrations/20240805012343_Initial.Designer.cs index 63d787f..31e6ba9 100644 --- a/src/Web/Features/Messages/Migrations/20240802044717_Initial.Designer.cs +++ b/src/Web/Features/Messages/Migrations/20240805012343_Initial.Designer.cs @@ -12,7 +12,7 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; namespace Hutopy.Web.Features.Messages.Migrations { [DbContext(typeof(MessagingDbContext))] - [Migration("20240802044717_Initial")] + [Migration("20240805012343_Initial")] partial class Initial { /// @@ -42,12 +42,12 @@ namespace Hutopy.Web.Features.Messages.Migrations b.Property("CreatedByName") .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)"); + .HasMaxLength(255) + .HasColumnType("character varying(255)"); b.Property("CreatedByPortraitUrl") - .HasMaxLength(256) - .HasColumnType("character varying(256)"); + .HasMaxLength(255) + .HasColumnType("character varying(255)"); b.Property("ParentId") .HasColumnType("uuid"); diff --git a/src/Web/Features/Messages/Migrations/20240802044717_Initial.cs b/src/Web/Features/Messages/Migrations/20240805012343_Initial.cs similarity index 93% rename from src/Web/Features/Messages/Migrations/20240802044717_Initial.cs rename to src/Web/Features/Messages/Migrations/20240805012343_Initial.cs index fa9c144..ce0f4cd 100644 --- a/src/Web/Features/Messages/Migrations/20240802044717_Initial.cs +++ b/src/Web/Features/Messages/Migrations/20240805012343_Initial.cs @@ -22,8 +22,8 @@ namespace Hutopy.Web.Features.Messages.Migrations Id = table.Column(type: "uuid", nullable: false), SubjectId = table.Column(type: "uuid", nullable: false), CreatedBy = table.Column(type: "uuid", nullable: false), - CreatedByName = table.Column(type: "character varying(64)", maxLength: 64, nullable: false), - CreatedByPortraitUrl = table.Column(type: "character varying(256)", maxLength: 256, nullable: true), + CreatedByName = table.Column(type: "character varying(255)", maxLength: 255, nullable: false), + CreatedByPortraitUrl = table.Column(type: "character varying(255)", maxLength: 255, nullable: true), CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, defaultValueSql: "CURRENT_TIMESTAMP"), ParentId = table.Column(type: "uuid", nullable: true), Value = table.Column(type: "text", nullable: false) diff --git a/src/Web/Features/Messages/Migrations/MessagingDbContextModelSnapshot.cs b/src/Web/Features/Messages/Migrations/MessagingDbContextModelSnapshot.cs index 111cb88..b1848d8 100644 --- a/src/Web/Features/Messages/Migrations/MessagingDbContextModelSnapshot.cs +++ b/src/Web/Features/Messages/Migrations/MessagingDbContextModelSnapshot.cs @@ -39,12 +39,12 @@ namespace Hutopy.Web.Features.Messages.Migrations b.Property("CreatedByName") .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)"); + .HasMaxLength(255) + .HasColumnType("character varying(255)"); b.Property("CreatedByPortraitUrl") - .HasMaxLength(256) - .HasColumnType("character varying(256)"); + .HasMaxLength(255) + .HasColumnType("character varying(255)"); b.Property("ParentId") .HasColumnType("uuid"); diff --git a/src/Web/TestDataSeeder.cs b/src/Web/TestDataSeeder.cs index 6bd5a16..1b23093 100644 --- a/src/Web/TestDataSeeder.cs +++ b/src/Web/TestDataSeeder.cs @@ -35,7 +35,8 @@ internal class TestDataSeeder( if (contentContext.Contents.Any()) return; _users.Add(await CreateUserAsync("admin", null, Roles.Administrator)); - _users.Add(await CreateUserAsync("userA", null)); + var userA = await CreateUserAsync("userA", null); + _users.Add(userA); _users.Add(await CreateUserAsync("userB", null)); foreach (var creator in _creators) @@ -48,6 +49,7 @@ internal class TestDataSeeder( creator.Id = creatorUser.Id; creator.CreatedBy = creator.Id; + await contentContext.Subscriptions.AddAsync(new() { CreatedBy = userA.Id, CreatorId = creator.Id }); await contentContext.Creators.AddAsync(creator); var contents = GenerateContent(creator, 10); @@ -256,14 +258,15 @@ internal class TestDataSeeder( ProfilePictureUrl = "/images/usersmedia/chloebeaugrand/profilepictures/profileChloeBeaugrand01.png" } }; - + private readonly static Creator GuillaumeMCreator = new() { Name = "guillaumem", About = new() { Title = "Page officielle", - Description = "Mettre en lumière le côté humain des entrepreneurs. Chaque service, chaque produit est porteur d’une histoire, d’une passion, d’une vision unique. Mon objectif est de faire rayonner cette unicité, de créer des connexions authentiques entre ces entrepreneurs et leurs clients potentiels. Parce que derrière chaque entreprise, il y a des personnes inspirantes qui méritent d’être entendues et comprises. Et toi, quel est ton objectif pour cette année?", + Description = + "Mettre en lumière le côté humain des entrepreneurs. Chaque service, chaque produit est porteur d’une histoire, d’une passion, d’une vision unique. Mon objectif est de faire rayonner cette unicité, de créer des connexions authentiques entre ces entrepreneurs et leurs clients potentiels. Parce que derrière chaque entreprise, il y a des personnes inspirantes qui méritent d’être entendues et comprises. Et toi, quel est ton objectif pour cette année?", }, ProfileColors = new() { @@ -279,17 +282,19 @@ internal class TestDataSeeder( StoredDataUrls = new() { BannerPictureUrl = "/images/usersmedia/guillaumeMousseau/banners/bannerGuillaumeMousseau01.png", - ProfilePictureUrl = "/images/usersmedia/guillaumeMousseau/profilepictures/profileGuillaumeMousseau01.png" + ProfilePictureUrl = + "/images/usersmedia/guillaumeMousseau/profilepictures/profileGuillaumeMousseau01.png" } }; - + private readonly static Creator LeffetCreator = new() { Name = "leffet", About = new() { Title = "Page officielle", - Description = "Mettre en lumière le côté humain des entrepreneurs. Chaque service, chaque produit est porteur d’une histoire, d’une passion, d’une vision unique. Mon objectif est de faire rayonner cette unicité, de créer des connexions authentiques entre ces entrepreneurs et leurs clients potentiels. Parce que derrière chaque entreprise, il y a des personnes inspirantes qui méritent d’être entendues et comprises. Et toi, quel est ton objectif pour cette année?", + Description = + "Mettre en lumière le côté humain des entrepreneurs. Chaque service, chaque produit est porteur d’une histoire, d’une passion, d’une vision unique. Mon objectif est de faire rayonner cette unicité, de créer des connexions authentiques entre ces entrepreneurs et leurs clients potentiels. Parce que derrière chaque entreprise, il y a des personnes inspirantes qui méritent d’être entendues et comprises. Et toi, quel est ton objectif pour cette année?", }, ProfileColors = new() { @@ -308,14 +313,15 @@ internal class TestDataSeeder( ProfilePictureUrl = "/images/usersmedia/leffet/profilepictures/leffetProfile01.png" } }; - + private readonly static Creator MathieuCaron = new() { Name = "mathieucaron", About = new() { Title = "Page officielle", - Description = "Mettre en lumière le côté humain des entrepreneurs. Chaque service, chaque produit est porteur d’une histoire, d’une passion, d’une vision unique. Mon objectif est de faire rayonner cette unicité, de créer des connexions authentiques entre ces entrepreneurs et leurs clients potentiels. Parce que derrière chaque entreprise, il y a des personnes inspirantes qui méritent d’être entendues et comprises. Et toi, quel est ton objectif pour cette année?", + Description = + "Mettre en lumière le côté humain des entrepreneurs. Chaque service, chaque produit est porteur d’une histoire, d’une passion, d’une vision unique. Mon objectif est de faire rayonner cette unicité, de créer des connexions authentiques entre ces entrepreneurs et leurs clients potentiels. Parce que derrière chaque entreprise, il y a des personnes inspirantes qui méritent d’être entendues et comprises. Et toi, quel est ton objectif pour cette année?", }, ProfileColors = new() { @@ -326,7 +332,6 @@ internal class TestDataSeeder( { FacebookUrl = "https://www.facebook.com/MathieuCaronPro/", YoutubeUrl = "https://www.youtube.com/@lesinterviewsatypiquesdema4692", - }, StoredDataUrls = new() { @@ -343,8 +348,5 @@ internal class TestDataSeeder( GuillaumeMCreator, LeffetCreator, MathieuCaron - - - ]; } From 8f0ed2644b5b51d0c0855d8884f00e2805e26290 Mon Sep 17 00:00:00 2001 From: Jonathan Bourdon Date: Mon, 5 Aug 2024 16:32:00 -0400 Subject: [PATCH 146/229] Adds ChangeBanner for Creators --- ...eBlobStorageService.cs => IBlobStorage.cs} | 2 +- .../Users/Commands/UploadProfilePicture.cs | 9 ++---- .../GetCurrentUserProfilePicture.cs | 4 +-- .../Utils/HttpContextAccessorExtensions.cs | 29 ------------------- ...bStorageService.cs => AzureBlobStorage.cs} | 15 +++++----- src/Infrastructure/DependencyInjection.cs | 2 +- .../Contents/Handlers/ChangeBanner.cs | 23 +++++++++------ .../Contents/Handlers/CreateContent.cs | 2 +- 8 files changed, 30 insertions(+), 56 deletions(-) rename src/Application/Common/Interfaces/{IAzureBlobStorageService.cs => IBlobStorage.cs} (88%) delete mode 100644 src/Application/Utils/HttpContextAccessorExtensions.cs rename src/Infrastructure/AzureBlob/{AzureBlobStorageService.cs => AzureBlobStorage.cs} (92%) diff --git a/src/Application/Common/Interfaces/IAzureBlobStorageService.cs b/src/Application/Common/Interfaces/IBlobStorage.cs similarity index 88% rename from src/Application/Common/Interfaces/IAzureBlobStorageService.cs rename to src/Application/Common/Interfaces/IBlobStorage.cs index 83537e9..7dac254 100644 --- a/src/Application/Common/Interfaces/IAzureBlobStorageService.cs +++ b/src/Application/Common/Interfaces/IBlobStorage.cs @@ -1,6 +1,6 @@ namespace Hutopy.Application.Common.Interfaces; -public interface IAzureBlobStorageService +public interface IBlobStorage { Task UploadFileAsync(string containerName, string blobName, Stream stream, string contentType, CancellationToken ct = default); diff --git a/src/Application/Users/Commands/UploadProfilePicture.cs b/src/Application/Users/Commands/UploadProfilePicture.cs index cbf4b00..3cc34cc 100644 --- a/src/Application/Users/Commands/UploadProfilePicture.cs +++ b/src/Application/Users/Commands/UploadProfilePicture.cs @@ -1,6 +1,5 @@ using Hutopy.Application.AzureBlobStorage.Constants; using Hutopy.Application.Common.Interfaces; -using Hutopy.Application.Utils; using Microsoft.AspNetCore.Http; namespace Hutopy.Application.Users.Commands; @@ -16,19 +15,17 @@ public class UploadProfilePictureCommand : IRequest public class UploadProfilePictureCommandHandler( IHttpContextAccessor contextAccessor, IIdentityService identityService, - IAzureBlobStorageService azureBlobStorageService) : IRequestHandler + IBlobStorage blobStorage) : IRequestHandler { public async Task Handle(UploadProfilePictureCommand request, CancellationToken ct) { - var contentType = contextAccessor.EnsureContentType(); - var identityUser = await identityService.GetCurrentUserAsync(); - var url = await azureBlobStorageService.UploadFileAsync( + var url = await blobStorage.UploadFileAsync( ContainerNames.Users, $"{identityUser.Id}/{SubDirectoryNames.Profile}/{CommonFileNames.ProfilePicture}", request.File.OpenReadStream(), - contentType, + request.File.ContentType, ct); await identityService.UpdateCurrentUserPortraitUrlAsync(url); diff --git a/src/Application/Users/Queries/GetCurrentUser/GetCurrentUserProfilePicture.cs b/src/Application/Users/Queries/GetCurrentUser/GetCurrentUserProfilePicture.cs index f598887..26865b7 100644 --- a/src/Application/Users/Queries/GetCurrentUser/GetCurrentUserProfilePicture.cs +++ b/src/Application/Users/Queries/GetCurrentUser/GetCurrentUserProfilePicture.cs @@ -7,7 +7,7 @@ public record GetCurrentUserProfilePictureQuery : IRequest; public class GetCurrentUserProfilePictureQueryHandler( IIdentityService identityService, - IAzureBlobStorageService azureBlobStorageService + IBlobStorage blobStorage ) : IRequestHandler { @@ -15,7 +15,7 @@ public class GetCurrentUserProfilePictureQueryHandler( { var identityUser = await identityService.GetCurrentUserAsync(); - return await azureBlobStorageService.DownloadFileAsync( + return await blobStorage.DownloadFileAsync( ContainerNames.Users, $"{identityUser.Id.ToString()}/{SubDirectoryNames.Profile}/{CommonFileNames.ProfilePicture}", cancellationToken); diff --git a/src/Application/Utils/HttpContextAccessorExtensions.cs b/src/Application/Utils/HttpContextAccessorExtensions.cs deleted file mode 100644 index 849e1a8..0000000 --- a/src/Application/Utils/HttpContextAccessorExtensions.cs +++ /dev/null @@ -1,29 +0,0 @@ -using Microsoft.AspNetCore.Http; - -namespace Hutopy.Application.Utils; - -public static class HttpContextAccessorExtensions -{ - public static HttpContext EnsureHttpContext(this IHttpContextAccessor httpContextAccessor) - { - if (httpContextAccessor.HttpContext == null) - { - throw new InvalidOperationException("HttpContext is null."); - } - - return httpContextAccessor.HttpContext; - } - - public static string EnsureContentType(this IHttpContextAccessor httpContextAccessor) - { - var httpContext = EnsureHttpContext(httpContextAccessor); - var contentType = httpContext.Request.ContentType; - - if (string.IsNullOrEmpty(contentType)) - { - throw new InvalidOperationException("Content-Type header is missing."); - } - - return contentType; - } -} diff --git a/src/Infrastructure/AzureBlob/AzureBlobStorageService.cs b/src/Infrastructure/AzureBlob/AzureBlobStorage.cs similarity index 92% rename from src/Infrastructure/AzureBlob/AzureBlobStorageService.cs rename to src/Infrastructure/AzureBlob/AzureBlobStorage.cs index 9fee071..2016b7f 100644 --- a/src/Infrastructure/AzureBlob/AzureBlobStorageService.cs +++ b/src/Infrastructure/AzureBlob/AzureBlobStorage.cs @@ -7,13 +7,14 @@ using Microsoft.Extensions.Logging; namespace Hutopy.Infrastructure.AzureBlob; -public class AzureBlobStorageService : IAzureBlobStorageService +public class AzureBlobStorage : IBlobStorage { + private const long MaxUploadSize = 10 * 1024 * 1024; // 10 MB in bytes + private readonly BlobServiceClient _blobServiceClient; - private readonly ILogger _logger; - private readonly long _maxUploadSize = 10 * 1024 * 1024; // 10 MB in bytes + private readonly ILogger _logger; - public AzureBlobStorageService(IConfiguration configuration, ILogger logger) + public AzureBlobStorage(IConfiguration configuration, ILogger logger) { _logger = logger; var connectionString = configuration["Azure-Blob-Connection-String"] ?? ""; @@ -37,12 +38,12 @@ public class AzureBlobStorageService : IAzureBlobStorageService stream.Position = 0; // Check if the file size exceeds the maximum upload size - if (stream.Length > _maxUploadSize) + if (stream.Length > MaxUploadSize) { _logger.LogError( - $"Blob storage: File size exceeds the maximum allowed size of {_maxUploadSize} bytes."); + $"Blob storage: File size exceeds the maximum allowed size of {MaxUploadSize} bytes."); throw new InvalidOperationException( - $"Blob storage: File size exceeds the maximum allowed size of {_maxUploadSize} bytes."); + $"Blob storage: File size exceeds the maximum allowed size of {MaxUploadSize} bytes."); } // Validate content type diff --git a/src/Infrastructure/DependencyInjection.cs b/src/Infrastructure/DependencyInjection.cs index f7c3525..f816daa 100644 --- a/src/Infrastructure/DependencyInjection.cs +++ b/src/Infrastructure/DependencyInjection.cs @@ -52,7 +52,7 @@ public static class DependencyInjection // Singleton services services.AddSingleton(TimeProvider.System); - services.AddSingleton(); + services.AddSingleton(); // Scoped services services.AddScoped(); diff --git a/src/Web/Features/Contents/Handlers/ChangeBanner.cs b/src/Web/Features/Contents/Handlers/ChangeBanner.cs index 8601ff4..e5f64da 100644 --- a/src/Web/Features/Contents/Handlers/ChangeBanner.cs +++ b/src/Web/Features/Contents/Handlers/ChangeBanner.cs @@ -1,7 +1,6 @@ using FastEndpoints; using Hutopy.Application.AzureBlobStorage.Constants; using Hutopy.Application.Common.Interfaces; -using Hutopy.Application.Utils; using Hutopy.Web.Features.Contents.Data; using Microsoft.EntityFrameworkCore; @@ -14,7 +13,7 @@ public record ChangeBannerRequest( public class ChangeBannerHandler( IHttpContextAccessor contextAccessor, ContentDbContext context, - IAzureBlobStorageService azureBlobStorageService) + IBlobStorage blobStorage) : Endpoint { public override void Configure() @@ -29,21 +28,27 @@ public class ChangeBannerHandler( var creator = await context .Creators .Include(c => c.StoredDataUrls) - .SingleAsync( + .SingleOrDefaultAsync( c => c.Id == request.CreatorId, cancellationToken: ct); - var contentType = contextAccessor.EnsureContentType(); - - var blobUrl = await azureBlobStorageService.UploadFileAsync( + if (creator is null) + { + await SendNotFoundAsync(ct); + return; + } + + var blobUrl = await blobStorage.UploadFileAsync( ContainerNames.Users, $"{request.CreatorId}/{SubDirectoryNames.Profile}/{CommonFileNames.BannerPicture}", request.File.OpenReadStream(), - contentType, + request.File.ContentType, ct); - + + creator.StoredDataUrls.BannerPictureUrl = blobUrl; + await context.SaveChangesAsync(ct); - + await SendOkAsync(blobUrl, ct); } } diff --git a/src/Web/Features/Contents/Handlers/CreateContent.cs b/src/Web/Features/Contents/Handlers/CreateContent.cs index 836dbe1..14496f0 100644 --- a/src/Web/Features/Contents/Handlers/CreateContent.cs +++ b/src/Web/Features/Contents/Handlers/CreateContent.cs @@ -38,7 +38,7 @@ public sealed class PostContentRequestValidator : Validator } public sealed class PostContent( - IAzureBlobStorageService blobStorage, + IBlobStorage blobStorage, ContentDbContext context) : Endpoint { From 5748799828f553a17219727143a8a398c04898c5 Mon Sep 17 00:00:00 2001 From: Jonathan Bourdon Date: Mon, 5 Aug 2024 22:40:35 -0400 Subject: [PATCH 147/229] Fix ChangeColors for Creators --- src/Web/Features/Contents/Handlers/ChangeColors.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Web/Features/Contents/Handlers/ChangeColors.cs b/src/Web/Features/Contents/Handlers/ChangeColors.cs index 76a003f..a7edc06 100644 --- a/src/Web/Features/Contents/Handlers/ChangeColors.cs +++ b/src/Web/Features/Contents/Handlers/ChangeColors.cs @@ -47,7 +47,6 @@ public class ChangeColorsHandler( { Post("/api/creators/{CreatorId}/colors"); Options(o => o.WithTags("Contents")); - AllowFileUploads(); } public override async Task HandleAsync(ChangeColorsRequest request, CancellationToken ct) From 9867528ffa1ee950dd0b76c8f834bec70190c4f8 Mon Sep 17 00:00:00 2001 From: Jonathan Bourdon Date: Mon, 5 Aug 2024 22:40:54 -0400 Subject: [PATCH 148/229] Fixes ChangeBanner for Creators --- src/Web/Features/Contents/Handlers/ChangeBanner.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Web/Features/Contents/Handlers/ChangeBanner.cs b/src/Web/Features/Contents/Handlers/ChangeBanner.cs index e5f64da..f75cc98 100644 --- a/src/Web/Features/Contents/Handlers/ChangeBanner.cs +++ b/src/Web/Features/Contents/Handlers/ChangeBanner.cs @@ -39,7 +39,7 @@ public class ChangeBannerHandler( } var blobUrl = await blobStorage.UploadFileAsync( - ContainerNames.Users, + ContainerNames.Creators, $"{request.CreatorId}/{SubDirectoryNames.Profile}/{CommonFileNames.BannerPicture}", request.File.OpenReadStream(), request.File.ContentType, From e2c345a7702636bcb788d8b65b1dd79aa0d2d051 Mon Sep 17 00:00:00 2001 From: Jonathan Bourdon Date: Mon, 5 Aug 2024 22:41:05 -0400 Subject: [PATCH 149/229] Adds ChangeLogo for Creators --- .../Features/Contents/Handlers/ChangeLogo.cs | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 src/Web/Features/Contents/Handlers/ChangeLogo.cs diff --git a/src/Web/Features/Contents/Handlers/ChangeLogo.cs b/src/Web/Features/Contents/Handlers/ChangeLogo.cs new file mode 100644 index 0000000..1d3d39e --- /dev/null +++ b/src/Web/Features/Contents/Handlers/ChangeLogo.cs @@ -0,0 +1,54 @@ +using FastEndpoints; +using Hutopy.Application.AzureBlobStorage.Constants; +using Hutopy.Application.Common.Interfaces; +using Hutopy.Web.Features.Contents.Data; +using Microsoft.EntityFrameworkCore; + +namespace Hutopy.Web.Features.Contents.Handlers; + +public record ChangeLogoRequest( + Guid CreatorId, + IFormFile File); + +public class ChangeLogoHandler( + IHttpContextAccessor contextAccessor, + ContentDbContext context, + IBlobStorage blobStorage) + : Endpoint +{ + public override void Configure() + { + Post("/api/creators/{CreatorId}/logo"); + Options(o => o.WithTags("Contents")); + AllowFileUploads(); + } + + public override async Task HandleAsync(ChangeLogoRequest request, CancellationToken ct) + { + var creator = await context + .Creators + .Include(c => c.StoredDataUrls) + .SingleOrDefaultAsync( + c => c.Id == request.CreatorId, + cancellationToken: ct); + + if (creator is null) + { + await SendNotFoundAsync(ct); + return; + } + + var blobUrl = await blobStorage.UploadFileAsync( + ContainerNames.Creators, + $"{request.CreatorId}/{SubDirectoryNames.Profile}/{CommonFileNames.ProfilePicture}", + request.File.OpenReadStream(), + request.File.ContentType, + ct); + + creator.StoredDataUrls.ProfilePictureUrl = blobUrl; + + await context.SaveChangesAsync(ct); + + await SendOkAsync(blobUrl, ct); + } +} From b2583738f5fb6e85cf09c698c7043fa96c5b70c6 Mon Sep 17 00:00:00 2001 From: Jonathan Bourdon Date: Mon, 5 Aug 2024 22:42:02 -0400 Subject: [PATCH 150/229] Adds ChangeSocials for Creators --- .../Contents/Handlers/ChangeSocials.cs | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 src/Web/Features/Contents/Handlers/ChangeSocials.cs diff --git a/src/Web/Features/Contents/Handlers/ChangeSocials.cs b/src/Web/Features/Contents/Handlers/ChangeSocials.cs new file mode 100644 index 0000000..cbb7bf0 --- /dev/null +++ b/src/Web/Features/Contents/Handlers/ChangeSocials.cs @@ -0,0 +1,50 @@ +using FastEndpoints; +using Hutopy.Web.Features.Contents.Data; +using Microsoft.EntityFrameworkCore; + +namespace Hutopy.Web.Features.Contents.Handlers; + +public record ChangeSocialsRequest( + Guid CreatorId, + string? FacebookUrl, + string? InstagramUrl, + string? XUrl, + string? LinkedInUrl, + string? TikTokUrl, + string? YoutubeUrl, + string? RedditUrl, + string? WebsiteUrl); + +public class ChangeSocialsHandler( + ContentDbContext context) + : Endpoint +{ + public override void Configure() + { + Post("/api/creators/{CreatorId}/socials"); + Options(o => o.WithTags("Contents")); + } + + public override async Task HandleAsync(ChangeSocialsRequest request, CancellationToken ct) + { + var creator = await context + .Creators + .Include(c => c.ProfileColors) + .SingleAsync( + c => c.Id == request.CreatorId, + cancellationToken: ct); + + creator.SocialNetworks.FacebookUrl = request.FacebookUrl; + creator.SocialNetworks.InstagramUrl = request.InstagramUrl; + creator.SocialNetworks.XUrl = request.XUrl; + creator.SocialNetworks.LinkedInUrl = request.LinkedInUrl; + creator.SocialNetworks.TikTokUrl = request.TikTokUrl; + creator.SocialNetworks.YoutubeUrl = request.YoutubeUrl; + creator.SocialNetworks.RedditUrl = request.RedditUrl; + creator.SocialNetworks.WebsiteUrl = request.WebsiteUrl; + + await context.SaveChangesAsync(ct); + + await SendOkAsync(ct); + } +} From 14bc4ce69b1d83b623ae2d32f6d7e75ae6ce44a1 Mon Sep 17 00:00:00 2001 From: Jonathan Bourdon Date: Tue, 6 Aug 2024 00:14:40 -0400 Subject: [PATCH 151/229] Renames SocialNetworks to Socials --- .../Features/Contents/Data/ContentDbContext.cs | 4 ++-- src/Web/Features/Contents/Data/Creator.cs | 4 ++-- .../Features/Contents/Handlers/ChangeSocials.cs | 16 ++++++++-------- .../Contents/Handlers/GetCreatorByAlias.cs | 2 +- .../Contents/Handlers/Models/CreatorModel.cs | 2 +- ...ner.cs => 20240806041040_Initial.Designer.cs} | 8 ++++---- ...2309_Initial.cs => 20240806041040_Initial.cs} | 8 ++++---- .../Migrations/ContentDbContextModelSnapshot.cs | 6 +++--- src/Web/TestDataSeeder.cs | 12 ++++++------ 9 files changed, 31 insertions(+), 31 deletions(-) rename src/Web/Features/Contents/Migrations/{20240805012309_Initial.Designer.cs => 20240806041040_Initial.Designer.cs} (97%) rename src/Web/Features/Contents/Migrations/{20240805012309_Initial.cs => 20240806041040_Initial.cs} (97%) diff --git a/src/Web/Features/Contents/Data/ContentDbContext.cs b/src/Web/Features/Contents/Data/ContentDbContext.cs index 29860e4..42359d6 100644 --- a/src/Web/Features/Contents/Data/ContentDbContext.cs +++ b/src/Web/Features/Contents/Data/ContentDbContext.cs @@ -44,8 +44,8 @@ public class ContentDbContext( modelBuilder .Entity() - .OwnsOne(x => x.SocialNetworks) - .ToTable(nameof(SocialNetworks)); + .OwnsOne(x => x.Socials) + .ToTable(nameof(Socials)); modelBuilder .Entity() diff --git a/src/Web/Features/Contents/Data/Creator.cs b/src/Web/Features/Contents/Data/Creator.cs index d0b0b37..a96d484 100644 --- a/src/Web/Features/Contents/Data/Creator.cs +++ b/src/Web/Features/Contents/Data/Creator.cs @@ -10,7 +10,7 @@ public class Creator [MaxLength(255)] public string Name { get; set; } = null!; public About About { get; set; } = new(); - public SocialNetworks SocialNetworks { get; set; } = new(); + public Socials Socials { get; set; } = new(); public ProfileColors ProfileColors { get; set; } = new(); public StoredDataUrls StoredDataUrls { get; set; } = new(); } @@ -29,7 +29,7 @@ public class ProfileColors [MaxLength(9)] public string? Menu { get; set; } } -public class SocialNetworks +public class Socials { [MaxLength(255)] public string? FacebookUrl { get; set; } [MaxLength(255)] public string? InstagramUrl { get; set; } diff --git a/src/Web/Features/Contents/Handlers/ChangeSocials.cs b/src/Web/Features/Contents/Handlers/ChangeSocials.cs index cbb7bf0..62d6848 100644 --- a/src/Web/Features/Contents/Handlers/ChangeSocials.cs +++ b/src/Web/Features/Contents/Handlers/ChangeSocials.cs @@ -34,14 +34,14 @@ public class ChangeSocialsHandler( c => c.Id == request.CreatorId, cancellationToken: ct); - creator.SocialNetworks.FacebookUrl = request.FacebookUrl; - creator.SocialNetworks.InstagramUrl = request.InstagramUrl; - creator.SocialNetworks.XUrl = request.XUrl; - creator.SocialNetworks.LinkedInUrl = request.LinkedInUrl; - creator.SocialNetworks.TikTokUrl = request.TikTokUrl; - creator.SocialNetworks.YoutubeUrl = request.YoutubeUrl; - creator.SocialNetworks.RedditUrl = request.RedditUrl; - creator.SocialNetworks.WebsiteUrl = request.WebsiteUrl; + creator.Socials.FacebookUrl = request.FacebookUrl; + creator.Socials.InstagramUrl = request.InstagramUrl; + creator.Socials.XUrl = request.XUrl; + creator.Socials.LinkedInUrl = request.LinkedInUrl; + creator.Socials.TikTokUrl = request.TikTokUrl; + creator.Socials.YoutubeUrl = request.YoutubeUrl; + creator.Socials.RedditUrl = request.RedditUrl; + creator.Socials.WebsiteUrl = request.WebsiteUrl; await context.SaveChangesAsync(ct); diff --git a/src/Web/Features/Contents/Handlers/GetCreatorByAlias.cs b/src/Web/Features/Contents/Handlers/GetCreatorByAlias.cs index cc3a677..30ed02a 100644 --- a/src/Web/Features/Contents/Handlers/GetCreatorByAlias.cs +++ b/src/Web/Features/Contents/Handlers/GetCreatorByAlias.cs @@ -61,7 +61,7 @@ public class GetCreatorByAliasHandler( CreatedAt = creator.CreatedAt, Name = creator.Name, About = creator.About, - SocialNetworks = creator.SocialNetworks, + Socials = creator.Socials, ProfileColors = creator.ProfileColors, StoredDataUrls = creator.StoredDataUrls, SubscriberCount = subscriberCount, diff --git a/src/Web/Features/Contents/Handlers/Models/CreatorModel.cs b/src/Web/Features/Contents/Handlers/Models/CreatorModel.cs index 90492e5..b43bcfe 100644 --- a/src/Web/Features/Contents/Handlers/Models/CreatorModel.cs +++ b/src/Web/Features/Contents/Handlers/Models/CreatorModel.cs @@ -9,7 +9,7 @@ public class CreatorModel public DateTimeOffset CreatedAt { get; set; } public string Name { get; set; } public About About { get; set; } - public SocialNetworks SocialNetworks { get; set; } + public Socials Socials { get; set; } public ProfileColors ProfileColors { get; set; } public StoredDataUrls StoredDataUrls { get; set; } public int SubscriberCount { get; set; } diff --git a/src/Web/Features/Contents/Migrations/20240805012309_Initial.Designer.cs b/src/Web/Features/Contents/Migrations/20240806041040_Initial.Designer.cs similarity index 97% rename from src/Web/Features/Contents/Migrations/20240805012309_Initial.Designer.cs rename to src/Web/Features/Contents/Migrations/20240806041040_Initial.Designer.cs index 25a08d7..154bd64 100644 --- a/src/Web/Features/Contents/Migrations/20240805012309_Initial.Designer.cs +++ b/src/Web/Features/Contents/Migrations/20240806041040_Initial.Designer.cs @@ -12,7 +12,7 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; namespace Hutopy.Web.Features.Contents.Migrations { [DbContext(typeof(ContentDbContext))] - [Migration("20240805012309_Initial")] + [Migration("20240806041040_Initial")] partial class Initial { /// @@ -163,7 +163,7 @@ namespace Hutopy.Web.Features.Contents.Migrations .HasForeignKey("CreatorId"); }); - b.OwnsOne("Hutopy.Web.Features.Contents.Data.SocialNetworks", "SocialNetworks", b1 => + b.OwnsOne("Hutopy.Web.Features.Contents.Data.Socials", "Socials", b1 => { b1.Property("CreatorId") .HasColumnType("uuid"); @@ -202,7 +202,7 @@ namespace Hutopy.Web.Features.Contents.Migrations b1.HasKey("CreatorId"); - b1.ToTable("SocialNetworks", "Content"); + b1.ToTable("Socials", "Content"); b1.WithOwner() .HasForeignKey("CreatorId"); @@ -235,7 +235,7 @@ namespace Hutopy.Web.Features.Contents.Migrations b.Navigation("ProfileColors") .IsRequired(); - b.Navigation("SocialNetworks") + b.Navigation("Socials") .IsRequired(); b.Navigation("StoredDataUrls") diff --git a/src/Web/Features/Contents/Migrations/20240805012309_Initial.cs b/src/Web/Features/Contents/Migrations/20240806041040_Initial.cs similarity index 97% rename from src/Web/Features/Contents/Migrations/20240805012309_Initial.cs rename to src/Web/Features/Contents/Migrations/20240806041040_Initial.cs index bb3198d..ab8d098 100644 --- a/src/Web/Features/Contents/Migrations/20240805012309_Initial.cs +++ b/src/Web/Features/Contents/Migrations/20240806041040_Initial.cs @@ -79,7 +79,7 @@ namespace Hutopy.Web.Features.Contents.Migrations }); migrationBuilder.CreateTable( - name: "SocialNetworks", + name: "Socials", schema: "Content", columns: table => new { @@ -95,9 +95,9 @@ namespace Hutopy.Web.Features.Contents.Migrations }, constraints: table => { - table.PrimaryKey("PK_SocialNetworks", x => x.CreatorId); + table.PrimaryKey("PK_Socials", x => x.CreatorId); table.ForeignKey( - name: "FK_SocialNetworks_Creators_CreatorId", + name: "FK_Socials_Creators_CreatorId", column: x => x.CreatorId, principalSchema: "Content", principalTable: "Creators", @@ -172,7 +172,7 @@ namespace Hutopy.Web.Features.Contents.Migrations schema: "Content"); migrationBuilder.DropTable( - name: "SocialNetworks", + name: "Socials", schema: "Content"); migrationBuilder.DropTable( diff --git a/src/Web/Features/Contents/Migrations/ContentDbContextModelSnapshot.cs b/src/Web/Features/Contents/Migrations/ContentDbContextModelSnapshot.cs index 2904a21..09fb617 100644 --- a/src/Web/Features/Contents/Migrations/ContentDbContextModelSnapshot.cs +++ b/src/Web/Features/Contents/Migrations/ContentDbContextModelSnapshot.cs @@ -160,7 +160,7 @@ namespace Hutopy.Web.Features.Contents.Migrations .HasForeignKey("CreatorId"); }); - b.OwnsOne("Hutopy.Web.Features.Contents.Data.SocialNetworks", "SocialNetworks", b1 => + b.OwnsOne("Hutopy.Web.Features.Contents.Data.Socials", "Socials", b1 => { b1.Property("CreatorId") .HasColumnType("uuid"); @@ -199,7 +199,7 @@ namespace Hutopy.Web.Features.Contents.Migrations b1.HasKey("CreatorId"); - b1.ToTable("SocialNetworks", "Content"); + b1.ToTable("Socials", "Content"); b1.WithOwner() .HasForeignKey("CreatorId"); @@ -232,7 +232,7 @@ namespace Hutopy.Web.Features.Contents.Migrations b.Navigation("ProfileColors") .IsRequired(); - b.Navigation("SocialNetworks") + b.Navigation("Socials") .IsRequired(); b.Navigation("StoredDataUrls") diff --git a/src/Web/TestDataSeeder.cs b/src/Web/TestDataSeeder.cs index 1b23093..105fb29 100644 --- a/src/Web/TestDataSeeder.cs +++ b/src/Web/TestDataSeeder.cs @@ -193,7 +193,7 @@ internal class TestDataSeeder( { BannerTop = "#A30E79", BannerBottom = "#6B0065", Accent = "#23393B", Menu = "#53B93B", }, - SocialNetworks = + Socials = new() { XUrl = "https://twitter.com/Hutopyinc", @@ -218,7 +218,7 @@ internal class TestDataSeeder( }, ProfileColors = new() { BannerTop = "#231F20", BannerBottom = "#231F20", Accent = "#272526", Menu = "#FFFFFF" }, - SocialNetworks = new() + Socials = new() { FacebookUrl = "https://www.facebook.com/arps.company", InstagramUrl = "https://www.instagram.com/arps.co/", @@ -246,7 +246,7 @@ internal class TestDataSeeder( { BannerTop = "#231F20", BannerBottom = "#272526", Accent = "#231F20", Menu = "#231F20", }, - SocialNetworks = + Socials = new() { FacebookUrl = "https://www.facebook.com/chloegestionmedias", @@ -272,7 +272,7 @@ internal class TestDataSeeder( { BannerTop = "#0BAAB2", BannerBottom = "#006D77", Accent = "#CC6F91", Menu = "#CC6F91", }, - SocialNetworks = + Socials = new() { FacebookUrl = "https://www.facebook.com/GuillaumeMousseau222", @@ -300,7 +300,7 @@ internal class TestDataSeeder( { BannerTop = "#CC6F91", BannerBottom = "#FBC702", Accent = "#FBC702", Menu = "#FBC702", }, - SocialNetworks = + Socials = new() { FacebookUrl = "https://www.facebook.com/Hutopy", @@ -327,7 +327,7 @@ internal class TestDataSeeder( { BannerTop = "#101B49", BannerBottom = "#698FE7", Accent = "#1D1D1B", Menu = "#1D1D1B", }, - SocialNetworks = + Socials = new() { FacebookUrl = "https://www.facebook.com/MathieuCaronPro/", From db740c161cc441185e7b9c7add24b2d7325e44eb Mon Sep 17 00:00:00 2001 From: Jonathan Bourdon Date: Tue, 6 Aug 2024 00:54:26 -0400 Subject: [PATCH 152/229] BUG - Bypass current issue with ContainerNames.Creators --- src/Web/Features/Contents/Handlers/ChangeBanner.cs | 3 ++- src/Web/Features/Contents/Handlers/ChangeLogo.cs | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Web/Features/Contents/Handlers/ChangeBanner.cs b/src/Web/Features/Contents/Handlers/ChangeBanner.cs index f75cc98..9121288 100644 --- a/src/Web/Features/Contents/Handlers/ChangeBanner.cs +++ b/src/Web/Features/Contents/Handlers/ChangeBanner.cs @@ -38,8 +38,9 @@ public class ChangeBannerHandler( return; } + // TODO: this upload should be done to the Creators container var blobUrl = await blobStorage.UploadFileAsync( - ContainerNames.Creators, + ContainerNames.Users, $"{request.CreatorId}/{SubDirectoryNames.Profile}/{CommonFileNames.BannerPicture}", request.File.OpenReadStream(), request.File.ContentType, diff --git a/src/Web/Features/Contents/Handlers/ChangeLogo.cs b/src/Web/Features/Contents/Handlers/ChangeLogo.cs index 1d3d39e..e491277 100644 --- a/src/Web/Features/Contents/Handlers/ChangeLogo.cs +++ b/src/Web/Features/Contents/Handlers/ChangeLogo.cs @@ -38,8 +38,9 @@ public class ChangeLogoHandler( return; } + // TODO: this upload should be done to the Creators container var blobUrl = await blobStorage.UploadFileAsync( - ContainerNames.Creators, + ContainerNames.Users, $"{request.CreatorId}/{SubDirectoryNames.Profile}/{CommonFileNames.ProfilePicture}", request.File.OpenReadStream(), request.File.ContentType, From d370c2a1519b073fba35ba456b06d0d487418d11 Mon Sep 17 00:00:00 2001 From: Jonathan Bourdon Date: Tue, 6 Aug 2024 01:04:15 -0400 Subject: [PATCH 153/229] Renames StoredDataUrls to Images --- .../Contents/Data/ContentDbContext.cs | 4 +- src/Web/Features/Contents/Data/Creator.cs | 8 +- .../Contents/Handlers/ChangeBanner.cs | 4 +- .../Features/Contents/Handlers/ChangeLogo.cs | 4 +- .../Contents/Handlers/GetCreatorByAlias.cs | 2 +- .../Contents/Handlers/GetSubscriptions.cs | 2 +- .../Contents/Handlers/Models/CreatorModel.cs | 2 +- .../Contents/Handlers/SubscribeToCreator.cs | 2 +- .../20240806041040_Initial.Designer.cs | 258 ------------------ .../Migrations/20240806041040_Initial.cs | 191 ------------- .../ContentDbContextModelSnapshot.cs | 255 ----------------- src/Web/TestDataSeeder.cs | 38 +-- 12 files changed, 33 insertions(+), 737 deletions(-) delete mode 100644 src/Web/Features/Contents/Migrations/20240806041040_Initial.Designer.cs delete mode 100644 src/Web/Features/Contents/Migrations/20240806041040_Initial.cs delete mode 100644 src/Web/Features/Contents/Migrations/ContentDbContextModelSnapshot.cs diff --git a/src/Web/Features/Contents/Data/ContentDbContext.cs b/src/Web/Features/Contents/Data/ContentDbContext.cs index 42359d6..8ebc843 100644 --- a/src/Web/Features/Contents/Data/ContentDbContext.cs +++ b/src/Web/Features/Contents/Data/ContentDbContext.cs @@ -54,7 +54,7 @@ public class ContentDbContext( modelBuilder .Entity() - .OwnsOne(x => x.StoredDataUrls) - .ToTable(nameof(StoredDataUrls)); + .OwnsOne(x => x.Images) + .ToTable(nameof(Images)); } } diff --git a/src/Web/Features/Contents/Data/Creator.cs b/src/Web/Features/Contents/Data/Creator.cs index a96d484..689b1d8 100644 --- a/src/Web/Features/Contents/Data/Creator.cs +++ b/src/Web/Features/Contents/Data/Creator.cs @@ -12,7 +12,7 @@ public class Creator public About About { get; set; } = new(); public Socials Socials { get; set; } = new(); public ProfileColors ProfileColors { get; set; } = new(); - public StoredDataUrls StoredDataUrls { get; set; } = new(); + public Images Images { get; set; } = new(); } public class About @@ -41,8 +41,8 @@ public class Socials [MaxLength(255)] public string? WebsiteUrl { get; set; } } -public class StoredDataUrls +public class Images { - [MaxLength(255)] public string? BannerPictureUrl { get; set; } - [MaxLength(255)] public string? ProfilePictureUrl { get; set; } + [MaxLength(255)] public string? Banner { get; set; } + [MaxLength(255)] public string? Logo { get; set; } } diff --git a/src/Web/Features/Contents/Handlers/ChangeBanner.cs b/src/Web/Features/Contents/Handlers/ChangeBanner.cs index 9121288..0a4f8d8 100644 --- a/src/Web/Features/Contents/Handlers/ChangeBanner.cs +++ b/src/Web/Features/Contents/Handlers/ChangeBanner.cs @@ -27,7 +27,7 @@ public class ChangeBannerHandler( { var creator = await context .Creators - .Include(c => c.StoredDataUrls) + .Include(c => c.Images) .SingleOrDefaultAsync( c => c.Id == request.CreatorId, cancellationToken: ct); @@ -46,7 +46,7 @@ public class ChangeBannerHandler( request.File.ContentType, ct); - creator.StoredDataUrls.BannerPictureUrl = blobUrl; + creator.Images.Banner = blobUrl; await context.SaveChangesAsync(ct); diff --git a/src/Web/Features/Contents/Handlers/ChangeLogo.cs b/src/Web/Features/Contents/Handlers/ChangeLogo.cs index e491277..4fda059 100644 --- a/src/Web/Features/Contents/Handlers/ChangeLogo.cs +++ b/src/Web/Features/Contents/Handlers/ChangeLogo.cs @@ -27,7 +27,7 @@ public class ChangeLogoHandler( { var creator = await context .Creators - .Include(c => c.StoredDataUrls) + .Include(c => c.Images) .SingleOrDefaultAsync( c => c.Id == request.CreatorId, cancellationToken: ct); @@ -46,7 +46,7 @@ public class ChangeLogoHandler( request.File.ContentType, ct); - creator.StoredDataUrls.ProfilePictureUrl = blobUrl; + creator.Images.Logo = blobUrl; await context.SaveChangesAsync(ct); diff --git a/src/Web/Features/Contents/Handlers/GetCreatorByAlias.cs b/src/Web/Features/Contents/Handlers/GetCreatorByAlias.cs index 30ed02a..fe5d8e5 100644 --- a/src/Web/Features/Contents/Handlers/GetCreatorByAlias.cs +++ b/src/Web/Features/Contents/Handlers/GetCreatorByAlias.cs @@ -63,7 +63,7 @@ public class GetCreatorByAliasHandler( About = creator.About, Socials = creator.Socials, ProfileColors = creator.ProfileColors, - StoredDataUrls = creator.StoredDataUrls, + Images = creator.Images, SubscriberCount = subscriberCount, }; diff --git a/src/Web/Features/Contents/Handlers/GetSubscriptions.cs b/src/Web/Features/Contents/Handlers/GetSubscriptions.cs index 1f5690c..035cb87 100644 --- a/src/Web/Features/Contents/Handlers/GetSubscriptions.cs +++ b/src/Web/Features/Contents/Handlers/GetSubscriptions.cs @@ -27,7 +27,7 @@ public class GetSubscriptionsHandler( .Select(s => new SubscriptionModel( s.CreatorId, s.Creator!.Name, - s.Creator.StoredDataUrls.ProfilePictureUrl)) + s.Creator.Images.Logo)) .ToListAsync(cancellationToken: ct); await SendOkAsync(subscriptions, ct); diff --git a/src/Web/Features/Contents/Handlers/Models/CreatorModel.cs b/src/Web/Features/Contents/Handlers/Models/CreatorModel.cs index b43bcfe..e59db4e 100644 --- a/src/Web/Features/Contents/Handlers/Models/CreatorModel.cs +++ b/src/Web/Features/Contents/Handlers/Models/CreatorModel.cs @@ -11,6 +11,6 @@ public class CreatorModel public About About { get; set; } public Socials Socials { get; set; } public ProfileColors ProfileColors { get; set; } - public StoredDataUrls StoredDataUrls { get; set; } + public Images Images { get; set; } public int SubscriberCount { get; set; } } diff --git a/src/Web/Features/Contents/Handlers/SubscribeToCreator.cs b/src/Web/Features/Contents/Handlers/SubscribeToCreator.cs index eb20946..9c37d3b 100644 --- a/src/Web/Features/Contents/Handlers/SubscribeToCreator.cs +++ b/src/Web/Features/Contents/Handlers/SubscribeToCreator.cs @@ -38,7 +38,7 @@ public sealed class SubscribeToCreatorHandler( .Select(c => new SubscriptionModel( req.CreatorId, c.Name, - c.StoredDataUrls.ProfilePictureUrl + c.Images.Logo )) .FirstOrDefaultAsync(cancellationToken: ct); diff --git a/src/Web/Features/Contents/Migrations/20240806041040_Initial.Designer.cs b/src/Web/Features/Contents/Migrations/20240806041040_Initial.Designer.cs deleted file mode 100644 index 154bd64..0000000 --- a/src/Web/Features/Contents/Migrations/20240806041040_Initial.Designer.cs +++ /dev/null @@ -1,258 +0,0 @@ -// -using System; -using Hutopy.Web.Features.Contents.Data; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; - -#nullable disable - -namespace Hutopy.Web.Features.Contents.Migrations -{ - [DbContext(typeof(ContentDbContext))] - [Migration("20240806041040_Initial")] - partial class Initial - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasDefaultSchema("Content") - .HasAnnotation("ProductVersion", "8.0.4") - .HasAnnotation("Relational:MaxIdentifierLength", 63); - - NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); - - modelBuilder.Entity("Hutopy.Web.Features.Contents.Data.Content", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid"); - - b.Property("CreatedAt") - .ValueGeneratedOnAdd() - .HasColumnType("timestamp with time zone") - .HasDefaultValueSql("CURRENT_TIMESTAMP"); - - b.Property("CreatedBy") - .HasColumnType("uuid"); - - b.Property("Description") - .IsRequired() - .HasMaxLength(2048) - .HasColumnType("character varying(2048)"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)"); - - b.Property("Urls") - .HasColumnType("text[]"); - - b.HasKey("Id"); - - b.HasIndex("CreatedBy"); - - b.ToTable("Contents", "Content"); - }); - - modelBuilder.Entity("Hutopy.Web.Features.Contents.Data.Creator", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("CreatedBy") - .HasColumnType("uuid"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("character varying(255)"); - - b.HasKey("Id"); - - b.ToTable("Creators", "Content"); - }); - - modelBuilder.Entity("Hutopy.Web.Features.Contents.Data.Subscription", b => - { - b.Property("CreatedBy") - .HasColumnType("uuid"); - - b.Property("CreatorId") - .HasColumnType("uuid"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone"); - - b.HasKey("CreatedBy", "CreatorId"); - - b.HasIndex("CreatorId"); - - b.ToTable("Subscriptions", "Content"); - }); - - modelBuilder.Entity("Hutopy.Web.Features.Contents.Data.Content", b => - { - b.HasOne("Hutopy.Web.Features.Contents.Data.Creator", "Creator") - .WithMany() - .HasForeignKey("CreatedBy") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Creator"); - }); - - modelBuilder.Entity("Hutopy.Web.Features.Contents.Data.Creator", b => - { - b.OwnsOne("Hutopy.Web.Features.Contents.Data.About", "About", b1 => - { - b1.Property("CreatorId") - .HasColumnType("uuid"); - - b1.Property("Description") - .HasMaxLength(2048) - .HasColumnType("character varying(2048)"); - - b1.Property("Title") - .HasMaxLength(255) - .HasColumnType("character varying(255)"); - - b1.HasKey("CreatorId"); - - b1.ToTable("Creators", "Content"); - - b1.WithOwner() - .HasForeignKey("CreatorId"); - }); - - b.OwnsOne("Hutopy.Web.Features.Contents.Data.ProfileColors", "ProfileColors", b1 => - { - b1.Property("CreatorId") - .HasColumnType("uuid"); - - b1.Property("Accent") - .HasMaxLength(9) - .HasColumnType("character varying(9)"); - - b1.Property("BannerBottom") - .HasMaxLength(9) - .HasColumnType("character varying(9)"); - - b1.Property("BannerTop") - .HasMaxLength(9) - .HasColumnType("character varying(9)"); - - b1.Property("Menu") - .HasMaxLength(9) - .HasColumnType("character varying(9)"); - - b1.HasKey("CreatorId"); - - b1.ToTable("ProfileColors", "Content"); - - b1.WithOwner() - .HasForeignKey("CreatorId"); - }); - - b.OwnsOne("Hutopy.Web.Features.Contents.Data.Socials", "Socials", b1 => - { - b1.Property("CreatorId") - .HasColumnType("uuid"); - - b1.Property("FacebookUrl") - .HasMaxLength(255) - .HasColumnType("character varying(255)"); - - b1.Property("InstagramUrl") - .HasMaxLength(255) - .HasColumnType("character varying(255)"); - - b1.Property("LinkedInUrl") - .HasMaxLength(255) - .HasColumnType("character varying(255)"); - - b1.Property("RedditUrl") - .HasMaxLength(255) - .HasColumnType("character varying(255)"); - - b1.Property("TikTokUrl") - .HasMaxLength(255) - .HasColumnType("character varying(255)"); - - b1.Property("WebsiteUrl") - .HasMaxLength(255) - .HasColumnType("character varying(255)"); - - b1.Property("XUrl") - .HasMaxLength(255) - .HasColumnType("character varying(255)"); - - b1.Property("YoutubeUrl") - .HasMaxLength(255) - .HasColumnType("character varying(255)"); - - b1.HasKey("CreatorId"); - - b1.ToTable("Socials", "Content"); - - b1.WithOwner() - .HasForeignKey("CreatorId"); - }); - - b.OwnsOne("Hutopy.Web.Features.Contents.Data.StoredDataUrls", "StoredDataUrls", b1 => - { - b1.Property("CreatorId") - .HasColumnType("uuid"); - - b1.Property("BannerPictureUrl") - .HasMaxLength(255) - .HasColumnType("character varying(255)"); - - b1.Property("ProfilePictureUrl") - .HasMaxLength(255) - .HasColumnType("character varying(255)"); - - b1.HasKey("CreatorId"); - - b1.ToTable("StoredDataUrls", "Content"); - - b1.WithOwner() - .HasForeignKey("CreatorId"); - }); - - b.Navigation("About") - .IsRequired(); - - b.Navigation("ProfileColors") - .IsRequired(); - - b.Navigation("Socials") - .IsRequired(); - - b.Navigation("StoredDataUrls") - .IsRequired(); - }); - - modelBuilder.Entity("Hutopy.Web.Features.Contents.Data.Subscription", b => - { - b.HasOne("Hutopy.Web.Features.Contents.Data.Creator", "Creator") - .WithMany() - .HasForeignKey("CreatorId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Creator"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Web/Features/Contents/Migrations/20240806041040_Initial.cs b/src/Web/Features/Contents/Migrations/20240806041040_Initial.cs deleted file mode 100644 index ab8d098..0000000 --- a/src/Web/Features/Contents/Migrations/20240806041040_Initial.cs +++ /dev/null @@ -1,191 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace Hutopy.Web.Features.Contents.Migrations -{ - /// - public partial class Initial : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.EnsureSchema( - name: "Content"); - - migrationBuilder.CreateTable( - name: "Creators", - schema: "Content", - columns: table => new - { - Id = table.Column(type: "uuid", nullable: false), - CreatedBy = table.Column(type: "uuid", nullable: false), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false), - Name = table.Column(type: "character varying(255)", maxLength: 255, nullable: false), - About_Title = table.Column(type: "character varying(255)", maxLength: 255, nullable: true), - About_Description = table.Column(type: "character varying(2048)", maxLength: 2048, nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_Creators", x => x.Id); - }); - - migrationBuilder.CreateTable( - name: "Contents", - schema: "Content", - columns: table => new - { - Id = table.Column(type: "uuid", nullable: false), - CreatedBy = table.Column(type: "uuid", nullable: false), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, defaultValueSql: "CURRENT_TIMESTAMP"), - Title = table.Column(type: "character varying(128)", maxLength: 128, nullable: false), - Description = table.Column(type: "character varying(2048)", maxLength: 2048, nullable: false), - Urls = table.Column(type: "text[]", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_Contents", x => x.Id); - table.ForeignKey( - name: "FK_Contents_Creators_CreatedBy", - column: x => x.CreatedBy, - principalSchema: "Content", - principalTable: "Creators", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "ProfileColors", - schema: "Content", - columns: table => new - { - CreatorId = table.Column(type: "uuid", nullable: false), - BannerTop = table.Column(type: "character varying(9)", maxLength: 9, nullable: true), - BannerBottom = table.Column(type: "character varying(9)", maxLength: 9, nullable: true), - Accent = table.Column(type: "character varying(9)", maxLength: 9, nullable: true), - Menu = table.Column(type: "character varying(9)", maxLength: 9, nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_ProfileColors", x => x.CreatorId); - table.ForeignKey( - name: "FK_ProfileColors_Creators_CreatorId", - column: x => x.CreatorId, - principalSchema: "Content", - principalTable: "Creators", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "Socials", - schema: "Content", - columns: table => new - { - CreatorId = table.Column(type: "uuid", nullable: false), - FacebookUrl = table.Column(type: "character varying(255)", maxLength: 255, nullable: true), - InstagramUrl = table.Column(type: "character varying(255)", maxLength: 255, nullable: true), - XUrl = table.Column(type: "character varying(255)", maxLength: 255, nullable: true), - LinkedInUrl = table.Column(type: "character varying(255)", maxLength: 255, nullable: true), - TikTokUrl = table.Column(type: "character varying(255)", maxLength: 255, nullable: true), - YoutubeUrl = table.Column(type: "character varying(255)", maxLength: 255, nullable: true), - RedditUrl = table.Column(type: "character varying(255)", maxLength: 255, nullable: true), - WebsiteUrl = table.Column(type: "character varying(255)", maxLength: 255, nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_Socials", x => x.CreatorId); - table.ForeignKey( - name: "FK_Socials_Creators_CreatorId", - column: x => x.CreatorId, - principalSchema: "Content", - principalTable: "Creators", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "StoredDataUrls", - schema: "Content", - columns: table => new - { - CreatorId = table.Column(type: "uuid", nullable: false), - BannerPictureUrl = table.Column(type: "character varying(255)", maxLength: 255, nullable: true), - ProfilePictureUrl = table.Column(type: "character varying(255)", maxLength: 255, nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_StoredDataUrls", x => x.CreatorId); - table.ForeignKey( - name: "FK_StoredDataUrls_Creators_CreatorId", - column: x => x.CreatorId, - principalSchema: "Content", - principalTable: "Creators", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "Subscriptions", - schema: "Content", - columns: table => new - { - CreatedBy = table.Column(type: "uuid", nullable: false), - CreatorId = table.Column(type: "uuid", nullable: false), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_Subscriptions", x => new { x.CreatedBy, x.CreatorId }); - table.ForeignKey( - name: "FK_Subscriptions_Creators_CreatorId", - column: x => x.CreatorId, - principalSchema: "Content", - principalTable: "Creators", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateIndex( - name: "IX_Contents_CreatedBy", - schema: "Content", - table: "Contents", - column: "CreatedBy"); - - migrationBuilder.CreateIndex( - name: "IX_Subscriptions_CreatorId", - schema: "Content", - table: "Subscriptions", - column: "CreatorId"); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "Contents", - schema: "Content"); - - migrationBuilder.DropTable( - name: "ProfileColors", - schema: "Content"); - - migrationBuilder.DropTable( - name: "Socials", - schema: "Content"); - - migrationBuilder.DropTable( - name: "StoredDataUrls", - schema: "Content"); - - migrationBuilder.DropTable( - name: "Subscriptions", - schema: "Content"); - - migrationBuilder.DropTable( - name: "Creators", - schema: "Content"); - } - } -} diff --git a/src/Web/Features/Contents/Migrations/ContentDbContextModelSnapshot.cs b/src/Web/Features/Contents/Migrations/ContentDbContextModelSnapshot.cs deleted file mode 100644 index 09fb617..0000000 --- a/src/Web/Features/Contents/Migrations/ContentDbContextModelSnapshot.cs +++ /dev/null @@ -1,255 +0,0 @@ -// -using System; -using Hutopy.Web.Features.Contents.Data; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; - -#nullable disable - -namespace Hutopy.Web.Features.Contents.Migrations -{ - [DbContext(typeof(ContentDbContext))] - partial class ContentDbContextModelSnapshot : ModelSnapshot - { - protected override void BuildModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasDefaultSchema("Content") - .HasAnnotation("ProductVersion", "8.0.4") - .HasAnnotation("Relational:MaxIdentifierLength", 63); - - NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); - - modelBuilder.Entity("Hutopy.Web.Features.Contents.Data.Content", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid"); - - b.Property("CreatedAt") - .ValueGeneratedOnAdd() - .HasColumnType("timestamp with time zone") - .HasDefaultValueSql("CURRENT_TIMESTAMP"); - - b.Property("CreatedBy") - .HasColumnType("uuid"); - - b.Property("Description") - .IsRequired() - .HasMaxLength(2048) - .HasColumnType("character varying(2048)"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)"); - - b.Property("Urls") - .HasColumnType("text[]"); - - b.HasKey("Id"); - - b.HasIndex("CreatedBy"); - - b.ToTable("Contents", "Content"); - }); - - modelBuilder.Entity("Hutopy.Web.Features.Contents.Data.Creator", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("CreatedBy") - .HasColumnType("uuid"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("character varying(255)"); - - b.HasKey("Id"); - - b.ToTable("Creators", "Content"); - }); - - modelBuilder.Entity("Hutopy.Web.Features.Contents.Data.Subscription", b => - { - b.Property("CreatedBy") - .HasColumnType("uuid"); - - b.Property("CreatorId") - .HasColumnType("uuid"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone"); - - b.HasKey("CreatedBy", "CreatorId"); - - b.HasIndex("CreatorId"); - - b.ToTable("Subscriptions", "Content"); - }); - - modelBuilder.Entity("Hutopy.Web.Features.Contents.Data.Content", b => - { - b.HasOne("Hutopy.Web.Features.Contents.Data.Creator", "Creator") - .WithMany() - .HasForeignKey("CreatedBy") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Creator"); - }); - - modelBuilder.Entity("Hutopy.Web.Features.Contents.Data.Creator", b => - { - b.OwnsOne("Hutopy.Web.Features.Contents.Data.About", "About", b1 => - { - b1.Property("CreatorId") - .HasColumnType("uuid"); - - b1.Property("Description") - .HasMaxLength(2048) - .HasColumnType("character varying(2048)"); - - b1.Property("Title") - .HasMaxLength(255) - .HasColumnType("character varying(255)"); - - b1.HasKey("CreatorId"); - - b1.ToTable("Creators", "Content"); - - b1.WithOwner() - .HasForeignKey("CreatorId"); - }); - - b.OwnsOne("Hutopy.Web.Features.Contents.Data.ProfileColors", "ProfileColors", b1 => - { - b1.Property("CreatorId") - .HasColumnType("uuid"); - - b1.Property("Accent") - .HasMaxLength(9) - .HasColumnType("character varying(9)"); - - b1.Property("BannerBottom") - .HasMaxLength(9) - .HasColumnType("character varying(9)"); - - b1.Property("BannerTop") - .HasMaxLength(9) - .HasColumnType("character varying(9)"); - - b1.Property("Menu") - .HasMaxLength(9) - .HasColumnType("character varying(9)"); - - b1.HasKey("CreatorId"); - - b1.ToTable("ProfileColors", "Content"); - - b1.WithOwner() - .HasForeignKey("CreatorId"); - }); - - b.OwnsOne("Hutopy.Web.Features.Contents.Data.Socials", "Socials", b1 => - { - b1.Property("CreatorId") - .HasColumnType("uuid"); - - b1.Property("FacebookUrl") - .HasMaxLength(255) - .HasColumnType("character varying(255)"); - - b1.Property("InstagramUrl") - .HasMaxLength(255) - .HasColumnType("character varying(255)"); - - b1.Property("LinkedInUrl") - .HasMaxLength(255) - .HasColumnType("character varying(255)"); - - b1.Property("RedditUrl") - .HasMaxLength(255) - .HasColumnType("character varying(255)"); - - b1.Property("TikTokUrl") - .HasMaxLength(255) - .HasColumnType("character varying(255)"); - - b1.Property("WebsiteUrl") - .HasMaxLength(255) - .HasColumnType("character varying(255)"); - - b1.Property("XUrl") - .HasMaxLength(255) - .HasColumnType("character varying(255)"); - - b1.Property("YoutubeUrl") - .HasMaxLength(255) - .HasColumnType("character varying(255)"); - - b1.HasKey("CreatorId"); - - b1.ToTable("Socials", "Content"); - - b1.WithOwner() - .HasForeignKey("CreatorId"); - }); - - b.OwnsOne("Hutopy.Web.Features.Contents.Data.StoredDataUrls", "StoredDataUrls", b1 => - { - b1.Property("CreatorId") - .HasColumnType("uuid"); - - b1.Property("BannerPictureUrl") - .HasMaxLength(255) - .HasColumnType("character varying(255)"); - - b1.Property("ProfilePictureUrl") - .HasMaxLength(255) - .HasColumnType("character varying(255)"); - - b1.HasKey("CreatorId"); - - b1.ToTable("StoredDataUrls", "Content"); - - b1.WithOwner() - .HasForeignKey("CreatorId"); - }); - - b.Navigation("About") - .IsRequired(); - - b.Navigation("ProfileColors") - .IsRequired(); - - b.Navigation("Socials") - .IsRequired(); - - b.Navigation("StoredDataUrls") - .IsRequired(); - }); - - modelBuilder.Entity("Hutopy.Web.Features.Contents.Data.Subscription", b => - { - b.HasOne("Hutopy.Web.Features.Contents.Data.Creator", "Creator") - .WithMany() - .HasForeignKey("CreatorId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Creator"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Web/TestDataSeeder.cs b/src/Web/TestDataSeeder.cs index 105fb29..f1b3189 100644 --- a/src/Web/TestDataSeeder.cs +++ b/src/Web/TestDataSeeder.cs @@ -43,7 +43,7 @@ internal class TestDataSeeder( { var creatorUser = await CreateUserAsync( creator.Name, - creator.StoredDataUrls.ProfilePictureUrl, + creator.Images.Logo, Roles.Creator); creator.Id = creatorUser.Id; @@ -200,10 +200,10 @@ internal class TestDataSeeder( FacebookUrl = "https://www.facebook.com/Hutopy", InstagramUrl = "https://www.instagram.com/hutopy.inc/" }, - StoredDataUrls = new() + Images = new() { - BannerPictureUrl = "/images/usersmedia/HutopyProfile/banners/banner01.png", - ProfilePictureUrl = "/images/usersmedia/HutopyProfile/profilepictures/profileHutopyProfile01.png" + Banner = "/images/usersmedia/HutopyProfile/banners/banner01.png", + Logo = "/images/usersmedia/HutopyProfile/profilepictures/profileHutopyProfile01.png" } }; @@ -227,10 +227,10 @@ internal class TestDataSeeder( LinkedInUrl = "https://www.linkedin.com/in/mickael-simard-96079a90/", WebsiteUrl = "https://www.arps.ca/" }, - StoredDataUrls = new() + Images = new() { - BannerPictureUrl = "/images/usersmedia/ARPS/banners/bannerARPS01.png", - ProfilePictureUrl = "/images/usersmedia/ARPS/profilepictures/profileARPS.png" + Banner = "/images/usersmedia/ARPS/banners/bannerARPS01.png", + Logo = "/images/usersmedia/ARPS/profilepictures/profileARPS.png" } }; @@ -252,10 +252,10 @@ internal class TestDataSeeder( FacebookUrl = "https://www.facebook.com/chloegestionmedias", InstagramUrl = "https://www.instagram.com/chloe.photo_gms", }, - StoredDataUrls = new() + Images = new() { - BannerPictureUrl = "/images/usersmedia/chloebeaugrand/banners/bannerChloeBeaugrand01.png", - ProfilePictureUrl = "/images/usersmedia/chloebeaugrand/profilepictures/profileChloeBeaugrand01.png" + Banner = "/images/usersmedia/chloebeaugrand/banners/bannerChloeBeaugrand01.png", + Logo = "/images/usersmedia/chloebeaugrand/profilepictures/profileChloeBeaugrand01.png" } }; @@ -279,10 +279,10 @@ internal class TestDataSeeder( InstagramUrl = "https://www.instagram.com/guillaumeaime/", TikTokUrl = "https://www.tiktok.com/@guillaumeaime" }, - StoredDataUrls = new() + Images = new() { - BannerPictureUrl = "/images/usersmedia/guillaumeMousseau/banners/bannerGuillaumeMousseau01.png", - ProfilePictureUrl = + Banner = "/images/usersmedia/guillaumeMousseau/banners/bannerGuillaumeMousseau01.png", + Logo = "/images/usersmedia/guillaumeMousseau/profilepictures/profileGuillaumeMousseau01.png" } }; @@ -307,10 +307,10 @@ internal class TestDataSeeder( InstagramUrl = "https://www.instagram.com/guillaumeaime/", WebsiteUrl = "https://fondationleffet.ca/" }, - StoredDataUrls = new() + Images = new() { - BannerPictureUrl = "/images/usersmedia/leffet/banners/banner02.png", - ProfilePictureUrl = "/images/usersmedia/leffet/profilepictures/leffetProfile01.png" + Banner = "/images/usersmedia/leffet/banners/banner02.png", + Logo = "/images/usersmedia/leffet/profilepictures/leffetProfile01.png" } }; @@ -333,10 +333,10 @@ internal class TestDataSeeder( FacebookUrl = "https://www.facebook.com/MathieuCaronPro/", YoutubeUrl = "https://www.youtube.com/@lesinterviewsatypiquesdema4692", }, - StoredDataUrls = new() + Images = new() { - BannerPictureUrl = "/images/usersmedia/mathieuCaron/banners/bannerMathieuCaron01.png", - ProfilePictureUrl = "/images/usersmedia/mathieuCaron/profilepictures/profileMathieuCaron01.png" + Banner = "/images/usersmedia/mathieuCaron/banners/bannerMathieuCaron01.png", + Logo = "/images/usersmedia/mathieuCaron/profilepictures/profileMathieuCaron01.png" } }; From c1ec28239813e961f4a91e1f2829de7ff4c17eda Mon Sep 17 00:00:00 2001 From: Jonathan Bourdon Date: Tue, 6 Aug 2024 01:04:15 -0400 Subject: [PATCH 154/229] Renames StoredDataUrls to Images --- .../20240806050040_Initial.Designer.cs | 258 ++++++++++++++++++ .../Migrations/20240806050040_Initial.cs | 191 +++++++++++++ .../ContentDbContextModelSnapshot.cs | 255 +++++++++++++++++ 3 files changed, 704 insertions(+) create mode 100644 src/Web/Features/Contents/Migrations/20240806050040_Initial.Designer.cs create mode 100644 src/Web/Features/Contents/Migrations/20240806050040_Initial.cs create mode 100644 src/Web/Features/Contents/Migrations/ContentDbContextModelSnapshot.cs diff --git a/src/Web/Features/Contents/Migrations/20240806050040_Initial.Designer.cs b/src/Web/Features/Contents/Migrations/20240806050040_Initial.Designer.cs new file mode 100644 index 0000000..7c9d53c --- /dev/null +++ b/src/Web/Features/Contents/Migrations/20240806050040_Initial.Designer.cs @@ -0,0 +1,258 @@ +// +using System; +using Hutopy.Web.Features.Contents.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace Hutopy.Web.Features.Contents.Migrations +{ + [DbContext(typeof(ContentDbContext))] + [Migration("20240806050040_Initial")] + partial class Initial + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasDefaultSchema("Content") + .HasAnnotation("ProductVersion", "8.0.4") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("Hutopy.Web.Features.Contents.Data.Content", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("CURRENT_TIMESTAMP"); + + b.Property("CreatedBy") + .HasColumnType("uuid"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(2048) + .HasColumnType("character varying(2048)"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("Urls") + .HasColumnType("text[]"); + + b.HasKey("Id"); + + b.HasIndex("CreatedBy"); + + b.ToTable("Contents", "Content"); + }); + + modelBuilder.Entity("Hutopy.Web.Features.Contents.Data.Creator", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("uuid"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.HasKey("Id"); + + b.ToTable("Creators", "Content"); + }); + + modelBuilder.Entity("Hutopy.Web.Features.Contents.Data.Subscription", b => + { + b.Property("CreatedBy") + .HasColumnType("uuid"); + + b.Property("CreatorId") + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("CreatedBy", "CreatorId"); + + b.HasIndex("CreatorId"); + + b.ToTable("Subscriptions", "Content"); + }); + + modelBuilder.Entity("Hutopy.Web.Features.Contents.Data.Content", b => + { + b.HasOne("Hutopy.Web.Features.Contents.Data.Creator", "Creator") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Creator"); + }); + + modelBuilder.Entity("Hutopy.Web.Features.Contents.Data.Creator", b => + { + b.OwnsOne("Hutopy.Web.Features.Contents.Data.About", "About", b1 => + { + b1.Property("CreatorId") + .HasColumnType("uuid"); + + b1.Property("Description") + .HasMaxLength(2048) + .HasColumnType("character varying(2048)"); + + b1.Property("Title") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.HasKey("CreatorId"); + + b1.ToTable("Creators", "Content"); + + b1.WithOwner() + .HasForeignKey("CreatorId"); + }); + + b.OwnsOne("Hutopy.Web.Features.Contents.Data.Images", "Images", b1 => + { + b1.Property("CreatorId") + .HasColumnType("uuid"); + + b1.Property("Banner") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.Property("Logo") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.HasKey("CreatorId"); + + b1.ToTable("Images", "Content"); + + b1.WithOwner() + .HasForeignKey("CreatorId"); + }); + + b.OwnsOne("Hutopy.Web.Features.Contents.Data.ProfileColors", "ProfileColors", b1 => + { + b1.Property("CreatorId") + .HasColumnType("uuid"); + + b1.Property("Accent") + .HasMaxLength(9) + .HasColumnType("character varying(9)"); + + b1.Property("BannerBottom") + .HasMaxLength(9) + .HasColumnType("character varying(9)"); + + b1.Property("BannerTop") + .HasMaxLength(9) + .HasColumnType("character varying(9)"); + + b1.Property("Menu") + .HasMaxLength(9) + .HasColumnType("character varying(9)"); + + b1.HasKey("CreatorId"); + + b1.ToTable("ProfileColors", "Content"); + + b1.WithOwner() + .HasForeignKey("CreatorId"); + }); + + b.OwnsOne("Hutopy.Web.Features.Contents.Data.Socials", "Socials", b1 => + { + b1.Property("CreatorId") + .HasColumnType("uuid"); + + b1.Property("FacebookUrl") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.Property("InstagramUrl") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.Property("LinkedInUrl") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.Property("RedditUrl") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.Property("TikTokUrl") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.Property("WebsiteUrl") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.Property("XUrl") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.Property("YoutubeUrl") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.HasKey("CreatorId"); + + b1.ToTable("Socials", "Content"); + + b1.WithOwner() + .HasForeignKey("CreatorId"); + }); + + b.Navigation("About") + .IsRequired(); + + b.Navigation("Images") + .IsRequired(); + + b.Navigation("ProfileColors") + .IsRequired(); + + b.Navigation("Socials") + .IsRequired(); + }); + + modelBuilder.Entity("Hutopy.Web.Features.Contents.Data.Subscription", b => + { + b.HasOne("Hutopy.Web.Features.Contents.Data.Creator", "Creator") + .WithMany() + .HasForeignKey("CreatorId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Creator"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Web/Features/Contents/Migrations/20240806050040_Initial.cs b/src/Web/Features/Contents/Migrations/20240806050040_Initial.cs new file mode 100644 index 0000000..2563d7c --- /dev/null +++ b/src/Web/Features/Contents/Migrations/20240806050040_Initial.cs @@ -0,0 +1,191 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Hutopy.Web.Features.Contents.Migrations +{ + /// + public partial class Initial : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.EnsureSchema( + name: "Content"); + + migrationBuilder.CreateTable( + name: "Creators", + schema: "Content", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + CreatedBy = table.Column(type: "uuid", nullable: false), + CreatedAt = table.Column(type: "timestamp with time zone", nullable: false), + Name = table.Column(type: "character varying(255)", maxLength: 255, nullable: false), + About_Title = table.Column(type: "character varying(255)", maxLength: 255, nullable: true), + About_Description = table.Column(type: "character varying(2048)", maxLength: 2048, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Creators", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "Contents", + schema: "Content", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + CreatedBy = table.Column(type: "uuid", nullable: false), + CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, defaultValueSql: "CURRENT_TIMESTAMP"), + Title = table.Column(type: "character varying(128)", maxLength: 128, nullable: false), + Description = table.Column(type: "character varying(2048)", maxLength: 2048, nullable: false), + Urls = table.Column(type: "text[]", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Contents", x => x.Id); + table.ForeignKey( + name: "FK_Contents_Creators_CreatedBy", + column: x => x.CreatedBy, + principalSchema: "Content", + principalTable: "Creators", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "Images", + schema: "Content", + columns: table => new + { + CreatorId = table.Column(type: "uuid", nullable: false), + Banner = table.Column(type: "character varying(255)", maxLength: 255, nullable: true), + Logo = table.Column(type: "character varying(255)", maxLength: 255, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Images", x => x.CreatorId); + table.ForeignKey( + name: "FK_Images_Creators_CreatorId", + column: x => x.CreatorId, + principalSchema: "Content", + principalTable: "Creators", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "ProfileColors", + schema: "Content", + columns: table => new + { + CreatorId = table.Column(type: "uuid", nullable: false), + BannerTop = table.Column(type: "character varying(9)", maxLength: 9, nullable: true), + BannerBottom = table.Column(type: "character varying(9)", maxLength: 9, nullable: true), + Accent = table.Column(type: "character varying(9)", maxLength: 9, nullable: true), + Menu = table.Column(type: "character varying(9)", maxLength: 9, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_ProfileColors", x => x.CreatorId); + table.ForeignKey( + name: "FK_ProfileColors_Creators_CreatorId", + column: x => x.CreatorId, + principalSchema: "Content", + principalTable: "Creators", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "Socials", + schema: "Content", + columns: table => new + { + CreatorId = table.Column(type: "uuid", nullable: false), + FacebookUrl = table.Column(type: "character varying(255)", maxLength: 255, nullable: true), + InstagramUrl = table.Column(type: "character varying(255)", maxLength: 255, nullable: true), + XUrl = table.Column(type: "character varying(255)", maxLength: 255, nullable: true), + LinkedInUrl = table.Column(type: "character varying(255)", maxLength: 255, nullable: true), + TikTokUrl = table.Column(type: "character varying(255)", maxLength: 255, nullable: true), + YoutubeUrl = table.Column(type: "character varying(255)", maxLength: 255, nullable: true), + RedditUrl = table.Column(type: "character varying(255)", maxLength: 255, nullable: true), + WebsiteUrl = table.Column(type: "character varying(255)", maxLength: 255, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Socials", x => x.CreatorId); + table.ForeignKey( + name: "FK_Socials_Creators_CreatorId", + column: x => x.CreatorId, + principalSchema: "Content", + principalTable: "Creators", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "Subscriptions", + schema: "Content", + columns: table => new + { + CreatedBy = table.Column(type: "uuid", nullable: false), + CreatorId = table.Column(type: "uuid", nullable: false), + CreatedAt = table.Column(type: "timestamp with time zone", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Subscriptions", x => new { x.CreatedBy, x.CreatorId }); + table.ForeignKey( + name: "FK_Subscriptions_Creators_CreatorId", + column: x => x.CreatorId, + principalSchema: "Content", + principalTable: "Creators", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "IX_Contents_CreatedBy", + schema: "Content", + table: "Contents", + column: "CreatedBy"); + + migrationBuilder.CreateIndex( + name: "IX_Subscriptions_CreatorId", + schema: "Content", + table: "Subscriptions", + column: "CreatorId"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "Contents", + schema: "Content"); + + migrationBuilder.DropTable( + name: "Images", + schema: "Content"); + + migrationBuilder.DropTable( + name: "ProfileColors", + schema: "Content"); + + migrationBuilder.DropTable( + name: "Socials", + schema: "Content"); + + migrationBuilder.DropTable( + name: "Subscriptions", + schema: "Content"); + + migrationBuilder.DropTable( + name: "Creators", + schema: "Content"); + } + } +} diff --git a/src/Web/Features/Contents/Migrations/ContentDbContextModelSnapshot.cs b/src/Web/Features/Contents/Migrations/ContentDbContextModelSnapshot.cs new file mode 100644 index 0000000..f50bd25 --- /dev/null +++ b/src/Web/Features/Contents/Migrations/ContentDbContextModelSnapshot.cs @@ -0,0 +1,255 @@ +// +using System; +using Hutopy.Web.Features.Contents.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace Hutopy.Web.Features.Contents.Migrations +{ + [DbContext(typeof(ContentDbContext))] + partial class ContentDbContextModelSnapshot : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasDefaultSchema("Content") + .HasAnnotation("ProductVersion", "8.0.4") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("Hutopy.Web.Features.Contents.Data.Content", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("CURRENT_TIMESTAMP"); + + b.Property("CreatedBy") + .HasColumnType("uuid"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(2048) + .HasColumnType("character varying(2048)"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("Urls") + .HasColumnType("text[]"); + + b.HasKey("Id"); + + b.HasIndex("CreatedBy"); + + b.ToTable("Contents", "Content"); + }); + + modelBuilder.Entity("Hutopy.Web.Features.Contents.Data.Creator", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("uuid"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.HasKey("Id"); + + b.ToTable("Creators", "Content"); + }); + + modelBuilder.Entity("Hutopy.Web.Features.Contents.Data.Subscription", b => + { + b.Property("CreatedBy") + .HasColumnType("uuid"); + + b.Property("CreatorId") + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("CreatedBy", "CreatorId"); + + b.HasIndex("CreatorId"); + + b.ToTable("Subscriptions", "Content"); + }); + + modelBuilder.Entity("Hutopy.Web.Features.Contents.Data.Content", b => + { + b.HasOne("Hutopy.Web.Features.Contents.Data.Creator", "Creator") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Creator"); + }); + + modelBuilder.Entity("Hutopy.Web.Features.Contents.Data.Creator", b => + { + b.OwnsOne("Hutopy.Web.Features.Contents.Data.About", "About", b1 => + { + b1.Property("CreatorId") + .HasColumnType("uuid"); + + b1.Property("Description") + .HasMaxLength(2048) + .HasColumnType("character varying(2048)"); + + b1.Property("Title") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.HasKey("CreatorId"); + + b1.ToTable("Creators", "Content"); + + b1.WithOwner() + .HasForeignKey("CreatorId"); + }); + + b.OwnsOne("Hutopy.Web.Features.Contents.Data.Images", "Images", b1 => + { + b1.Property("CreatorId") + .HasColumnType("uuid"); + + b1.Property("Banner") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.Property("Logo") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.HasKey("CreatorId"); + + b1.ToTable("Images", "Content"); + + b1.WithOwner() + .HasForeignKey("CreatorId"); + }); + + b.OwnsOne("Hutopy.Web.Features.Contents.Data.ProfileColors", "ProfileColors", b1 => + { + b1.Property("CreatorId") + .HasColumnType("uuid"); + + b1.Property("Accent") + .HasMaxLength(9) + .HasColumnType("character varying(9)"); + + b1.Property("BannerBottom") + .HasMaxLength(9) + .HasColumnType("character varying(9)"); + + b1.Property("BannerTop") + .HasMaxLength(9) + .HasColumnType("character varying(9)"); + + b1.Property("Menu") + .HasMaxLength(9) + .HasColumnType("character varying(9)"); + + b1.HasKey("CreatorId"); + + b1.ToTable("ProfileColors", "Content"); + + b1.WithOwner() + .HasForeignKey("CreatorId"); + }); + + b.OwnsOne("Hutopy.Web.Features.Contents.Data.Socials", "Socials", b1 => + { + b1.Property("CreatorId") + .HasColumnType("uuid"); + + b1.Property("FacebookUrl") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.Property("InstagramUrl") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.Property("LinkedInUrl") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.Property("RedditUrl") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.Property("TikTokUrl") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.Property("WebsiteUrl") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.Property("XUrl") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.Property("YoutubeUrl") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.HasKey("CreatorId"); + + b1.ToTable("Socials", "Content"); + + b1.WithOwner() + .HasForeignKey("CreatorId"); + }); + + b.Navigation("About") + .IsRequired(); + + b.Navigation("Images") + .IsRequired(); + + b.Navigation("ProfileColors") + .IsRequired(); + + b.Navigation("Socials") + .IsRequired(); + }); + + modelBuilder.Entity("Hutopy.Web.Features.Contents.Data.Subscription", b => + { + b.HasOne("Hutopy.Web.Features.Contents.Data.Creator", "Creator") + .WithMany() + .HasForeignKey("CreatorId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Creator"); + }); +#pragma warning restore 612, 618 + } + } +} From 7cd7ae30805f6ff5e2267ebf027aadd67c79b7de Mon Sep 17 00:00:00 2001 From: Jonathan Bourdon Date: Tue, 6 Aug 2024 02:26:10 -0400 Subject: [PATCH 155/229] Fix validation of ChangeColorsRequest --- src/Web/Features/Contents/Handlers/ChangeColors.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Web/Features/Contents/Handlers/ChangeColors.cs b/src/Web/Features/Contents/Handlers/ChangeColors.cs index a7edc06..226b61a 100644 --- a/src/Web/Features/Contents/Handlers/ChangeColors.cs +++ b/src/Web/Features/Contents/Handlers/ChangeColors.cs @@ -19,22 +19,22 @@ public sealed class ChangeColorsRequestValidator { RuleFor(x => x.BannerTop) .MinimumLength(4).WithMessage("The minimum value should be in the format #444") - .MinimumLength(9).WithMessage("The maximum value should be in the format #11223344") + .MaximumLength(9).WithMessage("The maximum value should be in the format #11223344") .Must(x => x.StartsWith('#')).WithMessage("The format should be a valid html color and start with #"); RuleFor(x => x.BannerBottom) .MinimumLength(4).WithMessage("The minimum value should be in the format #444") - .MinimumLength(9).WithMessage("The maximum value should be in the format #11223344") + .MaximumLength(9).WithMessage("The maximum value should be in the format #11223344") .Must(x => x.StartsWith('#')).WithMessage("The format should be a valid html color and start with #"); RuleFor(x => x.Accent) .MinimumLength(4).WithMessage("The minimum value should be in the format #444") - .MinimumLength(9).WithMessage("The maximum value should be in the format #11223344") + .MaximumLength(9).WithMessage("The maximum value should be in the format #11223344") .Must(x => x.StartsWith('#')).WithMessage("The format should be a valid html color and start with #"); RuleFor(x => x.Menu) .MinimumLength(4).WithMessage("The minimum value should be in the format #444") - .MinimumLength(9).WithMessage("The maximum value should be in the format #11223344") + .MaximumLength(9).WithMessage("The maximum value should be in the format #11223344") .Must(x => x.StartsWith('#')).WithMessage("The format should be a valid html color and start with #"); } } From f46d1146e174f550e2bcf5150f3c4ef47d21b9e3 Mon Sep 17 00:00:00 2001 From: Jonathan Bourdon Date: Tue, 6 Aug 2024 02:55:00 -0400 Subject: [PATCH 156/229] Renames ProfileColors to Colors --- .../Contents/Data/ContentDbContext.cs | 4 +- src/Web/Features/Contents/Data/Creator.cs | 4 +- .../Contents/Handlers/ChangeColors.cs | 10 ++-- .../Contents/Handlers/ChangeSocials.cs | 2 +- .../Contents/Handlers/GetCreatorByAlias.cs | 2 +- .../Contents/Handlers/Models/CreatorModel.cs | 2 +- ....cs => 20240806065219_Initial.Designer.cs} | 52 +++++++++--------- ...0_Initial.cs => 20240806065219_Initial.cs} | 54 +++++++++---------- .../ContentDbContextModelSnapshot.cs | 50 ++++++++--------- src/Web/TestDataSeeder.cs | 12 ++--- 10 files changed, 96 insertions(+), 96 deletions(-) rename src/Web/Features/Contents/Migrations/{20240806050040_Initial.Designer.cs => 20240806065219_Initial.Designer.cs} (97%) rename src/Web/Features/Contents/Migrations/{20240806050040_Initial.cs => 20240806065219_Initial.cs} (97%) diff --git a/src/Web/Features/Contents/Data/ContentDbContext.cs b/src/Web/Features/Contents/Data/ContentDbContext.cs index 8ebc843..994d6e7 100644 --- a/src/Web/Features/Contents/Data/ContentDbContext.cs +++ b/src/Web/Features/Contents/Data/ContentDbContext.cs @@ -49,8 +49,8 @@ public class ContentDbContext( modelBuilder .Entity() - .OwnsOne(x => x.ProfileColors) - .ToTable(nameof(ProfileColors)); + .OwnsOne(x => x.Colors) + .ToTable(nameof(Colors)); modelBuilder .Entity() diff --git a/src/Web/Features/Contents/Data/Creator.cs b/src/Web/Features/Contents/Data/Creator.cs index 689b1d8..75f5c50 100644 --- a/src/Web/Features/Contents/Data/Creator.cs +++ b/src/Web/Features/Contents/Data/Creator.cs @@ -11,7 +11,7 @@ public class Creator public About About { get; set; } = new(); public Socials Socials { get; set; } = new(); - public ProfileColors ProfileColors { get; set; } = new(); + public Colors Colors { get; set; } = new(); public Images Images { get; set; } = new(); } @@ -21,7 +21,7 @@ public class About [MaxLength(2048)] public string? Description { get; set; } } -public class ProfileColors +public class Colors { [MaxLength(9)] public string? BannerTop { get; set; } [MaxLength(9)] public string? BannerBottom { get; set; } diff --git a/src/Web/Features/Contents/Handlers/ChangeColors.cs b/src/Web/Features/Contents/Handlers/ChangeColors.cs index 226b61a..d08aaf0 100644 --- a/src/Web/Features/Contents/Handlers/ChangeColors.cs +++ b/src/Web/Features/Contents/Handlers/ChangeColors.cs @@ -53,15 +53,15 @@ public class ChangeColorsHandler( { var creator = await context .Creators - .Include(c => c.ProfileColors) + .Include(c => c.Colors) .SingleAsync( c => c.Id == request.CreatorId, cancellationToken: ct); - creator.ProfileColors.BannerTop = request.BannerTop; - creator.ProfileColors.BannerBottom = request.BannerBottom; - creator.ProfileColors.Accent = request.Accent; - creator.ProfileColors.Menu = request.Menu; + creator.Colors.BannerTop = request.BannerTop; + creator.Colors.BannerBottom = request.BannerBottom; + creator.Colors.Accent = request.Accent; + creator.Colors.Menu = request.Menu; await context.SaveChangesAsync(ct); diff --git a/src/Web/Features/Contents/Handlers/ChangeSocials.cs b/src/Web/Features/Contents/Handlers/ChangeSocials.cs index 62d6848..8c11aa4 100644 --- a/src/Web/Features/Contents/Handlers/ChangeSocials.cs +++ b/src/Web/Features/Contents/Handlers/ChangeSocials.cs @@ -29,7 +29,7 @@ public class ChangeSocialsHandler( { var creator = await context .Creators - .Include(c => c.ProfileColors) + .Include(c => c.Socials) .SingleAsync( c => c.Id == request.CreatorId, cancellationToken: ct); diff --git a/src/Web/Features/Contents/Handlers/GetCreatorByAlias.cs b/src/Web/Features/Contents/Handlers/GetCreatorByAlias.cs index fe5d8e5..0287b4e 100644 --- a/src/Web/Features/Contents/Handlers/GetCreatorByAlias.cs +++ b/src/Web/Features/Contents/Handlers/GetCreatorByAlias.cs @@ -62,7 +62,7 @@ public class GetCreatorByAliasHandler( Name = creator.Name, About = creator.About, Socials = creator.Socials, - ProfileColors = creator.ProfileColors, + Colors = creator.Colors, Images = creator.Images, SubscriberCount = subscriberCount, }; diff --git a/src/Web/Features/Contents/Handlers/Models/CreatorModel.cs b/src/Web/Features/Contents/Handlers/Models/CreatorModel.cs index e59db4e..b53bcea 100644 --- a/src/Web/Features/Contents/Handlers/Models/CreatorModel.cs +++ b/src/Web/Features/Contents/Handlers/Models/CreatorModel.cs @@ -10,7 +10,7 @@ public class CreatorModel public string Name { get; set; } public About About { get; set; } public Socials Socials { get; set; } - public ProfileColors ProfileColors { get; set; } + public Colors Colors { get; set; } public Images Images { get; set; } public int SubscriberCount { get; set; } } diff --git a/src/Web/Features/Contents/Migrations/20240806050040_Initial.Designer.cs b/src/Web/Features/Contents/Migrations/20240806065219_Initial.Designer.cs similarity index 97% rename from src/Web/Features/Contents/Migrations/20240806050040_Initial.Designer.cs rename to src/Web/Features/Contents/Migrations/20240806065219_Initial.Designer.cs index 7c9d53c..76dc6e2 100644 --- a/src/Web/Features/Contents/Migrations/20240806050040_Initial.Designer.cs +++ b/src/Web/Features/Contents/Migrations/20240806065219_Initial.Designer.cs @@ -12,7 +12,7 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; namespace Hutopy.Web.Features.Contents.Migrations { [DbContext(typeof(ContentDbContext))] - [Migration("20240806050040_Initial")] + [Migration("20240806065219_Initial")] partial class Initial { /// @@ -134,28 +134,7 @@ namespace Hutopy.Web.Features.Contents.Migrations .HasForeignKey("CreatorId"); }); - b.OwnsOne("Hutopy.Web.Features.Contents.Data.Images", "Images", b1 => - { - b1.Property("CreatorId") - .HasColumnType("uuid"); - - b1.Property("Banner") - .HasMaxLength(255) - .HasColumnType("character varying(255)"); - - b1.Property("Logo") - .HasMaxLength(255) - .HasColumnType("character varying(255)"); - - b1.HasKey("CreatorId"); - - b1.ToTable("Images", "Content"); - - b1.WithOwner() - .HasForeignKey("CreatorId"); - }); - - b.OwnsOne("Hutopy.Web.Features.Contents.Data.ProfileColors", "ProfileColors", b1 => + b.OwnsOne("Hutopy.Web.Features.Contents.Data.Colors", "Colors", b1 => { b1.Property("CreatorId") .HasColumnType("uuid"); @@ -178,7 +157,28 @@ namespace Hutopy.Web.Features.Contents.Migrations b1.HasKey("CreatorId"); - b1.ToTable("ProfileColors", "Content"); + b1.ToTable("Colors", "Content"); + + b1.WithOwner() + .HasForeignKey("CreatorId"); + }); + + b.OwnsOne("Hutopy.Web.Features.Contents.Data.Images", "Images", b1 => + { + b1.Property("CreatorId") + .HasColumnType("uuid"); + + b1.Property("Banner") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.Property("Logo") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.HasKey("CreatorId"); + + b1.ToTable("Images", "Content"); b1.WithOwner() .HasForeignKey("CreatorId"); @@ -232,10 +232,10 @@ namespace Hutopy.Web.Features.Contents.Migrations b.Navigation("About") .IsRequired(); - b.Navigation("Images") + b.Navigation("Colors") .IsRequired(); - b.Navigation("ProfileColors") + b.Navigation("Images") .IsRequired(); b.Navigation("Socials") diff --git a/src/Web/Features/Contents/Migrations/20240806050040_Initial.cs b/src/Web/Features/Contents/Migrations/20240806065219_Initial.cs similarity index 97% rename from src/Web/Features/Contents/Migrations/20240806050040_Initial.cs rename to src/Web/Features/Contents/Migrations/20240806065219_Initial.cs index 2563d7c..6ceb9b5 100644 --- a/src/Web/Features/Contents/Migrations/20240806050040_Initial.cs +++ b/src/Web/Features/Contents/Migrations/20240806065219_Initial.cs @@ -31,6 +31,29 @@ namespace Hutopy.Web.Features.Contents.Migrations table.PrimaryKey("PK_Creators", x => x.Id); }); + migrationBuilder.CreateTable( + name: "Colors", + schema: "Content", + columns: table => new + { + CreatorId = table.Column(type: "uuid", nullable: false), + BannerTop = table.Column(type: "character varying(9)", maxLength: 9, nullable: true), + BannerBottom = table.Column(type: "character varying(9)", maxLength: 9, nullable: true), + Accent = table.Column(type: "character varying(9)", maxLength: 9, nullable: true), + Menu = table.Column(type: "character varying(9)", maxLength: 9, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Colors", x => x.CreatorId); + table.ForeignKey( + name: "FK_Colors_Creators_CreatorId", + column: x => x.CreatorId, + principalSchema: "Content", + principalTable: "Creators", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + migrationBuilder.CreateTable( name: "Contents", schema: "Content", @@ -76,29 +99,6 @@ namespace Hutopy.Web.Features.Contents.Migrations onDelete: ReferentialAction.Cascade); }); - migrationBuilder.CreateTable( - name: "ProfileColors", - schema: "Content", - columns: table => new - { - CreatorId = table.Column(type: "uuid", nullable: false), - BannerTop = table.Column(type: "character varying(9)", maxLength: 9, nullable: true), - BannerBottom = table.Column(type: "character varying(9)", maxLength: 9, nullable: true), - Accent = table.Column(type: "character varying(9)", maxLength: 9, nullable: true), - Menu = table.Column(type: "character varying(9)", maxLength: 9, nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_ProfileColors", x => x.CreatorId); - table.ForeignKey( - name: "FK_ProfileColors_Creators_CreatorId", - column: x => x.CreatorId, - principalSchema: "Content", - principalTable: "Creators", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - migrationBuilder.CreateTable( name: "Socials", schema: "Content", @@ -163,6 +163,10 @@ namespace Hutopy.Web.Features.Contents.Migrations /// protected override void Down(MigrationBuilder migrationBuilder) { + migrationBuilder.DropTable( + name: "Colors", + schema: "Content"); + migrationBuilder.DropTable( name: "Contents", schema: "Content"); @@ -171,10 +175,6 @@ namespace Hutopy.Web.Features.Contents.Migrations name: "Images", schema: "Content"); - migrationBuilder.DropTable( - name: "ProfileColors", - schema: "Content"); - migrationBuilder.DropTable( name: "Socials", schema: "Content"); diff --git a/src/Web/Features/Contents/Migrations/ContentDbContextModelSnapshot.cs b/src/Web/Features/Contents/Migrations/ContentDbContextModelSnapshot.cs index f50bd25..245416b 100644 --- a/src/Web/Features/Contents/Migrations/ContentDbContextModelSnapshot.cs +++ b/src/Web/Features/Contents/Migrations/ContentDbContextModelSnapshot.cs @@ -131,28 +131,7 @@ namespace Hutopy.Web.Features.Contents.Migrations .HasForeignKey("CreatorId"); }); - b.OwnsOne("Hutopy.Web.Features.Contents.Data.Images", "Images", b1 => - { - b1.Property("CreatorId") - .HasColumnType("uuid"); - - b1.Property("Banner") - .HasMaxLength(255) - .HasColumnType("character varying(255)"); - - b1.Property("Logo") - .HasMaxLength(255) - .HasColumnType("character varying(255)"); - - b1.HasKey("CreatorId"); - - b1.ToTable("Images", "Content"); - - b1.WithOwner() - .HasForeignKey("CreatorId"); - }); - - b.OwnsOne("Hutopy.Web.Features.Contents.Data.ProfileColors", "ProfileColors", b1 => + b.OwnsOne("Hutopy.Web.Features.Contents.Data.Colors", "Colors", b1 => { b1.Property("CreatorId") .HasColumnType("uuid"); @@ -175,7 +154,28 @@ namespace Hutopy.Web.Features.Contents.Migrations b1.HasKey("CreatorId"); - b1.ToTable("ProfileColors", "Content"); + b1.ToTable("Colors", "Content"); + + b1.WithOwner() + .HasForeignKey("CreatorId"); + }); + + b.OwnsOne("Hutopy.Web.Features.Contents.Data.Images", "Images", b1 => + { + b1.Property("CreatorId") + .HasColumnType("uuid"); + + b1.Property("Banner") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.Property("Logo") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.HasKey("CreatorId"); + + b1.ToTable("Images", "Content"); b1.WithOwner() .HasForeignKey("CreatorId"); @@ -229,10 +229,10 @@ namespace Hutopy.Web.Features.Contents.Migrations b.Navigation("About") .IsRequired(); - b.Navigation("Images") + b.Navigation("Colors") .IsRequired(); - b.Navigation("ProfileColors") + b.Navigation("Images") .IsRequired(); b.Navigation("Socials") diff --git a/src/Web/TestDataSeeder.cs b/src/Web/TestDataSeeder.cs index f1b3189..68bc5e5 100644 --- a/src/Web/TestDataSeeder.cs +++ b/src/Web/TestDataSeeder.cs @@ -189,7 +189,7 @@ internal class TestDataSeeder( Title = "Page officielle", Description = "Site officiel pour Hutopy. Venez-nous-y retrouver avec tous vos fans!", }, - ProfileColors = new() + Colors = new() { BannerTop = "#A30E79", BannerBottom = "#6B0065", Accent = "#23393B", Menu = "#53B93B", }, @@ -216,7 +216,7 @@ internal class TestDataSeeder( Title = "Page officielle", Description = "Site officiel pour Arps. Venez-nous-y retrouver avec tous vos fans!", }, - ProfileColors = + Colors = new() { BannerTop = "#231F20", BannerBottom = "#231F20", Accent = "#272526", Menu = "#FFFFFF" }, Socials = new() { @@ -242,7 +242,7 @@ internal class TestDataSeeder( Title = "Page officielle", Description = "𝐿𝑎 𝑐𝑟𝑒́𝑎𝑡𝑖𝑣𝑖𝑡𝑒́ 𝑐’𝑒𝑠𝑡 𝑙’𝑖𝑛𝑡𝑒𝑙𝑙𝑖𝑔𝑒𝑛𝑐𝑒 𝑞𝑢𝑖 𝑠’𝑎𝑚𝑢𝑠𝑒!", }, - ProfileColors = new() + Colors = new() { BannerTop = "#231F20", BannerBottom = "#272526", Accent = "#231F20", Menu = "#231F20", }, @@ -268,7 +268,7 @@ internal class TestDataSeeder( Description = "Mettre en lumière le côté humain des entrepreneurs. Chaque service, chaque produit est porteur d’une histoire, d’une passion, d’une vision unique. Mon objectif est de faire rayonner cette unicité, de créer des connexions authentiques entre ces entrepreneurs et leurs clients potentiels. Parce que derrière chaque entreprise, il y a des personnes inspirantes qui méritent d’être entendues et comprises. Et toi, quel est ton objectif pour cette année?", }, - ProfileColors = new() + Colors = new() { BannerTop = "#0BAAB2", BannerBottom = "#006D77", Accent = "#CC6F91", Menu = "#CC6F91", }, @@ -296,7 +296,7 @@ internal class TestDataSeeder( Description = "Mettre en lumière le côté humain des entrepreneurs. Chaque service, chaque produit est porteur d’une histoire, d’une passion, d’une vision unique. Mon objectif est de faire rayonner cette unicité, de créer des connexions authentiques entre ces entrepreneurs et leurs clients potentiels. Parce que derrière chaque entreprise, il y a des personnes inspirantes qui méritent d’être entendues et comprises. Et toi, quel est ton objectif pour cette année?", }, - ProfileColors = new() + Colors = new() { BannerTop = "#CC6F91", BannerBottom = "#FBC702", Accent = "#FBC702", Menu = "#FBC702", }, @@ -323,7 +323,7 @@ internal class TestDataSeeder( Description = "Mettre en lumière le côté humain des entrepreneurs. Chaque service, chaque produit est porteur d’une histoire, d’une passion, d’une vision unique. Mon objectif est de faire rayonner cette unicité, de créer des connexions authentiques entre ces entrepreneurs et leurs clients potentiels. Parce que derrière chaque entreprise, il y a des personnes inspirantes qui méritent d’être entendues et comprises. Et toi, quel est ton objectif pour cette année?", }, - ProfileColors = new() + Colors = new() { BannerTop = "#101B49", BannerBottom = "#698FE7", Accent = "#1D1D1B", Menu = "#1D1D1B", }, From 162063facd1c2fcdcd760c1c063d41b0ed9a4b58 Mon Sep 17 00:00:00 2001 From: PascalMarchesseault <97350299+PascalMarchesseault@users.noreply.github.com> Date: Tue, 6 Aug 2024 23:59:09 -0400 Subject: [PATCH 157/229] Add max Length when creating a message. --- src/Web/Features/Messages/Data/Message.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Web/Features/Messages/Data/Message.cs b/src/Web/Features/Messages/Data/Message.cs index 83af411..fff397b 100644 --- a/src/Web/Features/Messages/Data/Message.cs +++ b/src/Web/Features/Messages/Data/Message.cs @@ -11,5 +11,5 @@ public class Message [MaxLength(255)] public string? CreatedByPortraitUrl { get; set; } public DateTimeOffset CreatedAt { get; set; } public Guid? ParentId { get; set; } - public required string Value { get; set; } + [MaxLength(2048)] public required string Value { get; set; } } From 6d9201e8aadd97d8d66a2263946d1ab1f266edb6 Mon Sep 17 00:00:00 2001 From: Jonathan Bourdon Date: Wed, 7 Aug 2024 02:19:04 -0400 Subject: [PATCH 158/229] Adds ChangeAbout for Creators --- .../Features/Contents/Handlers/ChangeAbout.cs | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 src/Web/Features/Contents/Handlers/ChangeAbout.cs diff --git a/src/Web/Features/Contents/Handlers/ChangeAbout.cs b/src/Web/Features/Contents/Handlers/ChangeAbout.cs new file mode 100644 index 0000000..0cbe19c --- /dev/null +++ b/src/Web/Features/Contents/Handlers/ChangeAbout.cs @@ -0,0 +1,40 @@ +using FastEndpoints; +using Hutopy.Web.Features.Contents.Data; +using Microsoft.EntityFrameworkCore; + +namespace Hutopy.Web.Features.Contents.Handlers; + +public record ChangeAboutRequest( + Guid CreatorId, + string? Title, + string? Description); + +public class ChangeAboutHandler( + ContentDbContext context) + : Endpoint +{ + public override void Configure() + { + Post("/api/creators/{CreatorId}/about"); + Options(o => o.WithTags("Contents")); + } + + public override async Task HandleAsync( + ChangeAboutRequest request, + CancellationToken ct) + { + var creator = await context + .Creators + .Include(c => c.About) + .SingleAsync( + c => c.Id == request.CreatorId, + cancellationToken: ct); + + creator.About.Title = request.Title; + creator.About.Description = request.Description; + + await context.SaveChangesAsync(ct); + + await SendOkAsync(ct); + } +} From f3b225d3a8470b23ac061abb8b97d4fc81781f57 Mon Sep 17 00:00:00 2001 From: Jonathan Bourdon Date: Wed, 7 Aug 2024 03:10:10 -0400 Subject: [PATCH 159/229] Adds Name and LogoUrl for CreatedBy Content --- .../Contents/Handlers/GetContentsByCreator.cs | 10 ++++--- .../Contents/Handlers/Models/ContentModel.cs | 26 +++++++++++++++++++ 2 files changed, 33 insertions(+), 3 deletions(-) create mode 100644 src/Web/Features/Contents/Handlers/Models/ContentModel.cs diff --git a/src/Web/Features/Contents/Handlers/GetContentsByCreator.cs b/src/Web/Features/Contents/Handlers/GetContentsByCreator.cs index 3ec2e83..8e2f5fd 100644 --- a/src/Web/Features/Contents/Handlers/GetContentsByCreator.cs +++ b/src/Web/Features/Contents/Handlers/GetContentsByCreator.cs @@ -1,5 +1,7 @@ -using FastEndpoints; +using System.Linq.Expressions; +using FastEndpoints; using Hutopy.Web.Features.Contents.Data; +using Hutopy.Web.Features.Contents.Handlers.Models; using Microsoft.EntityFrameworkCore; namespace Hutopy.Web.Features.Contents.Handlers; @@ -13,7 +15,7 @@ public sealed class GetContentsByCreatorRequest public class GetContentsByCreatorHandler( ContentDbContext context) - : Endpoint> + : Endpoint> { public override void Configure() { @@ -37,7 +39,9 @@ public class GetContentsByCreatorHandler( query = query.Take(req.PageSize); - var posts = await query.ToListAsync(cancellationToken: ct); + var posts = await query + .Select(x => x.ToResponse()) + .ToListAsync(cancellationToken: ct); await SendAsync(posts, cancellation: ct); } diff --git a/src/Web/Features/Contents/Handlers/Models/ContentModel.cs b/src/Web/Features/Contents/Handlers/Models/ContentModel.cs new file mode 100644 index 0000000..0d1439e --- /dev/null +++ b/src/Web/Features/Contents/Handlers/Models/ContentModel.cs @@ -0,0 +1,26 @@ +using Hutopy.Web.Features.Contents.Data; + +namespace Hutopy.Web.Features.Contents.Handlers.Models; + +public record struct ContentModel( + Guid Id, + Guid CreatedBy, + string CreatedByName, + string? CreatedByPortraitUrl, + DateTimeOffset CreatedAt, + string Title, + string Description, + string[]? Urls); + +public static class ContentExtensions +{ + public static ContentModel ToResponse(this Content c) => new( + c.Id, + c.CreatedBy, + c.Creator!.Name, + c.Creator.Images.Logo, + c.CreatedAt, + c.Title, + c.Description, + c.Urls); +} From 7baf1146ac6af6e676a84e77f8c6464a9a658dc8 Mon Sep 17 00:00:00 2001 From: Jonathan Bourdon Date: Wed, 7 Aug 2024 03:29:59 -0400 Subject: [PATCH 160/229] Adds JetBrains.Annotations to reduce amount of false positives by static code analysis --- Directory.Packages.props | 1 + src/Web/Common/GuidExtensions.cs | 24 +++++++-------- src/Web/Common/MissingClaimException.cs | 4 ++- src/Web/Controllers/FacebookController.cs | 2 +- src/Web/Controllers/GoogleController.cs | 4 +-- src/Web/DependencyInjection.cs | 1 + src/Web/Endpoints/GetMyUser.cs | 1 + src/Web/Endpoints/JoinUs.cs | 1 + src/Web/Endpoints/Stripe.cs | 1 + src/Web/Endpoints/UpdateMyUser.cs | 1 + src/Web/Endpoints/Users.cs | 1 + .../Contents/Data/ContentDbContext.cs | 4 +-- .../Features/Contents/DependencyInjection.cs | 1 - .../Features/Contents/Handlers/ChangeAbout.cs | 6 ++-- .../Contents/Handlers/ChangeBanner.cs | 17 +++++------ .../Contents/Handlers/ChangeColors.cs | 9 +++--- .../Features/Contents/Handlers/ChangeLogo.cs | 17 +++++------ .../Contents/Handlers/ChangeSocials.cs | 6 ++-- .../Contents/Handlers/CreateContent.cs | 4 +-- .../Contents/Handlers/CreateCreator.cs | 7 +++-- .../Features/Contents/Handlers/GetContent.cs | 6 ++-- .../Contents/Handlers/GetContentsByCreator.cs | 7 ++--- .../Contents/Handlers/GetCreatorByAlias.cs | 30 +++++++++---------- .../Contents/Handlers/GetCreatorById.cs | 7 +++-- .../Contents/Handlers/GetSubscriptions.cs | 7 ++--- .../Contents/Handlers/Models/ContentModel.cs | 1 + .../Contents/Handlers/Models/CreatorModel.cs | 23 +++++++------- .../Handlers/Models/SubscriptionModel.cs | 1 + .../Contents/Handlers/SubscribeToCreator.cs | 6 ++-- .../Handlers/UnsubscribeFromCreator.cs | 5 ++-- .../Messages/Data/MessagingDbContext.cs | 1 - .../Features/Messages/DependencyInjection.cs | 1 - .../Features/Messages/Handlers/AddMessage.cs | 4 +-- .../Features/Messages/Handlers/AddReply.cs | 4 +-- .../Features/Messages/Handlers/GetMessages.cs | 3 +- .../Messages/Handlers/GetMessagesByUser.cs | 4 +-- .../Features/Messages/Handlers/GetReplies.cs | 3 +- src/Web/GlobalUsings.cs | 5 +++- .../Infrastructure/CustomExceptionHandler.cs | 2 ++ src/Web/Pages/Shared/_LoginPartial.cshtml | 1 + src/Web/Program.cs | 3 +- src/Web/Web.csproj | 1 + 42 files changed, 118 insertions(+), 119 deletions(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 00e2212..438dfe2 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -15,6 +15,7 @@ + diff --git a/src/Web/Common/GuidExtensions.cs b/src/Web/Common/GuidExtensions.cs index 0c71da8..c91b23f 100644 --- a/src/Web/Common/GuidExtensions.cs +++ b/src/Web/Common/GuidExtensions.cs @@ -2,7 +2,7 @@ /// /// Adapted from https://raw.githubusercontent.com/uuidjs/uuid/main/src/v7.ts. -/// to match the uuidv7 generated on the client +/// to match the uuid v7 generated on the client /// public static class GuidHelper { @@ -27,14 +27,14 @@ public static class GuidHelper var values = V7Bytes(randomValues, State.Msecs, State.Seq); - return new(values); + return new Guid(values); } - private static void UpdateV7State(V7State state, long now, byte[] rnds) + private static void UpdateV7State(V7State state, long now, byte[] randomBytes) { if (now > state.Msecs) { - state.Seq = (rnds[6] << 23) | (rnds[7] << 16) | (rnds[8] << 8) | rnds[9]; + state.Seq = (randomBytes[6] << 23) | (randomBytes[7] << 16) | (randomBytes[8] << 8) | randomBytes[9]; state.Msecs = now; } else @@ -47,7 +47,7 @@ public static class GuidHelper } } - private static byte[] V7Bytes(byte[] rnds, long? msecs = null, int? seq = null, byte[] buf = null, int offset = 0) + private static byte[] V7Bytes(byte[] randomBytes, long? msecs = null, int? seq = null, byte[]? buf = null, int offset = 0) { if (buf == null) { @@ -57,7 +57,7 @@ public static class GuidHelper // Defaults msecs ??= DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(); - seq ??= ((rnds[6] & 0x7f) << 24) | (rnds[7] << 16) | (rnds[8] << 8) | rnds[9]; + seq ??= ((randomBytes[6] & 0x7f) << 24) | (randomBytes[7] << 16) | (randomBytes[8] << 8) | randomBytes[9]; // byte 0-5: timestamp (48 bits) buf[offset++] = (byte)((msecs.Value / 0x10000000000) & 0xff); @@ -80,14 +80,14 @@ public static class GuidHelper buf[offset++] = (byte)((seq.Value >> 6) & 0xff); // byte 10: sequence bits 0-5 (6 bits) | random (2 bits) - buf[offset++] = (byte)(((seq.Value << 2) & 0xff) | (rnds[10] & 0x03)); + buf[offset++] = (byte)(((seq.Value << 2) & 0xff) | (randomBytes[10] & 0x03)); // bytes 11-15: random (40 bits) - buf[offset++] = rnds[11]; - buf[offset++] = rnds[12]; - buf[offset++] = rnds[13]; - buf[offset++] = rnds[14]; - buf[offset++] = rnds[15]; + buf[offset++] = randomBytes[11]; + buf[offset++] = randomBytes[12]; + buf[offset++] = randomBytes[13]; + buf[offset++] = randomBytes[14]; + buf[offset] = randomBytes[15]; return buf; } diff --git a/src/Web/Common/MissingClaimException.cs b/src/Web/Common/MissingClaimException.cs index 266d109..258fbcd 100644 --- a/src/Web/Common/MissingClaimException.cs +++ b/src/Web/Common/MissingClaimException.cs @@ -1,3 +1,5 @@ namespace Hutopy.Web.Common; -public class MissingClaimException(string claimName) : Exception; +public class MissingClaimException( + string claimName) + : Exception; diff --git a/src/Web/Controllers/FacebookController.cs b/src/Web/Controllers/FacebookController.cs index 3178b5f..9efee0b 100644 --- a/src/Web/Controllers/FacebookController.cs +++ b/src/Web/Controllers/FacebookController.cs @@ -10,7 +10,7 @@ namespace Hutopy.Web.Controllers; public class FacebookController(IIdentityService identityService) : Controller { - [HttpGet("/api/facebook/sign-in")] + [Microsoft.AspNetCore.Mvc.HttpGet("/api/facebook/sign-in")] public async Task SignIn() { await HttpContext.ChallengeAsync(FacebookDefaults.AuthenticationScheme, diff --git a/src/Web/Controllers/GoogleController.cs b/src/Web/Controllers/GoogleController.cs index 1030f43..34609ab 100644 --- a/src/Web/Controllers/GoogleController.cs +++ b/src/Web/Controllers/GoogleController.cs @@ -16,8 +16,8 @@ public class GoogleController( IOptionsSnapshot jwtOptions) : Controller { - [HttpPost("/api/google/sign-in")] - public async Task SignIn([FromBody] GoogleSignInRequest request) + [Microsoft.AspNetCore.Mvc.HttpPost("/api/google/sign-in")] + public async Task SignIn([Microsoft.AspNetCore.Mvc.FromBody] GoogleSignInRequest request) { using var httpClient = httpClientFactory.CreateClient(); diff --git a/src/Web/DependencyInjection.cs b/src/Web/DependencyInjection.cs index e1ca536..4161aad 100644 --- a/src/Web/DependencyInjection.cs +++ b/src/Web/DependencyInjection.cs @@ -2,6 +2,7 @@ using Azure.Identity; using Hutopy.Application.Common.Interfaces; using Hutopy.Infrastructure.Data; +using Hutopy.Web.Infrastructure; using Hutopy.Web.Services; using Microsoft.AspNetCore.Authentication.Cookies; using Microsoft.AspNetCore.Authentication.Facebook; diff --git a/src/Web/Endpoints/GetMyUser.cs b/src/Web/Endpoints/GetMyUser.cs index 4d88e2b..e891a2e 100644 --- a/src/Web/Endpoints/GetMyUser.cs +++ b/src/Web/Endpoints/GetMyUser.cs @@ -1,4 +1,5 @@ using Hutopy.Application.Users.Queries.GetCurrentUser; +using Hutopy.Web.Infrastructure; namespace Hutopy.Web.Endpoints; diff --git a/src/Web/Endpoints/JoinUs.cs b/src/Web/Endpoints/JoinUs.cs index 2f1d1a5..8353ba1 100644 --- a/src/Web/Endpoints/JoinUs.cs +++ b/src/Web/Endpoints/JoinUs.cs @@ -1,6 +1,7 @@ using Hutopy.Application.Common.Models; using Hutopy.Application.FutureCreators.Commands; using Hutopy.Application.FutureCreators.Queries; +using Hutopy.Web.Infrastructure; namespace Hutopy.Web.Endpoints; diff --git a/src/Web/Endpoints/Stripe.cs b/src/Web/Endpoints/Stripe.cs index 2eb01dc..be76a0b 100644 --- a/src/Web/Endpoints/Stripe.cs +++ b/src/Web/Endpoints/Stripe.cs @@ -1,5 +1,6 @@ using Hutopy.Application.Stripe.Commands; using Hutopy.Application.Stripe.Queries; +using Hutopy.Web.Infrastructure; namespace Hutopy.Web.Endpoints; diff --git a/src/Web/Endpoints/UpdateMyUser.cs b/src/Web/Endpoints/UpdateMyUser.cs index 3416dfd..072152f 100644 --- a/src/Web/Endpoints/UpdateMyUser.cs +++ b/src/Web/Endpoints/UpdateMyUser.cs @@ -1,4 +1,5 @@ using Hutopy.Application.Users.Commands; +using Hutopy.Web.Infrastructure; namespace Hutopy.Web.Endpoints; diff --git a/src/Web/Endpoints/Users.cs b/src/Web/Endpoints/Users.cs index 4757789..820aa37 100644 --- a/src/Web/Endpoints/Users.cs +++ b/src/Web/Endpoints/Users.cs @@ -1,5 +1,6 @@ using Hutopy.Application.Users.Commands; using Hutopy.Application.Users.Queries.GetUser; +using Hutopy.Web.Infrastructure; namespace Hutopy.Web.Endpoints; diff --git a/src/Web/Features/Contents/Data/ContentDbContext.cs b/src/Web/Features/Contents/Data/ContentDbContext.cs index 994d6e7..c47a453 100644 --- a/src/Web/Features/Contents/Data/ContentDbContext.cs +++ b/src/Web/Features/Contents/Data/ContentDbContext.cs @@ -1,6 +1,4 @@ -using Microsoft.EntityFrameworkCore; - -namespace Hutopy.Web.Features.Contents.Data; +namespace Hutopy.Web.Features.Contents.Data; public class ContentDbContext( DbContextOptions options) diff --git a/src/Web/Features/Contents/DependencyInjection.cs b/src/Web/Features/Contents/DependencyInjection.cs index 8cac7cb..77c7c40 100644 --- a/src/Web/Features/Contents/DependencyInjection.cs +++ b/src/Web/Features/Contents/DependencyInjection.cs @@ -1,5 +1,4 @@ using Hutopy.Web.Features.Contents.Data; -using Microsoft.EntityFrameworkCore; namespace Hutopy.Web.Features.Contents; diff --git a/src/Web/Features/Contents/Handlers/ChangeAbout.cs b/src/Web/Features/Contents/Handlers/ChangeAbout.cs index 0cbe19c..6098e80 100644 --- a/src/Web/Features/Contents/Handlers/ChangeAbout.cs +++ b/src/Web/Features/Contents/Handlers/ChangeAbout.cs @@ -1,14 +1,14 @@ -using FastEndpoints; -using Hutopy.Web.Features.Contents.Data; -using Microsoft.EntityFrameworkCore; +using Hutopy.Web.Features.Contents.Data; namespace Hutopy.Web.Features.Contents.Handlers; +[PublicAPI] public record ChangeAboutRequest( Guid CreatorId, string? Title, string? Description); +[PublicAPI] public class ChangeAboutHandler( ContentDbContext context) : Endpoint diff --git a/src/Web/Features/Contents/Handlers/ChangeBanner.cs b/src/Web/Features/Contents/Handlers/ChangeBanner.cs index 0a4f8d8..9081cb6 100644 --- a/src/Web/Features/Contents/Handlers/ChangeBanner.cs +++ b/src/Web/Features/Contents/Handlers/ChangeBanner.cs @@ -1,17 +1,16 @@ -using FastEndpoints; -using Hutopy.Application.AzureBlobStorage.Constants; +using Hutopy.Application.AzureBlobStorage.Constants; using Hutopy.Application.Common.Interfaces; using Hutopy.Web.Features.Contents.Data; -using Microsoft.EntityFrameworkCore; namespace Hutopy.Web.Features.Contents.Handlers; +[PublicAPI] public record ChangeBannerRequest( Guid CreatorId, IFormFile File); +[PublicAPI] public class ChangeBannerHandler( - IHttpContextAccessor contextAccessor, ContentDbContext context, IBlobStorage blobStorage) : Endpoint @@ -22,7 +21,7 @@ public class ChangeBannerHandler( Options(o => o.WithTags("Contents")); AllowFileUploads(); } - + public override async Task HandleAsync(ChangeBannerRequest request, CancellationToken ct) { var creator = await context @@ -37,7 +36,7 @@ public class ChangeBannerHandler( await SendNotFoundAsync(ct); return; } - + // TODO: this upload should be done to the Creators container var blobUrl = await blobStorage.UploadFileAsync( ContainerNames.Users, @@ -45,11 +44,11 @@ public class ChangeBannerHandler( request.File.OpenReadStream(), request.File.ContentType, ct); - + creator.Images.Banner = blobUrl; - + await context.SaveChangesAsync(ct); - + await SendOkAsync(blobUrl, ct); } } diff --git a/src/Web/Features/Contents/Handlers/ChangeColors.cs b/src/Web/Features/Contents/Handlers/ChangeColors.cs index d08aaf0..40b45fe 100644 --- a/src/Web/Features/Contents/Handlers/ChangeColors.cs +++ b/src/Web/Features/Contents/Handlers/ChangeColors.cs @@ -1,10 +1,8 @@ -using FastEndpoints; -using FluentValidation; -using Hutopy.Web.Features.Contents.Data; -using Microsoft.EntityFrameworkCore; +using Hutopy.Web.Features.Contents.Data; namespace Hutopy.Web.Features.Contents.Handlers; +[PublicAPI] public record ChangeColorsRequest( Guid CreatorId, string? BannerTop, @@ -12,7 +10,8 @@ public record ChangeColorsRequest( string? Accent, string? Menu); -public sealed class ChangeColorsRequestValidator +[PublicAPI] +public sealed class ChangeColorsRequestValidator : Validator { public ChangeColorsRequestValidator() diff --git a/src/Web/Features/Contents/Handlers/ChangeLogo.cs b/src/Web/Features/Contents/Handlers/ChangeLogo.cs index 4fda059..6d4d839 100644 --- a/src/Web/Features/Contents/Handlers/ChangeLogo.cs +++ b/src/Web/Features/Contents/Handlers/ChangeLogo.cs @@ -1,17 +1,16 @@ -using FastEndpoints; -using Hutopy.Application.AzureBlobStorage.Constants; +using Hutopy.Application.AzureBlobStorage.Constants; using Hutopy.Application.Common.Interfaces; using Hutopy.Web.Features.Contents.Data; -using Microsoft.EntityFrameworkCore; namespace Hutopy.Web.Features.Contents.Handlers; +[PublicAPI] public record ChangeLogoRequest( Guid CreatorId, IFormFile File); +[PublicAPI] public class ChangeLogoHandler( - IHttpContextAccessor contextAccessor, ContentDbContext context, IBlobStorage blobStorage) : Endpoint @@ -22,7 +21,7 @@ public class ChangeLogoHandler( Options(o => o.WithTags("Contents")); AllowFileUploads(); } - + public override async Task HandleAsync(ChangeLogoRequest request, CancellationToken ct) { var creator = await context @@ -37,7 +36,7 @@ public class ChangeLogoHandler( await SendNotFoundAsync(ct); return; } - + // TODO: this upload should be done to the Creators container var blobUrl = await blobStorage.UploadFileAsync( ContainerNames.Users, @@ -45,11 +44,11 @@ public class ChangeLogoHandler( request.File.OpenReadStream(), request.File.ContentType, ct); - + creator.Images.Logo = blobUrl; - + await context.SaveChangesAsync(ct); - + await SendOkAsync(blobUrl, ct); } } diff --git a/src/Web/Features/Contents/Handlers/ChangeSocials.cs b/src/Web/Features/Contents/Handlers/ChangeSocials.cs index 8c11aa4..ab8a5e8 100644 --- a/src/Web/Features/Contents/Handlers/ChangeSocials.cs +++ b/src/Web/Features/Contents/Handlers/ChangeSocials.cs @@ -1,9 +1,8 @@ -using FastEndpoints; -using Hutopy.Web.Features.Contents.Data; -using Microsoft.EntityFrameworkCore; +using Hutopy.Web.Features.Contents.Data; namespace Hutopy.Web.Features.Contents.Handlers; +[PublicAPI] public record ChangeSocialsRequest( Guid CreatorId, string? FacebookUrl, @@ -15,6 +14,7 @@ public record ChangeSocialsRequest( string? RedditUrl, string? WebsiteUrl); +[PublicAPI] public class ChangeSocialsHandler( ContentDbContext context) : Endpoint diff --git a/src/Web/Features/Contents/Handlers/CreateContent.cs b/src/Web/Features/Contents/Handlers/CreateContent.cs index 14496f0..964e507 100644 --- a/src/Web/Features/Contents/Handlers/CreateContent.cs +++ b/src/Web/Features/Contents/Handlers/CreateContent.cs @@ -1,6 +1,4 @@ using System.Collections.Concurrent; -using FastEndpoints; -using FluentValidation; using Hutopy.Application.AzureBlobStorage.Constants; using Hutopy.Application.Common.Interfaces; using Hutopy.Web.Common; @@ -8,6 +6,7 @@ using Hutopy.Web.Features.Contents.Data; namespace Hutopy.Web.Features.Contents.Handlers; +[PublicAPI] public record PostContentRequest( Guid Id, Guid CreatorId, @@ -15,6 +14,7 @@ public record PostContentRequest( string Description, IFormFileCollection Files); +[PublicAPI] public sealed class PostContentRequestValidator : Validator { public PostContentRequestValidator() diff --git a/src/Web/Features/Contents/Handlers/CreateCreator.cs b/src/Web/Features/Contents/Handlers/CreateCreator.cs index f68e96b..a70bd27 100644 --- a/src/Web/Features/Contents/Handlers/CreateCreator.cs +++ b/src/Web/Features/Contents/Handlers/CreateCreator.cs @@ -1,14 +1,14 @@ -using FastEndpoints; -using FluentValidation; -using Hutopy.Web.Common; +using Hutopy.Web.Common; using Hutopy.Web.Features.Contents.Data; namespace Hutopy.Web.Features.Contents.Handlers; +[PublicAPI] public record CreateCreatorRequest( Guid CreatorId, string Name); +[UsedImplicitly] public sealed class CreateCreatorRequestValidator : Validator { public CreateCreatorRequestValidator() @@ -23,6 +23,7 @@ public sealed class CreateCreatorRequestValidator : Validator diff --git a/src/Web/Features/Contents/Handlers/GetContent.cs b/src/Web/Features/Contents/Handlers/GetContent.cs index 7e79021..398d9c0 100644 --- a/src/Web/Features/Contents/Handlers/GetContent.cs +++ b/src/Web/Features/Contents/Handlers/GetContent.cs @@ -1,14 +1,14 @@ -using FastEndpoints; -using Hutopy.Web.Features.Contents.Data; -using Microsoft.EntityFrameworkCore; +using Hutopy.Web.Features.Contents.Data; namespace Hutopy.Web.Features.Contents.Handlers; +[PublicAPI] public sealed class GetContentRequest { public Guid ContentId { get; set; } } +[PublicAPI] public class GetContent( ContentDbContext context) : Endpoint diff --git a/src/Web/Features/Contents/Handlers/GetContentsByCreator.cs b/src/Web/Features/Contents/Handlers/GetContentsByCreator.cs index 8e2f5fd..910eaa3 100644 --- a/src/Web/Features/Contents/Handlers/GetContentsByCreator.cs +++ b/src/Web/Features/Contents/Handlers/GetContentsByCreator.cs @@ -1,11 +1,9 @@ -using System.Linq.Expressions; -using FastEndpoints; -using Hutopy.Web.Features.Contents.Data; +using Hutopy.Web.Features.Contents.Data; using Hutopy.Web.Features.Contents.Handlers.Models; -using Microsoft.EntityFrameworkCore; namespace Hutopy.Web.Features.Contents.Handlers; +[PublicAPI] public sealed class GetContentsByCreatorRequest { public Guid UserId { get; set; } @@ -13,6 +11,7 @@ public sealed class GetContentsByCreatorRequest [BindFrom("last_id")] public Guid? LastId { get; set; } } +[PublicAPI] public class GetContentsByCreatorHandler( ContentDbContext context) : Endpoint> diff --git a/src/Web/Features/Contents/Handlers/GetCreatorByAlias.cs b/src/Web/Features/Contents/Handlers/GetCreatorByAlias.cs index 0287b4e..87ca6ec 100644 --- a/src/Web/Features/Contents/Handlers/GetCreatorByAlias.cs +++ b/src/Web/Features/Contents/Handlers/GetCreatorByAlias.cs @@ -1,16 +1,15 @@ -using FastEndpoints; -using FluentValidation; -using Hutopy.Web.Features.Contents.Data; +using Hutopy.Web.Features.Contents.Data; using Hutopy.Web.Features.Contents.Handlers.Models; -using Microsoft.EntityFrameworkCore; namespace Hutopy.Web.Features.Contents.Handlers; +[PublicAPI] public sealed class GetCreatorByAliasRequest { public required string Name { get; set; } } +[UsedImplicitly] public sealed class GetCreatorByAliasRequestValidator : Validator { @@ -22,6 +21,7 @@ public sealed class GetCreatorByAliasRequestValidator } } +[PublicAPI] public class GetCreatorByAliasHandler( ContentDbContext context) : Endpoint @@ -54,18 +54,16 @@ public class GetCreatorByAliasHandler( s => s.CreatorId == creator.Id, cancellationToken: ct); - var model = new CreatorModel - { - Id = creator.Id, - CreatedBy = creator.CreatedBy, - CreatedAt = creator.CreatedAt, - Name = creator.Name, - About = creator.About, - Socials = creator.Socials, - Colors = creator.Colors, - Images = creator.Images, - SubscriberCount = subscriberCount, - }; + var model = new CreatorModel( + creator.Id, + creator.CreatedBy, + creator.CreatedAt, + creator.Name, + creator.About, + creator.Socials, + creator.Colors, + creator.Images, + subscriberCount); await SendAsync(model, cancellation: ct); } diff --git a/src/Web/Features/Contents/Handlers/GetCreatorById.cs b/src/Web/Features/Contents/Handlers/GetCreatorById.cs index 0022515..ae167e0 100644 --- a/src/Web/Features/Contents/Handlers/GetCreatorById.cs +++ b/src/Web/Features/Contents/Handlers/GetCreatorById.cs @@ -1,14 +1,14 @@ -using FastEndpoints; -using FluentValidation; -using Hutopy.Web.Features.Contents.Data; +using Hutopy.Web.Features.Contents.Data; namespace Hutopy.Web.Features.Contents.Handlers; +[PublicAPI] public sealed class GetCreatorByIdRequest { public required Guid CreatorId { get; set; } } +[UsedImplicitly] public sealed class GetCreatorByIdRequestValidator : Validator { @@ -20,6 +20,7 @@ public sealed class GetCreatorByIdRequestValidator } } +[PublicAPI] public class GetCreatorByIdHandler( ContentDbContext context) : Endpoint diff --git a/src/Web/Features/Contents/Handlers/GetSubscriptions.cs b/src/Web/Features/Contents/Handlers/GetSubscriptions.cs index 035cb87..545a469 100644 --- a/src/Web/Features/Contents/Handlers/GetSubscriptions.cs +++ b/src/Web/Features/Contents/Handlers/GetSubscriptions.cs @@ -1,11 +1,10 @@ -using FastEndpoints; -using Hutopy.Web.Common; +using Hutopy.Web.Common; using Hutopy.Web.Features.Contents.Data; using Hutopy.Web.Features.Contents.Handlers.Models; -using Microsoft.EntityFrameworkCore; namespace Hutopy.Web.Features.Contents.Handlers; +[PublicAPI] public class GetSubscriptionsHandler( ContentDbContext context) : EndpointWithoutRequest> @@ -25,7 +24,7 @@ public class GetSubscriptionsHandler( .Subscriptions .Where(s => s.CreatedBy == userId) .Select(s => new SubscriptionModel( - s.CreatorId, + s.CreatorId, s.Creator!.Name, s.Creator.Images.Logo)) .ToListAsync(cancellationToken: ct); diff --git a/src/Web/Features/Contents/Handlers/Models/ContentModel.cs b/src/Web/Features/Contents/Handlers/Models/ContentModel.cs index 0d1439e..56eccf5 100644 --- a/src/Web/Features/Contents/Handlers/Models/ContentModel.cs +++ b/src/Web/Features/Contents/Handlers/Models/ContentModel.cs @@ -2,6 +2,7 @@ namespace Hutopy.Web.Features.Contents.Handlers.Models; +[PublicAPI] public record struct ContentModel( Guid Id, Guid CreatedBy, diff --git a/src/Web/Features/Contents/Handlers/Models/CreatorModel.cs b/src/Web/Features/Contents/Handlers/Models/CreatorModel.cs index b53bcea..5502231 100644 --- a/src/Web/Features/Contents/Handlers/Models/CreatorModel.cs +++ b/src/Web/Features/Contents/Handlers/Models/CreatorModel.cs @@ -2,15 +2,14 @@ namespace Hutopy.Web.Features.Contents.Handlers.Models; -public class CreatorModel -{ - public Guid Id { get; set; } - public Guid CreatedBy { get; set; } - public DateTimeOffset CreatedAt { get; set; } - public string Name { get; set; } - public About About { get; set; } - public Socials Socials { get; set; } - public Colors Colors { get; set; } - public Images Images { get; set; } - public int SubscriberCount { get; set; } -} +[PublicAPI] +public record struct CreatorModel( + Guid Id, + Guid CreatedBy, + DateTimeOffset CreatedAt, + string Name, + About About, + Socials Socials, + Colors Colors, + Images Images, + int SubscriberCount); diff --git a/src/Web/Features/Contents/Handlers/Models/SubscriptionModel.cs b/src/Web/Features/Contents/Handlers/Models/SubscriptionModel.cs index 7c3df21..7c748aa 100644 --- a/src/Web/Features/Contents/Handlers/Models/SubscriptionModel.cs +++ b/src/Web/Features/Contents/Handlers/Models/SubscriptionModel.cs @@ -1,5 +1,6 @@ namespace Hutopy.Web.Features.Contents.Handlers.Models; +[PublicAPI] public record SubscriptionModel( Guid CreatorId, string CreatorName, diff --git a/src/Web/Features/Contents/Handlers/SubscribeToCreator.cs b/src/Web/Features/Contents/Handlers/SubscribeToCreator.cs index 9c37d3b..50614c7 100644 --- a/src/Web/Features/Contents/Handlers/SubscribeToCreator.cs +++ b/src/Web/Features/Contents/Handlers/SubscribeToCreator.cs @@ -1,16 +1,16 @@ -using FastEndpoints; -using Hutopy.Web.Common; +using Hutopy.Web.Common; using Hutopy.Web.Features.Contents.Data; using Hutopy.Web.Features.Contents.Handlers.Models; -using Microsoft.EntityFrameworkCore; namespace Hutopy.Web.Features.Contents.Handlers; +[PublicAPI] public sealed class SubscribeToCreatorRequest { public Guid CreatorId { get; set; } } +[PublicAPI] public sealed class SubscribeToCreatorHandler( ContentDbContext context) : Endpoint diff --git a/src/Web/Features/Contents/Handlers/UnsubscribeFromCreator.cs b/src/Web/Features/Contents/Handlers/UnsubscribeFromCreator.cs index 87c4855..3b181fe 100644 --- a/src/Web/Features/Contents/Handlers/UnsubscribeFromCreator.cs +++ b/src/Web/Features/Contents/Handlers/UnsubscribeFromCreator.cs @@ -1,14 +1,15 @@ -using FastEndpoints; -using Hutopy.Web.Common; +using Hutopy.Web.Common; using Hutopy.Web.Features.Contents.Data; namespace Hutopy.Web.Features.Contents.Handlers; +[PublicAPI] public sealed class UnsubscribeFromCreatorRequest { public Guid CreatorId { get; set; } } +[PublicAPI] public class UnsubscribeFromCreatorHandler( ContentDbContext context) : Endpoint diff --git a/src/Web/Features/Messages/Data/MessagingDbContext.cs b/src/Web/Features/Messages/Data/MessagingDbContext.cs index 2d59e52..a7b2028 100644 --- a/src/Web/Features/Messages/Data/MessagingDbContext.cs +++ b/src/Web/Features/Messages/Data/MessagingDbContext.cs @@ -1,5 +1,4 @@ using Hutopy.Web.Features.Messages.Handlers.Models; -using Microsoft.EntityFrameworkCore; namespace Hutopy.Web.Features.Messages.Data; diff --git a/src/Web/Features/Messages/DependencyInjection.cs b/src/Web/Features/Messages/DependencyInjection.cs index 0693a3e..6f4bf3c 100644 --- a/src/Web/Features/Messages/DependencyInjection.cs +++ b/src/Web/Features/Messages/DependencyInjection.cs @@ -1,5 +1,4 @@ using Hutopy.Web.Features.Messages.Data; -using Microsoft.EntityFrameworkCore; namespace Hutopy.Web.Features.Messages; diff --git a/src/Web/Features/Messages/Handlers/AddMessage.cs b/src/Web/Features/Messages/Handlers/AddMessage.cs index 81c12b8..84131a4 100644 --- a/src/Web/Features/Messages/Handlers/AddMessage.cs +++ b/src/Web/Features/Messages/Handlers/AddMessage.cs @@ -1,6 +1,4 @@ -using FastEndpoints; -using FluentValidation; -using Hutopy.Web.Common; +using Hutopy.Web.Common; using Hutopy.Web.Features.Messages.Data; namespace Hutopy.Web.Features.Messages.Handlers; diff --git a/src/Web/Features/Messages/Handlers/AddReply.cs b/src/Web/Features/Messages/Handlers/AddReply.cs index 8b2ea91..b1c7aa8 100644 --- a/src/Web/Features/Messages/Handlers/AddReply.cs +++ b/src/Web/Features/Messages/Handlers/AddReply.cs @@ -1,6 +1,4 @@ -using FastEndpoints; -using FluentValidation; -using Hutopy.Web.Common; +using Hutopy.Web.Common; using Hutopy.Web.Features.Messages.Data; namespace Hutopy.Web.Features.Messages.Handlers; diff --git a/src/Web/Features/Messages/Handlers/GetMessages.cs b/src/Web/Features/Messages/Handlers/GetMessages.cs index de98a5e..1fb7236 100644 --- a/src/Web/Features/Messages/Handlers/GetMessages.cs +++ b/src/Web/Features/Messages/Handlers/GetMessages.cs @@ -1,5 +1,4 @@ -using FastEndpoints; -using Hutopy.Web.Features.Messages.Data; +using Hutopy.Web.Features.Messages.Data; using Hutopy.Web.Features.Messages.Handlers.Models; namespace Hutopy.Web.Features.Messages.Handlers; diff --git a/src/Web/Features/Messages/Handlers/GetMessagesByUser.cs b/src/Web/Features/Messages/Handlers/GetMessagesByUser.cs index db611a0..bdd5105 100644 --- a/src/Web/Features/Messages/Handlers/GetMessagesByUser.cs +++ b/src/Web/Features/Messages/Handlers/GetMessagesByUser.cs @@ -1,7 +1,5 @@ -using FastEndpoints; -using Hutopy.Web.Features.Messages.Data; +using Hutopy.Web.Features.Messages.Data; using Hutopy.Web.Features.Messages.Handlers.Models; -using Microsoft.EntityFrameworkCore; namespace Hutopy.Web.Features.Messages.Handlers; diff --git a/src/Web/Features/Messages/Handlers/GetReplies.cs b/src/Web/Features/Messages/Handlers/GetReplies.cs index 9c39fef..40b5f5f 100644 --- a/src/Web/Features/Messages/Handlers/GetReplies.cs +++ b/src/Web/Features/Messages/Handlers/GetReplies.cs @@ -1,5 +1,4 @@ -using FastEndpoints; -using Hutopy.Web.Features.Messages.Data; +using Hutopy.Web.Features.Messages.Data; using Hutopy.Web.Features.Messages.Handlers.Models; namespace Hutopy.Web.Features.Messages.Handlers; diff --git a/src/Web/GlobalUsings.cs b/src/Web/GlobalUsings.cs index a69805b..4f99808 100644 --- a/src/Web/GlobalUsings.cs +++ b/src/Web/GlobalUsings.cs @@ -1,3 +1,6 @@ global using Ardalis.GuardClauses; -global using Hutopy.Web.Infrastructure; +global using FastEndpoints; +global using FluentValidation; +global using JetBrains.Annotations; global using MediatR; +global using Microsoft.EntityFrameworkCore; diff --git a/src/Web/Infrastructure/CustomExceptionHandler.cs b/src/Web/Infrastructure/CustomExceptionHandler.cs index a94d865..6f321cb 100644 --- a/src/Web/Infrastructure/CustomExceptionHandler.cs +++ b/src/Web/Infrastructure/CustomExceptionHandler.cs @@ -1,6 +1,8 @@ using Hutopy.Application.Common.Exceptions; using Microsoft.AspNetCore.Diagnostics; using Microsoft.AspNetCore.Mvc; +using ProblemDetails = Microsoft.AspNetCore.Mvc.ProblemDetails; +using ValidationException = Hutopy.Application.Common.Exceptions.ValidationException; namespace Hutopy.Web.Infrastructure; diff --git a/src/Web/Pages/Shared/_LoginPartial.cshtml b/src/Web/Pages/Shared/_LoginPartial.cshtml index b8197de..252b86b 100644 --- a/src/Web/Pages/Shared/_LoginPartial.cshtml +++ b/src/Web/Pages/Shared/_LoginPartial.cshtml @@ -1,5 +1,6 @@ @using Hutopy.Infrastructure.Identity @using Microsoft.AspNetCore.Identity +@using Microsoft.AspNetCore.Mvc.TagHelpers @inject SignInManager SignInManager @{ diff --git a/src/Web/Program.cs b/src/Web/Program.cs index f44349a..575d391 100644 --- a/src/Web/Program.cs +++ b/src/Web/Program.cs @@ -1,5 +1,4 @@ using Azure.Identity; -using FastEndpoints; using Hutopy.Application; using Hutopy.Infrastructure; using Hutopy.Infrastructure.Data; @@ -9,8 +8,8 @@ using Hutopy.Web.Features.Contents; using Hutopy.Web.Features.Contents.Data; using Hutopy.Web.Features.Messages; using Hutopy.Web.Features.Messages.Data; +using Hutopy.Web.Infrastructure; using Microsoft.AspNetCore.HttpOverrides; -using Microsoft.EntityFrameworkCore; using NSwag; using NSwag.Generation.AspNetCore.Processors; using NSwag.Generation.Processors.Security; diff --git a/src/Web/Web.csproj b/src/Web/Web.csproj index 605e476..97eb60a 100644 --- a/src/Web/Web.csproj +++ b/src/Web/Web.csproj @@ -16,6 +16,7 @@ + From 50ecfa397ca60bc23cc5ebc88a09154ea678fb93 Mon Sep 17 00:00:00 2001 From: Jonathan Bourdon Date: Wed, 7 Aug 2024 13:05:33 -0400 Subject: [PATCH 161/229] Fix GetContentsByCreator ugly ef query --- .../Contents/Handlers/GetContentsByCreator.cs | 40 ++++++++++++------- .../Contents/Handlers/Models/ContentModel.cs | 33 +++++---------- src/Web/Web.http | 6 ++- 3 files changed, 41 insertions(+), 38 deletions(-) diff --git a/src/Web/Features/Contents/Handlers/GetContentsByCreator.cs b/src/Web/Features/Contents/Handlers/GetContentsByCreator.cs index 910eaa3..cba8624 100644 --- a/src/Web/Features/Contents/Handlers/GetContentsByCreator.cs +++ b/src/Web/Features/Contents/Handlers/GetContentsByCreator.cs @@ -1,4 +1,5 @@ -using Hutopy.Web.Features.Contents.Data; +using System.Text; +using Hutopy.Web.Features.Contents.Data; using Hutopy.Web.Features.Contents.Handlers.Models; namespace Hutopy.Web.Features.Contents.Handlers; @@ -6,7 +7,7 @@ namespace Hutopy.Web.Features.Contents.Handlers; [PublicAPI] public sealed class GetContentsByCreatorRequest { - public Guid UserId { get; set; } + public Guid CreatorId { get; set; } [BindFrom("page_size")] public int PageSize { get; set; } = 10; [BindFrom("last_id")] public Guid? LastId { get; set; } } @@ -18,7 +19,7 @@ public class GetContentsByCreatorHandler( { public override void Configure() { - Get("/api/contents/creator/{UserId:guid}"); + Get("/api/contents/creator/{CreatorId:guid}"); Options(o => o.WithTags("Contents")); AllowAnonymous(); } @@ -27,21 +28,32 @@ public class GetContentsByCreatorHandler( GetContentsByCreatorRequest req, CancellationToken ct) { - var query = context - .Contents - .Where(c => c.CreatedBy == req.UserId); + var queryBuilder = new StringBuilder(); + queryBuilder.AppendLine($""" + SELECT content."Id", content."CreatedBy", creator."Name" as CreatedByName, i."Logo" as CreatedByPortraitUrl, content."CreatedAt", content."Title", content."Description", content."Urls" + FROM "Content"."Contents" AS content + INNER JOIN "Content"."Creators" AS creator ON content."CreatedBy" = creator."Id" + LEFT JOIN "Content"."Images" AS i ON creator."Id" = i."CreatorId" + WHERE content."CreatedBy" = '{req.CreatorId}' + """); - query = query.OrderByDescending(c => c.CreatedAt); + if (req.LastId.HasValue) + { + queryBuilder.AppendLine($"""AND content."Id" < '{req.LastId.Value}'"""); + } - if (req.LastId is not null) - query = query.Where(c => c.Id < req.LastId.Value); + queryBuilder.AppendLine($""" + ORDER BY content."CreatedAt" DESC + LIMIT {req.PageSize} + """); - query = query.Take(req.PageSize); - - var posts = await query - .Select(x => x.ToResponse()) + var query = queryBuilder.ToString(); + + var results = await context + .Database + .SqlQueryRaw(query) .ToListAsync(cancellationToken: ct); - await SendAsync(posts, cancellation: ct); + await SendAsync(results, cancellation: ct); } } diff --git a/src/Web/Features/Contents/Handlers/Models/ContentModel.cs b/src/Web/Features/Contents/Handlers/Models/ContentModel.cs index 56eccf5..2746b99 100644 --- a/src/Web/Features/Contents/Handlers/Models/ContentModel.cs +++ b/src/Web/Features/Contents/Handlers/Models/ContentModel.cs @@ -1,27 +1,14 @@ -using Hutopy.Web.Features.Contents.Data; - -namespace Hutopy.Web.Features.Contents.Handlers.Models; +namespace Hutopy.Web.Features.Contents.Handlers.Models; [PublicAPI] -public record struct ContentModel( - Guid Id, - Guid CreatedBy, - string CreatedByName, - string? CreatedByPortraitUrl, - DateTimeOffset CreatedAt, - string Title, - string Description, - string[]? Urls); - -public static class ContentExtensions +public class ContentModel { - public static ContentModel ToResponse(this Content c) => new( - c.Id, - c.CreatedBy, - c.Creator!.Name, - c.Creator.Images.Logo, - c.CreatedAt, - c.Title, - c.Description, - c.Urls); + public Guid Id { get; set; } + public Guid CreatedBy { get; set; } + public string CreatedByName { get; set; } + public string? CreatedByPortraitUrl { get; set; } + public DateTimeOffset CreatedAt { get; set; } + public string Title { get; set; } + public string Description { get; set; } + public string[]? Urls { get; set; } } diff --git a/src/Web/Web.http b/src/Web/Web.http index bc91375..9f24562 100644 --- a/src/Web/Web.http +++ b/src/Web/Web.http @@ -59,4 +59,8 @@ Authorization: Bearer {{auth_token}} ### # GET /api/posts/by-user GET {{base_url}}/api/messages/by-user/325C69E8-DBC4-4CEE-B56E-C3C90AEE7963 -Authorization: Bearer {{auth_token}} \ No newline at end of file +Authorization: Bearer {{auth_token}} + +### +# GET /api/contents/creator/{CreatorId} +GET {{base_url}}/api/contents/creator/8590ba59-58a7-4466-bb50-08dcb5e47c6d/ From 4255afb0a56d6cd78db472806126dca8e116db8c Mon Sep 17 00:00:00 2001 From: Jonathan Bourdon Date: Wed, 7 Aug 2024 13:12:41 -0400 Subject: [PATCH 162/229] Remove warnings from ContentModel --- .../Contents/Handlers/Models/ContentModel.cs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/Web/Features/Contents/Handlers/Models/ContentModel.cs b/src/Web/Features/Contents/Handlers/Models/ContentModel.cs index 2746b99..123532a 100644 --- a/src/Web/Features/Contents/Handlers/Models/ContentModel.cs +++ b/src/Web/Features/Contents/Handlers/Models/ContentModel.cs @@ -3,12 +3,12 @@ [PublicAPI] public class ContentModel { - public Guid Id { get; set; } - public Guid CreatedBy { get; set; } - public string CreatedByName { get; set; } - public string? CreatedByPortraitUrl { get; set; } - public DateTimeOffset CreatedAt { get; set; } - public string Title { get; set; } - public string Description { get; set; } - public string[]? Urls { get; set; } + public required Guid Id { get; init; } + public required Guid CreatedBy { get; init; } + public required string CreatedByName { get; init; } + public required string? CreatedByPortraitUrl { get; init; } + public required DateTimeOffset CreatedAt { get; init; } + public required string Title { get; init; } + public required string Description { get; init; } + public required string[]? Urls { get; init; } } From 256d7b7ff7a64a80458cdd1b9049fa3e787e8a5a Mon Sep 17 00:00:00 2001 From: Jonathan Bourdon Date: Thu, 15 Aug 2024 12:18:54 -0400 Subject: [PATCH 163/229] Add missing dev configuration --- src/Infrastructure/AzureBlob/AzureBlobStorage.cs | 2 +- src/Web/appsettings.Development.json | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Infrastructure/AzureBlob/AzureBlobStorage.cs b/src/Infrastructure/AzureBlob/AzureBlobStorage.cs index 2016b7f..53b4342 100644 --- a/src/Infrastructure/AzureBlob/AzureBlobStorage.cs +++ b/src/Infrastructure/AzureBlob/AzureBlobStorage.cs @@ -17,7 +17,7 @@ public class AzureBlobStorage : IBlobStorage public AzureBlobStorage(IConfiguration configuration, ILogger logger) { _logger = logger; - var connectionString = configuration["Azure-Blob-Connection-String"] ?? ""; + var connectionString = configuration.GetConnectionString("AzureBlob"); _blobServiceClient = new BlobServiceClient(connectionString); } diff --git a/src/Web/appsettings.Development.json b/src/Web/appsettings.Development.json index f7ec248..3428fe2 100644 --- a/src/Web/appsettings.Development.json +++ b/src/Web/appsettings.Development.json @@ -8,6 +8,7 @@ } }, "ConnectionStrings": { + "AzureBlob": "DefaultEndpointsProtocol=https;AccountName=hutopyblob;AccountKey=AjK9vQMCIAG280PFIAWDjTtiFc/fIj/fb1NA9xtC7SLm6ZMZa/Agg0JFGYcHuJEaoZKDme7mNx/U+AStt9o7LQ==;EndpointSuffix=core.windows.net", "MssqlConnection": "Server=localhost,1433;Initial Catalog=Hutopy;User Id=sa;Password=P@ssword123!;MultipleActiveResultSets=true;TrustServerCertificate=True;MultiSubnetFailover=True", "PostgresConnection": "Server=localhost,5432;Database=Hutopy;Uid=sa;Pwd=P@ssword123!;" }, From 536e192ff4393353f140718ab12c132eb43423d7 Mon Sep 17 00:00:00 2001 From: Jonathan Bourdon Date: Thu, 15 Aug 2024 12:38:40 -0400 Subject: [PATCH 164/229] Change CreateContent to allows content without images --- .../Contents/Handlers/CreateContent.cs | 46 ++++++++++--------- 1 file changed, 24 insertions(+), 22 deletions(-) diff --git a/src/Web/Features/Contents/Handlers/CreateContent.cs b/src/Web/Features/Contents/Handlers/CreateContent.cs index 964e507..999fdd6 100644 --- a/src/Web/Features/Contents/Handlers/CreateContent.cs +++ b/src/Web/Features/Contents/Handlers/CreateContent.cs @@ -12,7 +12,7 @@ public record PostContentRequest( Guid CreatorId, string Title, string Description, - IFormFileCollection Files); + IFormFileCollection? Files); [PublicAPI] public sealed class PostContentRequestValidator : Validator @@ -53,38 +53,40 @@ public sealed class PostContent( PostContentRequest req, CancellationToken ct) { - var urls = new ConcurrentBag(); - await Parallel.ForEachAsync( - req.Files, - ct, - async (file, ict) => - { - try + if (req.Files is not null) + { + await Parallel.ForEachAsync( + req.Files, + ct, + async (file, ict) => { - var contentUrl = await SaveFileAsync( - req.CreatorId, - req.Id, - file, - ict); + try + { + var contentUrl = await SaveFileAsync( + req.CreatorId, + req.Id, + file, + ict); - urls.Add(contentUrl); - } - catch (Exception ex) - { - Logger.LogError("{ErrorMessage}", ex.Message); - } - }); + urls.Add(contentUrl); + } + catch (Exception ex) + { + Logger.LogError("{ErrorMessage}", ex.Message); + } + }); + } await context.Contents.AddAsync( - new() + new Content { Id = req.Id, CreatedBy = User.GetUserId(), Title = req.Title, Description = req.Description, - Urls = urls.ToArray() + Urls = urls.IsEmpty ? null : urls.ToArray() }, ct); From 634e79b1326d8580d8c83b4d17d34c3efd6c25bc Mon Sep 17 00:00:00 2001 From: Jonathan Bourdon Date: Thu, 15 Aug 2024 15:36:39 -0400 Subject: [PATCH 165/229] Adds Creator's Color to each Content response --- src/Web/Features/Contents/Handlers/GetContent.cs | 16 +++++++++++++++- .../Contents/Handlers/GetContentsByCreator.cs | 12 +++++++++++- .../Contents/Handlers/Models/ContentModel.cs | 2 ++ 3 files changed, 28 insertions(+), 2 deletions(-) diff --git a/src/Web/Features/Contents/Handlers/GetContent.cs b/src/Web/Features/Contents/Handlers/GetContent.cs index 398d9c0..a097020 100644 --- a/src/Web/Features/Contents/Handlers/GetContent.cs +++ b/src/Web/Features/Contents/Handlers/GetContent.cs @@ -1,4 +1,5 @@ using Hutopy.Web.Features.Contents.Data; +using Hutopy.Web.Features.Contents.Handlers.Models; namespace Hutopy.Web.Features.Contents.Handlers; @@ -11,7 +12,7 @@ public sealed class GetContentRequest [PublicAPI] public class GetContent( ContentDbContext context) - : Endpoint + : Endpoint { public override void Configure() { @@ -26,6 +27,19 @@ public class GetContent( { var content = await context .Contents + .Select(c => new ContentModel + { + Id = c.Id, + CreatedBy = c.CreatedBy, + CreatedByName = c.Creator!.Name, + CreatedByPortraitUrl = c.Creator.Images.Logo, + CreatedAt = c.CreatedAt, + ColorMenu = c.Creator.Colors.Menu, + ColorAccent = c.Creator.Colors.Accent, + Title = c.Title, + Description = c.Description, + Urls = c.Urls, + }) .SingleOrDefaultAsync( c => c.Id == req.ContentId, cancellationToken: ct); diff --git a/src/Web/Features/Contents/Handlers/GetContentsByCreator.cs b/src/Web/Features/Contents/Handlers/GetContentsByCreator.cs index cba8624..983d902 100644 --- a/src/Web/Features/Contents/Handlers/GetContentsByCreator.cs +++ b/src/Web/Features/Contents/Handlers/GetContentsByCreator.cs @@ -30,10 +30,20 @@ public class GetContentsByCreatorHandler( { var queryBuilder = new StringBuilder(); queryBuilder.AppendLine($""" - SELECT content."Id", content."CreatedBy", creator."Name" as CreatedByName, i."Logo" as CreatedByPortraitUrl, content."CreatedAt", content."Title", content."Description", content."Urls" + SELECT content."Id", + content."CreatedBy", + creator."Name" as CreatedByName, + i."Logo" as CreatedByPortraitUrl, + c."Menu" as ColorMenu, + c."Accent" as ColorAccent, + content."CreatedAt", + content."Title", + content."Description", + content."Urls" FROM "Content"."Contents" AS content INNER JOIN "Content"."Creators" AS creator ON content."CreatedBy" = creator."Id" LEFT JOIN "Content"."Images" AS i ON creator."Id" = i."CreatorId" + LEFT JOIN "Content"."Colors" AS c ON creator."Id" = c."CreatorId" WHERE content."CreatedBy" = '{req.CreatorId}' """); diff --git a/src/Web/Features/Contents/Handlers/Models/ContentModel.cs b/src/Web/Features/Contents/Handlers/Models/ContentModel.cs index 123532a..f6cff02 100644 --- a/src/Web/Features/Contents/Handlers/Models/ContentModel.cs +++ b/src/Web/Features/Contents/Handlers/Models/ContentModel.cs @@ -7,6 +7,8 @@ public class ContentModel public required Guid CreatedBy { get; init; } public required string CreatedByName { get; init; } public required string? CreatedByPortraitUrl { get; init; } + public required string? ColorMenu { get; init; } + public required string? ColorAccent { get; init; } public required DateTimeOffset CreatedAt { get; init; } public required string Title { get; init; } public required string Description { get; init; } From 84deb59e4b5d1f6ab102e56a2e5b5d90661ef0bf Mon Sep 17 00:00:00 2001 From: Jonathan Bourdon Date: Fri, 16 Aug 2024 14:38:11 -0400 Subject: [PATCH 166/229] Fix GetCreatorByAlias to be case-insensitive --- src/Web/Features/Contents/Handlers/GetCreatorByAlias.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Web/Features/Contents/Handlers/GetCreatorByAlias.cs b/src/Web/Features/Contents/Handlers/GetCreatorByAlias.cs index 87ca6ec..7f72f38 100644 --- a/src/Web/Features/Contents/Handlers/GetCreatorByAlias.cs +++ b/src/Web/Features/Contents/Handlers/GetCreatorByAlias.cs @@ -41,7 +41,7 @@ public class GetCreatorByAliasHandler( var creator = await context .Creators - .Where(c => EF.Functions.Like(c.Name, creatorName)) + .Where(c => EF.Functions.ILike(c.Name, creatorName)) .FirstOrDefaultAsync(ct); if (creator is null) From d1557f92c6e77029a323ebdbbf259c1ec9917849 Mon Sep 17 00:00:00 2001 From: Jonathan Bourdon Date: Fri, 16 Aug 2024 17:03:04 -0400 Subject: [PATCH 167/229] Fix GetContentsByCreator returning the same content multiple times --- src/Web/Features/Contents/Handlers/GetContentsByCreator.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Web/Features/Contents/Handlers/GetContentsByCreator.cs b/src/Web/Features/Contents/Handlers/GetContentsByCreator.cs index 983d902..c9ffb50 100644 --- a/src/Web/Features/Contents/Handlers/GetContentsByCreator.cs +++ b/src/Web/Features/Contents/Handlers/GetContentsByCreator.cs @@ -49,7 +49,7 @@ public class GetContentsByCreatorHandler( if (req.LastId.HasValue) { - queryBuilder.AppendLine($"""AND content."Id" < '{req.LastId.Value}'"""); + queryBuilder.AppendLine($"""AND content."Id" > '{req.LastId.Value}'"""); } queryBuilder.AppendLine($""" From 8b702d16d6ae8b5691dea6c3b29df7e113e3c43e Mon Sep 17 00:00:00 2001 From: Jonathan Bourdon Date: Fri, 16 Aug 2024 18:14:48 -0400 Subject: [PATCH 168/229] Adds Content deletion --- src/Web/Features/Contents/Data/Content.cs | 2 + .../Contents/Handlers/DeleteContent.cs | 59 ++++ .../Features/Contents/Handlers/GetContent.cs | 2 + .../Contents/Handlers/GetContentsByCreator.cs | 5 +- .../Contents/Handlers/Models/ContentModel.cs | 2 + .../20240816212531_AddsSoftDelete.Designer.cs | 264 ++++++++++++++++++ .../20240816212531_AddsSoftDelete.cs | 43 +++ .../ContentDbContextModelSnapshot.cs | 6 + 8 files changed, 382 insertions(+), 1 deletion(-) create mode 100644 src/Web/Features/Contents/Handlers/DeleteContent.cs create mode 100644 src/Web/Features/Contents/Migrations/20240816212531_AddsSoftDelete.Designer.cs create mode 100644 src/Web/Features/Contents/Migrations/20240816212531_AddsSoftDelete.cs diff --git a/src/Web/Features/Contents/Data/Content.cs b/src/Web/Features/Contents/Data/Content.cs index dff459a..3e5d03a 100644 --- a/src/Web/Features/Contents/Data/Content.cs +++ b/src/Web/Features/Contents/Data/Content.cs @@ -8,6 +8,8 @@ public class Content public Guid CreatedBy { get; init; } public Creator? Creator { get; set; } public DateTimeOffset CreatedAt { get; init; } + public Guid? DeletedBy { get; set; } + public DateTimeOffset? DeletedAt { get; set; } [MaxLength(128)] public required string Title { get; set; } [MaxLength(2048)] public required string Description { get; set; } diff --git a/src/Web/Features/Contents/Handlers/DeleteContent.cs b/src/Web/Features/Contents/Handlers/DeleteContent.cs new file mode 100644 index 0000000..eb5b512 --- /dev/null +++ b/src/Web/Features/Contents/Handlers/DeleteContent.cs @@ -0,0 +1,59 @@ +using Hutopy.Web.Common; +using Hutopy.Web.Features.Contents.Data; + +namespace Hutopy.Web.Features.Contents.Handlers; + +[PublicAPI] +public record DeleteContentRequest( + Guid ContentId); + +[PublicAPI] +public sealed class DeleteContentRequestValidator : Validator +{ + public DeleteContentRequestValidator() + { + RuleFor(r => r.ContentId) + .NotNull().WithMessage("You should specify the ContentId") + .NotEmpty().WithMessage("You should specify a valid/not empty ContentId"); + } +} + +public sealed class DeleteContent( + ContentDbContext context) + : Endpoint +{ + public override void Configure() + { + Delete("/api/contents/{ContentId}"); + Options(o => o.WithTags("Contents")); + } + + public override async Task HandleAsync( + DeleteContentRequest req, + CancellationToken ct) + { + var content = await context.Contents.FindAsync( + [req.ContentId], + ct); + + if (content is null) + { + await SendNotFoundAsync(ct); + return; + } + + var userId = HttpContext.User.GetUserId(); + if (content.CreatedBy != userId) + { + await SendForbiddenAsync(ct); + return; + } + + content.DeletedAt = DateTimeOffset.UtcNow; + content.DeletedBy = userId; + + await context.SaveChangesAsync(ct); + + await SendOkAsync(ct); + } +} diff --git a/src/Web/Features/Contents/Handlers/GetContent.cs b/src/Web/Features/Contents/Handlers/GetContent.cs index a097020..3fe1c38 100644 --- a/src/Web/Features/Contents/Handlers/GetContent.cs +++ b/src/Web/Features/Contents/Handlers/GetContent.cs @@ -36,6 +36,8 @@ public class GetContent( CreatedAt = c.CreatedAt, ColorMenu = c.Creator.Colors.Menu, ColorAccent = c.Creator.Colors.Accent, + DeletedBy = c.DeletedBy, + DeletedAt = c.DeletedAt, Title = c.Title, Description = c.Description, Urls = c.Urls, diff --git a/src/Web/Features/Contents/Handlers/GetContentsByCreator.cs b/src/Web/Features/Contents/Handlers/GetContentsByCreator.cs index c9ffb50..6392ee3 100644 --- a/src/Web/Features/Contents/Handlers/GetContentsByCreator.cs +++ b/src/Web/Features/Contents/Handlers/GetContentsByCreator.cs @@ -37,6 +37,8 @@ public class GetContentsByCreatorHandler( c."Menu" as ColorMenu, c."Accent" as ColorAccent, content."CreatedAt", + content."DeletedBy", + content."DeletedAt", content."Title", content."Description", content."Urls" @@ -44,7 +46,8 @@ public class GetContentsByCreatorHandler( INNER JOIN "Content"."Creators" AS creator ON content."CreatedBy" = creator."Id" LEFT JOIN "Content"."Images" AS i ON creator."Id" = i."CreatorId" LEFT JOIN "Content"."Colors" AS c ON creator."Id" = c."CreatorId" - WHERE content."CreatedBy" = '{req.CreatorId}' + WHERE content."CreatedBy" = '{req.CreatorId}' + AND content."DeletedBy" IS NULL """); if (req.LastId.HasValue) diff --git a/src/Web/Features/Contents/Handlers/Models/ContentModel.cs b/src/Web/Features/Contents/Handlers/Models/ContentModel.cs index f6cff02..c3cecc9 100644 --- a/src/Web/Features/Contents/Handlers/Models/ContentModel.cs +++ b/src/Web/Features/Contents/Handlers/Models/ContentModel.cs @@ -10,6 +10,8 @@ public class ContentModel public required string? ColorMenu { get; init; } public required string? ColorAccent { get; init; } public required DateTimeOffset CreatedAt { get; init; } + public Guid? DeletedBy { get; init; } + public DateTimeOffset? DeletedAt { get; init; } public required string Title { get; init; } public required string Description { get; init; } public required string[]? Urls { get; init; } diff --git a/src/Web/Features/Contents/Migrations/20240816212531_AddsSoftDelete.Designer.cs b/src/Web/Features/Contents/Migrations/20240816212531_AddsSoftDelete.Designer.cs new file mode 100644 index 0000000..4ffcce3 --- /dev/null +++ b/src/Web/Features/Contents/Migrations/20240816212531_AddsSoftDelete.Designer.cs @@ -0,0 +1,264 @@ +// +using System; +using Hutopy.Web.Features.Contents.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace Hutopy.Web.Features.Contents.Migrations +{ + [DbContext(typeof(ContentDbContext))] + [Migration("20240816212531_AddsSoftDelete")] + partial class AddsSoftDelete + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasDefaultSchema("Content") + .HasAnnotation("ProductVersion", "8.0.4") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("Hutopy.Web.Features.Contents.Data.Content", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("CURRENT_TIMESTAMP"); + + b.Property("CreatedBy") + .HasColumnType("uuid"); + + b.Property("DeletedBy") + .HasColumnType("uuid"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(2048) + .HasColumnType("character varying(2048)"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("Urls") + .HasColumnType("text[]"); + + b.HasKey("Id"); + + b.HasIndex("CreatedBy"); + + b.ToTable("Contents", "Content"); + }); + + modelBuilder.Entity("Hutopy.Web.Features.Contents.Data.Creator", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("uuid"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.HasKey("Id"); + + b.ToTable("Creators", "Content"); + }); + + modelBuilder.Entity("Hutopy.Web.Features.Contents.Data.Subscription", b => + { + b.Property("CreatedBy") + .HasColumnType("uuid"); + + b.Property("CreatorId") + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("CreatedBy", "CreatorId"); + + b.HasIndex("CreatorId"); + + b.ToTable("Subscriptions", "Content"); + }); + + modelBuilder.Entity("Hutopy.Web.Features.Contents.Data.Content", b => + { + b.HasOne("Hutopy.Web.Features.Contents.Data.Creator", "Creator") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Creator"); + }); + + modelBuilder.Entity("Hutopy.Web.Features.Contents.Data.Creator", b => + { + b.OwnsOne("Hutopy.Web.Features.Contents.Data.About", "About", b1 => + { + b1.Property("CreatorId") + .HasColumnType("uuid"); + + b1.Property("Description") + .HasMaxLength(2048) + .HasColumnType("character varying(2048)"); + + b1.Property("Title") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.HasKey("CreatorId"); + + b1.ToTable("Creators", "Content"); + + b1.WithOwner() + .HasForeignKey("CreatorId"); + }); + + b.OwnsOne("Hutopy.Web.Features.Contents.Data.Colors", "Colors", b1 => + { + b1.Property("CreatorId") + .HasColumnType("uuid"); + + b1.Property("Accent") + .HasMaxLength(9) + .HasColumnType("character varying(9)"); + + b1.Property("BannerBottom") + .HasMaxLength(9) + .HasColumnType("character varying(9)"); + + b1.Property("BannerTop") + .HasMaxLength(9) + .HasColumnType("character varying(9)"); + + b1.Property("Menu") + .HasMaxLength(9) + .HasColumnType("character varying(9)"); + + b1.HasKey("CreatorId"); + + b1.ToTable("Colors", "Content"); + + b1.WithOwner() + .HasForeignKey("CreatorId"); + }); + + b.OwnsOne("Hutopy.Web.Features.Contents.Data.Images", "Images", b1 => + { + b1.Property("CreatorId") + .HasColumnType("uuid"); + + b1.Property("Banner") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.Property("Logo") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.HasKey("CreatorId"); + + b1.ToTable("Images", "Content"); + + b1.WithOwner() + .HasForeignKey("CreatorId"); + }); + + b.OwnsOne("Hutopy.Web.Features.Contents.Data.Socials", "Socials", b1 => + { + b1.Property("CreatorId") + .HasColumnType("uuid"); + + b1.Property("FacebookUrl") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.Property("InstagramUrl") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.Property("LinkedInUrl") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.Property("RedditUrl") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.Property("TikTokUrl") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.Property("WebsiteUrl") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.Property("XUrl") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.Property("YoutubeUrl") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.HasKey("CreatorId"); + + b1.ToTable("Socials", "Content"); + + b1.WithOwner() + .HasForeignKey("CreatorId"); + }); + + b.Navigation("About") + .IsRequired(); + + b.Navigation("Colors") + .IsRequired(); + + b.Navigation("Images") + .IsRequired(); + + b.Navigation("Socials") + .IsRequired(); + }); + + modelBuilder.Entity("Hutopy.Web.Features.Contents.Data.Subscription", b => + { + b.HasOne("Hutopy.Web.Features.Contents.Data.Creator", "Creator") + .WithMany() + .HasForeignKey("CreatorId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Creator"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Web/Features/Contents/Migrations/20240816212531_AddsSoftDelete.cs b/src/Web/Features/Contents/Migrations/20240816212531_AddsSoftDelete.cs new file mode 100644 index 0000000..a6b528d --- /dev/null +++ b/src/Web/Features/Contents/Migrations/20240816212531_AddsSoftDelete.cs @@ -0,0 +1,43 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Hutopy.Web.Features.Contents.Migrations +{ + /// + public partial class AddsSoftDelete : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "DeletedBy", + schema: "Content", + table: "Contents", + type: "uuid", + nullable: true); + + migrationBuilder.AddColumn( + name: "DeletedAt", + schema: "Content", + table: "Contents", + type: "timestamp with time zone", + nullable: true); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "DeletedBy", + schema: "Content", + table: "Contents"); + + migrationBuilder.DropColumn( + name: "DeletedAt", + schema: "Content", + table: "Contents"); + } + } +} diff --git a/src/Web/Features/Contents/Migrations/ContentDbContextModelSnapshot.cs b/src/Web/Features/Contents/Migrations/ContentDbContextModelSnapshot.cs index 245416b..e4821b9 100644 --- a/src/Web/Features/Contents/Migrations/ContentDbContextModelSnapshot.cs +++ b/src/Web/Features/Contents/Migrations/ContentDbContextModelSnapshot.cs @@ -37,6 +37,12 @@ namespace Hutopy.Web.Features.Contents.Migrations b.Property("CreatedBy") .HasColumnType("uuid"); + b.Property("DeletedBy") + .HasColumnType("uuid"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone"); + b.Property("Description") .IsRequired() .HasMaxLength(2048) From f5f80fa234b7ed19ad0fdb49a805f14e7d7b177a Mon Sep 17 00:00:00 2001 From: Jonathan Bourdon Date: Fri, 16 Aug 2024 23:41:45 -0400 Subject: [PATCH 169/229] Now returns the created content upon posting --- .../Contents/Handlers/CreateContent.cs | 24 ++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/src/Web/Features/Contents/Handlers/CreateContent.cs b/src/Web/Features/Contents/Handlers/CreateContent.cs index 999fdd6..8d01e5c 100644 --- a/src/Web/Features/Contents/Handlers/CreateContent.cs +++ b/src/Web/Features/Contents/Handlers/CreateContent.cs @@ -3,6 +3,7 @@ using Hutopy.Application.AzureBlobStorage.Constants; using Hutopy.Application.Common.Interfaces; using Hutopy.Web.Common; using Hutopy.Web.Features.Contents.Data; +using Hutopy.Web.Features.Contents.Handlers.Models; namespace Hutopy.Web.Features.Contents.Handlers; @@ -92,7 +93,28 @@ public sealed class PostContent( await context.SaveChangesAsync(ct); - await SendOkAsync(ct); + var content = await context + .Contents + .Select(c => new ContentModel + { + Id = c.Id, + CreatedBy = c.CreatedBy, + CreatedByName = c.Creator!.Name, + CreatedByPortraitUrl = c.Creator.Images.Logo, + CreatedAt = c.CreatedAt, + ColorMenu = c.Creator.Colors.Menu, + ColorAccent = c.Creator.Colors.Accent, + DeletedBy = c.DeletedBy, + DeletedAt = c.DeletedAt, + Title = c.Title, + Description = c.Description, + Urls = c.Urls, + }) + .SingleOrDefaultAsync( + c => c.Id == req.Id, + cancellationToken: ct); + + await SendOkAsync(content, ct); } private async Task SaveFileAsync( From 558fe7bc6786fae892c2dde20defb19a1c617b56 Mon Sep 17 00:00:00 2001 From: Dominic Villemure Date: Sun, 18 Aug 2024 11:06:32 -0400 Subject: [PATCH 170/229] Added initializer for dev environment for the new dbContexts --- .../Data/ContentDbContextInitializer.cs | 32 +++++++++++++++++++ .../Features/Contents/DependencyInjection.cs | 1 + .../Data/MessagingDbContextInitializer.cs | 32 +++++++++++++++++++ .../Features/Messages/DependencyInjection.cs | 1 + src/Web/Program.cs | 2 ++ 5 files changed, 68 insertions(+) create mode 100644 src/Web/Features/Contents/Data/ContentDbContextInitializer.cs create mode 100644 src/Web/Features/Messages/Data/MessagingDbContextInitializer.cs diff --git a/src/Web/Features/Contents/Data/ContentDbContextInitializer.cs b/src/Web/Features/Contents/Data/ContentDbContextInitializer.cs new file mode 100644 index 0000000..571e8f5 --- /dev/null +++ b/src/Web/Features/Contents/Data/ContentDbContextInitializer.cs @@ -0,0 +1,32 @@ +namespace Hutopy.Web.Features.Contents.Data; + +public static class InitializerExtensions +{ + public static async Task InitialiseContentDbContextAsync(this WebApplication app) + { + using var scope = app.Services.CreateScope(); + + var initializer = scope.ServiceProvider.GetRequiredService(); + + await initializer.InitialiseAsync(); + } +} + +public class ContentDbContextInitializer( + ILogger logger, + ContentDbContext context + ) +{ + public async Task InitialiseAsync() + { + try + { + await context.Database.MigrateAsync(); + } + catch (Exception ex) + { + logger.LogError(ex, "An error occurred while initialising the content database."); + throw; + } + } +} diff --git a/src/Web/Features/Contents/DependencyInjection.cs b/src/Web/Features/Contents/DependencyInjection.cs index 77c7c40..cbb16d3 100644 --- a/src/Web/Features/Contents/DependencyInjection.cs +++ b/src/Web/Features/Contents/DependencyInjection.cs @@ -9,6 +9,7 @@ public static class DependencyInjection Action? configureAction = null) { services.AddDbContext(configureAction); + services.AddScoped(); return services; } diff --git a/src/Web/Features/Messages/Data/MessagingDbContextInitializer.cs b/src/Web/Features/Messages/Data/MessagingDbContextInitializer.cs new file mode 100644 index 0000000..cd40485 --- /dev/null +++ b/src/Web/Features/Messages/Data/MessagingDbContextInitializer.cs @@ -0,0 +1,32 @@ +namespace Hutopy.Web.Features.Messages.Data; + +public static class InitializerExtensions +{ + public static async Task InitialiseMessagingDbContextAsync(this WebApplication app) + { + using var scope = app.Services.CreateScope(); + + var initializer = scope.ServiceProvider.GetRequiredService(); + + await initializer.InitialiseAsync(); + } +} + +public class MessagingDbContextInitializer( + ILogger logger, + MessagingDbContext context + ) +{ + public async Task InitialiseAsync() + { + try + { + await context.Database.MigrateAsync(); + } + catch (Exception ex) + { + logger.LogError(ex, "An error occurred while initialising the messaging database."); + throw; + } + } +} diff --git a/src/Web/Features/Messages/DependencyInjection.cs b/src/Web/Features/Messages/DependencyInjection.cs index 6f4bf3c..67ff59b 100644 --- a/src/Web/Features/Messages/DependencyInjection.cs +++ b/src/Web/Features/Messages/DependencyInjection.cs @@ -9,6 +9,7 @@ public static class DependencyInjection Action? configureAction = null) { services.AddDbContext(configureAction); + services.AddScoped(); return services; } diff --git a/src/Web/Program.cs b/src/Web/Program.cs index 575d391..132c462 100644 --- a/src/Web/Program.cs +++ b/src/Web/Program.cs @@ -109,6 +109,8 @@ app.UseAuthorization(); // Initialize and seed the db. await app.InitialiseApplicationDatabaseAsync(); +await app.InitialiseContentDbContextAsync(); +await app.InitialiseMessagingDbContextAsync(); await app.SeedDatabaseWithTestDataOnlyIfNoDataIsPresentAsync(); // Configure the HTTP request pipeline. From 127ddb07cc56e1b491b1c9d9b9a5f94ead5c9eb4 Mon Sep 17 00:00:00 2001 From: Dominic Villemure Date: Sun, 18 Aug 2024 11:08:36 -0400 Subject: [PATCH 171/229] Added info for the new setup with Postgres docker --- README.md | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index fb5f274..a3820fe 100644 --- a/README.md +++ b/README.md @@ -11,12 +11,19 @@ ## Database setup in docker for local dev ``` -docker run -e "ACCEPT_EULA=Y" -e "MSSQL_SA_PASSWORD=" -p 1433:1433 -d mcr.microsoft.com/mssql/server:2022-latest +docker run -e "ACCEPT_EULA=Y" -e "MSSQL_SA_PASSWORD=P@ssword123!" -p 1433:1433 -d mcr.microsoft.com/mssql/server:2022-latest ``` Or with a mounted volume to persist data on the computer instead ( persist data even if the container is deleted ) ``` -docker run -e 'ACCEPT_EULA=Y' -e 'MSSQL_SA_PASSWORD=' -p 1433:1433 -v C:\dev\DockerVolumes\SqlServer-Utopy-1\data:/var/opt/mssql/data -v C:\dev\DockerVolumes\SqlServer-Utopy-1\log:/var/opt/mssql/log -v C:\dev\DockerVolumes\SqlServer-Utopy-1\secrets:/var/opt/mssql/secrets -d mcr.microsoft.com/mssql/server:2022-latest +docker run -e 'ACCEPT_EULA=Y' -e 'MSSQL_SA_PASSWORD=P@ssword123!' -p 1433:1433 -v C:\dev\DockerVolumes\SqlServer-Utopy-1\data:/var/opt/mssql/data -v C:\dev\DockerVolumes\SqlServer-Utopy-1\log:/var/opt/mssql/log -v C:\dev\DockerVolumes\SqlServer-Utopy-1\secrets:/var/opt/mssql/secrets -d mcr.microsoft.com/mssql/server:2022-latest +``` + +## Postgres DB setup in docker for local dev +``` +docker run -p 5432:5432 --name Hutopy -e POSTGRES_PASSWORD=P@ssword123! -e POSTGRES_USER=sa -d postgres + + ``` ## Entity Framework From 4e6f49b9109e1775fa51685918ba94705fd399a0 Mon Sep 17 00:00:00 2001 From: Dominic Villemure Date: Sun, 18 Aug 2024 12:04:07 -0400 Subject: [PATCH 172/229] Fixed color validator ( they are selected one by one in the UI ) --- .../Contents/Handlers/ChangeColors.cs | 47 +++++++++++-------- 1 file changed, 28 insertions(+), 19 deletions(-) diff --git a/src/Web/Features/Contents/Handlers/ChangeColors.cs b/src/Web/Features/Contents/Handlers/ChangeColors.cs index 40b45fe..9e2f1c9 100644 --- a/src/Web/Features/Contents/Handlers/ChangeColors.cs +++ b/src/Web/Features/Contents/Handlers/ChangeColors.cs @@ -16,25 +16,34 @@ public sealed class ChangeColorsRequestValidator { public ChangeColorsRequestValidator() { - RuleFor(x => x.BannerTop) - .MinimumLength(4).WithMessage("The minimum value should be in the format #444") - .MaximumLength(9).WithMessage("The maximum value should be in the format #11223344") - .Must(x => x.StartsWith('#')).WithMessage("The format should be a valid html color and start with #"); - - RuleFor(x => x.BannerBottom) - .MinimumLength(4).WithMessage("The minimum value should be in the format #444") - .MaximumLength(9).WithMessage("The maximum value should be in the format #11223344") - .Must(x => x.StartsWith('#')).WithMessage("The format should be a valid html color and start with #"); - - RuleFor(x => x.Accent) - .MinimumLength(4).WithMessage("The minimum value should be in the format #444") - .MaximumLength(9).WithMessage("The maximum value should be in the format #11223344") - .Must(x => x.StartsWith('#')).WithMessage("The format should be a valid html color and start with #"); - - RuleFor(x => x.Menu) - .MinimumLength(4).WithMessage("The minimum value should be in the format #444") - .MaximumLength(9).WithMessage("The maximum value should be in the format #11223344") - .Must(x => x.StartsWith('#')).WithMessage("The format should be a valid html color and start with #"); + When(x => x.BannerTop is not null, () => + { + RuleFor(x => x.BannerTop) + .MinimumLength(4).WithMessage("The minimum value should be in the format #444") + .MaximumLength(9).WithMessage("The maximum value should be in the format #11223344") + .Must(x => x.StartsWith('#')).WithMessage("The format should be a valid html color and start with #"); + }); + When(x => x.BannerBottom is not null, () => + { + RuleFor(x => x.BannerBottom) + .MinimumLength(4).WithMessage("The minimum value should be in the format #444") + .MaximumLength(9).WithMessage("The maximum value should be in the format #11223344") + .Must(x => x.StartsWith('#')).WithMessage("The format should be a valid html color and start with #"); + }); + When(x => x.Accent is not null, () => + { + RuleFor(x => x.Accent) + .MinimumLength(4).WithMessage("The minimum value should be in the format #444") + .MaximumLength(9).WithMessage("The maximum value should be in the format #11223344") + .Must(x => x.StartsWith('#')).WithMessage("The format should be a valid html color and start with #"); + }); + When(x => x.Menu is not null, () => + { + RuleFor(x => x.Menu) + .MinimumLength(4).WithMessage("The minimum value should be in the format #444") + .MaximumLength(9).WithMessage("The maximum value should be in the format #11223344") + .Must(x => x.StartsWith('#')).WithMessage("The format should be a valid html color and start with #"); + }); } } From 61b3096db82c6466e3b9d2d2d1457b321cd698d8 Mon Sep 17 00:00:00 2001 From: Jonathan Bourdon Date: Thu, 22 Aug 2024 12:49:33 -0400 Subject: [PATCH 173/229] Separate the endpoints by new groups --- src/Web/Features/Contents/Handlers/ChangeAbout.cs | 2 +- src/Web/Features/Contents/Handlers/ChangeBanner.cs | 2 +- src/Web/Features/Contents/Handlers/ChangeColors.cs | 2 +- src/Web/Features/Contents/Handlers/ChangeLogo.cs | 2 +- src/Web/Features/Contents/Handlers/ChangeSocials.cs | 2 +- src/Web/Features/Contents/Handlers/CreateCreator.cs | 2 +- src/Web/Features/Contents/Handlers/GetCreatorByAlias.cs | 2 +- src/Web/Features/Contents/Handlers/GetCreatorById.cs | 2 +- src/Web/Features/Contents/Handlers/GetSubscriptions.cs | 2 +- src/Web/Features/Contents/Handlers/SubscribeToCreator.cs | 2 +- src/Web/Features/Contents/Handlers/UnsubscribeFromCreator.cs | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/Web/Features/Contents/Handlers/ChangeAbout.cs b/src/Web/Features/Contents/Handlers/ChangeAbout.cs index 6098e80..662b4e6 100644 --- a/src/Web/Features/Contents/Handlers/ChangeAbout.cs +++ b/src/Web/Features/Contents/Handlers/ChangeAbout.cs @@ -16,7 +16,7 @@ public class ChangeAboutHandler( public override void Configure() { Post("/api/creators/{CreatorId}/about"); - Options(o => o.WithTags("Contents")); + Options(o => o.WithTags("Creators")); } public override async Task HandleAsync( diff --git a/src/Web/Features/Contents/Handlers/ChangeBanner.cs b/src/Web/Features/Contents/Handlers/ChangeBanner.cs index 9081cb6..b69affb 100644 --- a/src/Web/Features/Contents/Handlers/ChangeBanner.cs +++ b/src/Web/Features/Contents/Handlers/ChangeBanner.cs @@ -18,7 +18,7 @@ public class ChangeBannerHandler( public override void Configure() { Post("/api/creators/{CreatorId}/banner"); - Options(o => o.WithTags("Contents")); + Options(o => o.WithTags("Creators")); AllowFileUploads(); } diff --git a/src/Web/Features/Contents/Handlers/ChangeColors.cs b/src/Web/Features/Contents/Handlers/ChangeColors.cs index 9e2f1c9..25e80f3 100644 --- a/src/Web/Features/Contents/Handlers/ChangeColors.cs +++ b/src/Web/Features/Contents/Handlers/ChangeColors.cs @@ -54,7 +54,7 @@ public class ChangeColorsHandler( public override void Configure() { Post("/api/creators/{CreatorId}/colors"); - Options(o => o.WithTags("Contents")); + Options(o => o.WithTags("Creators")); } public override async Task HandleAsync(ChangeColorsRequest request, CancellationToken ct) diff --git a/src/Web/Features/Contents/Handlers/ChangeLogo.cs b/src/Web/Features/Contents/Handlers/ChangeLogo.cs index 6d4d839..44dd8b8 100644 --- a/src/Web/Features/Contents/Handlers/ChangeLogo.cs +++ b/src/Web/Features/Contents/Handlers/ChangeLogo.cs @@ -18,7 +18,7 @@ public class ChangeLogoHandler( public override void Configure() { Post("/api/creators/{CreatorId}/logo"); - Options(o => o.WithTags("Contents")); + Options(o => o.WithTags("Creators")); AllowFileUploads(); } diff --git a/src/Web/Features/Contents/Handlers/ChangeSocials.cs b/src/Web/Features/Contents/Handlers/ChangeSocials.cs index ab8a5e8..5b86c3e 100644 --- a/src/Web/Features/Contents/Handlers/ChangeSocials.cs +++ b/src/Web/Features/Contents/Handlers/ChangeSocials.cs @@ -22,7 +22,7 @@ public class ChangeSocialsHandler( public override void Configure() { Post("/api/creators/{CreatorId}/socials"); - Options(o => o.WithTags("Contents")); + Options(o => o.WithTags("Creators")); } public override async Task HandleAsync(ChangeSocialsRequest request, CancellationToken ct) diff --git a/src/Web/Features/Contents/Handlers/CreateCreator.cs b/src/Web/Features/Contents/Handlers/CreateCreator.cs index a70bd27..1e3cca2 100644 --- a/src/Web/Features/Contents/Handlers/CreateCreator.cs +++ b/src/Web/Features/Contents/Handlers/CreateCreator.cs @@ -31,7 +31,7 @@ public sealed class CreateCreatorHandler( public override void Configure() { Post("/api/creators"); - Options(o => o.WithTags("Contents")); + Options(o => o.WithTags("Creators")); } public override async Task HandleAsync( diff --git a/src/Web/Features/Contents/Handlers/GetCreatorByAlias.cs b/src/Web/Features/Contents/Handlers/GetCreatorByAlias.cs index 7f72f38..9d7c3f3 100644 --- a/src/Web/Features/Contents/Handlers/GetCreatorByAlias.cs +++ b/src/Web/Features/Contents/Handlers/GetCreatorByAlias.cs @@ -29,7 +29,7 @@ public class GetCreatorByAliasHandler( public override void Configure() { Get("/api/creators/@{Name}"); - Options((o => o.WithTags("Contents"))); + Options((o => o.WithTags("Creators"))); AllowAnonymous(); } diff --git a/src/Web/Features/Contents/Handlers/GetCreatorById.cs b/src/Web/Features/Contents/Handlers/GetCreatorById.cs index ae167e0..d7e630c 100644 --- a/src/Web/Features/Contents/Handlers/GetCreatorById.cs +++ b/src/Web/Features/Contents/Handlers/GetCreatorById.cs @@ -28,7 +28,7 @@ public class GetCreatorByIdHandler( public override void Configure() { Get("/api/creators/{CreatorId}"); - Options((o => o.WithTags("Contents"))); + Options((o => o.WithTags("Creators"))); AllowAnonymous(); } diff --git a/src/Web/Features/Contents/Handlers/GetSubscriptions.cs b/src/Web/Features/Contents/Handlers/GetSubscriptions.cs index 545a469..02c320e 100644 --- a/src/Web/Features/Contents/Handlers/GetSubscriptions.cs +++ b/src/Web/Features/Contents/Handlers/GetSubscriptions.cs @@ -12,7 +12,7 @@ public class GetSubscriptionsHandler( public override void Configure() { Get("/api/subscriptions"); - Options((o => o.WithTags("Creators"))); + Options((o => o.WithTags("Subscriptions"))); } public override async Task HandleAsync( diff --git a/src/Web/Features/Contents/Handlers/SubscribeToCreator.cs b/src/Web/Features/Contents/Handlers/SubscribeToCreator.cs index 50614c7..39352ff 100644 --- a/src/Web/Features/Contents/Handlers/SubscribeToCreator.cs +++ b/src/Web/Features/Contents/Handlers/SubscribeToCreator.cs @@ -18,7 +18,7 @@ public sealed class SubscribeToCreatorHandler( public override void Configure() { Post("/api/creators/{CreatorId}/subscribe"); - Options((o => o.WithTags("Creators"))); + Options((o => o.WithTags("Subscriptions"))); Description(x => x.Accepts("*/*")); } diff --git a/src/Web/Features/Contents/Handlers/UnsubscribeFromCreator.cs b/src/Web/Features/Contents/Handlers/UnsubscribeFromCreator.cs index 3b181fe..69ac37e 100644 --- a/src/Web/Features/Contents/Handlers/UnsubscribeFromCreator.cs +++ b/src/Web/Features/Contents/Handlers/UnsubscribeFromCreator.cs @@ -17,7 +17,7 @@ public class UnsubscribeFromCreatorHandler( public override void Configure() { Post("/api/creators/{CreatorId}/unsubscribe"); - Options((o => o.WithTags("Creators"))); + Options((o => o.WithTags("Subscriptions"))); Description(x => x.Accepts("*/*")); } From 63dc032aa401ed4a87b9712cfcac5e280fdffe5e Mon Sep 17 00:00:00 2001 From: Jonathan Bourdon Date: Thu, 22 Aug 2024 13:02:26 -0400 Subject: [PATCH 174/229] Adds 'Hutopy' to dictionary --- Hutopy.sln.DotSettings | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 Hutopy.sln.DotSettings diff --git a/Hutopy.sln.DotSettings b/Hutopy.sln.DotSettings new file mode 100644 index 0000000..140a817 --- /dev/null +++ b/Hutopy.sln.DotSettings @@ -0,0 +1,2 @@ + + True \ No newline at end of file From 588be7941c37e3e6e34c9fa45f979fe609da47e2 Mon Sep 17 00:00:00 2001 From: Dominic Villemure Date: Sat, 24 Aug 2024 18:39:09 -0400 Subject: [PATCH 175/229] Add and remove reaction from a content --- Ef.ps1 => EfApplicationDbContext.ps1 | 0 EfContentDbContext.ps1 | 1 + EfMessagingDbContext.ps1 | 1 + src/Web/Extensions/EnumExtensions.cs | 34 ++ src/Web/Features/Contents/Data/Content.cs | 2 +- .../Contents/Data/ContentDbContext.cs | 9 +- .../Features/Contents/Data/ContentReaction.cs | 11 + .../Features/Contents/Data/Enums/Reaction.cs | 13 + .../Features/Contents/Handlers/AddReaction.cs | 93 ++++++ .../Features/Contents/Handlers/GetContent.cs | 7 +- .../Contents/Handlers/GetContentsByCreator.cs | 103 +++--- .../Contents/Handlers/Models/ContentModel.cs | 5 +- .../Contents/Handlers/Models/ReactionModel.cs | 8 + .../Contents/Handlers/RemoveReaction.cs | 36 +++ ...824185551_AddReactionToContent.Designer.cs | 296 ++++++++++++++++++ .../20240824185551_AddReactionToContent.cs | 48 +++ .../ContentDbContextModelSnapshot.cs | 38 ++- 17 files changed, 660 insertions(+), 45 deletions(-) rename Ef.ps1 => EfApplicationDbContext.ps1 (100%) create mode 100644 EfContentDbContext.ps1 create mode 100644 EfMessagingDbContext.ps1 create mode 100644 src/Web/Extensions/EnumExtensions.cs create mode 100644 src/Web/Features/Contents/Data/ContentReaction.cs create mode 100644 src/Web/Features/Contents/Data/Enums/Reaction.cs create mode 100644 src/Web/Features/Contents/Handlers/AddReaction.cs create mode 100644 src/Web/Features/Contents/Handlers/Models/ReactionModel.cs create mode 100644 src/Web/Features/Contents/Handlers/RemoveReaction.cs create mode 100644 src/Web/Features/Contents/Migrations/20240824185551_AddReactionToContent.Designer.cs create mode 100644 src/Web/Features/Contents/Migrations/20240824185551_AddReactionToContent.cs diff --git a/Ef.ps1 b/EfApplicationDbContext.ps1 similarity index 100% rename from Ef.ps1 rename to EfApplicationDbContext.ps1 diff --git a/EfContentDbContext.ps1 b/EfContentDbContext.ps1 new file mode 100644 index 0000000..c484fd2 --- /dev/null +++ b/EfContentDbContext.ps1 @@ -0,0 +1 @@ +dotnet ef $args --startup-project ./src/Web/Web.csproj --project ./src/Web/Web.csproj --context ContentDbContext \ No newline at end of file diff --git a/EfMessagingDbContext.ps1 b/EfMessagingDbContext.ps1 new file mode 100644 index 0000000..6e5f39e --- /dev/null +++ b/EfMessagingDbContext.ps1 @@ -0,0 +1 @@ +dotnet ef $args --startup-project ./src/Web/Web.csproj --project ./src/Web/Web.csproj --context MessagingDbContext \ No newline at end of file diff --git a/src/Web/Extensions/EnumExtensions.cs b/src/Web/Extensions/EnumExtensions.cs new file mode 100644 index 0000000..c820a5e --- /dev/null +++ b/src/Web/Extensions/EnumExtensions.cs @@ -0,0 +1,34 @@ +namespace Hutopy.Web.Extensions; + +public static class EnumExtensions +{ + /// + /// Converts a string to the specified enum type. + /// + /// The type of the enum to convert to. Must be an enum. + /// The string value to convert. + /// Specifies whether the string comparison should ignore case. Default is true. + /// + /// The corresponding enum value if the conversion is successful; otherwise, null if the string + /// cannot be converted to the specified enum type. + /// + public static TEnum? ToEnum(this string value, bool ignoreCase = true) where TEnum : struct + { + if (Enum.TryParse(value, ignoreCase, out TEnum result)) + { + return result; + } + return null; + } + + /// + /// Converts an enum value to its string representation. + /// + /// The type of the enum. + /// The enum value to convert. + /// The string representation of the enum value. + public static string FromEnum(this TEnum enumValue) where TEnum : struct, Enum + { + return enumValue.ToString(); + } +} diff --git a/src/Web/Features/Contents/Data/Content.cs b/src/Web/Features/Contents/Data/Content.cs index 3e5d03a..f782698 100644 --- a/src/Web/Features/Contents/Data/Content.cs +++ b/src/Web/Features/Contents/Data/Content.cs @@ -10,8 +10,8 @@ public class Content public DateTimeOffset CreatedAt { get; init; } public Guid? DeletedBy { get; set; } public DateTimeOffset? DeletedAt { get; set; } - [MaxLength(128)] public required string Title { get; set; } [MaxLength(2048)] public required string Description { get; set; } + public IList Reactions { get; set; } = new List(); public string[]? Urls { get; init; } } diff --git a/src/Web/Features/Contents/Data/ContentDbContext.cs b/src/Web/Features/Contents/Data/ContentDbContext.cs index c47a453..478c576 100644 --- a/src/Web/Features/Contents/Data/ContentDbContext.cs +++ b/src/Web/Features/Contents/Data/ContentDbContext.cs @@ -1,4 +1,6 @@ -namespace Hutopy.Web.Features.Contents.Data; +using Humanizer; + +namespace Hutopy.Web.Features.Contents.Data; public class ContentDbContext( DbContextOptions options) @@ -25,6 +27,11 @@ public class ContentDbContext( .HasOne(c => c.Creator) .WithMany() .HasForeignKey(c => c.CreatedBy); + + modelBuilder + .Entity() + .OwnsMany(c => c.Reactions) + .ToTable(nameof(ContentReaction).Pluralize()); modelBuilder .Entity() diff --git a/src/Web/Features/Contents/Data/ContentReaction.cs b/src/Web/Features/Contents/Data/ContentReaction.cs new file mode 100644 index 0000000..475bc86 --- /dev/null +++ b/src/Web/Features/Contents/Data/ContentReaction.cs @@ -0,0 +1,11 @@ +using System.ComponentModel.DataAnnotations; +using Hutopy.Web.Features.Contents.Handlers.Enums; + +namespace Hutopy.Web.Features.Contents.Data; + +public class ContentReaction +{ + public required Reaction Reaction { get; set; } + public required Guid UserId { get; set; } + [MaxLength(128)] public required string UserName { get; set; } +} diff --git a/src/Web/Features/Contents/Data/Enums/Reaction.cs b/src/Web/Features/Contents/Data/Enums/Reaction.cs new file mode 100644 index 0000000..1e898db --- /dev/null +++ b/src/Web/Features/Contents/Data/Enums/Reaction.cs @@ -0,0 +1,13 @@ +namespace Hutopy.Web.Features.Contents.Handlers.Enums; + +public enum Reaction +{ + None = 0, + Like = 1, + Dislike = 2, + Love = 3, + Haha = 4, + Wow = 5, + Sad = 6, + Angry = 7 +} diff --git a/src/Web/Features/Contents/Handlers/AddReaction.cs b/src/Web/Features/Contents/Handlers/AddReaction.cs new file mode 100644 index 0000000..855ffa7 --- /dev/null +++ b/src/Web/Features/Contents/Handlers/AddReaction.cs @@ -0,0 +1,93 @@ +using Hutopy.Web.Extensions; +using Hutopy.Web.Features.Contents.Data; +using Hutopy.Web.Features.Contents.Handlers.Enums; + +namespace Hutopy.Web.Features.Contents.Handlers; + +[PublicAPI] +public sealed class AddReactionRequest +{ + public required Guid ContentId { get; set; } + public required string Reaction { get; set; } + public required Guid UserId { get; set; } + public required string UserName { get; set; } +} + +[PublicAPI] +internal sealed class AddReactionRequestValidator + : Validator +{ + public AddReactionRequestValidator() + { + RuleFor(r => r.Reaction) + .NotNull() + .Must(BeAValidReaction) + .WithMessage("'{PropertyValue}' is not a valid reaction."); + } + + private bool BeAValidReaction(string reaction) + { + return Enum.TryParse(typeof(Reaction), reaction, true, out _); + } +} + +[PublicAPI] +public class AddReaction( + ContentDbContext context) + : Endpoint +{ + public override void Configure() + { + Post("/api/content/reaction"); + Options(o => o.WithTags("Contents")); + } + + public override async Task HandleAsync( + AddReactionRequest req, + CancellationToken ct) + { + var content = await context.Contents.SingleAsync(x => x.Id == req.ContentId, ct); + var reactionEnum = req.Reaction.ToEnum(); + + var hasReacted = content.Reactions.Any(x => x.UserId == req.UserId); + + if (hasReacted) + { + var currentReaction = content.Reactions.Single(x => x.UserId == req.UserId); + if (currentReaction.Reaction == reactionEnum) return; + + if (reactionEnum.HasValue) + { + content.Reactions.Remove(currentReaction); + + var reaction = new ContentReaction + { + Reaction = reactionEnum.Value, + UserId = req.UserId, + UserName = req.UserName + }; + + content.Reactions.Add(reaction); + } + } + else + { + if (reactionEnum.HasValue) + { + var reaction = new ContentReaction + { + Reaction = reactionEnum.Value, + UserId = req.UserId, + UserName = req.UserName + }; + + content.Reactions.Add(reaction); + } + } + + await context.SaveChangesAsync(ct); + } +} + + + diff --git a/src/Web/Features/Contents/Handlers/GetContent.cs b/src/Web/Features/Contents/Handlers/GetContent.cs index 3fe1c38..fc89f32 100644 --- a/src/Web/Features/Contents/Handlers/GetContent.cs +++ b/src/Web/Features/Contents/Handlers/GetContent.cs @@ -1,4 +1,5 @@ -using Hutopy.Web.Features.Contents.Data; +using Hutopy.Web.Extensions; +using Hutopy.Web.Features.Contents.Data; using Hutopy.Web.Features.Contents.Handlers.Models; namespace Hutopy.Web.Features.Contents.Handlers; @@ -41,6 +42,10 @@ public class GetContent( Title = c.Title, Description = c.Description, Urls = c.Urls, + Reactions = c.Reactions.Select(x => new ReactionModel + { + Reaction = x.Reaction.FromEnum(), UserId = x.UserId, UserName = x.UserName + }).ToList() }) .SingleOrDefaultAsync( c => c.Id == req.ContentId, diff --git a/src/Web/Features/Contents/Handlers/GetContentsByCreator.cs b/src/Web/Features/Contents/Handlers/GetContentsByCreator.cs index 6392ee3..52247c9 100644 --- a/src/Web/Features/Contents/Handlers/GetContentsByCreator.cs +++ b/src/Web/Features/Contents/Handlers/GetContentsByCreator.cs @@ -1,4 +1,4 @@ -using System.Text; +using Hutopy.Web.Extensions; using Hutopy.Web.Features.Contents.Data; using Hutopy.Web.Features.Contents.Handlers.Models; @@ -28,45 +28,72 @@ public class GetContentsByCreatorHandler( GetContentsByCreatorRequest req, CancellationToken ct) { - var queryBuilder = new StringBuilder(); - queryBuilder.AppendLine($""" - SELECT content."Id", - content."CreatedBy", - creator."Name" as CreatedByName, - i."Logo" as CreatedByPortraitUrl, - c."Menu" as ColorMenu, - c."Accent" as ColorAccent, - content."CreatedAt", - content."DeletedBy", - content."DeletedAt", - content."Title", - content."Description", - content."Urls" - FROM "Content"."Contents" AS content - INNER JOIN "Content"."Creators" AS creator ON content."CreatedBy" = creator."Id" - LEFT JOIN "Content"."Images" AS i ON creator."Id" = i."CreatorId" - LEFT JOIN "Content"."Colors" AS c ON creator."Id" = c."CreatorId" - WHERE content."CreatedBy" = '{req.CreatorId}' - AND content."DeletedBy" IS NULL - """); +// var queryBuilder = new StringBuilder(); +// queryBuilder.AppendLine($""" +// SELECT content."Id", +// content."CreatedBy", +// creator."Name" as CreatedByName, +// i."Logo" as CreatedByPortraitUrl, +// c."Menu" as ColorMenu, +// c."Accent" as ColorAccent, +// content."CreatedAt", +// content."DeletedBy", +// content."DeletedAt", +// content."Title", +// content."Description", +// content."Urls", +// FROM "Content"."Contents" AS content +// INNER JOIN "Content"."Creators" AS creator ON content."CreatedBy" = creator."Id" +// LEFT JOIN "Content"."Images" AS i ON creator."Id" = i."CreatorId" +// LEFT JOIN "Content"."Colors" AS c ON creator."Id" = c."CreatorId" +// LEFT JOIN "Content"."ContentReactions" AS cr ON content."Id" = cr."ContentId" +// WHERE content."CreatedBy" = '{req.CreatorId}' +// AND content."DeletedBy" IS NULL +// """); +// +// if (req.LastId.HasValue) +// { +// queryBuilder.AppendLine($"""AND content."Id" > '{req.LastId.Value}'"""); +// } +// +// queryBuilder.AppendLine($""" +// ORDER BY content."CreatedAt" DESC +// LIMIT {req.PageSize} +// """); +// +// var query = queryBuilder.ToString(); +// +// var results = await context +// .Database +// .SqlQueryRaw(query) +// .Include(c => c.Reactions) +// .ToListAsync(cancellationToken: ct); - if (req.LastId.HasValue) - { - queryBuilder.AppendLine($"""AND content."Id" > '{req.LastId.Value}'"""); - } - queryBuilder.AppendLine($""" - ORDER BY content."CreatedAt" DESC - LIMIT {req.PageSize} - """); + var content = await context + .Contents + .Select(c => new ContentModel + { + Id = c.Id, + CreatedBy = c.CreatedBy, + CreatedByName = c.Creator!.Name, + CreatedByPortraitUrl = c.Creator.Images.Logo, + CreatedAt = c.CreatedAt, + ColorMenu = c.Creator.Colors.Menu, + ColorAccent = c.Creator.Colors.Accent, + DeletedBy = c.DeletedBy, + DeletedAt = c.DeletedAt, + Title = c.Title, + Description = c.Description, + Urls = c.Urls, + Reactions = c.Reactions.Select(x => new ReactionModel + { + Reaction = x.Reaction.FromEnum(), UserId = x.UserId, UserName = x.UserName + }).ToList() + }) + .Where(x => x.CreatedBy == req.CreatorId && x.DeletedAt == null) + .ToListAsync(ct); - var query = queryBuilder.ToString(); - - var results = await context - .Database - .SqlQueryRaw(query) - .ToListAsync(cancellationToken: ct); - - await SendAsync(results, cancellation: ct); + await SendAsync(content, cancellation: ct); } } diff --git a/src/Web/Features/Contents/Handlers/Models/ContentModel.cs b/src/Web/Features/Contents/Handlers/Models/ContentModel.cs index c3cecc9..c110b0b 100644 --- a/src/Web/Features/Contents/Handlers/Models/ContentModel.cs +++ b/src/Web/Features/Contents/Handlers/Models/ContentModel.cs @@ -1,4 +1,6 @@ -namespace Hutopy.Web.Features.Contents.Handlers.Models; +using System.ComponentModel.DataAnnotations.Schema; + +namespace Hutopy.Web.Features.Contents.Handlers.Models; [PublicAPI] public class ContentModel @@ -15,4 +17,5 @@ public class ContentModel public required string Title { get; init; } public required string Description { get; init; } public required string[]? Urls { get; init; } + public IList? Reactions { get; set; } = new List(); } diff --git a/src/Web/Features/Contents/Handlers/Models/ReactionModel.cs b/src/Web/Features/Contents/Handlers/Models/ReactionModel.cs new file mode 100644 index 0000000..514efd3 --- /dev/null +++ b/src/Web/Features/Contents/Handlers/Models/ReactionModel.cs @@ -0,0 +1,8 @@ +namespace Hutopy.Web.Features.Contents.Handlers.Models; + +public class ReactionModel +{ + public required string Reaction { get; set; } + public required Guid UserId { get; set; } + public required string UserName { get; set; } +} diff --git a/src/Web/Features/Contents/Handlers/RemoveReaction.cs b/src/Web/Features/Contents/Handlers/RemoveReaction.cs new file mode 100644 index 0000000..04d2b43 --- /dev/null +++ b/src/Web/Features/Contents/Handlers/RemoveReaction.cs @@ -0,0 +1,36 @@ +using Hutopy.Web.Features.Contents.Data; + +namespace Hutopy.Web.Features.Contents.Handlers; + +[PublicAPI] +public sealed class RemoveReactionRequest +{ + public required Guid ContentId { get; set; } + public required Guid UserId { get; set; } +} + +[PublicAPI] +public class RemoveReaction( + ContentDbContext context) + : Endpoint +{ + public override void Configure() + { + Post("/api/content/reaction/remove"); + Options(o => o.WithTags("Contents")); + } + + public override async Task HandleAsync( + RemoveReactionRequest req, + CancellationToken ct) + { + var content = await context.Contents + .SingleAsync(x => x.Id == req.ContentId, ct); + + var reaction = content.Reactions.Single(x => x.UserId == req.UserId); + + content.Reactions.Remove(reaction); + + await context.SaveChangesAsync(ct); + } +} diff --git a/src/Web/Features/Contents/Migrations/20240824185551_AddReactionToContent.Designer.cs b/src/Web/Features/Contents/Migrations/20240824185551_AddReactionToContent.Designer.cs new file mode 100644 index 0000000..8f13557 --- /dev/null +++ b/src/Web/Features/Contents/Migrations/20240824185551_AddReactionToContent.Designer.cs @@ -0,0 +1,296 @@ +// +using System; +using Hutopy.Web.Features.Contents.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace Hutopy.Web.Features.Contents.Migrations +{ + [DbContext(typeof(ContentDbContext))] + [Migration("20240824185551_AddReactionToContent")] + partial class AddReactionToContent + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasDefaultSchema("Content") + .HasAnnotation("ProductVersion", "8.0.4") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("Hutopy.Web.Features.Contents.Data.Content", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("CURRENT_TIMESTAMP"); + + b.Property("CreatedBy") + .HasColumnType("uuid"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("DeletedBy") + .HasColumnType("uuid"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(2048) + .HasColumnType("character varying(2048)"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("Urls") + .HasColumnType("text[]"); + + b.HasKey("Id"); + + b.HasIndex("CreatedBy"); + + b.ToTable("Contents", "Content"); + }); + + modelBuilder.Entity("Hutopy.Web.Features.Contents.Data.Creator", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("uuid"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.HasKey("Id"); + + b.ToTable("Creators", "Content"); + }); + + modelBuilder.Entity("Hutopy.Web.Features.Contents.Data.Subscription", b => + { + b.Property("CreatedBy") + .HasColumnType("uuid"); + + b.Property("CreatorId") + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("CreatedBy", "CreatorId"); + + b.HasIndex("CreatorId"); + + b.ToTable("Subscriptions", "Content"); + }); + + modelBuilder.Entity("Hutopy.Web.Features.Contents.Data.Content", b => + { + b.HasOne("Hutopy.Web.Features.Contents.Data.Creator", "Creator") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.OwnsMany("Hutopy.Web.Features.Contents.Data.ContentReaction", "Reactions", b1 => + { + b1.Property("ContentId") + .HasColumnType("uuid"); + + b1.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b1.Property("Id")); + + b1.Property("Reaction") + .HasColumnType("integer"); + + b1.Property("UserId") + .HasColumnType("uuid"); + + b1.Property("UserName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b1.HasKey("ContentId", "Id"); + + b1.ToTable("ContentReactions", "Content"); + + b1.WithOwner() + .HasForeignKey("ContentId"); + }); + + b.Navigation("Creator"); + + b.Navigation("Reactions"); + }); + + modelBuilder.Entity("Hutopy.Web.Features.Contents.Data.Creator", b => + { + b.OwnsOne("Hutopy.Web.Features.Contents.Data.About", "About", b1 => + { + b1.Property("CreatorId") + .HasColumnType("uuid"); + + b1.Property("Description") + .HasMaxLength(2048) + .HasColumnType("character varying(2048)"); + + b1.Property("Title") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.HasKey("CreatorId"); + + b1.ToTable("Creators", "Content"); + + b1.WithOwner() + .HasForeignKey("CreatorId"); + }); + + b.OwnsOne("Hutopy.Web.Features.Contents.Data.Colors", "Colors", b1 => + { + b1.Property("CreatorId") + .HasColumnType("uuid"); + + b1.Property("Accent") + .HasMaxLength(9) + .HasColumnType("character varying(9)"); + + b1.Property("BannerBottom") + .HasMaxLength(9) + .HasColumnType("character varying(9)"); + + b1.Property("BannerTop") + .HasMaxLength(9) + .HasColumnType("character varying(9)"); + + b1.Property("Menu") + .HasMaxLength(9) + .HasColumnType("character varying(9)"); + + b1.HasKey("CreatorId"); + + b1.ToTable("Colors", "Content"); + + b1.WithOwner() + .HasForeignKey("CreatorId"); + }); + + b.OwnsOne("Hutopy.Web.Features.Contents.Data.Images", "Images", b1 => + { + b1.Property("CreatorId") + .HasColumnType("uuid"); + + b1.Property("Banner") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.Property("Logo") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.HasKey("CreatorId"); + + b1.ToTable("Images", "Content"); + + b1.WithOwner() + .HasForeignKey("CreatorId"); + }); + + b.OwnsOne("Hutopy.Web.Features.Contents.Data.Socials", "Socials", b1 => + { + b1.Property("CreatorId") + .HasColumnType("uuid"); + + b1.Property("FacebookUrl") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.Property("InstagramUrl") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.Property("LinkedInUrl") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.Property("RedditUrl") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.Property("TikTokUrl") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.Property("WebsiteUrl") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.Property("XUrl") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.Property("YoutubeUrl") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.HasKey("CreatorId"); + + b1.ToTable("Socials", "Content"); + + b1.WithOwner() + .HasForeignKey("CreatorId"); + }); + + b.Navigation("About") + .IsRequired(); + + b.Navigation("Colors") + .IsRequired(); + + b.Navigation("Images") + .IsRequired(); + + b.Navigation("Socials") + .IsRequired(); + }); + + modelBuilder.Entity("Hutopy.Web.Features.Contents.Data.Subscription", b => + { + b.HasOne("Hutopy.Web.Features.Contents.Data.Creator", "Creator") + .WithMany() + .HasForeignKey("CreatorId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Creator"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Web/Features/Contents/Migrations/20240824185551_AddReactionToContent.cs b/src/Web/Features/Contents/Migrations/20240824185551_AddReactionToContent.cs new file mode 100644 index 0000000..6b28a31 --- /dev/null +++ b/src/Web/Features/Contents/Migrations/20240824185551_AddReactionToContent.cs @@ -0,0 +1,48 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace Hutopy.Web.Features.Contents.Migrations +{ + /// + public partial class AddReactionToContent : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "ContentReactions", + schema: "Content", + columns: table => new + { + ContentId = table.Column(type: "uuid", nullable: false), + Id = table.Column(type: "integer", nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + Reaction = table.Column(type: "integer", nullable: false), + UserId = table.Column(type: "uuid", nullable: false), + UserName = table.Column(type: "character varying(128)", maxLength: 128, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_ContentReactions", x => new { x.ContentId, x.Id }); + table.ForeignKey( + name: "FK_ContentReactions_Contents_ContentId", + column: x => x.ContentId, + principalSchema: "Content", + principalTable: "Contents", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "ContentReactions", + schema: "Content"); + } + } +} diff --git a/src/Web/Features/Contents/Migrations/ContentDbContextModelSnapshot.cs b/src/Web/Features/Contents/Migrations/ContentDbContextModelSnapshot.cs index e4821b9..a3d9e3f 100644 --- a/src/Web/Features/Contents/Migrations/ContentDbContextModelSnapshot.cs +++ b/src/Web/Features/Contents/Migrations/ContentDbContextModelSnapshot.cs @@ -37,12 +37,12 @@ namespace Hutopy.Web.Features.Contents.Migrations b.Property("CreatedBy") .HasColumnType("uuid"); - b.Property("DeletedBy") - .HasColumnType("uuid"); - b.Property("DeletedAt") .HasColumnType("timestamp with time zone"); + b.Property("DeletedBy") + .HasColumnType("uuid"); + b.Property("Description") .IsRequired() .HasMaxLength(2048) @@ -111,7 +111,39 @@ namespace Hutopy.Web.Features.Contents.Migrations .OnDelete(DeleteBehavior.Cascade) .IsRequired(); + b.OwnsMany("Hutopy.Web.Features.Contents.Data.ContentReaction", "Reactions", b1 => + { + b1.Property("ContentId") + .HasColumnType("uuid"); + + b1.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b1.Property("Id")); + + b1.Property("Reaction") + .HasColumnType("integer"); + + b1.Property("UserId") + .HasColumnType("uuid"); + + b1.Property("UserName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b1.HasKey("ContentId", "Id"); + + b1.ToTable("ContentReactions", "Content"); + + b1.WithOwner() + .HasForeignKey("ContentId"); + }); + b.Navigation("Creator"); + + b.Navigation("Reactions"); }); modelBuilder.Entity("Hutopy.Web.Features.Contents.Data.Creator", b => From 79c87f2091b9283c349470c281775147bb8c9180 Mon Sep 17 00:00:00 2001 From: Dominic Villemure Date: Sun, 25 Aug 2024 10:05:34 -0400 Subject: [PATCH 176/229] re-add the missing ordering in the query --- .../Contents/Handlers/GetContentsByCreator.cs | 21 +++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/src/Web/Features/Contents/Handlers/GetContentsByCreator.cs b/src/Web/Features/Contents/Handlers/GetContentsByCreator.cs index 52247c9..571815d 100644 --- a/src/Web/Features/Contents/Handlers/GetContentsByCreator.cs +++ b/src/Web/Features/Contents/Handlers/GetContentsByCreator.cs @@ -46,7 +46,6 @@ public class GetContentsByCreatorHandler( // INNER JOIN "Content"."Creators" AS creator ON content."CreatedBy" = creator."Id" // LEFT JOIN "Content"."Images" AS i ON creator."Id" = i."CreatorId" // LEFT JOIN "Content"."Colors" AS c ON creator."Id" = c."CreatorId" -// LEFT JOIN "Content"."ContentReactions" AS cr ON content."Id" = cr."ContentId" // WHERE content."CreatedBy" = '{req.CreatorId}' // AND content."DeletedBy" IS NULL // """); @@ -66,12 +65,20 @@ public class GetContentsByCreatorHandler( // var results = await context // .Database // .SqlQueryRaw(query) -// .Include(c => c.Reactions) // .ToListAsync(cancellationToken: ct); - var content = await context - .Contents + var query = context.Contents + .Where(c => c.CreatedBy == req.CreatorId && c.DeletedAt == null) + .OrderByDescending(c => c.CreatedAt); + + if (req.LastId.HasValue) + { + query = query.Where(c => c.Id > req.LastId.Value) + .OrderByDescending(c => c.CreatedAt); + } + + var content = await query .Select(c => new ContentModel { Id = c.Id, @@ -88,10 +95,12 @@ public class GetContentsByCreatorHandler( Urls = c.Urls, Reactions = c.Reactions.Select(x => new ReactionModel { - Reaction = x.Reaction.FromEnum(), UserId = x.UserId, UserName = x.UserName + Reaction = x.Reaction.FromEnum(), + UserId = x.UserId, + UserName = x.UserName }).ToList() }) - .Where(x => x.CreatedBy == req.CreatorId && x.DeletedAt == null) + .Take(req.PageSize) .ToListAsync(ct); await SendAsync(content, cancellation: ct); From c395cea0f55018bf63d2d754225a5de1334da746 Mon Sep 17 00:00:00 2001 From: Dominic Villemure Date: Sun, 25 Aug 2024 10:35:06 -0400 Subject: [PATCH 177/229] Simplify code in AddReaction --- .../Features/Contents/Handlers/AddReaction.cs | 52 ++++++++----------- 1 file changed, 21 insertions(+), 31 deletions(-) diff --git a/src/Web/Features/Contents/Handlers/AddReaction.cs b/src/Web/Features/Contents/Handlers/AddReaction.cs index 855ffa7..7097c36 100644 --- a/src/Web/Features/Contents/Handlers/AddReaction.cs +++ b/src/Web/Features/Contents/Handlers/AddReaction.cs @@ -48,43 +48,33 @@ public class AddReaction( { var content = await context.Contents.SingleAsync(x => x.Id == req.ContentId, ct); var reactionEnum = req.Reaction.ToEnum(); + var currentReaction = content.Reactions.SingleOrDefault(x => x.UserId == req.UserId); - var hasReacted = content.Reactions.Any(x => x.UserId == req.UserId); - - if (hasReacted) + // Already reacted or reaction didn't change, do nothing + if (currentReaction != null && currentReaction.Reaction == reactionEnum) { - var currentReaction = content.Reactions.Single(x => x.UserId == req.UserId); - if (currentReaction.Reaction == reactionEnum) return; - - if (reactionEnum.HasValue) - { - content.Reactions.Remove(currentReaction); - - var reaction = new ContentReaction - { - Reaction = reactionEnum.Value, - UserId = req.UserId, - UserName = req.UserName - }; - - content.Reactions.Add(reaction); - } + return; } - else + + // User has already reacted, remove the existing reaction + if (currentReaction != null) { - if (reactionEnum.HasValue) - { - var reaction = new ContentReaction - { - Reaction = reactionEnum.Value, - UserId = req.UserId, - UserName = req.UserName - }; - - content.Reactions.Add(reaction); - } + content.Reactions.Remove(currentReaction); } + // If the new reaction is valid, add or update the reaction + if (reactionEnum.HasValue) + { + var reaction = new ContentReaction + { + Reaction = reactionEnum.Value, + UserId = req.UserId, + UserName = req.UserName + }; + + content.Reactions.Add(reaction); + } + await context.SaveChangesAsync(ct); } } From 7ceff3861cde9b78a47b6d110f8ee2f58cfe9cea Mon Sep 17 00:00:00 2001 From: Dominic Villemure Date: Sun, 25 Aug 2024 12:54:14 -0400 Subject: [PATCH 178/229] Added message count endpoint --- .../Messages/Data/MessagingDbContext.cs | 17 +++++++ .../Messages/Handlers/GetMessageCount.cs | 44 +++++++++++++++++++ 2 files changed, 61 insertions(+) create mode 100644 src/Web/Features/Messages/Handlers/GetMessageCount.cs diff --git a/src/Web/Features/Messages/Data/MessagingDbContext.cs b/src/Web/Features/Messages/Data/MessagingDbContext.cs index a7b2028..5f19b86 100644 --- a/src/Web/Features/Messages/Data/MessagingDbContext.cs +++ b/src/Web/Features/Messages/Data/MessagingDbContext.cs @@ -56,4 +56,21 @@ public class MessagingDbContext( return messages; } + + public async Task GetMessageCountAsync( + Guid subjectId, + Guid? parentId, + int pageSize, + CancellationToken ct = default) + { + var query = Messages + .Where(c => c.SubjectId == subjectId) + .Where(c => c.ParentId == parentId); + + var messageCount = await query + .Take(pageSize) + .CountAsync(ct); + + return messageCount; + } } diff --git a/src/Web/Features/Messages/Handlers/GetMessageCount.cs b/src/Web/Features/Messages/Handlers/GetMessageCount.cs new file mode 100644 index 0000000..0aea77a --- /dev/null +++ b/src/Web/Features/Messages/Handlers/GetMessageCount.cs @@ -0,0 +1,44 @@ +using Hutopy.Web.Features.Messages.Data; + +namespace Hutopy.Web.Features.Messages.Handlers; + +public sealed class GetMessageCountRequest +{ + public Guid SubjectId { get; set; } + [BindFrom("page_size")] public int PageSize { get; set; } = 1000; +} + +public record struct GetMessageCountResponse +{ + public required int Count { get; init; } +} + +public class GetMessageCount( + MessagingDbContext context) + : Endpoint +{ + public override void Configure() + { + Get("/api/message-count/{SubjectId:guid}"); + Options(o => o.WithTags("Messages")); + AllowAnonymous(); + } + + public override async Task HandleAsync( + GetMessageCountRequest req, + CancellationToken ct) + { + var messageCount = await context.GetMessageCountAsync( + req.SubjectId, + null, + req.PageSize, + ct); + + await SendAsync( + new() + { + Count = messageCount + }, + cancellation: ct); + } +} From c5cfce30b2b752dea8b5f99645e7e78e9152e61b Mon Sep 17 00:00:00 2001 From: Dominic Villemure Date: Sun, 25 Aug 2024 13:45:31 -0400 Subject: [PATCH 179/229] Accept new origin --- src/Web/Program.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Web/Program.cs b/src/Web/Program.cs index 132c462..156130f 100644 --- a/src/Web/Program.cs +++ b/src/Web/Program.cs @@ -33,7 +33,7 @@ builder.Services.AddCors(options => options.AddPolicy("AllowHutopyUi", policy => { - policy.WithOrigins("https://zealous-bay-08204590f.5.azurestaticapps.net") + policy.WithOrigins("https://jolly-stone-078869d0f.5.azurestaticapps.net") .AllowAnyMethod() .AllowAnyHeader() .AllowCredentials(); From 5e9588ce7bee4a9f97230c4834b0b38dd0149d02 Mon Sep 17 00:00:00 2001 From: Dominic Villemure Date: Sun, 25 Aug 2024 14:14:54 -0400 Subject: [PATCH 180/229] Stripe key re-added --- src/Infrastructure/Stripe/StripeService.cs | 2 +- src/Web/appsettings.Development.json | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Infrastructure/Stripe/StripeService.cs b/src/Infrastructure/Stripe/StripeService.cs index 7b78fff..863db7c 100644 --- a/src/Infrastructure/Stripe/StripeService.cs +++ b/src/Infrastructure/Stripe/StripeService.cs @@ -15,7 +15,7 @@ public class StripeService : IStripeService public StripeService(IHttpContextAccessor httpContextAccessor, IConfiguration configuration) { _httpContextAccessor = httpContextAccessor; - var stripeKey = configuration["STRIPE-API-KEY"] ?? ""; + var stripeKey = configuration["Stripe:apiKey"] ?? ""; StripeConfiguration.ApiKey = stripeKey; } diff --git a/src/Web/appsettings.Development.json b/src/Web/appsettings.Development.json index 3428fe2..d23ea44 100644 --- a/src/Web/appsettings.Development.json +++ b/src/Web/appsettings.Development.json @@ -19,5 +19,8 @@ "Issuer": "https://auth.hutopy.com", "Key": "b2df428b9929d3ace7c598bbf4e496b2f0b71ab3cd4f94540356cfc35b000000" } + }, + "Stripe": { + "apiKey": "sk_test_51OoveVDrRyqXtNdBaOs1DFFja0XhrQtJoAo83uSySMuqw4Wyt9NsuugrIHRqet9a50cr5GvolpTP8EZuTSttcgYx00gOUPNDoI" } } \ No newline at end of file From 6e36d1327c8f78207a4fe25bdd5a741799b8f74b Mon Sep 17 00:00:00 2001 From: Dominic Villemure Date: Sun, 25 Aug 2024 16:15:06 -0400 Subject: [PATCH 181/229] Added endpoint for the feed ( for you page ) --- .../Features/Contents/Handlers/GetContents.cs | 68 +++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 src/Web/Features/Contents/Handlers/GetContents.cs diff --git a/src/Web/Features/Contents/Handlers/GetContents.cs b/src/Web/Features/Contents/Handlers/GetContents.cs new file mode 100644 index 0000000..1f9a87b --- /dev/null +++ b/src/Web/Features/Contents/Handlers/GetContents.cs @@ -0,0 +1,68 @@ +using Hutopy.Web.Extensions; +using Hutopy.Web.Features.Contents.Data; +using Hutopy.Web.Features.Contents.Handlers.Models; + +namespace Hutopy.Web.Features.Contents.Handlers; + +[PublicAPI] +public sealed class GetContentsRequest +{ + [BindFrom("page_size")] public int PageSize { get; set; } = 10; + [BindFrom("last_id")] public Guid? LastId { get; set; } +} + +[PublicAPI] +public class GetContentsHandler( + ContentDbContext context) + : Endpoint> +{ + public override void Configure() + { + Get("/api/contents/all"); + Options(o => o.WithTags("Contents")); + AllowAnonymous(); + } + + public override async Task HandleAsync( + GetContentsRequest req, + CancellationToken ct) + { + + var query = context.Contents + .Where(c => c.DeletedAt == null) + .OrderByDescending(c => c.CreatedAt); + + if (req.LastId.HasValue) + { + query = query.Where(c => c.Id > req.LastId.Value) + .OrderByDescending(c => c.CreatedAt); + } + + var content = await query + .Select(c => new ContentModel + { + Id = c.Id, + CreatedBy = c.CreatedBy, + CreatedByName = c.Creator!.Name, + CreatedByPortraitUrl = c.Creator.Images.Logo, + CreatedAt = c.CreatedAt, + ColorMenu = c.Creator.Colors.Menu, + ColorAccent = c.Creator.Colors.Accent, + DeletedBy = c.DeletedBy, + DeletedAt = c.DeletedAt, + Title = c.Title, + Description = c.Description, + Urls = c.Urls, + Reactions = c.Reactions.Select(x => new ReactionModel + { + Reaction = x.Reaction.FromEnum(), + UserId = x.UserId, + UserName = x.UserName + }).ToList() + }) + .Take(req.PageSize) + .ToListAsync(ct); + + await SendAsync(content, cancellation: ct); + } +} From 7e820e166f72277987f0b08ffde12e6c1f02e841 Mon Sep 17 00:00:00 2001 From: Dominic Villemure Date: Thu, 29 Aug 2024 00:24:56 -0400 Subject: [PATCH 182/229] Change and Delete messages --- .../Contents/Handlers/GetContentsByCreator.cs | 40 ------------ .../Messages/Handlers/ChangeMessage.cs | 64 +++++++++++++++++++ .../Messages/Handlers/DeleteMessage.cs | 52 +++++++++++++++ 3 files changed, 116 insertions(+), 40 deletions(-) create mode 100644 src/Web/Features/Messages/Handlers/ChangeMessage.cs create mode 100644 src/Web/Features/Messages/Handlers/DeleteMessage.cs diff --git a/src/Web/Features/Contents/Handlers/GetContentsByCreator.cs b/src/Web/Features/Contents/Handlers/GetContentsByCreator.cs index 571815d..33ce7ae 100644 --- a/src/Web/Features/Contents/Handlers/GetContentsByCreator.cs +++ b/src/Web/Features/Contents/Handlers/GetContentsByCreator.cs @@ -28,46 +28,6 @@ public class GetContentsByCreatorHandler( GetContentsByCreatorRequest req, CancellationToken ct) { -// var queryBuilder = new StringBuilder(); -// queryBuilder.AppendLine($""" -// SELECT content."Id", -// content."CreatedBy", -// creator."Name" as CreatedByName, -// i."Logo" as CreatedByPortraitUrl, -// c."Menu" as ColorMenu, -// c."Accent" as ColorAccent, -// content."CreatedAt", -// content."DeletedBy", -// content."DeletedAt", -// content."Title", -// content."Description", -// content."Urls", -// FROM "Content"."Contents" AS content -// INNER JOIN "Content"."Creators" AS creator ON content."CreatedBy" = creator."Id" -// LEFT JOIN "Content"."Images" AS i ON creator."Id" = i."CreatorId" -// LEFT JOIN "Content"."Colors" AS c ON creator."Id" = c."CreatorId" -// WHERE content."CreatedBy" = '{req.CreatorId}' -// AND content."DeletedBy" IS NULL -// """); -// -// if (req.LastId.HasValue) -// { -// queryBuilder.AppendLine($"""AND content."Id" > '{req.LastId.Value}'"""); -// } -// -// queryBuilder.AppendLine($""" -// ORDER BY content."CreatedAt" DESC -// LIMIT {req.PageSize} -// """); -// -// var query = queryBuilder.ToString(); -// -// var results = await context -// .Database -// .SqlQueryRaw(query) -// .ToListAsync(cancellationToken: ct); - - var query = context.Contents .Where(c => c.CreatedBy == req.CreatorId && c.DeletedAt == null) .OrderByDescending(c => c.CreatedAt); diff --git a/src/Web/Features/Messages/Handlers/ChangeMessage.cs b/src/Web/Features/Messages/Handlers/ChangeMessage.cs new file mode 100644 index 0000000..0889af9 --- /dev/null +++ b/src/Web/Features/Messages/Handlers/ChangeMessage.cs @@ -0,0 +1,64 @@ +using Hutopy.Web.Common; +using Hutopy.Web.Features.Messages.Data; + +namespace Hutopy.Web.Features.Messages.Handlers; + +public sealed class ChangeMessageRequest +{ + public Guid? Id { get; set; } + public required Guid SubjectId { get; set; } + public required string Message { get; set; } +} + +internal sealed class ChangeMessageRequestValidator + : Validator +{ + public ChangeMessageRequestValidator() + { + RuleFor(r => r.SubjectId) + .NotNull().WithMessage("You must specify a SubjectId") + .NotEmpty().WithMessage("You must specify a non-empty SubjectId"); + + RuleFor(r => r.Message) + .NotNull().WithMessage("You must specify a Message") + .NotEmpty().WithMessage("You must specify a non-empty Message"); + } +} + +public class ChangeMessage( + MessagingDbContext context) + : Endpoint +{ + public override void Configure() + { + Post("/api/messages/update"); + Options(o => o.WithTags("Messages")); + } + + public override async Task HandleAsync( + ChangeMessageRequest req, + CancellationToken ct) + { + var message = await context.Messages.FirstOrDefaultAsync(x => x.Id == req.Id, ct); + + if (message is null) + { + await SendNotFoundAsync(ct); + return; + } + + var userId = HttpContext.User.GetUserId(); + if (message.CreatedBy != userId) + { + await SendForbiddenAsync(ct); + return; + } + + message.SubjectId = req.SubjectId; + message.Value = req.Message; + + context.Update(message); + + await context.SaveChangesAsync(ct); + } +} diff --git a/src/Web/Features/Messages/Handlers/DeleteMessage.cs b/src/Web/Features/Messages/Handlers/DeleteMessage.cs new file mode 100644 index 0000000..dc5a9f0 --- /dev/null +++ b/src/Web/Features/Messages/Handlers/DeleteMessage.cs @@ -0,0 +1,52 @@ +using Hutopy.Web.Common; +using Hutopy.Web.Features.Messages.Data; + +namespace Hutopy.Web.Features.Messages.Handlers; + +public record DeleteMessageRequest(Guid MessageId); + +internal sealed class DeleteMessageRequestValidator + : Validator +{ + public DeleteMessageRequestValidator() + { + RuleFor(r => r.MessageId) + .NotNull().WithMessage("You must specify a MessageId") + .NotEmpty().WithMessage("You must specify a non-empty MessageId"); + } +} + +public class DeleteMessage( + MessagingDbContext context) + : Endpoint +{ + public override void Configure() + { + Delete("/api/messages/{MessageId}"); + Options(o => o.WithTags("Messages")); + } + + public override async Task HandleAsync( + DeleteMessageRequest req, + CancellationToken ct) + { + var message = await context.Messages.FirstOrDefaultAsync(x => x.Id == req.MessageId, ct); + + if (message is null) + { + await SendNotFoundAsync(ct); + return; + } + + var userId = HttpContext.User.GetUserId(); + if (message.CreatedBy != userId) + { + await SendForbiddenAsync(ct); + return; + } + + context.Messages.Remove(message); + + await context.SaveChangesAsync(ct); + } +} From 14b43a39518300730f192abee987babc29d6fe99 Mon Sep 17 00:00:00 2001 From: Dominic Villemure Date: Thu, 29 Aug 2024 19:37:12 -0400 Subject: [PATCH 183/229] Features + filter on Followed content --- ...{GetContents.cs => GetFeaturedContents.cs} | 19 +++-- .../Contents/Handlers/GetFollowedContents.cs | 77 +++++++++++++++++++ 2 files changed, 86 insertions(+), 10 deletions(-) rename src/Web/Features/Contents/Handlers/{GetContents.cs => GetFeaturedContents.cs} (80%) create mode 100644 src/Web/Features/Contents/Handlers/GetFollowedContents.cs diff --git a/src/Web/Features/Contents/Handlers/GetContents.cs b/src/Web/Features/Contents/Handlers/GetFeaturedContents.cs similarity index 80% rename from src/Web/Features/Contents/Handlers/GetContents.cs rename to src/Web/Features/Contents/Handlers/GetFeaturedContents.cs index 1f9a87b..6df55ad 100644 --- a/src/Web/Features/Contents/Handlers/GetContents.cs +++ b/src/Web/Features/Contents/Handlers/GetFeaturedContents.cs @@ -5,39 +5,38 @@ using Hutopy.Web.Features.Contents.Handlers.Models; namespace Hutopy.Web.Features.Contents.Handlers; [PublicAPI] -public sealed class GetContentsRequest +public sealed class GetFeaturedContentsRequest { [BindFrom("page_size")] public int PageSize { get; set; } = 10; [BindFrom("last_id")] public Guid? LastId { get; set; } } [PublicAPI] -public class GetContentsHandler( +public class GetFeaturedContentsHandler( ContentDbContext context) - : Endpoint> + : Endpoint> { public override void Configure() { - Get("/api/contents/all"); + Get("/api/contents/featured"); Options(o => o.WithTags("Contents")); AllowAnonymous(); } public override async Task HandleAsync( - GetContentsRequest req, + GetFeaturedContentsRequest req, CancellationToken ct) { - var query = context.Contents - .Where(c => c.DeletedAt == null) - .OrderByDescending(c => c.CreatedAt); + .Where(c => c.DeletedAt == null); if (req.LastId.HasValue) { - query = query.Where(c => c.Id > req.LastId.Value) - .OrderByDescending(c => c.CreatedAt); + query = query.Where(c => c.Id > req.LastId.Value); } + query = query.OrderByDescending(x => x.Reactions.Count); + var content = await query .Select(c => new ContentModel { diff --git a/src/Web/Features/Contents/Handlers/GetFollowedContents.cs b/src/Web/Features/Contents/Handlers/GetFollowedContents.cs new file mode 100644 index 0000000..aa80309 --- /dev/null +++ b/src/Web/Features/Contents/Handlers/GetFollowedContents.cs @@ -0,0 +1,77 @@ +using Hutopy.Web.Common; +using Hutopy.Web.Extensions; +using Hutopy.Web.Features.Contents.Data; +using Hutopy.Web.Features.Contents.Handlers.Models; + +namespace Hutopy.Web.Features.Contents.Handlers; + +[PublicAPI] +public sealed class GetFollowedContentsRequest +{ + [BindFrom("page_size")] public int PageSize { get; set; } = 10; + [BindFrom("last_id")] public Guid? LastId { get; set; } +} + +[PublicAPI] +public class GetFollowedContentsHandler( + ContentDbContext context) + : Endpoint> +{ + public override void Configure() + { + Get("/api/contents/followed"); + Options(o => o.WithTags("Contents")); + AllowAnonymous(); + } + + public override async Task HandleAsync( + GetFollowedContentsRequest req, + CancellationToken ct) + { + + var userId = HttpContext.User.GetUserId(); + + var userSubscriptionIds = await context + .Subscriptions + .Where(s => s.CreatedBy == userId) + .Select(s => s.CreatorId) + .ToListAsync(cancellationToken: ct); + + var query = context.Contents + .Where(c => c.DeletedAt == null) + .Where(x => userSubscriptionIds.Contains(x.CreatedBy)); + if (req.LastId.HasValue) + { + query = query.Where(c => c.Id > req.LastId.Value); + } + + query = query.OrderByDescending(c => c.CreatedAt); + + var content = await query + .Select(c => new ContentModel + { + Id = c.Id, + CreatedBy = c.CreatedBy, + CreatedByName = c.Creator!.Name, + CreatedByPortraitUrl = c.Creator.Images.Logo, + CreatedAt = c.CreatedAt, + ColorMenu = c.Creator.Colors.Menu, + ColorAccent = c.Creator.Colors.Accent, + DeletedBy = c.DeletedBy, + DeletedAt = c.DeletedAt, + Title = c.Title, + Description = c.Description, + Urls = c.Urls, + Reactions = c.Reactions.Select(x => new ReactionModel + { + Reaction = x.Reaction.FromEnum(), + UserId = x.UserId, + UserName = x.UserName + }).ToList() + }) + .Take(req.PageSize) + .ToListAsync(ct); + + await SendAsync(content, cancellation: ct); + } +} From f12418bc7942b1c48f435f2ffa2ca49cf8855716 Mon Sep 17 00:00:00 2001 From: Jonathan Bourdon Date: Tue, 3 Sep 2024 20:59:43 -0400 Subject: [PATCH 184/229] Adds edition of user profile --- src/Application/Common/Models/UserModel.cs | 9 +- .../Queries/GetCurrentUser/GetCurrentUser.cs | 50 -- .../GetCurrentUserProfilePicture.cs | 23 - .../Users/Queries/GetCurrentUser/UserDto.cs | 19 - .../Users/Queries/GetUser/UserDto.cs | 7 +- .../Identity/ApplicationUser.cs | 7 +- .../Identity/IdentityService.cs | 29 +- ...0821_ChangeBirthDateToDateTime.Designer.cs | 436 ++++++++++++++++++ ...0240903230821_ChangeBirthDateToDateTime.cs | 83 ++++ ...0240903231429_RemoveOccupation.Designer.cs | 432 +++++++++++++++++ .../20240903231429_RemoveOccupation.cs | 29 ++ .../ApplicationDbContextModelSnapshot.cs | 20 +- src/Web/Controllers/GoogleController.cs | 4 +- src/Web/Endpoints/GetMyUser.cs | 25 - .../Contents/Handlers/GetCreatorProfile.cs | 30 ++ .../Contents/Handlers/Models/ContentModel.cs | 4 +- .../Features/Users/Handlers/ChangeAddress.cs | 43 ++ .../Features/Users/Handlers/ChangeAlias.cs | 42 ++ .../Users/Handlers/ChangeBirthDate.cs | 42 ++ .../Features/Users/Handlers/ChangeEmail.cs | 43 ++ .../Features/Users/Handlers/ChangeFullname.cs | 44 ++ .../Features/Users/Handlers/ChangePhone.cs | 43 ++ .../Features/Users/Handlers/GetCurrentUser.cs | 48 ++ .../Handlers/GetCurrentUserProfilePicture.cs | 31 ++ .../Features/Users/Handlers/Models/UserDto.cs | 16 + .../Features/Wallets}/UserTransactionDto.cs | 11 +- src/Web/TestDataSeeder.cs | 8 +- tests/Application.FunctionalTests/Testing.cs | 2 +- 28 files changed, 1398 insertions(+), 182 deletions(-) delete mode 100644 src/Application/Users/Queries/GetCurrentUser/GetCurrentUser.cs delete mode 100644 src/Application/Users/Queries/GetCurrentUser/GetCurrentUserProfilePicture.cs delete mode 100644 src/Application/Users/Queries/GetCurrentUser/UserDto.cs create mode 100644 src/Infrastructure/Migrations/20240903230821_ChangeBirthDateToDateTime.Designer.cs create mode 100644 src/Infrastructure/Migrations/20240903230821_ChangeBirthDateToDateTime.cs create mode 100644 src/Infrastructure/Migrations/20240903231429_RemoveOccupation.Designer.cs create mode 100644 src/Infrastructure/Migrations/20240903231429_RemoveOccupation.cs delete mode 100644 src/Web/Endpoints/GetMyUser.cs create mode 100644 src/Web/Features/Contents/Handlers/GetCreatorProfile.cs create mode 100644 src/Web/Features/Users/Handlers/ChangeAddress.cs create mode 100644 src/Web/Features/Users/Handlers/ChangeAlias.cs create mode 100644 src/Web/Features/Users/Handlers/ChangeBirthDate.cs create mode 100644 src/Web/Features/Users/Handlers/ChangeEmail.cs create mode 100644 src/Web/Features/Users/Handlers/ChangeFullname.cs create mode 100644 src/Web/Features/Users/Handlers/ChangePhone.cs create mode 100644 src/Web/Features/Users/Handlers/GetCurrentUser.cs create mode 100644 src/Web/Features/Users/Handlers/GetCurrentUserProfilePicture.cs create mode 100644 src/Web/Features/Users/Handlers/Models/UserDto.cs rename src/{Application/Users/Queries/GetCurrentUser => Web/Features/Wallets}/UserTransactionDto.cs (55%) diff --git a/src/Application/Common/Models/UserModel.cs b/src/Application/Common/Models/UserModel.cs index b38e4b4..2a28ec7 100644 --- a/src/Application/Common/Models/UserModel.cs +++ b/src/Application/Common/Models/UserModel.cs @@ -3,14 +3,13 @@ namespace Hutopy.Application.Common.Models; public class UserModel { public Guid Id { get; set; } - public string UserName { get; init; } = null!; + public string Username { get; init; } = null!; public string? Alias { get; init; } public string? PortraitUrl { get; init; } - public string? FirstName { get; init; } - public string? LastName { get; init; } - public string? Occupation { get; init; } + public string? Firstname { get; init; } + public string? Lastname { get; init; } public string? Email { get; init; } public string? PhoneNumber { get; init; } - public string? BirthDate { get; init; } + public DateTime? BirthDate { get; init; } public string? Address { get; init; } } diff --git a/src/Application/Users/Queries/GetCurrentUser/GetCurrentUser.cs b/src/Application/Users/Queries/GetCurrentUser/GetCurrentUser.cs deleted file mode 100644 index 18e3f8e..0000000 --- a/src/Application/Users/Queries/GetCurrentUser/GetCurrentUser.cs +++ /dev/null @@ -1,50 +0,0 @@ -using Hutopy.Application.Common.Interfaces; - -namespace Hutopy.Application.Users.Queries.GetCurrentUser; - -public record GetCurrentUserQuery : IRequest; - -public class GetCurrentUserQueryHandler( - IApplicationDbContext context, - IMapper mapper, - IIdentityService identityService -) - : IRequestHandler -{ - public async Task Handle(GetCurrentUserQuery request, CancellationToken cancellationToken) - { - var userModel = await identityService.GetCurrentUserAsync(); - - if (userModel is null) return null; - - var transactions = await context - .UserTransactions - .Where(x => x.ApplicationUserId == userModel.Id) - .OrderBy(x => x.LastModifiedAt) - .ProjectTo(mapper.ConfigurationProvider) - .Where(x => x.IsConfirmed == true) - .ToListAsync(cancellationToken); - - var roles = await identityService.GetCurrentUserRolesAsync(); - - var user = new UserDto - { - Id = userModel.Id, - Alias = userModel.Alias, - PortraitUrl = userModel.PortraitUrl, - FirstName = userModel.FirstName, - LastName = userModel.LastName, - UserName = userModel.UserName, - Occupation = userModel.Occupation, - PhoneNumber = userModel.PhoneNumber, - Email = userModel.Email, - BirthDate = userModel.BirthDate, - Address = userModel.Address, - UserTransactions = transactions, - TotalBalance = transactions.Sum(x => x.Amount), - UserRoles = roles, - }; - - return user; - } -} diff --git a/src/Application/Users/Queries/GetCurrentUser/GetCurrentUserProfilePicture.cs b/src/Application/Users/Queries/GetCurrentUser/GetCurrentUserProfilePicture.cs deleted file mode 100644 index 26865b7..0000000 --- a/src/Application/Users/Queries/GetCurrentUser/GetCurrentUserProfilePicture.cs +++ /dev/null @@ -1,23 +0,0 @@ -using Hutopy.Application.AzureBlobStorage.Constants; -using Hutopy.Application.Common.Interfaces; - -namespace Hutopy.Application.Users.Queries.GetCurrentUser; - -public record GetCurrentUserProfilePictureQuery : IRequest; - -public class GetCurrentUserProfilePictureQueryHandler( - IIdentityService identityService, - IBlobStorage blobStorage -) - : IRequestHandler -{ - public async Task Handle(GetCurrentUserProfilePictureQuery request, CancellationToken cancellationToken) - { - var identityUser = await identityService.GetCurrentUserAsync(); - - return await blobStorage.DownloadFileAsync( - ContainerNames.Users, - $"{identityUser.Id.ToString()}/{SubDirectoryNames.Profile}/{CommonFileNames.ProfilePicture}", - cancellationToken); - } -} diff --git a/src/Application/Users/Queries/GetCurrentUser/UserDto.cs b/src/Application/Users/Queries/GetCurrentUser/UserDto.cs deleted file mode 100644 index 689c411..0000000 --- a/src/Application/Users/Queries/GetCurrentUser/UserDto.cs +++ /dev/null @@ -1,19 +0,0 @@ -namespace Hutopy.Application.Users.Queries.GetCurrentUser; - -public class UserDto -{ - public Guid Id { get; init; } - public IList UserRoles { get; init; } = []; - public string UserName { get; init; } = null!; - public string? Alias { get; init; } - public string? PortraitUrl { get; init; } - public string? FirstName { get; init; } - public string? LastName { get; init; } - public string? Occupation { get; init; } - public string? Email { get; init; } - public string? PhoneNumber { get; init; } - public string? BirthDate { get; init; } - public string? Address { get; init; } - public List UserTransactions { get; init; } = []; - public required decimal TotalBalance { get; init; } -} diff --git a/src/Application/Users/Queries/GetUser/UserDto.cs b/src/Application/Users/Queries/GetUser/UserDto.cs index 86ce3d4..c64bb21 100644 --- a/src/Application/Users/Queries/GetUser/UserDto.cs +++ b/src/Application/Users/Queries/GetUser/UserDto.cs @@ -17,9 +17,8 @@ public static class UserDtoExtensions new() { Id = model.Id, - FirstName = model.FirstName, - LastName = model.LastName, - UserName = model.UserName, - Occupation = model.Occupation + FirstName = model.Firstname, + LastName = model.Lastname, + UserName = model.Username }; } diff --git a/src/Infrastructure/Identity/ApplicationUser.cs b/src/Infrastructure/Identity/ApplicationUser.cs index 7d52e10..8a1ed8e 100644 --- a/src/Infrastructure/Identity/ApplicationUser.cs +++ b/src/Infrastructure/Identity/ApplicationUser.cs @@ -6,10 +6,9 @@ namespace Hutopy.Infrastructure.Identity; public class ApplicationUser : IdentityUser { [MaxLength(255)] public string? Alias { get; set; } - [MaxLength(255)] public string? FirstName { get; set; } - [MaxLength(255)] public string? LastName { get; set; } - [MaxLength(255)] public string? Occupation { get; set; } - [MaxLength(255)] public string? BirthDate { get; set; } + [MaxLength(255)] public string? Firstname { get; set; } + [MaxLength(255)] public string? Lastname { get; set; } + public DateTime? BirthDate { get; set; } [MaxLength(255)] public string? Address { get; set; } [MaxLength(255)] public string? PortraitUrl { get; set; } } diff --git a/src/Infrastructure/Identity/IdentityService.cs b/src/Infrastructure/Identity/IdentityService.cs index f853d1f..6cf9a0f 100644 --- a/src/Infrastructure/Identity/IdentityService.cs +++ b/src/Infrastructure/Identity/IdentityService.cs @@ -36,13 +36,12 @@ public class IdentityService( return new() { Id = user.Id, - UserName = user.UserName!, + Username = user.UserName!, PhoneNumber = user.PhoneNumber, Email = user.Email, Alias = user.Alias, - FirstName = user.FirstName, - LastName = user.LastName, - Occupation = user.Occupation, + Firstname = user.Firstname, + Lastname = user.Lastname, BirthDate = user.BirthDate, Address = user.Address, PortraitUrl = user.PortraitUrl @@ -55,8 +54,8 @@ public class IdentityService( { UserName = userInfo.Name, Email = userInfo.Email, - FirstName = userInfo.GivenName, - LastName = userInfo.FamilyName + Firstname = userInfo.GivenName, + Lastname = userInfo.FamilyName }; var password = Guid.NewGuid().ToString("N")[..32]; @@ -75,7 +74,7 @@ public class IdentityService( { var applicationUser = new ApplicationUser { - UserName = userName, Email = email, FirstName = firstName, LastName = lastName + UserName = userName, Email = email, Firstname = firstName, Lastname = lastName }; var response = await userManager.CreateAsync(applicationUser, password); @@ -95,9 +94,8 @@ public class IdentityService( applicationUser.Email = userModel.Email; applicationUser.PhoneNumber = userModel.PhoneNumber; applicationUser.Alias = userModel.Alias; - applicationUser.FirstName = userModel.FirstName; - applicationUser.LastName = userModel.LastName; - applicationUser.Occupation = userModel.Occupation; + applicationUser.Firstname = userModel.Firstname; + applicationUser.Lastname = userModel.Lastname; applicationUser.BirthDate = userModel.BirthDate; applicationUser.Address = userModel.Address; applicationUser.PortraitUrl = userModel.PortraitUrl; @@ -120,14 +118,13 @@ public class IdentityService( var userModel = new UserModel { Id = response.Id, - UserName = response.UserName ?? string.Empty, + Username = response.UserName ?? string.Empty, PhoneNumber = response.PhoneNumber ?? string.Empty, Email = response.Email ?? string.Empty, PortraitUrl = response.PortraitUrl, Alias = response.Alias, - FirstName = response.FirstName, - LastName = response.LastName, - Occupation = response.Occupation, + Firstname = response.Firstname, + Lastname = response.Lastname, BirthDate = response.BirthDate, Address = response.Address, }; @@ -275,8 +272,8 @@ public class IdentityService( userId: user.Id.ToString(), email: user.Email, alias: user.Alias, - firstname: user.FirstName, - lastname: user.LastName, + firstname: user.Firstname, + lastname: user.Lastname, portraitUrl: user.PortraitUrl); return token; diff --git a/src/Infrastructure/Migrations/20240903230821_ChangeBirthDateToDateTime.Designer.cs b/src/Infrastructure/Migrations/20240903230821_ChangeBirthDateToDateTime.Designer.cs new file mode 100644 index 0000000..fbdfc47 --- /dev/null +++ b/src/Infrastructure/Migrations/20240903230821_ChangeBirthDateToDateTime.Designer.cs @@ -0,0 +1,436 @@ +// +using System; +using Hutopy.Infrastructure.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Hutopy.Infrastructure.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + [Migration("20240903230821_ChangeBirthDateToDateTime")] + partial class ChangeBirthDateToDateTime + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.4") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("Hutopy.Domain.Entities.FutureCreator", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("CreatedAt") + .HasColumnType("datetimeoffset"); + + b.Property("CreatedBy") + .HasColumnType("uniqueidentifier"); + + b.Property("EmailAddress") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("FirstName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("LastModifiedAt") + .HasColumnType("datetimeoffset"); + + b.Property("LastModifiedBy") + .HasColumnType("uniqueidentifier"); + + b.Property("LastName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumber") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("ReasonToJoin") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("SocialNetworkAccount") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("FutureCreators"); + }); + + modelBuilder.Entity("Hutopy.Domain.Entities.UserTransaction", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Amount") + .HasPrecision(18, 2) + .HasColumnType("decimal(18,2)"); + + b.Property("ApplicationUserId") + .HasColumnType("uniqueidentifier"); + + b.Property("CreatedAt") + .HasColumnType("datetimeoffset"); + + b.Property("CreatedBy") + .HasColumnType("uniqueidentifier"); + + b.Property("Currency") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("IsConfirmed") + .HasColumnType("bit"); + + b.Property("LastModifiedAt") + .HasColumnType("datetimeoffset"); + + b.Property("LastModifiedBy") + .HasColumnType("uniqueidentifier"); + + b.Property("Paid") + .HasColumnType("bit"); + + b.Property("StripeBillingDetailEmail") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("StripeBillingDetailName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("StripeChargeId") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("StripeEventId") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("StripePaymentIntent") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("StripePaymentMethod") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("StripeReceiptUrl") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("TipMessage") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationUserId"); + + b.ToTable("UserTransactions"); + }); + + modelBuilder.Entity("Hutopy.Infrastructure.Identity.ApplicationRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("nvarchar(max)"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex") + .HasFilter("[NormalizedName] IS NOT NULL"); + + b.ToTable("AspNetRoles", (string)null); + }); + + modelBuilder.Entity("Hutopy.Infrastructure.Identity.ApplicationUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("AccessFailedCount") + .HasColumnType("int"); + + b.Property("Address") + .HasMaxLength(255) + .HasColumnType("nvarchar(255)"); + + b.Property("Alias") + .HasMaxLength(255) + .HasColumnType("nvarchar(255)"); + + b.Property("BirthDate") + .HasMaxLength(255) + .HasColumnType("datetime2"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("nvarchar(max)"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("EmailConfirmed") + .HasColumnType("bit"); + + b.Property("Firstname") + .HasMaxLength(255) + .HasColumnType("nvarchar(255)"); + + b.Property("Lastname") + .HasMaxLength(255) + .HasColumnType("nvarchar(255)"); + + b.Property("LockoutEnabled") + .HasColumnType("bit"); + + b.Property("LockoutEnd") + .HasColumnType("datetimeoffset"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("Occupation") + .HasMaxLength(255) + .HasColumnType("nvarchar(255)"); + + b.Property("PasswordHash") + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumber") + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("bit"); + + b.Property("PortraitUrl") + .HasMaxLength(255) + .HasColumnType("nvarchar(255)"); + + b.Property("SecurityStamp") + .HasColumnType("nvarchar(max)"); + + b.Property("TwoFactorEnabled") + .HasColumnType("bit"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex") + .HasFilter("[NormalizedUserName] IS NOT NULL"); + + b.ToTable("AspNetUsers", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("nvarchar(max)"); + + b.Property("ClaimValue") + .HasColumnType("nvarchar(max)"); + + b.Property("RoleId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("nvarchar(max)"); + + b.Property("ClaimValue") + .HasColumnType("nvarchar(max)"); + + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("nvarchar(450)"); + + b.Property("ProviderKey") + .HasColumnType("nvarchar(450)"); + + b.Property("ProviderDisplayName") + .HasColumnType("nvarchar(max)"); + + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.Property("RoleId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.Property("LoginProvider") + .HasColumnType("nvarchar(450)"); + + b.Property("Name") + .HasColumnType("nvarchar(450)"); + + b.Property("Value") + .HasColumnType("nvarchar(max)"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens", (string)null); + }); + + modelBuilder.Entity("Hutopy.Domain.Entities.UserTransaction", b => + { + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("ApplicationUserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Infrastructure/Migrations/20240903230821_ChangeBirthDateToDateTime.cs b/src/Infrastructure/Migrations/20240903230821_ChangeBirthDateToDateTime.cs new file mode 100644 index 0000000..6e94cdb --- /dev/null +++ b/src/Infrastructure/Migrations/20240903230821_ChangeBirthDateToDateTime.cs @@ -0,0 +1,83 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Hutopy.Infrastructure.Migrations +{ + /// + public partial class ChangeBirthDateToDateTime : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "City", + table: "AspNetUsers"); + + migrationBuilder.DropColumn( + name: "Country", + table: "AspNetUsers"); + + migrationBuilder.RenameColumn( + name: "LastName", + table: "AspNetUsers", + newName: "Lastname"); + + migrationBuilder.RenameColumn( + name: "FirstName", + table: "AspNetUsers", + newName: "Firstname"); + + migrationBuilder.AlterColumn( + name: "BirthDate", + table: "AspNetUsers", + type: "datetime2", + maxLength: 255, + nullable: true, + oldClrType: typeof(string), + oldType: "nvarchar(255)", + oldMaxLength: 255, + oldNullable: true); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.RenameColumn( + name: "Lastname", + table: "AspNetUsers", + newName: "LastName"); + + migrationBuilder.RenameColumn( + name: "Firstname", + table: "AspNetUsers", + newName: "FirstName"); + + migrationBuilder.AlterColumn( + name: "BirthDate", + table: "AspNetUsers", + type: "nvarchar(255)", + maxLength: 255, + nullable: true, + oldClrType: typeof(DateTime), + oldType: "datetime2", + oldMaxLength: 255, + oldNullable: true); + + migrationBuilder.AddColumn( + name: "City", + table: "AspNetUsers", + type: "nvarchar(255)", + maxLength: 255, + nullable: true); + + migrationBuilder.AddColumn( + name: "Country", + table: "AspNetUsers", + type: "nvarchar(255)", + maxLength: 255, + nullable: true); + } + } +} diff --git a/src/Infrastructure/Migrations/20240903231429_RemoveOccupation.Designer.cs b/src/Infrastructure/Migrations/20240903231429_RemoveOccupation.Designer.cs new file mode 100644 index 0000000..dd3ab98 --- /dev/null +++ b/src/Infrastructure/Migrations/20240903231429_RemoveOccupation.Designer.cs @@ -0,0 +1,432 @@ +// +using System; +using Hutopy.Infrastructure.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Hutopy.Infrastructure.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + [Migration("20240903231429_RemoveOccupation")] + partial class RemoveOccupation + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.4") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("Hutopy.Domain.Entities.FutureCreator", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("CreatedAt") + .HasColumnType("datetimeoffset"); + + b.Property("CreatedBy") + .HasColumnType("uniqueidentifier"); + + b.Property("EmailAddress") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("FirstName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("LastModifiedAt") + .HasColumnType("datetimeoffset"); + + b.Property("LastModifiedBy") + .HasColumnType("uniqueidentifier"); + + b.Property("LastName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumber") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("ReasonToJoin") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("SocialNetworkAccount") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("FutureCreators"); + }); + + modelBuilder.Entity("Hutopy.Domain.Entities.UserTransaction", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Amount") + .HasPrecision(18, 2) + .HasColumnType("decimal(18,2)"); + + b.Property("ApplicationUserId") + .HasColumnType("uniqueidentifier"); + + b.Property("CreatedAt") + .HasColumnType("datetimeoffset"); + + b.Property("CreatedBy") + .HasColumnType("uniqueidentifier"); + + b.Property("Currency") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("IsConfirmed") + .HasColumnType("bit"); + + b.Property("LastModifiedAt") + .HasColumnType("datetimeoffset"); + + b.Property("LastModifiedBy") + .HasColumnType("uniqueidentifier"); + + b.Property("Paid") + .HasColumnType("bit"); + + b.Property("StripeBillingDetailEmail") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("StripeBillingDetailName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("StripeChargeId") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("StripeEventId") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("StripePaymentIntent") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("StripePaymentMethod") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("StripeReceiptUrl") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("TipMessage") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationUserId"); + + b.ToTable("UserTransactions"); + }); + + modelBuilder.Entity("Hutopy.Infrastructure.Identity.ApplicationRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("nvarchar(max)"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex") + .HasFilter("[NormalizedName] IS NOT NULL"); + + b.ToTable("AspNetRoles", (string)null); + }); + + modelBuilder.Entity("Hutopy.Infrastructure.Identity.ApplicationUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("AccessFailedCount") + .HasColumnType("int"); + + b.Property("Address") + .HasMaxLength(255) + .HasColumnType("nvarchar(255)"); + + b.Property("Alias") + .HasMaxLength(255) + .HasColumnType("nvarchar(255)"); + + b.Property("BirthDate") + .HasMaxLength(255) + .HasColumnType("datetime2"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("nvarchar(max)"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("EmailConfirmed") + .HasColumnType("bit"); + + b.Property("Firstname") + .HasMaxLength(255) + .HasColumnType("nvarchar(255)"); + + b.Property("Lastname") + .HasMaxLength(255) + .HasColumnType("nvarchar(255)"); + + b.Property("LockoutEnabled") + .HasColumnType("bit"); + + b.Property("LockoutEnd") + .HasColumnType("datetimeoffset"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("PasswordHash") + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumber") + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("bit"); + + b.Property("PortraitUrl") + .HasMaxLength(255) + .HasColumnType("nvarchar(255)"); + + b.Property("SecurityStamp") + .HasColumnType("nvarchar(max)"); + + b.Property("TwoFactorEnabled") + .HasColumnType("bit"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex") + .HasFilter("[NormalizedUserName] IS NOT NULL"); + + b.ToTable("AspNetUsers", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("nvarchar(max)"); + + b.Property("ClaimValue") + .HasColumnType("nvarchar(max)"); + + b.Property("RoleId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("nvarchar(max)"); + + b.Property("ClaimValue") + .HasColumnType("nvarchar(max)"); + + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("nvarchar(450)"); + + b.Property("ProviderKey") + .HasColumnType("nvarchar(450)"); + + b.Property("ProviderDisplayName") + .HasColumnType("nvarchar(max)"); + + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.Property("RoleId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.Property("LoginProvider") + .HasColumnType("nvarchar(450)"); + + b.Property("Name") + .HasColumnType("nvarchar(450)"); + + b.Property("Value") + .HasColumnType("nvarchar(max)"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens", (string)null); + }); + + modelBuilder.Entity("Hutopy.Domain.Entities.UserTransaction", b => + { + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("ApplicationUserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Infrastructure/Migrations/20240903231429_RemoveOccupation.cs b/src/Infrastructure/Migrations/20240903231429_RemoveOccupation.cs new file mode 100644 index 0000000..c1cb1b0 --- /dev/null +++ b/src/Infrastructure/Migrations/20240903231429_RemoveOccupation.cs @@ -0,0 +1,29 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Hutopy.Infrastructure.Migrations +{ + /// + public partial class RemoveOccupation : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "Occupation", + table: "AspNetUsers"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "Occupation", + table: "AspNetUsers", + type: "nvarchar(255)", + maxLength: 255, + nullable: true); + } + } +} diff --git a/src/Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs b/src/Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs index 7e0e9ed..b3d38bc 100644 --- a/src/Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs +++ b/src/Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs @@ -188,22 +188,14 @@ namespace Hutopy.Infrastructure.Migrations .HasMaxLength(255) .HasColumnType("nvarchar(255)"); - b.Property("BirthDate") + b.Property("BirthDate") .HasMaxLength(255) - .HasColumnType("nvarchar(255)"); - - b.Property("City") - .HasMaxLength(255) - .HasColumnType("nvarchar(255)"); + .HasColumnType("datetime2"); b.Property("ConcurrencyStamp") .IsConcurrencyToken() .HasColumnType("nvarchar(max)"); - b.Property("Country") - .HasMaxLength(255) - .HasColumnType("nvarchar(255)"); - b.Property("Email") .HasMaxLength(256) .HasColumnType("nvarchar(256)"); @@ -211,11 +203,11 @@ namespace Hutopy.Infrastructure.Migrations b.Property("EmailConfirmed") .HasColumnType("bit"); - b.Property("FirstName") + b.Property("Firstname") .HasMaxLength(255) .HasColumnType("nvarchar(255)"); - b.Property("LastName") + b.Property("Lastname") .HasMaxLength(255) .HasColumnType("nvarchar(255)"); @@ -233,10 +225,6 @@ namespace Hutopy.Infrastructure.Migrations .HasMaxLength(256) .HasColumnType("nvarchar(256)"); - b.Property("Occupation") - .HasMaxLength(255) - .HasColumnType("nvarchar(255)"); - b.Property("PasswordHash") .HasColumnType("nvarchar(max)"); diff --git a/src/Web/Controllers/GoogleController.cs b/src/Web/Controllers/GoogleController.cs index 34609ab..fd48001 100644 --- a/src/Web/Controllers/GoogleController.cs +++ b/src/Web/Controllers/GoogleController.cs @@ -75,8 +75,8 @@ public class GoogleController( user.Id.ToString(), user.Email, user.Alias, - user.FirstName, - user.LastName, + user.Firstname, + user.Lastname, user.PortraitUrl); return Ok(new { accessToken = token, email }); diff --git a/src/Web/Endpoints/GetMyUser.cs b/src/Web/Endpoints/GetMyUser.cs deleted file mode 100644 index e891a2e..0000000 --- a/src/Web/Endpoints/GetMyUser.cs +++ /dev/null @@ -1,25 +0,0 @@ -using Hutopy.Application.Users.Queries.GetCurrentUser; -using Hutopy.Web.Infrastructure; - -namespace Hutopy.Web.Endpoints; - -public class GetMyUser : EndpointGroupBase -{ - public override void Map(WebApplication app) - { - app.MapGroup(this) - .RequireAuthorization() - .MapGet(GetCurrentUser) - .MapGet(GetCurrentUserProfilePicture, "profile-picture"); - } - - private static async Task GetCurrentUser(ISender sender, [AsParameters] GetCurrentUserQuery query) - { - return await sender.Send(query); - } - - private static async Task GetCurrentUserProfilePicture(ISender sender, [AsParameters] GetCurrentUserProfilePictureQuery query) - { - return await sender.Send(query); - } -} diff --git a/src/Web/Features/Contents/Handlers/GetCreatorProfile.cs b/src/Web/Features/Contents/Handlers/GetCreatorProfile.cs new file mode 100644 index 0000000..67dd5cb --- /dev/null +++ b/src/Web/Features/Contents/Handlers/GetCreatorProfile.cs @@ -0,0 +1,30 @@ +using Hutopy.Web.Common; +using Hutopy.Web.Features.Contents.Data; + +namespace Hutopy.Web.Features.Contents.Handlers; + +[PublicAPI] +public class GetCreatorProfileHandler( + ContentDbContext context) + : EndpointWithoutRequest +{ + public override void Configure() + { + Get("/api/creators/profile"); + Options((o => o.WithTags("Creators"))); + AllowAnonymous(); + } + + public override async Task HandleAsync( + CancellationToken ct) + { + var creator = await context + .Creators + .FindAsync( + [HttpContext.User.GetUserId()], + cancellationToken: ct); + + if (creator is null) await SendNotFoundAsync(ct); + else await SendAsync(creator, cancellation: ct); + } +} diff --git a/src/Web/Features/Contents/Handlers/Models/ContentModel.cs b/src/Web/Features/Contents/Handlers/Models/ContentModel.cs index c110b0b..d317529 100644 --- a/src/Web/Features/Contents/Handlers/Models/ContentModel.cs +++ b/src/Web/Features/Contents/Handlers/Models/ContentModel.cs @@ -1,6 +1,4 @@ -using System.ComponentModel.DataAnnotations.Schema; - -namespace Hutopy.Web.Features.Contents.Handlers.Models; +namespace Hutopy.Web.Features.Contents.Handlers.Models; [PublicAPI] public class ContentModel diff --git a/src/Web/Features/Users/Handlers/ChangeAddress.cs b/src/Web/Features/Users/Handlers/ChangeAddress.cs new file mode 100644 index 0000000..b139f44 --- /dev/null +++ b/src/Web/Features/Users/Handlers/ChangeAddress.cs @@ -0,0 +1,43 @@ +using Hutopy.Infrastructure.Identity; +using Hutopy.Web.Common; + +namespace Hutopy.Web.Features.Users.Handlers; + +[PublicAPI] +public record ChangeAddressRequest( + string? Address); + +[PublicAPI] +public class ChangeAddressHandler( + ApplicationUserManager userManager) + : Endpoint +{ + public override void Configure() + { + Post("/api/users/address"); + Options(o => o.WithTags("Users")); + } + + public override async Task HandleAsync( + ChangeAddressRequest request, + CancellationToken ct) + { + var user = await userManager.FindByIdAsync(HttpContext.User.GetUserId().ToString()); + + if (user is null) + { + await SendNotFoundAsync(ct); + return; + } + + user.Address = request.Address; + // TODO: check to see if identity resets the email-validated flag - @jonathan + + var result = await userManager.UpdateAsync(user); + + if (result.Succeeded) + await SendOkAsync(ct); + else + await SendUnauthorizedAsync(ct); + } +} diff --git a/src/Web/Features/Users/Handlers/ChangeAlias.cs b/src/Web/Features/Users/Handlers/ChangeAlias.cs new file mode 100644 index 0000000..7272075 --- /dev/null +++ b/src/Web/Features/Users/Handlers/ChangeAlias.cs @@ -0,0 +1,42 @@ +using Hutopy.Infrastructure.Identity; +using Hutopy.Web.Common; + +namespace Hutopy.Web.Features.Users.Handlers; + +[PublicAPI] +public record ChangeAliasRequest( + string? Alias); + +[PublicAPI] +public class ChangeAliasHandler( + ApplicationUserManager userManager) + : Endpoint +{ + public override void Configure() + { + Post("/api/users/alias"); + Options(o => o.WithTags("Users")); + } + + public override async Task HandleAsync( + ChangeAliasRequest request, + CancellationToken ct) + { + var user = await userManager.FindByIdAsync(HttpContext.User.GetUserId().ToString()); + + if (user is null) + { + await SendNotFoundAsync(ct); + return; + } + + user.Alias = request.Alias; + + var result = await userManager.UpdateAsync(user); + + if (result.Succeeded) + await SendOkAsync(ct); + else + await SendUnauthorizedAsync(ct); + } +} diff --git a/src/Web/Features/Users/Handlers/ChangeBirthDate.cs b/src/Web/Features/Users/Handlers/ChangeBirthDate.cs new file mode 100644 index 0000000..661bd8a --- /dev/null +++ b/src/Web/Features/Users/Handlers/ChangeBirthDate.cs @@ -0,0 +1,42 @@ +using Hutopy.Infrastructure.Identity; +using Hutopy.Web.Common; + +namespace Hutopy.Web.Features.Users.Handlers; + +[PublicAPI] +public record ChangeBirthDateRequest( + DateTime BirthDate); + +[PublicAPI] +public class ChangeBirthDateHandler( + ApplicationUserManager userManager) + : Endpoint +{ + public override void Configure() + { + Post("/api/users/birthdate"); + Options(o => o.WithTags("Users")); + } + + public override async Task HandleAsync( + ChangeBirthDateRequest request, + CancellationToken ct) + { + var user = await userManager.FindByIdAsync(HttpContext.User.GetUserId().ToString()); + + if (user is null) + { + await SendNotFoundAsync(ct); + return; + } + + user.BirthDate = request.BirthDate; + + var result = await userManager.UpdateAsync(user); + + if (result.Succeeded) + await SendOkAsync(ct); + else + await SendUnauthorizedAsync(ct); + } +} diff --git a/src/Web/Features/Users/Handlers/ChangeEmail.cs b/src/Web/Features/Users/Handlers/ChangeEmail.cs new file mode 100644 index 0000000..8f7c844 --- /dev/null +++ b/src/Web/Features/Users/Handlers/ChangeEmail.cs @@ -0,0 +1,43 @@ +using Hutopy.Infrastructure.Identity; +using Hutopy.Web.Common; + +namespace Hutopy.Web.Features.Users.Handlers; + +[PublicAPI] +public record ChangeEmailRequest( + string? Email); + +[PublicAPI] +public class ChangeEmailHandler( + ApplicationUserManager userManager) + : Endpoint +{ + public override void Configure() + { + Post("/api/users/email"); + Options(o => o.WithTags("Users")); + } + + public override async Task HandleAsync( + ChangeEmailRequest request, + CancellationToken ct) + { + var user = await userManager.FindByIdAsync(HttpContext.User.GetUserId().ToString()); + + if (user is null) + { + await SendNotFoundAsync(ct); + return; + } + + user.Email = request.Email; + // TODO: check to see if identity resets the email-validated flag - @jonathan + + var result = await userManager.UpdateAsync(user); + + if (result.Succeeded) + await SendOkAsync(ct); + else + await SendUnauthorizedAsync(ct); + } +} diff --git a/src/Web/Features/Users/Handlers/ChangeFullname.cs b/src/Web/Features/Users/Handlers/ChangeFullname.cs new file mode 100644 index 0000000..b71762e --- /dev/null +++ b/src/Web/Features/Users/Handlers/ChangeFullname.cs @@ -0,0 +1,44 @@ +using Hutopy.Infrastructure.Identity; +using Hutopy.Web.Common; + +namespace Hutopy.Web.Features.Users.Handlers; + +[PublicAPI] +public record ChangeFullnameRequest( + string? Firstname, + string? Lastname); + +[PublicAPI] +public class ChangeFullnameHandler( + ApplicationUserManager userManager) + : Endpoint +{ + public override void Configure() + { + Post("/api/users/fullname"); + Options(o => o.WithTags("Users")); + } + + public override async Task HandleAsync( + ChangeFullnameRequest request, + CancellationToken ct) + { + var user = await userManager.FindByIdAsync(HttpContext.User.GetUserId().ToString()); + + if (user is null) + { + await SendNotFoundAsync(ct); + return; + } + + user.Firstname = request.Firstname; + user.Lastname = request.Lastname; + + var result = await userManager.UpdateAsync(user); + + if (result.Succeeded) + await SendOkAsync(ct); + else + await SendUnauthorizedAsync(ct); + } +} diff --git a/src/Web/Features/Users/Handlers/ChangePhone.cs b/src/Web/Features/Users/Handlers/ChangePhone.cs new file mode 100644 index 0000000..8e7a91f --- /dev/null +++ b/src/Web/Features/Users/Handlers/ChangePhone.cs @@ -0,0 +1,43 @@ +using Hutopy.Infrastructure.Identity; +using Hutopy.Web.Common; + +namespace Hutopy.Web.Features.Users.Handlers; + +[PublicAPI] +public record ChangePhoneRequest( + string? PhoneNumber); + +[PublicAPI] +public class ChangePhoneHandler( + ApplicationUserManager userManager) + : Endpoint +{ + public override void Configure() + { + Post("/api/users/phone"); + Options(o => o.WithTags("Users")); + } + + public override async Task HandleAsync( + ChangePhoneRequest request, + CancellationToken ct) + { + var user = await userManager.FindByIdAsync(HttpContext.User.GetUserId().ToString()); + + if (user is null) + { + await SendNotFoundAsync(ct); + return; + } + + user.PhoneNumber = request.PhoneNumber; + // TODO: check to see if identity resets the email-validated flag - @jonathan + + var result = await userManager.UpdateAsync(user); + + if (result.Succeeded) + await SendOkAsync(ct); + else + await SendUnauthorizedAsync(ct); + } +} diff --git a/src/Web/Features/Users/Handlers/GetCurrentUser.cs b/src/Web/Features/Users/Handlers/GetCurrentUser.cs new file mode 100644 index 0000000..30981ac --- /dev/null +++ b/src/Web/Features/Users/Handlers/GetCurrentUser.cs @@ -0,0 +1,48 @@ +using Hutopy.Application.Common.Interfaces; +using Hutopy.Web.Features.Users.Handlers.Models; + +namespace Hutopy.Web.Features.Users.Handlers; + +[PublicAPI] +public class GetCurrentUserQueryHandler( + IIdentityService identityService +) + : EndpointWithoutRequest +{ + public override void Configure() + { + Get("/api/users/profile"); + Options(o => o.WithTags("Users")); + } + + public override async Task HandleAsync( + CancellationToken cancellationToken) + { + var userModel = await identityService.GetCurrentUserAsync(); + + if (userModel is null) + { + await SendNotFoundAsync(cancellationToken); + return; + } + + var roles = await identityService.GetCurrentUserRolesAsync(); + + await SendOkAsync( + new UserDto + { + Id = userModel.Id, + Alias = userModel.Alias, + PortraitUrl = userModel.PortraitUrl, + Firstname = userModel.Firstname, + Lastname = userModel.Lastname, + Username = userModel.Username, + PhoneNumber = userModel.PhoneNumber, + Email = userModel.Email, + BirthDate = userModel.BirthDate, + Address = userModel.Address, + UserRoles = roles, + }, + cancellationToken); + } +} diff --git a/src/Web/Features/Users/Handlers/GetCurrentUserProfilePicture.cs b/src/Web/Features/Users/Handlers/GetCurrentUserProfilePicture.cs new file mode 100644 index 0000000..806fef9 --- /dev/null +++ b/src/Web/Features/Users/Handlers/GetCurrentUserProfilePicture.cs @@ -0,0 +1,31 @@ +using Hutopy.Application.AzureBlobStorage.Constants; +using Hutopy.Application.Common.Interfaces; + +namespace Hutopy.Web.Features.Users.Handlers; + +[PublicAPI] +public class GetCurrentUserPortraitHandler( + IIdentityService identityService, + IBlobStorage blobStorage +) + : EndpointWithoutRequest +{ + public override void Configure() + { + Get("/api/users/portrait"); + Options(o => o.WithTags("Users")); + } + + public override async Task HandleAsync( + CancellationToken cancellationToken) + { + var identityUser = await identityService.GetCurrentUserAsync(); + + var stream = await blobStorage.DownloadFileAsync( + ContainerNames.Users, + $"{identityUser.Id.ToString()}/{SubDirectoryNames.Profile}/{CommonFileNames.ProfilePicture}", + cancellationToken); + + await SendOkAsync(stream, cancellationToken); + } +} diff --git a/src/Web/Features/Users/Handlers/Models/UserDto.cs b/src/Web/Features/Users/Handlers/Models/UserDto.cs new file mode 100644 index 0000000..b546f29 --- /dev/null +++ b/src/Web/Features/Users/Handlers/Models/UserDto.cs @@ -0,0 +1,16 @@ +namespace Hutopy.Web.Features.Users.Handlers.Models; + +public class UserDto +{ + public Guid Id { get; init; } + public IList UserRoles { get; init; } = []; + public string Username { get; init; } = null!; + public string? Alias { get; init; } + public string? PortraitUrl { get; init; } + public string? Firstname { get; init; } + public string? Lastname { get; init; } + public string? Email { get; init; } + public string? PhoneNumber { get; init; } + public DateTime? BirthDate { get; init; } + public string? Address { get; init; } +} diff --git a/src/Application/Users/Queries/GetCurrentUser/UserTransactionDto.cs b/src/Web/Features/Wallets/UserTransactionDto.cs similarity index 55% rename from src/Application/Users/Queries/GetCurrentUser/UserTransactionDto.cs rename to src/Web/Features/Wallets/UserTransactionDto.cs index f682df4..361dcff 100644 --- a/src/Application/Users/Queries/GetCurrentUser/UserTransactionDto.cs +++ b/src/Web/Features/Wallets/UserTransactionDto.cs @@ -1,6 +1,4 @@ -using Hutopy.Domain.Entities; - -namespace Hutopy.Application.Users.Queries.GetCurrentUser; +namespace Hutopy.Web.Features.Wallets; public class UserTransactionDto { @@ -13,11 +11,4 @@ public class UserTransactionDto public DateTimeOffset Created { get; init; } public bool IsConfirmed { get; init; } - private class Mapping : Profile - { - public Mapping() - { - CreateMap(); - } - } } diff --git a/src/Web/TestDataSeeder.cs b/src/Web/TestDataSeeder.cs index 68bc5e5..08c7bbf 100644 --- a/src/Web/TestDataSeeder.cs +++ b/src/Web/TestDataSeeder.cs @@ -113,7 +113,7 @@ internal class TestDataSeeder( SubjectId = content.Id, CreatedAt = currentDate, CreatedBy = author.Id, - CreatedByName = author.Alias ?? $"{author.FirstName} {author.LastName}", + CreatedByName = author.Alias ?? $"{author.Firstname} {author.Lastname}", CreatedByPortraitUrl = author.PortraitUrl, Value = $"Message #{m} on {content.Title}" }; @@ -143,7 +143,7 @@ internal class TestDataSeeder( SubjectId = content.Id, ParentId = parent.Id, CreatedBy = author.Id, - CreatedByName = author.Alias ?? $"{author.FirstName} {author.LastName}", + CreatedByName = author.Alias ?? $"{author.Firstname} {author.Lastname}", CreatedByPortraitUrl = author.PortraitUrl, CreatedAt = currentDate, Value = $"Reply {r} to {parent.Value} on {content.Title}" @@ -165,8 +165,8 @@ internal class TestDataSeeder( Email = $"{name}@test", EmailConfirmed = true, Alias = name, - FirstName = $"FirstName of {name}", - LastName = $"LastName of {name}", + Firstname = $"FirstName of {name}", + Lastname = $"LastName of {name}", PortraitUrl = portraitUrl }; diff --git a/tests/Application.FunctionalTests/Testing.cs b/tests/Application.FunctionalTests/Testing.cs index 74cd4d0..dc44dc4 100644 --- a/tests/Application.FunctionalTests/Testing.cs +++ b/tests/Application.FunctionalTests/Testing.cs @@ -73,7 +73,7 @@ public partial class Testing var user = new ApplicationUser { - UserName = userName, Email = userName, FirstName = "FirstName", LastName = "LastName" + UserName = userName, Email = userName, Firstname = "FirstName", Lastname = "LastName" }; var result = await userManager.CreateAsync(user, password); From 3e341e00197e993b36f13f0cc0e0175310b2d847 Mon Sep 17 00:00:00 2001 From: Jonathan Bourdon Date: Wed, 4 Sep 2024 13:52:47 -0400 Subject: [PATCH 185/229] Adds ChangePortrait for User --- .../Users/Commands/UploadProfilePicture.cs | 35 --------- src/Web/Endpoints/UpdateMyUser.cs | 9 --- .../Contents/Handlers/ChangeBanner.cs | 14 +++- .../Features/Contents/Handlers/ChangeLogo.cs | 19 ++++- .../Features/Users/Handlers/ChangePortrait.cs | 74 +++++++++++++++++++ 5 files changed, 103 insertions(+), 48 deletions(-) delete mode 100644 src/Application/Users/Commands/UploadProfilePicture.cs create mode 100644 src/Web/Features/Users/Handlers/ChangePortrait.cs diff --git a/src/Application/Users/Commands/UploadProfilePicture.cs b/src/Application/Users/Commands/UploadProfilePicture.cs deleted file mode 100644 index 3cc34cc..0000000 --- a/src/Application/Users/Commands/UploadProfilePicture.cs +++ /dev/null @@ -1,35 +0,0 @@ -using Hutopy.Application.AzureBlobStorage.Constants; -using Hutopy.Application.Common.Interfaces; -using Microsoft.AspNetCore.Http; - -namespace Hutopy.Application.Users.Commands; - -/// -/// Upload a profile picture. If the user has the url already, set the ProfilePictureUrl in the user only without upload. -/// -public class UploadProfilePictureCommand : IRequest -{ - public required IFormFile File { get; init; } -} - -public class UploadProfilePictureCommandHandler( - IHttpContextAccessor contextAccessor, - IIdentityService identityService, - IBlobStorage blobStorage) : IRequestHandler -{ - public async Task Handle(UploadProfilePictureCommand request, CancellationToken ct) - { - var identityUser = await identityService.GetCurrentUserAsync(); - - var url = await blobStorage.UploadFileAsync( - ContainerNames.Users, - $"{identityUser.Id}/{SubDirectoryNames.Profile}/{CommonFileNames.ProfilePicture}", - request.File.OpenReadStream(), - request.File.ContentType, - ct); - - await identityService.UpdateCurrentUserPortraitUrlAsync(url); - - return Results.Ok(url); - } -} diff --git a/src/Web/Endpoints/UpdateMyUser.cs b/src/Web/Endpoints/UpdateMyUser.cs index 072152f..7118e4e 100644 --- a/src/Web/Endpoints/UpdateMyUser.cs +++ b/src/Web/Endpoints/UpdateMyUser.cs @@ -9,7 +9,6 @@ public class UpdateMyUser : EndpointGroupBase { app.MapGroup(this) .RequireAuthorization() - .MapPost(UpdateCurrentUserProfilePicture, "/profile-picture") .MapPatch("/profile", UpdateCurrentUser); } @@ -17,12 +16,4 @@ public class UpdateMyUser : EndpointGroupBase { return await sender.Send(command); } - - private static async Task UpdateCurrentUserProfilePicture( - ISender sender, - IFormFile formFile) - { - var command = new UploadProfilePictureCommand { File = formFile }; - return await sender.Send(command); - } } diff --git a/src/Web/Features/Contents/Handlers/ChangeBanner.cs b/src/Web/Features/Contents/Handlers/ChangeBanner.cs index b69affb..d33e72a 100644 --- a/src/Web/Features/Contents/Handlers/ChangeBanner.cs +++ b/src/Web/Features/Contents/Handlers/ChangeBanner.cs @@ -9,11 +9,15 @@ public record ChangeBannerRequest( Guid CreatorId, IFormFile File); +[PublicAPI] +public record ChangeBannerResponse( + string BlobUrl); + [PublicAPI] public class ChangeBannerHandler( ContentDbContext context, IBlobStorage blobStorage) - : Endpoint + : Endpoint { public override void Configure() { @@ -22,7 +26,9 @@ public class ChangeBannerHandler( AllowFileUploads(); } - public override async Task HandleAsync(ChangeBannerRequest request, CancellationToken ct) + public override async Task HandleAsync( + ChangeBannerRequest request, + CancellationToken ct) { var creator = await context .Creators @@ -49,6 +55,8 @@ public class ChangeBannerHandler( await context.SaveChangesAsync(ct); - await SendOkAsync(blobUrl, ct); + await SendOkAsync( + new ChangeBannerResponse(blobUrl), + ct); } } diff --git a/src/Web/Features/Contents/Handlers/ChangeLogo.cs b/src/Web/Features/Contents/Handlers/ChangeLogo.cs index 44dd8b8..656bf62 100644 --- a/src/Web/Features/Contents/Handlers/ChangeLogo.cs +++ b/src/Web/Features/Contents/Handlers/ChangeLogo.cs @@ -9,6 +9,21 @@ public record ChangeLogoRequest( Guid CreatorId, IFormFile File); +[PublicAPI] +public sealed class ChangeLogoRequestValidator : Validator +{ + public ChangeLogoRequestValidator() + { + RuleFor(x => x.CreatorId) + .NotNull() + .NotEmpty(); + + RuleFor(x => x.File) + .NotNull() + .NotEmpty(); + } +} + [PublicAPI] public class ChangeLogoHandler( ContentDbContext context, @@ -22,7 +37,9 @@ public class ChangeLogoHandler( AllowFileUploads(); } - public override async Task HandleAsync(ChangeLogoRequest request, CancellationToken ct) + public override async Task HandleAsync( + ChangeLogoRequest request, + CancellationToken ct) { var creator = await context .Creators diff --git a/src/Web/Features/Users/Handlers/ChangePortrait.cs b/src/Web/Features/Users/Handlers/ChangePortrait.cs new file mode 100644 index 0000000..1424fb8 --- /dev/null +++ b/src/Web/Features/Users/Handlers/ChangePortrait.cs @@ -0,0 +1,74 @@ +using Hutopy.Application.AzureBlobStorage.Constants; +using Hutopy.Application.Common.Interfaces; +using Hutopy.Infrastructure.Identity; +using Hutopy.Web.Common; + +namespace Hutopy.Web.Features.Users.Handlers; + +[PublicAPI] +public record ChangePortraitRequest( + IFormFile File); + +[PublicAPI] +public record ChangePortraitResponse( + string BlobUrl); + +[PublicAPI] +public sealed class ChangePortraitRequestValidator : Validator +{ + public ChangePortraitRequestValidator() + { + RuleFor(x => x.File) + .NotNull() + .NotEmpty(); + } +} + +[PublicAPI] +public class ChangePortraitHandler( + ApplicationUserManager userManager, + IBlobStorage blobStorage) + : Endpoint +{ + public override void Configure() + { + Post("/api/users/portrait"); + Options(o => o.WithTags("Users")); + AllowFileUploads(); + } + + public override async Task HandleAsync( + ChangePortraitRequest request, + CancellationToken ct) + { + var user = await userManager.FindByIdAsync(HttpContext.User.GetUserId().ToString()); + + if (user is null) + { + await SendNotFoundAsync(ct); + return; + } + + var blobUrl = await blobStorage.UploadFileAsync( + ContainerNames.Users, + $"{user.Id}/{SubDirectoryNames.Profile}/{CommonFileNames.ProfilePicture}", + request.File.OpenReadStream(), + request.File.ContentType, + ct); + + user.PortraitUrl = blobUrl; + + var result = await userManager.UpdateAsync(user); + + if (result.Succeeded) + { + await SendOkAsync( + new ChangePortraitResponse(blobUrl), + ct); + } + else + { + await SendUnauthorizedAsync(ct); + } + } +} From a4a2c96922920323161c7eda38b03b2b2d5e3521 Mon Sep 17 00:00:00 2001 From: Jonathan Bourdon Date: Wed, 4 Sep 2024 14:28:45 -0400 Subject: [PATCH 186/229] Reformat RuleBuilder in ChangeColorValidator --- .../Contents/Handlers/ChangeColors.cs | 55 +++++++++---------- 1 file changed, 26 insertions(+), 29 deletions(-) diff --git a/src/Web/Features/Contents/Handlers/ChangeColors.cs b/src/Web/Features/Contents/Handlers/ChangeColors.cs index 25e80f3..db88aa3 100644 --- a/src/Web/Features/Contents/Handlers/ChangeColors.cs +++ b/src/Web/Features/Contents/Handlers/ChangeColors.cs @@ -16,34 +16,29 @@ public sealed class ChangeColorsRequestValidator { public ChangeColorsRequestValidator() { - When(x => x.BannerTop is not null, () => - { - RuleFor(x => x.BannerTop) - .MinimumLength(4).WithMessage("The minimum value should be in the format #444") - .MaximumLength(9).WithMessage("The maximum value should be in the format #11223344") - .Must(x => x.StartsWith('#')).WithMessage("The format should be a valid html color and start with #"); - }); - When(x => x.BannerBottom is not null, () => - { - RuleFor(x => x.BannerBottom) - .MinimumLength(4).WithMessage("The minimum value should be in the format #444") - .MaximumLength(9).WithMessage("The maximum value should be in the format #11223344") - .Must(x => x.StartsWith('#')).WithMessage("The format should be a valid html color and start with #"); - }); - When(x => x.Accent is not null, () => - { - RuleFor(x => x.Accent) - .MinimumLength(4).WithMessage("The minimum value should be in the format #444") - .MaximumLength(9).WithMessage("The maximum value should be in the format #11223344") - .Must(x => x.StartsWith('#')).WithMessage("The format should be a valid html color and start with #"); - }); - When(x => x.Menu is not null, () => - { - RuleFor(x => x.Menu) - .MinimumLength(4).WithMessage("The minimum value should be in the format #444") - .MaximumLength(9).WithMessage("The maximum value should be in the format #11223344") - .Must(x => x.StartsWith('#')).WithMessage("The format should be a valid html color and start with #"); - }); + RuleFor(x => x.BannerTop) + .MinimumLength(4).WithMessage("The minimum value should be in the format #444") + .MaximumLength(9).WithMessage("The maximum value should be in the format #11223344") + .Must(x => x.StartsWith('#')).WithMessage("The format should be a valid html color and start with #") + .When(x => x.BannerTop is not null); + + RuleFor(x => x.BannerBottom) + .MinimumLength(4).WithMessage("The minimum value should be in the format #444") + .MaximumLength(9).WithMessage("The maximum value should be in the format #11223344") + .Must(x => x.StartsWith('#')).WithMessage("The format should be a valid html color and start with #") + .When(x => x.BannerBottom is not null); + + RuleFor(x => x.Accent) + .MinimumLength(4).WithMessage("The minimum value should be in the format #444") + .MaximumLength(9).WithMessage("The maximum value should be in the format #11223344") + .Must(x => x.StartsWith('#')).WithMessage("The format should be a valid html color and start with #") + .When(x => x.Accent is not null); + + RuleFor(x => x.Menu) + .MinimumLength(4).WithMessage("The minimum value should be in the format #444") + .MaximumLength(9).WithMessage("The maximum value should be in the format #11223344") + .Must(x => x.StartsWith('#')).WithMessage("The format should be a valid html color and start with #") + .When(x => x.Menu is not null); } } @@ -57,7 +52,9 @@ public class ChangeColorsHandler( Options(o => o.WithTags("Creators")); } - public override async Task HandleAsync(ChangeColorsRequest request, CancellationToken ct) + public override async Task HandleAsync( + ChangeColorsRequest request, + CancellationToken ct) { var creator = await context .Creators From 1fc6ddaf8dcfd701ff7dc62ac3e273cb31185f47 Mon Sep 17 00:00:00 2001 From: Jonathan Bourdon Date: Wed, 4 Sep 2024 15:28:07 -0400 Subject: [PATCH 187/229] Adds external urls to create content --- .../Contents/Handlers/CreateContent.cs | 21 ++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/src/Web/Features/Contents/Handlers/CreateContent.cs b/src/Web/Features/Contents/Handlers/CreateContent.cs index 8d01e5c..cd8934a 100644 --- a/src/Web/Features/Contents/Handlers/CreateContent.cs +++ b/src/Web/Features/Contents/Handlers/CreateContent.cs @@ -13,7 +13,8 @@ public record PostContentRequest( Guid CreatorId, string Title, string Description, - IFormFileCollection? Files); + IFormFileCollection? Files, + string[]? ExternalUrls); [PublicAPI] public sealed class PostContentRequestValidator : Validator @@ -35,6 +36,10 @@ public sealed class PostContentRequestValidator : Validator RuleFor(r => r.Description) .NotNull().WithMessage("You should specify the Description") .NotEmpty().WithMessage("You should specify a valid/not empty Description"); + + RuleForEach(r => r.ExternalUrls) + .NotEmpty().WithMessage("External URL cannot be empty") + .Must(url => Uri.IsWellFormedUriString(url, UriKind.Absolute)).WithMessage("External URL is not valid"); } } @@ -61,7 +66,9 @@ public sealed class PostContent( await Parallel.ForEachAsync( req.Files, ct, - async (file, ict) => + async ( + file, + ict) => { try { @@ -79,7 +86,15 @@ public sealed class PostContent( } }); } - + + if (req.ExternalUrls is not null) + { + foreach (var externalUrl in req.ExternalUrls) + { + urls.Add(externalUrl); + } + } + await context.Contents.AddAsync( new Content { From 6dc83ff9bd6695db54bd558c155419480c9be066 Mon Sep 17 00:00:00 2001 From: Jonathan Bourdon Date: Wed, 4 Sep 2024 22:08:02 -0400 Subject: [PATCH 188/229] Ensure creator related blobs are stored in the creator container --- src/Application/AzureBlobStorage/Constants/ContainerNames.cs | 4 ++-- src/Web/Features/Contents/Handlers/ChangeBanner.cs | 3 +-- src/Web/Features/Contents/Handlers/ChangeLogo.cs | 2 +- src/Web/Features/Contents/Handlers/CreateContent.cs | 3 +-- src/Web/Features/Users/Handlers/ChangeAddress.cs | 1 - src/Web/Features/Users/Handlers/ChangeEmail.cs | 2 +- src/Web/Features/Users/Handlers/ChangePhone.cs | 2 +- 7 files changed, 7 insertions(+), 10 deletions(-) diff --git a/src/Application/AzureBlobStorage/Constants/ContainerNames.cs b/src/Application/AzureBlobStorage/Constants/ContainerNames.cs index 1f49c7e..039a27d 100644 --- a/src/Application/AzureBlobStorage/Constants/ContainerNames.cs +++ b/src/Application/AzureBlobStorage/Constants/ContainerNames.cs @@ -2,6 +2,6 @@ public static class ContainerNames { - public static string Users = "users"; - public static string Creators = "creators"; + public const string Users = "users"; + public const string Creators = "creators"; } diff --git a/src/Web/Features/Contents/Handlers/ChangeBanner.cs b/src/Web/Features/Contents/Handlers/ChangeBanner.cs index d33e72a..c13aa95 100644 --- a/src/Web/Features/Contents/Handlers/ChangeBanner.cs +++ b/src/Web/Features/Contents/Handlers/ChangeBanner.cs @@ -43,9 +43,8 @@ public class ChangeBannerHandler( return; } - // TODO: this upload should be done to the Creators container var blobUrl = await blobStorage.UploadFileAsync( - ContainerNames.Users, + ContainerNames.Creators, $"{request.CreatorId}/{SubDirectoryNames.Profile}/{CommonFileNames.BannerPicture}", request.File.OpenReadStream(), request.File.ContentType, diff --git a/src/Web/Features/Contents/Handlers/ChangeLogo.cs b/src/Web/Features/Contents/Handlers/ChangeLogo.cs index 656bf62..0caf367 100644 --- a/src/Web/Features/Contents/Handlers/ChangeLogo.cs +++ b/src/Web/Features/Contents/Handlers/ChangeLogo.cs @@ -56,7 +56,7 @@ public class ChangeLogoHandler( // TODO: this upload should be done to the Creators container var blobUrl = await blobStorage.UploadFileAsync( - ContainerNames.Users, + ContainerNames.Creators, $"{request.CreatorId}/{SubDirectoryNames.Profile}/{CommonFileNames.ProfilePicture}", request.File.OpenReadStream(), request.File.ContentType, diff --git a/src/Web/Features/Contents/Handlers/CreateContent.cs b/src/Web/Features/Contents/Handlers/CreateContent.cs index cd8934a..3a0dd6f 100644 --- a/src/Web/Features/Contents/Handlers/CreateContent.cs +++ b/src/Web/Features/Contents/Handlers/CreateContent.cs @@ -138,9 +138,8 @@ public sealed class PostContent( IFormFile file, CancellationToken ct = default) { - // TODO: I would like us to use ContainerNames.Creators but it seems we are missing configurations @jbourdon var url = await blobStorage.UploadFileAsync( - ContainerNames.Users, + ContainerNames.Creators, $"{creatorId}/{SubDirectoryNames.Contents}/{contentId}/{file.FileName}", file.OpenReadStream(), file.ContentType, diff --git a/src/Web/Features/Users/Handlers/ChangeAddress.cs b/src/Web/Features/Users/Handlers/ChangeAddress.cs index b139f44..7eea146 100644 --- a/src/Web/Features/Users/Handlers/ChangeAddress.cs +++ b/src/Web/Features/Users/Handlers/ChangeAddress.cs @@ -31,7 +31,6 @@ public class ChangeAddressHandler( } user.Address = request.Address; - // TODO: check to see if identity resets the email-validated flag - @jonathan var result = await userManager.UpdateAsync(user); diff --git a/src/Web/Features/Users/Handlers/ChangeEmail.cs b/src/Web/Features/Users/Handlers/ChangeEmail.cs index 8f7c844..9af2864 100644 --- a/src/Web/Features/Users/Handlers/ChangeEmail.cs +++ b/src/Web/Features/Users/Handlers/ChangeEmail.cs @@ -31,8 +31,8 @@ public class ChangeEmailHandler( } user.Email = request.Email; - // TODO: check to see if identity resets the email-validated flag - @jonathan + // TODO: check to see if identity resets the `email confirmed` flag - @jonathan var result = await userManager.UpdateAsync(user); if (result.Succeeded) diff --git a/src/Web/Features/Users/Handlers/ChangePhone.cs b/src/Web/Features/Users/Handlers/ChangePhone.cs index 8e7a91f..4341ff2 100644 --- a/src/Web/Features/Users/Handlers/ChangePhone.cs +++ b/src/Web/Features/Users/Handlers/ChangePhone.cs @@ -31,7 +31,7 @@ public class ChangePhoneHandler( } user.PhoneNumber = request.PhoneNumber; - // TODO: check to see if identity resets the email-validated flag - @jonathan + // TODO: check to see if identity resets the `phone confirmed` flag - @jonathan var result = await userManager.UpdateAsync(user); From 646e5e66b4ad11c4018c20bd2f8f0596d3023d02 Mon Sep 17 00:00:00 2001 From: Dominic Villemure Date: Sat, 7 Sep 2024 10:55:46 -0400 Subject: [PATCH 189/229] Small fix on user creation --- src/Infrastructure/Identity/IdentityService.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Infrastructure/Identity/IdentityService.cs b/src/Infrastructure/Identity/IdentityService.cs index 6cf9a0f..6195a70 100644 --- a/src/Infrastructure/Identity/IdentityService.cs +++ b/src/Infrastructure/Identity/IdentityService.cs @@ -79,6 +79,11 @@ public class IdentityService( var response = await userManager.CreateAsync(applicationUser, password); + if (!response.Succeeded) + { + throw new BadHttpRequestException(response.Errors.First().Description); + } + var result = new Result(applicationUser.Id, response.Succeeded, response.ToApplicationResult().Errors); return result; From e482a0726f2c0e5e0015aa47087ab320d854d3f8 Mon Sep 17 00:00:00 2001 From: Jonathan Bourdon Date: Sun, 22 Sep 2024 03:10:00 -0400 Subject: [PATCH 190/229] Remove creator's about, adds title. Remove extra content properties. Change creator's colors to materials palette. --- .../Contents/Data/ContentDbContext.cs | 4 - src/Web/Features/Contents/Data/Creator.cs | 22 +- .../Contents/Handlers/ChangeColors.cs | 78 +++-- .../{ChangeAbout.cs => ChangeTitle.cs} | 17 +- .../Contents/Handlers/CreateContent.cs | 2 - .../Features/Contents/Handlers/GetContent.cs | 2 - .../Contents/Handlers/GetContentsByCreator.cs | 2 - .../Contents/Handlers/GetCreatorByAlias.cs | 2 +- .../Contents/Handlers/GetFeaturedContents.cs | 2 - .../Contents/Handlers/GetFollowedContents.cs | 2 - .../Contents/Handlers/Models/ContentModel.cs | 2 - .../Contents/Handlers/Models/CreatorModel.cs | 2 +- ...9045548_UseMeterialColorSchema.Designer.cs | 320 +++++++++++++++++ .../20240919045548_UseMeterialColorSchema.cs | 144 ++++++++ ...919051151_NoMoreOptionalColors.Designer.cs | 330 ++++++++++++++++++ .../20240919051151_NoMoreOptionalColors.cs | 258 ++++++++++++++ ...22064815_RemovesAboutAddsTitle.Designer.cs | 310 ++++++++++++++++ .../20240922064815_RemovesAboutAddsTitle.cs | 43 +++ .../ContentDbContextModelSnapshot.cs | 70 ++-- src/Web/TestDataSeeder.cs | 171 +++++---- src/Web/Web.http | 26 +- 21 files changed, 1656 insertions(+), 153 deletions(-) rename src/Web/Features/Contents/Handlers/{ChangeAbout.cs => ChangeTitle.cs} (62%) create mode 100644 src/Web/Features/Contents/Migrations/20240919045548_UseMeterialColorSchema.Designer.cs create mode 100644 src/Web/Features/Contents/Migrations/20240919045548_UseMeterialColorSchema.cs create mode 100644 src/Web/Features/Contents/Migrations/20240919051151_NoMoreOptionalColors.Designer.cs create mode 100644 src/Web/Features/Contents/Migrations/20240919051151_NoMoreOptionalColors.cs create mode 100644 src/Web/Features/Contents/Migrations/20240922064815_RemovesAboutAddsTitle.Designer.cs create mode 100644 src/Web/Features/Contents/Migrations/20240922064815_RemovesAboutAddsTitle.cs diff --git a/src/Web/Features/Contents/Data/ContentDbContext.cs b/src/Web/Features/Contents/Data/ContentDbContext.cs index 478c576..11edff0 100644 --- a/src/Web/Features/Contents/Data/ContentDbContext.cs +++ b/src/Web/Features/Contents/Data/ContentDbContext.cs @@ -43,10 +43,6 @@ public class ContentDbContext( .Entity() .HasKey(s => new { s.CreatedBy, s.CreatorId }); - modelBuilder - .Entity() - .OwnsOne(x => x.About); - modelBuilder .Entity() .OwnsOne(x => x.Socials) diff --git a/src/Web/Features/Contents/Data/Creator.cs b/src/Web/Features/Contents/Data/Creator.cs index 75f5c50..c916cfb 100644 --- a/src/Web/Features/Contents/Data/Creator.cs +++ b/src/Web/Features/Contents/Data/Creator.cs @@ -9,24 +9,24 @@ public class Creator public DateTimeOffset CreatedAt { get; init; } [MaxLength(255)] public string Name { get; set; } = null!; - public About About { get; set; } = new(); + [MaxLength(255)] public string? Title { get; set; } public Socials Socials { get; set; } = new(); public Colors Colors { get; set; } = new(); public Images Images { get; set; } = new(); } -public class About -{ - [MaxLength(255)] public string? Title { get; set; } - [MaxLength(2048)] public string? Description { get; set; } -} - public class Colors { - [MaxLength(9)] public string? BannerTop { get; set; } - [MaxLength(9)] public string? BannerBottom { get; set; } - [MaxLength(9)] public string? Accent { get; set; } - [MaxLength(9)] public string? Menu { get; set; } + [MaxLength(9)] public string Primary { get; set; } = null!; + [MaxLength(9)] public string Secondary { get; set; } = null!; + [MaxLength(9)] public string Background { get; set; } = null!; + [MaxLength(9)] public string Surface { get; set; } = null!; + [MaxLength(9)] public string Error { get; set; } = null!; + [MaxLength(9)] public string OnPrimary { get; set; } = null!; + [MaxLength(9)] public string OnSecondary { get; set; } = null!; + [MaxLength(9)] public string OnBackground { get; set; } = null!; + [MaxLength(9)] public string OnSurface { get; set; } = null!; + [MaxLength(9)] public string OnError { get; set; } = null!; } public class Socials diff --git a/src/Web/Features/Contents/Handlers/ChangeColors.cs b/src/Web/Features/Contents/Handlers/ChangeColors.cs index db88aa3..0aa63d3 100644 --- a/src/Web/Features/Contents/Handlers/ChangeColors.cs +++ b/src/Web/Features/Contents/Handlers/ChangeColors.cs @@ -5,10 +5,16 @@ namespace Hutopy.Web.Features.Contents.Handlers; [PublicAPI] public record ChangeColorsRequest( Guid CreatorId, - string? BannerTop, - string? BannerBottom, - string? Accent, - string? Menu); + string Primary, + string Secondary, + string Background, + string Surface, + string Error, + string OnPrimary, + string OnSecondary, + string OnBackground, + string OnSurface, + string OnError); [PublicAPI] public sealed class ChangeColorsRequestValidator @@ -16,29 +22,55 @@ public sealed class ChangeColorsRequestValidator { public ChangeColorsRequestValidator() { - RuleFor(x => x.BannerTop) + RuleFor(x => x.Primary) .MinimumLength(4).WithMessage("The minimum value should be in the format #444") .MaximumLength(9).WithMessage("The maximum value should be in the format #11223344") - .Must(x => x.StartsWith('#')).WithMessage("The format should be a valid html color and start with #") - .When(x => x.BannerTop is not null); + .Must(x => x.StartsWith('#')).WithMessage("The format should be a valid html color and start with #"); - RuleFor(x => x.BannerBottom) + RuleFor(x => x.Secondary) .MinimumLength(4).WithMessage("The minimum value should be in the format #444") .MaximumLength(9).WithMessage("The maximum value should be in the format #11223344") - .Must(x => x.StartsWith('#')).WithMessage("The format should be a valid html color and start with #") - .When(x => x.BannerBottom is not null); + .Must(x => x.StartsWith('#')).WithMessage("The format should be a valid html color and start with #"); - RuleFor(x => x.Accent) + RuleFor(x => x.Background) .MinimumLength(4).WithMessage("The minimum value should be in the format #444") .MaximumLength(9).WithMessage("The maximum value should be in the format #11223344") - .Must(x => x.StartsWith('#')).WithMessage("The format should be a valid html color and start with #") - .When(x => x.Accent is not null); + .Must(x => x.StartsWith('#')).WithMessage("The format should be a valid html color and start with #"); - RuleFor(x => x.Menu) + RuleFor(x => x.Surface) .MinimumLength(4).WithMessage("The minimum value should be in the format #444") .MaximumLength(9).WithMessage("The maximum value should be in the format #11223344") - .Must(x => x.StartsWith('#')).WithMessage("The format should be a valid html color and start with #") - .When(x => x.Menu is not null); + .Must(x => x.StartsWith('#')).WithMessage("The format should be a valid html color and start with #"); + + RuleFor(x => x.Error) + .MinimumLength(4).WithMessage("The minimum value should be in the format #444") + .MaximumLength(9).WithMessage("The maximum value should be in the format #11223344") + .Must(x => x.StartsWith('#')).WithMessage("The format should be a valid html color and start with #"); + + RuleFor(x => x.OnPrimary) + .MinimumLength(4).WithMessage("The minimum value should be in the format #444") + .MaximumLength(9).WithMessage("The maximum value should be in the format #11223344") + .Must(x => x.StartsWith('#')).WithMessage("The format should be a valid html color and start with #"); + + RuleFor(x => x.OnSecondary) + .MinimumLength(4).WithMessage("The minimum value should be in the format #444") + .MaximumLength(9).WithMessage("The maximum value should be in the format #11223344") + .Must(x => x.StartsWith('#')).WithMessage("The format should be a valid html color and start with #"); + + RuleFor(x => x.OnBackground) + .MinimumLength(4).WithMessage("The minimum value should be in the format #444") + .MaximumLength(9).WithMessage("The maximum value should be in the format #11223344") + .Must(x => x.StartsWith('#')).WithMessage("The format should be a valid html color and start with #"); + + RuleFor(x => x.OnSurface) + .MinimumLength(4).WithMessage("The minimum value should be in the format #444") + .MaximumLength(9).WithMessage("The maximum value should be in the format #11223344") + .Must(x => x.StartsWith('#')).WithMessage("The format should be a valid html color and start with #"); + + RuleFor(x => x.OnError) + .MinimumLength(4).WithMessage("The minimum value should be in the format #444") + .MaximumLength(9).WithMessage("The maximum value should be in the format #11223344") + .Must(x => x.StartsWith('#')).WithMessage("The format should be a valid html color and start with #"); } } @@ -63,10 +95,16 @@ public class ChangeColorsHandler( c => c.Id == request.CreatorId, cancellationToken: ct); - creator.Colors.BannerTop = request.BannerTop; - creator.Colors.BannerBottom = request.BannerBottom; - creator.Colors.Accent = request.Accent; - creator.Colors.Menu = request.Menu; + creator.Colors.Primary = request.Primary; + creator.Colors.Secondary = request.Secondary; + creator.Colors.Background = request.Background; + creator.Colors.Surface = request.Surface; + creator.Colors.Error = request.Error; + creator.Colors.OnPrimary = request.OnPrimary; + creator.Colors.OnSecondary = request.OnSecondary; + creator.Colors.OnBackground = request.OnBackground; + creator.Colors.OnSurface = request.OnSurface; + creator.Colors.OnError = request.OnError; await context.SaveChangesAsync(ct); diff --git a/src/Web/Features/Contents/Handlers/ChangeAbout.cs b/src/Web/Features/Contents/Handlers/ChangeTitle.cs similarity index 62% rename from src/Web/Features/Contents/Handlers/ChangeAbout.cs rename to src/Web/Features/Contents/Handlers/ChangeTitle.cs index 662b4e6..16a357a 100644 --- a/src/Web/Features/Contents/Handlers/ChangeAbout.cs +++ b/src/Web/Features/Contents/Handlers/ChangeTitle.cs @@ -3,35 +3,32 @@ namespace Hutopy.Web.Features.Contents.Handlers; [PublicAPI] -public record ChangeAboutRequest( +public record ChangeTitleRequest( Guid CreatorId, - string? Title, - string? Description); + string? Title); [PublicAPI] -public class ChangeAboutHandler( +public class ChangeTitleHandler( ContentDbContext context) - : Endpoint + : Endpoint { public override void Configure() { - Post("/api/creators/{CreatorId}/about"); + Post("/api/creators/{CreatorId}/title"); Options(o => o.WithTags("Creators")); } public override async Task HandleAsync( - ChangeAboutRequest request, + ChangeTitleRequest request, CancellationToken ct) { var creator = await context .Creators - .Include(c => c.About) .SingleAsync( c => c.Id == request.CreatorId, cancellationToken: ct); - creator.About.Title = request.Title; - creator.About.Description = request.Description; + creator.Title = request.Title; await context.SaveChangesAsync(ct); diff --git a/src/Web/Features/Contents/Handlers/CreateContent.cs b/src/Web/Features/Contents/Handlers/CreateContent.cs index 3a0dd6f..e98f7f1 100644 --- a/src/Web/Features/Contents/Handlers/CreateContent.cs +++ b/src/Web/Features/Contents/Handlers/CreateContent.cs @@ -117,8 +117,6 @@ public sealed class PostContent( CreatedByName = c.Creator!.Name, CreatedByPortraitUrl = c.Creator.Images.Logo, CreatedAt = c.CreatedAt, - ColorMenu = c.Creator.Colors.Menu, - ColorAccent = c.Creator.Colors.Accent, DeletedBy = c.DeletedBy, DeletedAt = c.DeletedAt, Title = c.Title, diff --git a/src/Web/Features/Contents/Handlers/GetContent.cs b/src/Web/Features/Contents/Handlers/GetContent.cs index fc89f32..fddba07 100644 --- a/src/Web/Features/Contents/Handlers/GetContent.cs +++ b/src/Web/Features/Contents/Handlers/GetContent.cs @@ -35,8 +35,6 @@ public class GetContent( CreatedByName = c.Creator!.Name, CreatedByPortraitUrl = c.Creator.Images.Logo, CreatedAt = c.CreatedAt, - ColorMenu = c.Creator.Colors.Menu, - ColorAccent = c.Creator.Colors.Accent, DeletedBy = c.DeletedBy, DeletedAt = c.DeletedAt, Title = c.Title, diff --git a/src/Web/Features/Contents/Handlers/GetContentsByCreator.cs b/src/Web/Features/Contents/Handlers/GetContentsByCreator.cs index 33ce7ae..9689808 100644 --- a/src/Web/Features/Contents/Handlers/GetContentsByCreator.cs +++ b/src/Web/Features/Contents/Handlers/GetContentsByCreator.cs @@ -46,8 +46,6 @@ public class GetContentsByCreatorHandler( CreatedByName = c.Creator!.Name, CreatedByPortraitUrl = c.Creator.Images.Logo, CreatedAt = c.CreatedAt, - ColorMenu = c.Creator.Colors.Menu, - ColorAccent = c.Creator.Colors.Accent, DeletedBy = c.DeletedBy, DeletedAt = c.DeletedAt, Title = c.Title, diff --git a/src/Web/Features/Contents/Handlers/GetCreatorByAlias.cs b/src/Web/Features/Contents/Handlers/GetCreatorByAlias.cs index 9d7c3f3..2a2b161 100644 --- a/src/Web/Features/Contents/Handlers/GetCreatorByAlias.cs +++ b/src/Web/Features/Contents/Handlers/GetCreatorByAlias.cs @@ -59,7 +59,7 @@ public class GetCreatorByAliasHandler( creator.CreatedBy, creator.CreatedAt, creator.Name, - creator.About, + creator.Title, creator.Socials, creator.Colors, creator.Images, diff --git a/src/Web/Features/Contents/Handlers/GetFeaturedContents.cs b/src/Web/Features/Contents/Handlers/GetFeaturedContents.cs index 6df55ad..0929503 100644 --- a/src/Web/Features/Contents/Handlers/GetFeaturedContents.cs +++ b/src/Web/Features/Contents/Handlers/GetFeaturedContents.cs @@ -45,8 +45,6 @@ public class GetFeaturedContentsHandler( CreatedByName = c.Creator!.Name, CreatedByPortraitUrl = c.Creator.Images.Logo, CreatedAt = c.CreatedAt, - ColorMenu = c.Creator.Colors.Menu, - ColorAccent = c.Creator.Colors.Accent, DeletedBy = c.DeletedBy, DeletedAt = c.DeletedAt, Title = c.Title, diff --git a/src/Web/Features/Contents/Handlers/GetFollowedContents.cs b/src/Web/Features/Contents/Handlers/GetFollowedContents.cs index aa80309..39de093 100644 --- a/src/Web/Features/Contents/Handlers/GetFollowedContents.cs +++ b/src/Web/Features/Contents/Handlers/GetFollowedContents.cs @@ -55,8 +55,6 @@ public class GetFollowedContentsHandler( CreatedByName = c.Creator!.Name, CreatedByPortraitUrl = c.Creator.Images.Logo, CreatedAt = c.CreatedAt, - ColorMenu = c.Creator.Colors.Menu, - ColorAccent = c.Creator.Colors.Accent, DeletedBy = c.DeletedBy, DeletedAt = c.DeletedAt, Title = c.Title, diff --git a/src/Web/Features/Contents/Handlers/Models/ContentModel.cs b/src/Web/Features/Contents/Handlers/Models/ContentModel.cs index d317529..d91b23f 100644 --- a/src/Web/Features/Contents/Handlers/Models/ContentModel.cs +++ b/src/Web/Features/Contents/Handlers/Models/ContentModel.cs @@ -7,8 +7,6 @@ public class ContentModel public required Guid CreatedBy { get; init; } public required string CreatedByName { get; init; } public required string? CreatedByPortraitUrl { get; init; } - public required string? ColorMenu { get; init; } - public required string? ColorAccent { get; init; } public required DateTimeOffset CreatedAt { get; init; } public Guid? DeletedBy { get; init; } public DateTimeOffset? DeletedAt { get; init; } diff --git a/src/Web/Features/Contents/Handlers/Models/CreatorModel.cs b/src/Web/Features/Contents/Handlers/Models/CreatorModel.cs index 5502231..83b7bd6 100644 --- a/src/Web/Features/Contents/Handlers/Models/CreatorModel.cs +++ b/src/Web/Features/Contents/Handlers/Models/CreatorModel.cs @@ -8,7 +8,7 @@ public record struct CreatorModel( Guid CreatedBy, DateTimeOffset CreatedAt, string Name, - About About, + string? Title, Socials Socials, Colors Colors, Images Images, diff --git a/src/Web/Features/Contents/Migrations/20240919045548_UseMeterialColorSchema.Designer.cs b/src/Web/Features/Contents/Migrations/20240919045548_UseMeterialColorSchema.Designer.cs new file mode 100644 index 0000000..2a6f961 --- /dev/null +++ b/src/Web/Features/Contents/Migrations/20240919045548_UseMeterialColorSchema.Designer.cs @@ -0,0 +1,320 @@ +// +using System; +using Hutopy.Web.Features.Contents.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace Hutopy.Web.Features.Contents.Migrations +{ + [DbContext(typeof(ContentDbContext))] + [Migration("20240919045548_UseMeterialColorSchema")] + partial class UseMeterialColorSchema + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasDefaultSchema("Content") + .HasAnnotation("ProductVersion", "8.0.4") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("Hutopy.Web.Features.Contents.Data.Content", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("CURRENT_TIMESTAMP"); + + b.Property("CreatedBy") + .HasColumnType("uuid"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("DeletedBy") + .HasColumnType("uuid"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(2048) + .HasColumnType("character varying(2048)"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("Urls") + .HasColumnType("text[]"); + + b.HasKey("Id"); + + b.HasIndex("CreatedBy"); + + b.ToTable("Contents", "Content"); + }); + + modelBuilder.Entity("Hutopy.Web.Features.Contents.Data.Creator", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("uuid"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.HasKey("Id"); + + b.ToTable("Creators", "Content"); + }); + + modelBuilder.Entity("Hutopy.Web.Features.Contents.Data.Subscription", b => + { + b.Property("CreatedBy") + .HasColumnType("uuid"); + + b.Property("CreatorId") + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("CreatedBy", "CreatorId"); + + b.HasIndex("CreatorId"); + + b.ToTable("Subscriptions", "Content"); + }); + + modelBuilder.Entity("Hutopy.Web.Features.Contents.Data.Content", b => + { + b.HasOne("Hutopy.Web.Features.Contents.Data.Creator", "Creator") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.OwnsMany("Hutopy.Web.Features.Contents.Data.ContentReaction", "Reactions", b1 => + { + b1.Property("ContentId") + .HasColumnType("uuid"); + + b1.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b1.Property("Id")); + + b1.Property("Reaction") + .HasColumnType("integer"); + + b1.Property("UserId") + .HasColumnType("uuid"); + + b1.Property("UserName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b1.HasKey("ContentId", "Id"); + + b1.ToTable("ContentReactions", "Content"); + + b1.WithOwner() + .HasForeignKey("ContentId"); + }); + + b.Navigation("Creator"); + + b.Navigation("Reactions"); + }); + + modelBuilder.Entity("Hutopy.Web.Features.Contents.Data.Creator", b => + { + b.OwnsOne("Hutopy.Web.Features.Contents.Data.About", "About", b1 => + { + b1.Property("CreatorId") + .HasColumnType("uuid"); + + b1.Property("Description") + .HasMaxLength(2048) + .HasColumnType("character varying(2048)"); + + b1.Property("Title") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.HasKey("CreatorId"); + + b1.ToTable("Creators", "Content"); + + b1.WithOwner() + .HasForeignKey("CreatorId"); + }); + + b.OwnsOne("Hutopy.Web.Features.Contents.Data.Colors", "Colors", b1 => + { + b1.Property("CreatorId") + .HasColumnType("uuid"); + + b1.Property("Background") + .HasMaxLength(9) + .HasColumnType("character varying(9)"); + + b1.Property("Error") + .HasMaxLength(9) + .HasColumnType("character varying(9)"); + + b1.Property("OnBackground") + .HasMaxLength(9) + .HasColumnType("character varying(9)"); + + b1.Property("OnError") + .HasMaxLength(9) + .HasColumnType("character varying(9)"); + + b1.Property("OnPrimary") + .HasMaxLength(9) + .HasColumnType("character varying(9)"); + + b1.Property("OnSecondary") + .HasMaxLength(9) + .HasColumnType("character varying(9)"); + + b1.Property("OnSurface") + .HasMaxLength(9) + .HasColumnType("character varying(9)"); + + b1.Property("Primary") + .HasMaxLength(9) + .HasColumnType("character varying(9)"); + + b1.Property("Secondary") + .HasMaxLength(9) + .HasColumnType("character varying(9)"); + + b1.Property("Surface") + .HasMaxLength(9) + .HasColumnType("character varying(9)"); + + b1.HasKey("CreatorId"); + + b1.ToTable("Colors", "Content"); + + b1.WithOwner() + .HasForeignKey("CreatorId"); + }); + + b.OwnsOne("Hutopy.Web.Features.Contents.Data.Images", "Images", b1 => + { + b1.Property("CreatorId") + .HasColumnType("uuid"); + + b1.Property("Banner") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.Property("Logo") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.HasKey("CreatorId"); + + b1.ToTable("Images", "Content"); + + b1.WithOwner() + .HasForeignKey("CreatorId"); + }); + + b.OwnsOne("Hutopy.Web.Features.Contents.Data.Socials", "Socials", b1 => + { + b1.Property("CreatorId") + .HasColumnType("uuid"); + + b1.Property("FacebookUrl") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.Property("InstagramUrl") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.Property("LinkedInUrl") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.Property("RedditUrl") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.Property("TikTokUrl") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.Property("WebsiteUrl") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.Property("XUrl") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.Property("YoutubeUrl") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.HasKey("CreatorId"); + + b1.ToTable("Socials", "Content"); + + b1.WithOwner() + .HasForeignKey("CreatorId"); + }); + + b.Navigation("About") + .IsRequired(); + + b.Navigation("Colors") + .IsRequired(); + + b.Navigation("Images") + .IsRequired(); + + b.Navigation("Socials") + .IsRequired(); + }); + + modelBuilder.Entity("Hutopy.Web.Features.Contents.Data.Subscription", b => + { + b.HasOne("Hutopy.Web.Features.Contents.Data.Creator", "Creator") + .WithMany() + .HasForeignKey("CreatorId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Creator"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Web/Features/Contents/Migrations/20240919045548_UseMeterialColorSchema.cs b/src/Web/Features/Contents/Migrations/20240919045548_UseMeterialColorSchema.cs new file mode 100644 index 0000000..400104e --- /dev/null +++ b/src/Web/Features/Contents/Migrations/20240919045548_UseMeterialColorSchema.cs @@ -0,0 +1,144 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Hutopy.Web.Features.Contents.Migrations +{ + /// + public partial class UseMeterialColorSchema : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.RenameColumn( + name: "Menu", + schema: "Content", + table: "Colors", + newName: "Surface"); + + migrationBuilder.RenameColumn( + name: "BannerTop", + schema: "Content", + table: "Colors", + newName: "Secondary"); + + migrationBuilder.RenameColumn( + name: "BannerBottom", + schema: "Content", + table: "Colors", + newName: "Primary"); + + migrationBuilder.RenameColumn( + name: "Accent", + schema: "Content", + table: "Colors", + newName: "OnSurface"); + + migrationBuilder.AddColumn( + name: "Background", + schema: "Content", + table: "Colors", + type: "character varying(9)", + maxLength: 9, + nullable: true); + + migrationBuilder.AddColumn( + name: "Error", + schema: "Content", + table: "Colors", + type: "character varying(9)", + maxLength: 9, + nullable: true); + + migrationBuilder.AddColumn( + name: "OnBackground", + schema: "Content", + table: "Colors", + type: "character varying(9)", + maxLength: 9, + nullable: true); + + migrationBuilder.AddColumn( + name: "OnError", + schema: "Content", + table: "Colors", + type: "character varying(9)", + maxLength: 9, + nullable: true); + + migrationBuilder.AddColumn( + name: "OnPrimary", + schema: "Content", + table: "Colors", + type: "character varying(9)", + maxLength: 9, + nullable: true); + + migrationBuilder.AddColumn( + name: "OnSecondary", + schema: "Content", + table: "Colors", + type: "character varying(9)", + maxLength: 9, + nullable: true); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "Background", + schema: "Content", + table: "Colors"); + + migrationBuilder.DropColumn( + name: "Error", + schema: "Content", + table: "Colors"); + + migrationBuilder.DropColumn( + name: "OnBackground", + schema: "Content", + table: "Colors"); + + migrationBuilder.DropColumn( + name: "OnError", + schema: "Content", + table: "Colors"); + + migrationBuilder.DropColumn( + name: "OnPrimary", + schema: "Content", + table: "Colors"); + + migrationBuilder.DropColumn( + name: "OnSecondary", + schema: "Content", + table: "Colors"); + + migrationBuilder.RenameColumn( + name: "Surface", + schema: "Content", + table: "Colors", + newName: "Menu"); + + migrationBuilder.RenameColumn( + name: "Secondary", + schema: "Content", + table: "Colors", + newName: "BannerTop"); + + migrationBuilder.RenameColumn( + name: "Primary", + schema: "Content", + table: "Colors", + newName: "BannerBottom"); + + migrationBuilder.RenameColumn( + name: "OnSurface", + schema: "Content", + table: "Colors", + newName: "Accent"); + } + } +} diff --git a/src/Web/Features/Contents/Migrations/20240919051151_NoMoreOptionalColors.Designer.cs b/src/Web/Features/Contents/Migrations/20240919051151_NoMoreOptionalColors.Designer.cs new file mode 100644 index 0000000..5793a13 --- /dev/null +++ b/src/Web/Features/Contents/Migrations/20240919051151_NoMoreOptionalColors.Designer.cs @@ -0,0 +1,330 @@ +// +using System; +using Hutopy.Web.Features.Contents.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace Hutopy.Web.Features.Contents.Migrations +{ + [DbContext(typeof(ContentDbContext))] + [Migration("20240919051151_NoMoreOptionalColors")] + partial class NoMoreOptionalColors + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasDefaultSchema("Content") + .HasAnnotation("ProductVersion", "8.0.4") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("Hutopy.Web.Features.Contents.Data.Content", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("CURRENT_TIMESTAMP"); + + b.Property("CreatedBy") + .HasColumnType("uuid"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("DeletedBy") + .HasColumnType("uuid"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(2048) + .HasColumnType("character varying(2048)"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("Urls") + .HasColumnType("text[]"); + + b.HasKey("Id"); + + b.HasIndex("CreatedBy"); + + b.ToTable("Contents", "Content"); + }); + + modelBuilder.Entity("Hutopy.Web.Features.Contents.Data.Creator", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("uuid"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.HasKey("Id"); + + b.ToTable("Creators", "Content"); + }); + + modelBuilder.Entity("Hutopy.Web.Features.Contents.Data.Subscription", b => + { + b.Property("CreatedBy") + .HasColumnType("uuid"); + + b.Property("CreatorId") + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("CreatedBy", "CreatorId"); + + b.HasIndex("CreatorId"); + + b.ToTable("Subscriptions", "Content"); + }); + + modelBuilder.Entity("Hutopy.Web.Features.Contents.Data.Content", b => + { + b.HasOne("Hutopy.Web.Features.Contents.Data.Creator", "Creator") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.OwnsMany("Hutopy.Web.Features.Contents.Data.ContentReaction", "Reactions", b1 => + { + b1.Property("ContentId") + .HasColumnType("uuid"); + + b1.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b1.Property("Id")); + + b1.Property("Reaction") + .HasColumnType("integer"); + + b1.Property("UserId") + .HasColumnType("uuid"); + + b1.Property("UserName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b1.HasKey("ContentId", "Id"); + + b1.ToTable("ContentReactions", "Content"); + + b1.WithOwner() + .HasForeignKey("ContentId"); + }); + + b.Navigation("Creator"); + + b.Navigation("Reactions"); + }); + + modelBuilder.Entity("Hutopy.Web.Features.Contents.Data.Creator", b => + { + b.OwnsOne("Hutopy.Web.Features.Contents.Data.About", "About", b1 => + { + b1.Property("CreatorId") + .HasColumnType("uuid"); + + b1.Property("Description") + .HasMaxLength(2048) + .HasColumnType("character varying(2048)"); + + b1.Property("Title") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.HasKey("CreatorId"); + + b1.ToTable("Creators", "Content"); + + b1.WithOwner() + .HasForeignKey("CreatorId"); + }); + + b.OwnsOne("Hutopy.Web.Features.Contents.Data.Colors", "Colors", b1 => + { + b1.Property("CreatorId") + .HasColumnType("uuid"); + + b1.Property("Background") + .IsRequired() + .HasMaxLength(9) + .HasColumnType("character varying(9)"); + + b1.Property("Error") + .IsRequired() + .HasMaxLength(9) + .HasColumnType("character varying(9)"); + + b1.Property("OnBackground") + .IsRequired() + .HasMaxLength(9) + .HasColumnType("character varying(9)"); + + b1.Property("OnError") + .IsRequired() + .HasMaxLength(9) + .HasColumnType("character varying(9)"); + + b1.Property("OnPrimary") + .IsRequired() + .HasMaxLength(9) + .HasColumnType("character varying(9)"); + + b1.Property("OnSecondary") + .IsRequired() + .HasMaxLength(9) + .HasColumnType("character varying(9)"); + + b1.Property("OnSurface") + .IsRequired() + .HasMaxLength(9) + .HasColumnType("character varying(9)"); + + b1.Property("Primary") + .IsRequired() + .HasMaxLength(9) + .HasColumnType("character varying(9)"); + + b1.Property("Secondary") + .IsRequired() + .HasMaxLength(9) + .HasColumnType("character varying(9)"); + + b1.Property("Surface") + .IsRequired() + .HasMaxLength(9) + .HasColumnType("character varying(9)"); + + b1.HasKey("CreatorId"); + + b1.ToTable("Colors", "Content"); + + b1.WithOwner() + .HasForeignKey("CreatorId"); + }); + + b.OwnsOne("Hutopy.Web.Features.Contents.Data.Images", "Images", b1 => + { + b1.Property("CreatorId") + .HasColumnType("uuid"); + + b1.Property("Banner") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.Property("Logo") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.HasKey("CreatorId"); + + b1.ToTable("Images", "Content"); + + b1.WithOwner() + .HasForeignKey("CreatorId"); + }); + + b.OwnsOne("Hutopy.Web.Features.Contents.Data.Socials", "Socials", b1 => + { + b1.Property("CreatorId") + .HasColumnType("uuid"); + + b1.Property("FacebookUrl") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.Property("InstagramUrl") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.Property("LinkedInUrl") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.Property("RedditUrl") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.Property("TikTokUrl") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.Property("WebsiteUrl") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.Property("XUrl") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.Property("YoutubeUrl") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.HasKey("CreatorId"); + + b1.ToTable("Socials", "Content"); + + b1.WithOwner() + .HasForeignKey("CreatorId"); + }); + + b.Navigation("About") + .IsRequired(); + + b.Navigation("Colors") + .IsRequired(); + + b.Navigation("Images") + .IsRequired(); + + b.Navigation("Socials") + .IsRequired(); + }); + + modelBuilder.Entity("Hutopy.Web.Features.Contents.Data.Subscription", b => + { + b.HasOne("Hutopy.Web.Features.Contents.Data.Creator", "Creator") + .WithMany() + .HasForeignKey("CreatorId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Creator"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Web/Features/Contents/Migrations/20240919051151_NoMoreOptionalColors.cs b/src/Web/Features/Contents/Migrations/20240919051151_NoMoreOptionalColors.cs new file mode 100644 index 0000000..7af839e --- /dev/null +++ b/src/Web/Features/Contents/Migrations/20240919051151_NoMoreOptionalColors.cs @@ -0,0 +1,258 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Hutopy.Web.Features.Contents.Migrations +{ + /// + public partial class NoMoreOptionalColors : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AlterColumn( + name: "Surface", + schema: "Content", + table: "Colors", + type: "character varying(9)", + maxLength: 9, + nullable: false, + defaultValue: "", + oldClrType: typeof(string), + oldType: "character varying(9)", + oldMaxLength: 9, + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Secondary", + schema: "Content", + table: "Colors", + type: "character varying(9)", + maxLength: 9, + nullable: false, + defaultValue: "", + oldClrType: typeof(string), + oldType: "character varying(9)", + oldMaxLength: 9, + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Primary", + schema: "Content", + table: "Colors", + type: "character varying(9)", + maxLength: 9, + nullable: false, + defaultValue: "", + oldClrType: typeof(string), + oldType: "character varying(9)", + oldMaxLength: 9, + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "OnSurface", + schema: "Content", + table: "Colors", + type: "character varying(9)", + maxLength: 9, + nullable: false, + defaultValue: "", + oldClrType: typeof(string), + oldType: "character varying(9)", + oldMaxLength: 9, + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "OnSecondary", + schema: "Content", + table: "Colors", + type: "character varying(9)", + maxLength: 9, + nullable: false, + defaultValue: "", + oldClrType: typeof(string), + oldType: "character varying(9)", + oldMaxLength: 9, + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "OnPrimary", + schema: "Content", + table: "Colors", + type: "character varying(9)", + maxLength: 9, + nullable: false, + defaultValue: "", + oldClrType: typeof(string), + oldType: "character varying(9)", + oldMaxLength: 9, + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "OnError", + schema: "Content", + table: "Colors", + type: "character varying(9)", + maxLength: 9, + nullable: false, + defaultValue: "", + oldClrType: typeof(string), + oldType: "character varying(9)", + oldMaxLength: 9, + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "OnBackground", + schema: "Content", + table: "Colors", + type: "character varying(9)", + maxLength: 9, + nullable: false, + defaultValue: "", + oldClrType: typeof(string), + oldType: "character varying(9)", + oldMaxLength: 9, + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Error", + schema: "Content", + table: "Colors", + type: "character varying(9)", + maxLength: 9, + nullable: false, + defaultValue: "", + oldClrType: typeof(string), + oldType: "character varying(9)", + oldMaxLength: 9, + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Background", + schema: "Content", + table: "Colors", + type: "character varying(9)", + maxLength: 9, + nullable: false, + defaultValue: "", + oldClrType: typeof(string), + oldType: "character varying(9)", + oldMaxLength: 9, + oldNullable: true); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.AlterColumn( + name: "Surface", + schema: "Content", + table: "Colors", + type: "character varying(9)", + maxLength: 9, + nullable: true, + oldClrType: typeof(string), + oldType: "character varying(9)", + oldMaxLength: 9); + + migrationBuilder.AlterColumn( + name: "Secondary", + schema: "Content", + table: "Colors", + type: "character varying(9)", + maxLength: 9, + nullable: true, + oldClrType: typeof(string), + oldType: "character varying(9)", + oldMaxLength: 9); + + migrationBuilder.AlterColumn( + name: "Primary", + schema: "Content", + table: "Colors", + type: "character varying(9)", + maxLength: 9, + nullable: true, + oldClrType: typeof(string), + oldType: "character varying(9)", + oldMaxLength: 9); + + migrationBuilder.AlterColumn( + name: "OnSurface", + schema: "Content", + table: "Colors", + type: "character varying(9)", + maxLength: 9, + nullable: true, + oldClrType: typeof(string), + oldType: "character varying(9)", + oldMaxLength: 9); + + migrationBuilder.AlterColumn( + name: "OnSecondary", + schema: "Content", + table: "Colors", + type: "character varying(9)", + maxLength: 9, + nullable: true, + oldClrType: typeof(string), + oldType: "character varying(9)", + oldMaxLength: 9); + + migrationBuilder.AlterColumn( + name: "OnPrimary", + schema: "Content", + table: "Colors", + type: "character varying(9)", + maxLength: 9, + nullable: true, + oldClrType: typeof(string), + oldType: "character varying(9)", + oldMaxLength: 9); + + migrationBuilder.AlterColumn( + name: "OnError", + schema: "Content", + table: "Colors", + type: "character varying(9)", + maxLength: 9, + nullable: true, + oldClrType: typeof(string), + oldType: "character varying(9)", + oldMaxLength: 9); + + migrationBuilder.AlterColumn( + name: "OnBackground", + schema: "Content", + table: "Colors", + type: "character varying(9)", + maxLength: 9, + nullable: true, + oldClrType: typeof(string), + oldType: "character varying(9)", + oldMaxLength: 9); + + migrationBuilder.AlterColumn( + name: "Error", + schema: "Content", + table: "Colors", + type: "character varying(9)", + maxLength: 9, + nullable: true, + oldClrType: typeof(string), + oldType: "character varying(9)", + oldMaxLength: 9); + + migrationBuilder.AlterColumn( + name: "Background", + schema: "Content", + table: "Colors", + type: "character varying(9)", + maxLength: 9, + nullable: true, + oldClrType: typeof(string), + oldType: "character varying(9)", + oldMaxLength: 9); + } + } +} diff --git a/src/Web/Features/Contents/Migrations/20240922064815_RemovesAboutAddsTitle.Designer.cs b/src/Web/Features/Contents/Migrations/20240922064815_RemovesAboutAddsTitle.Designer.cs new file mode 100644 index 0000000..5a5cb91 --- /dev/null +++ b/src/Web/Features/Contents/Migrations/20240922064815_RemovesAboutAddsTitle.Designer.cs @@ -0,0 +1,310 @@ +// +using System; +using Hutopy.Web.Features.Contents.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace Hutopy.Web.Features.Contents.Migrations +{ + [DbContext(typeof(ContentDbContext))] + [Migration("20240922064815_RemovesAboutAddsTitle")] + partial class RemovesAboutAddsTitle + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasDefaultSchema("Content") + .HasAnnotation("ProductVersion", "8.0.4") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("Hutopy.Web.Features.Contents.Data.Content", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("CURRENT_TIMESTAMP"); + + b.Property("CreatedBy") + .HasColumnType("uuid"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("DeletedBy") + .HasColumnType("uuid"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(2048) + .HasColumnType("character varying(2048)"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("Urls") + .HasColumnType("text[]"); + + b.HasKey("Id"); + + b.HasIndex("CreatedBy"); + + b.ToTable("Contents", "Content"); + }); + + modelBuilder.Entity("Hutopy.Web.Features.Contents.Data.Creator", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("uuid"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("Title") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.HasKey("Id"); + + b.ToTable("Creators", "Content"); + }); + + modelBuilder.Entity("Hutopy.Web.Features.Contents.Data.Subscription", b => + { + b.Property("CreatedBy") + .HasColumnType("uuid"); + + b.Property("CreatorId") + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("CreatedBy", "CreatorId"); + + b.HasIndex("CreatorId"); + + b.ToTable("Subscriptions", "Content"); + }); + + modelBuilder.Entity("Hutopy.Web.Features.Contents.Data.Content", b => + { + b.HasOne("Hutopy.Web.Features.Contents.Data.Creator", "Creator") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.OwnsMany("Hutopy.Web.Features.Contents.Data.ContentReaction", "Reactions", b1 => + { + b1.Property("ContentId") + .HasColumnType("uuid"); + + b1.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b1.Property("Id")); + + b1.Property("Reaction") + .HasColumnType("integer"); + + b1.Property("UserId") + .HasColumnType("uuid"); + + b1.Property("UserName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b1.HasKey("ContentId", "Id"); + + b1.ToTable("ContentReactions", "Content"); + + b1.WithOwner() + .HasForeignKey("ContentId"); + }); + + b.Navigation("Creator"); + + b.Navigation("Reactions"); + }); + + modelBuilder.Entity("Hutopy.Web.Features.Contents.Data.Creator", b => + { + b.OwnsOne("Hutopy.Web.Features.Contents.Data.Colors", "Colors", b1 => + { + b1.Property("CreatorId") + .HasColumnType("uuid"); + + b1.Property("Background") + .IsRequired() + .HasMaxLength(9) + .HasColumnType("character varying(9)"); + + b1.Property("Error") + .IsRequired() + .HasMaxLength(9) + .HasColumnType("character varying(9)"); + + b1.Property("OnBackground") + .IsRequired() + .HasMaxLength(9) + .HasColumnType("character varying(9)"); + + b1.Property("OnError") + .IsRequired() + .HasMaxLength(9) + .HasColumnType("character varying(9)"); + + b1.Property("OnPrimary") + .IsRequired() + .HasMaxLength(9) + .HasColumnType("character varying(9)"); + + b1.Property("OnSecondary") + .IsRequired() + .HasMaxLength(9) + .HasColumnType("character varying(9)"); + + b1.Property("OnSurface") + .IsRequired() + .HasMaxLength(9) + .HasColumnType("character varying(9)"); + + b1.Property("Primary") + .IsRequired() + .HasMaxLength(9) + .HasColumnType("character varying(9)"); + + b1.Property("Secondary") + .IsRequired() + .HasMaxLength(9) + .HasColumnType("character varying(9)"); + + b1.Property("Surface") + .IsRequired() + .HasMaxLength(9) + .HasColumnType("character varying(9)"); + + b1.HasKey("CreatorId"); + + b1.ToTable("Colors", "Content"); + + b1.WithOwner() + .HasForeignKey("CreatorId"); + }); + + b.OwnsOne("Hutopy.Web.Features.Contents.Data.Images", "Images", b1 => + { + b1.Property("CreatorId") + .HasColumnType("uuid"); + + b1.Property("Banner") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.Property("Logo") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.HasKey("CreatorId"); + + b1.ToTable("Images", "Content"); + + b1.WithOwner() + .HasForeignKey("CreatorId"); + }); + + b.OwnsOne("Hutopy.Web.Features.Contents.Data.Socials", "Socials", b1 => + { + b1.Property("CreatorId") + .HasColumnType("uuid"); + + b1.Property("FacebookUrl") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.Property("InstagramUrl") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.Property("LinkedInUrl") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.Property("RedditUrl") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.Property("TikTokUrl") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.Property("WebsiteUrl") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.Property("XUrl") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.Property("YoutubeUrl") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.HasKey("CreatorId"); + + b1.ToTable("Socials", "Content"); + + b1.WithOwner() + .HasForeignKey("CreatorId"); + }); + + b.Navigation("Colors") + .IsRequired(); + + b.Navigation("Images") + .IsRequired(); + + b.Navigation("Socials") + .IsRequired(); + }); + + modelBuilder.Entity("Hutopy.Web.Features.Contents.Data.Subscription", b => + { + b.HasOne("Hutopy.Web.Features.Contents.Data.Creator", "Creator") + .WithMany() + .HasForeignKey("CreatorId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Creator"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Web/Features/Contents/Migrations/20240922064815_RemovesAboutAddsTitle.cs b/src/Web/Features/Contents/Migrations/20240922064815_RemovesAboutAddsTitle.cs new file mode 100644 index 0000000..ff88fb5 --- /dev/null +++ b/src/Web/Features/Contents/Migrations/20240922064815_RemovesAboutAddsTitle.cs @@ -0,0 +1,43 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Hutopy.Web.Features.Contents.Migrations +{ + /// + public partial class RemovesAboutAddsTitle : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "About_Description", + schema: "Content", + table: "Creators"); + + migrationBuilder.RenameColumn( + name: "About_Title", + schema: "Content", + table: "Creators", + newName: "Title"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.RenameColumn( + name: "Title", + schema: "Content", + table: "Creators", + newName: "About_Title"); + + migrationBuilder.AddColumn( + name: "About_Description", + schema: "Content", + table: "Creators", + type: "character varying(2048)", + maxLength: 2048, + nullable: true); + } + } +} diff --git a/src/Web/Features/Contents/Migrations/ContentDbContextModelSnapshot.cs b/src/Web/Features/Contents/Migrations/ContentDbContextModelSnapshot.cs index a3d9e3f..f67224a 100644 --- a/src/Web/Features/Contents/Migrations/ContentDbContextModelSnapshot.cs +++ b/src/Web/Features/Contents/Migrations/ContentDbContextModelSnapshot.cs @@ -80,6 +80,10 @@ namespace Hutopy.Web.Features.Contents.Migrations .HasMaxLength(255) .HasColumnType("character varying(255)"); + b.Property("Title") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + b.HasKey("Id"); b.ToTable("Creators", "Content"); @@ -148,45 +152,58 @@ namespace Hutopy.Web.Features.Contents.Migrations modelBuilder.Entity("Hutopy.Web.Features.Contents.Data.Creator", b => { - b.OwnsOne("Hutopy.Web.Features.Contents.Data.About", "About", b1 => - { - b1.Property("CreatorId") - .HasColumnType("uuid"); - - b1.Property("Description") - .HasMaxLength(2048) - .HasColumnType("character varying(2048)"); - - b1.Property("Title") - .HasMaxLength(255) - .HasColumnType("character varying(255)"); - - b1.HasKey("CreatorId"); - - b1.ToTable("Creators", "Content"); - - b1.WithOwner() - .HasForeignKey("CreatorId"); - }); - b.OwnsOne("Hutopy.Web.Features.Contents.Data.Colors", "Colors", b1 => { b1.Property("CreatorId") .HasColumnType("uuid"); - b1.Property("Accent") + b1.Property("Background") + .IsRequired() .HasMaxLength(9) .HasColumnType("character varying(9)"); - b1.Property("BannerBottom") + b1.Property("Error") + .IsRequired() .HasMaxLength(9) .HasColumnType("character varying(9)"); - b1.Property("BannerTop") + b1.Property("OnBackground") + .IsRequired() .HasMaxLength(9) .HasColumnType("character varying(9)"); - b1.Property("Menu") + b1.Property("OnError") + .IsRequired() + .HasMaxLength(9) + .HasColumnType("character varying(9)"); + + b1.Property("OnPrimary") + .IsRequired() + .HasMaxLength(9) + .HasColumnType("character varying(9)"); + + b1.Property("OnSecondary") + .IsRequired() + .HasMaxLength(9) + .HasColumnType("character varying(9)"); + + b1.Property("OnSurface") + .IsRequired() + .HasMaxLength(9) + .HasColumnType("character varying(9)"); + + b1.Property("Primary") + .IsRequired() + .HasMaxLength(9) + .HasColumnType("character varying(9)"); + + b1.Property("Secondary") + .IsRequired() + .HasMaxLength(9) + .HasColumnType("character varying(9)"); + + b1.Property("Surface") + .IsRequired() .HasMaxLength(9) .HasColumnType("character varying(9)"); @@ -264,9 +281,6 @@ namespace Hutopy.Web.Features.Contents.Migrations .HasForeignKey("CreatorId"); }); - b.Navigation("About") - .IsRequired(); - b.Navigation("Colors") .IsRequired(); diff --git a/src/Web/TestDataSeeder.cs b/src/Web/TestDataSeeder.cs index 08c7bbf..b2f624f 100644 --- a/src/Web/TestDataSeeder.cs +++ b/src/Web/TestDataSeeder.cs @@ -49,7 +49,10 @@ internal class TestDataSeeder( creator.Id = creatorUser.Id; creator.CreatedBy = creator.Id; - await contentContext.Subscriptions.AddAsync(new() { CreatedBy = userA.Id, CreatorId = creator.Id }); + await contentContext.Subscriptions.AddAsync(new Subscription + { + CreatedBy = userA.Id, CreatorId = creator.Id + }); await contentContext.Creators.AddAsync(creator); var contents = GenerateContent(creator, 10); @@ -57,7 +60,9 @@ internal class TestDataSeeder( { var messages = GenerateMessages(content, 10); - var parentMessages = messages.Where((_, index) => index % 2 == 0).ToList(); + var parentMessages = messages.Where(( + _, + index) => index % 2 == 0).ToList(); foreach (var parentMessage in parentMessages) { _ = GenerateReplies(content, parentMessage, 10); @@ -68,7 +73,9 @@ internal class TestDataSeeder( } } - private List GenerateContent(Creator creator, int contentCount) + private List GenerateContent( + Creator creator, + int contentCount) { var currentDate = DateTimeOffset.UtcNow; @@ -97,7 +104,9 @@ internal class TestDataSeeder( return contents; } - private List GenerateMessages(Content content, int messageCount) + private List GenerateMessages( + Content content, + int messageCount) { var currentDate = content.CreatedAt; var messages = new List(); @@ -126,7 +135,10 @@ internal class TestDataSeeder( return messages; } - private List GenerateReplies(Content content, Message parent, int replyCount) + private List GenerateReplies( + Content content, + Message parent, + int replyCount) { var currentDate = parent.CreatedAt; var replies = new List(); @@ -157,7 +169,10 @@ internal class TestDataSeeder( return replies; } - private async Task CreateUserAsync(string name, string? portraitUrl, params string[] roles) + private async Task CreateUserAsync( + string name, + string? portraitUrl, + params string[] roles) { var user = new ApplicationUser { @@ -184,23 +199,28 @@ internal class TestDataSeeder( private readonly static Creator HutopyCreator = new() { Name = "hutopy", - About = new() + Title = "Page officielle", + Colors = new Colors { - Title = "Page officielle", - Description = "Site officiel pour Hutopy. Venez-nous-y retrouver avec tous vos fans!", - }, - Colors = new() - { - BannerTop = "#A30E79", BannerBottom = "#6B0065", Accent = "#23393B", Menu = "#53B93B", + Primary = "#A30E79", + Secondary = "#6B0065", + Background = "#53B93B", + Surface = "#23393B", + Error = "#B00020", + OnPrimary = "#ffffff", + OnSecondary = "#000000", + OnBackground = "#000000", + OnSurface = "#000000", + OnError = "#ffffff", }, Socials = - new() + new Socials { XUrl = "https://twitter.com/Hutopyinc", FacebookUrl = "https://www.facebook.com/Hutopy", InstagramUrl = "https://www.instagram.com/hutopy.inc/" }, - Images = new() + Images = new Images { Banner = "/images/usersmedia/HutopyProfile/banners/banner01.png", Logo = "/images/usersmedia/HutopyProfile/profilepictures/profileHutopyProfile01.png" @@ -210,15 +230,21 @@ internal class TestDataSeeder( private readonly static Creator ArpsCreator = new() { Name = "arps", - About = - new() - { - Title = "Page officielle", - Description = "Site officiel pour Arps. Venez-nous-y retrouver avec tous vos fans!", - }, - Colors = - new() { BannerTop = "#231F20", BannerBottom = "#231F20", Accent = "#272526", Menu = "#FFFFFF" }, - Socials = new() + Title = "Créateur de contenu", + Colors = new Colors + { + Primary = "#A30E79", + Secondary = "#6B0065", + Background = "#53B93B", + Surface = "#23393B", + Error = "#B00020", + OnPrimary = "#ffffff", + OnSecondary = "#000000", + OnBackground = "#000000", + OnSurface = "#000000", + OnError = "#ffffff", + }, + Socials = new Socials { FacebookUrl = "https://www.facebook.com/arps.company", InstagramUrl = "https://www.instagram.com/arps.co/", @@ -227,7 +253,7 @@ internal class TestDataSeeder( LinkedInUrl = "https://www.linkedin.com/in/mickael-simard-96079a90/", WebsiteUrl = "https://www.arps.ca/" }, - Images = new() + Images = new Images { Banner = "/images/usersmedia/ARPS/banners/bannerARPS01.png", Logo = "/images/usersmedia/ARPS/profilepictures/profileARPS.png" @@ -237,22 +263,27 @@ internal class TestDataSeeder( private readonly static Creator ChloeBeaugrandCreator = new() { Name = "chloebeaugrand", - About = new() + Title = "Page officielle", + Colors = new Colors { - Title = "Page officielle", - Description = "𝐿𝑎 𝑐𝑟𝑒́𝑎𝑡𝑖𝑣𝑖𝑡𝑒́ 𝑐’𝑒𝑠𝑡 𝑙’𝑖𝑛𝑡𝑒𝑙𝑙𝑖𝑔𝑒𝑛𝑐𝑒 𝑞𝑢𝑖 𝑠’𝑎𝑚𝑢𝑠𝑒!", - }, - Colors = new() - { - BannerTop = "#231F20", BannerBottom = "#272526", Accent = "#231F20", Menu = "#231F20", + Primary = "#A30E79", + Secondary = "#6B0065", + Background = "#53B93B", + Surface = "#23393B", + Error = "#B00020", + OnPrimary = "#ffffff", + OnSecondary = "#000000", + OnBackground = "#000000", + OnSurface = "#000000", + OnError = "#ffffff", }, Socials = - new() + new Socials { FacebookUrl = "https://www.facebook.com/chloegestionmedias", InstagramUrl = "https://www.instagram.com/chloe.photo_gms", }, - Images = new() + Images = new Images { Banner = "/images/usersmedia/chloebeaugrand/banners/bannerChloeBeaugrand01.png", Logo = "/images/usersmedia/chloebeaugrand/profilepictures/profileChloeBeaugrand01.png" @@ -262,24 +293,28 @@ internal class TestDataSeeder( private readonly static Creator GuillaumeMCreator = new() { Name = "guillaumem", - About = new() + Title = "Page officielle", + Colors = new Colors { - Title = "Page officielle", - Description = - "Mettre en lumière le côté humain des entrepreneurs. Chaque service, chaque produit est porteur d’une histoire, d’une passion, d’une vision unique. Mon objectif est de faire rayonner cette unicité, de créer des connexions authentiques entre ces entrepreneurs et leurs clients potentiels. Parce que derrière chaque entreprise, il y a des personnes inspirantes qui méritent d’être entendues et comprises. Et toi, quel est ton objectif pour cette année?", - }, - Colors = new() - { - BannerTop = "#0BAAB2", BannerBottom = "#006D77", Accent = "#CC6F91", Menu = "#CC6F91", + Primary = "#A30E79", + Secondary = "#6B0065", + Background = "#53B93B", + Surface = "#23393B", + Error = "#B00020", + OnPrimary = "#ffffff", + OnSecondary = "#000000", + OnBackground = "#000000", + OnSurface = "#000000", + OnError = "#ffffff", }, Socials = - new() + new Socials { FacebookUrl = "https://www.facebook.com/GuillaumeMousseau222", InstagramUrl = "https://www.instagram.com/guillaumeaime/", TikTokUrl = "https://www.tiktok.com/@guillaumeaime" }, - Images = new() + Images = new Images { Banner = "/images/usersmedia/guillaumeMousseau/banners/bannerGuillaumeMousseau01.png", Logo = @@ -290,24 +325,28 @@ internal class TestDataSeeder( private readonly static Creator LeffetCreator = new() { Name = "leffet", - About = new() + Title = "Page officielle", + Colors = new Colors { - Title = "Page officielle", - Description = - "Mettre en lumière le côté humain des entrepreneurs. Chaque service, chaque produit est porteur d’une histoire, d’une passion, d’une vision unique. Mon objectif est de faire rayonner cette unicité, de créer des connexions authentiques entre ces entrepreneurs et leurs clients potentiels. Parce que derrière chaque entreprise, il y a des personnes inspirantes qui méritent d’être entendues et comprises. Et toi, quel est ton objectif pour cette année?", - }, - Colors = new() - { - BannerTop = "#CC6F91", BannerBottom = "#FBC702", Accent = "#FBC702", Menu = "#FBC702", + Primary = "#A30E79", + Secondary = "#6B0065", + Background = "#53B93B", + Surface = "#23393B", + Error = "#B00020", + OnPrimary = "#ffffff", + OnSecondary = "#000000", + OnBackground = "#000000", + OnSurface = "#000000", + OnError = "#ffffff", }, Socials = - new() + new Socials { FacebookUrl = "https://www.facebook.com/Hutopy", InstagramUrl = "https://www.instagram.com/guillaumeaime/", WebsiteUrl = "https://fondationleffet.ca/" }, - Images = new() + Images = new Images { Banner = "/images/usersmedia/leffet/banners/banner02.png", Logo = "/images/usersmedia/leffet/profilepictures/leffetProfile01.png" @@ -317,23 +356,27 @@ internal class TestDataSeeder( private readonly static Creator MathieuCaron = new() { Name = "mathieucaron", - About = new() + Title = "Page officielle", + Colors = new Colors { - Title = "Page officielle", - Description = - "Mettre en lumière le côté humain des entrepreneurs. Chaque service, chaque produit est porteur d’une histoire, d’une passion, d’une vision unique. Mon objectif est de faire rayonner cette unicité, de créer des connexions authentiques entre ces entrepreneurs et leurs clients potentiels. Parce que derrière chaque entreprise, il y a des personnes inspirantes qui méritent d’être entendues et comprises. Et toi, quel est ton objectif pour cette année?", - }, - Colors = new() - { - BannerTop = "#101B49", BannerBottom = "#698FE7", Accent = "#1D1D1B", Menu = "#1D1D1B", + Primary = "#A30E79", + Secondary = "#6B0065", + Background = "#53B93B", + Surface = "#23393B", + Error = "#B00020", + OnPrimary = "#ffffff", + OnSecondary = "#000000", + OnBackground = "#000000", + OnSurface = "#000000", + OnError = "#ffffff", }, Socials = - new() + new Socials { FacebookUrl = "https://www.facebook.com/MathieuCaronPro/", YoutubeUrl = "https://www.youtube.com/@lesinterviewsatypiquesdema4692", }, - Images = new() + Images = new Images { Banner = "/images/usersmedia/mathieuCaron/banners/bannerMathieuCaron01.png", Logo = "/images/usersmedia/mathieuCaron/profilepictures/profileMathieuCaron01.png" diff --git a/src/Web/Web.http b/src/Web/Web.http index 9f24562..acbc0c9 100644 --- a/src/Web/Web.http +++ b/src/Web/Web.http @@ -1,5 +1,5 @@ # For more info on HTTP files go to https://aka.ms/vs/httpfile -@Email=userA@test +@Email=hutopy@test @Password=Test123# @auth_token= @@ -23,7 +23,9 @@ Content-Type: application/json "password": "{{Password}}" } -> {% client.global.set("auth_token", response.body.accessToken); %} +> {% + client.global.set("auth_token", response.body.accessToken); +%} ### @@ -64,3 +66,23 @@ Authorization: Bearer {{auth_token}} ### # GET /api/contents/creator/{CreatorId} GET {{base_url}}/api/contents/creator/8590ba59-58a7-4466-bb50-08dcb5e47c6d/ + + +### +# GET /api/creators/{CreatorId}/colors +POST {{base_url}}/api/creators/8590ba59-58a7-4466-bb50-08dcb5e47c6d/colors/ +Authorization: Bearer {{auth_token}} +Content-Type: application/json + +{ + "Primary" : "#fffff0", + "Secondary" : "#fffff0", + "Background" : "#fffff0", + "Surface" : "#fffff0", + "Error" : "#fffff0", + "OnPrimary" : "#fffff0", + "OnSecondary" : "#fffff0", + "OnBackground" : "#fffff0", + "OnSurface" : "#fffff0", + "OnError" : "#fffff0" +} \ No newline at end of file From 1aa940fa05d24b3a6b721eb6a8e0bc330a072542 Mon Sep 17 00:00:00 2001 From: Jonathan Bourdon Date: Tue, 24 Sep 2024 01:37:53 -0400 Subject: [PATCH 191/229] LoginWithGoogle feature now working. --- .../Identity/ApplicationUser.cs | 1 + .../20240924044131_AddGoogleId.Designer.cs | 435 ++++++++++++++++++ .../Migrations/20240924044131_AddGoogleId.cs | 29 ++ .../ApplicationDbContextModelSnapshot.cs | 5 +- src/Infrastructure/Utils/PasswordGenerator.cs | 70 +++ src/Infrastructure/Utils/RandomGenerator.cs | 58 --- src/Web/Controllers/FacebookController.cs | 2 +- src/Web/Controllers/GoogleController.cs | 89 ---- .../Users/Handlers/LoginWithGoogle.cs | 140 ++++++ 9 files changed, 680 insertions(+), 149 deletions(-) create mode 100644 src/Infrastructure/Migrations/20240924044131_AddGoogleId.Designer.cs create mode 100644 src/Infrastructure/Migrations/20240924044131_AddGoogleId.cs create mode 100644 src/Infrastructure/Utils/PasswordGenerator.cs delete mode 100644 src/Infrastructure/Utils/RandomGenerator.cs delete mode 100644 src/Web/Controllers/GoogleController.cs create mode 100644 src/Web/Features/Users/Handlers/LoginWithGoogle.cs diff --git a/src/Infrastructure/Identity/ApplicationUser.cs b/src/Infrastructure/Identity/ApplicationUser.cs index 8a1ed8e..5ed71b2 100644 --- a/src/Infrastructure/Identity/ApplicationUser.cs +++ b/src/Infrastructure/Identity/ApplicationUser.cs @@ -11,4 +11,5 @@ public class ApplicationUser : IdentityUser public DateTime? BirthDate { get; set; } [MaxLength(255)] public string? Address { get; set; } [MaxLength(255)] public string? PortraitUrl { get; set; } + [MaxLength(255)] public string? GoogleId { get; set; } } diff --git a/src/Infrastructure/Migrations/20240924044131_AddGoogleId.Designer.cs b/src/Infrastructure/Migrations/20240924044131_AddGoogleId.Designer.cs new file mode 100644 index 0000000..9eb0111 --- /dev/null +++ b/src/Infrastructure/Migrations/20240924044131_AddGoogleId.Designer.cs @@ -0,0 +1,435 @@ +// +using System; +using Hutopy.Infrastructure.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Hutopy.Infrastructure.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + [Migration("20240924044131_AddGoogleId")] + partial class AddGoogleId + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.4") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("Hutopy.Domain.Entities.FutureCreator", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("CreatedAt") + .HasColumnType("datetimeoffset"); + + b.Property("CreatedBy") + .HasColumnType("uniqueidentifier"); + + b.Property("EmailAddress") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("FirstName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("LastModifiedAt") + .HasColumnType("datetimeoffset"); + + b.Property("LastModifiedBy") + .HasColumnType("uniqueidentifier"); + + b.Property("LastName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumber") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("ReasonToJoin") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("SocialNetworkAccount") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("FutureCreators"); + }); + + modelBuilder.Entity("Hutopy.Domain.Entities.UserTransaction", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Amount") + .HasPrecision(18, 2) + .HasColumnType("decimal(18,2)"); + + b.Property("ApplicationUserId") + .HasColumnType("uniqueidentifier"); + + b.Property("CreatedAt") + .HasColumnType("datetimeoffset"); + + b.Property("CreatedBy") + .HasColumnType("uniqueidentifier"); + + b.Property("Currency") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("IsConfirmed") + .HasColumnType("bit"); + + b.Property("LastModifiedAt") + .HasColumnType("datetimeoffset"); + + b.Property("LastModifiedBy") + .HasColumnType("uniqueidentifier"); + + b.Property("Paid") + .HasColumnType("bit"); + + b.Property("StripeBillingDetailEmail") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("StripeBillingDetailName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("StripeChargeId") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("StripeEventId") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("StripePaymentIntent") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("StripePaymentMethod") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("StripeReceiptUrl") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("TipMessage") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationUserId"); + + b.ToTable("UserTransactions"); + }); + + modelBuilder.Entity("Hutopy.Infrastructure.Identity.ApplicationRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("nvarchar(max)"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex") + .HasFilter("[NormalizedName] IS NOT NULL"); + + b.ToTable("AspNetRoles", (string)null); + }); + + modelBuilder.Entity("Hutopy.Infrastructure.Identity.ApplicationUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("AccessFailedCount") + .HasColumnType("int"); + + b.Property("Address") + .HasMaxLength(255) + .HasColumnType("nvarchar(255)"); + + b.Property("Alias") + .HasMaxLength(255) + .HasColumnType("nvarchar(255)"); + + b.Property("BirthDate") + .HasColumnType("datetime2"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("nvarchar(max)"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("EmailConfirmed") + .HasColumnType("bit"); + + b.Property("Firstname") + .HasMaxLength(255) + .HasColumnType("nvarchar(255)"); + + b.Property("GoogleId") + .HasMaxLength(255) + .HasColumnType("nvarchar(255)"); + + b.Property("Lastname") + .HasMaxLength(255) + .HasColumnType("nvarchar(255)"); + + b.Property("LockoutEnabled") + .HasColumnType("bit"); + + b.Property("LockoutEnd") + .HasColumnType("datetimeoffset"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("PasswordHash") + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumber") + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("bit"); + + b.Property("PortraitUrl") + .HasMaxLength(255) + .HasColumnType("nvarchar(255)"); + + b.Property("SecurityStamp") + .HasColumnType("nvarchar(max)"); + + b.Property("TwoFactorEnabled") + .HasColumnType("bit"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex") + .HasFilter("[NormalizedUserName] IS NOT NULL"); + + b.ToTable("AspNetUsers", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("nvarchar(max)"); + + b.Property("ClaimValue") + .HasColumnType("nvarchar(max)"); + + b.Property("RoleId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("nvarchar(max)"); + + b.Property("ClaimValue") + .HasColumnType("nvarchar(max)"); + + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("nvarchar(450)"); + + b.Property("ProviderKey") + .HasColumnType("nvarchar(450)"); + + b.Property("ProviderDisplayName") + .HasColumnType("nvarchar(max)"); + + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.Property("RoleId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.Property("LoginProvider") + .HasColumnType("nvarchar(450)"); + + b.Property("Name") + .HasColumnType("nvarchar(450)"); + + b.Property("Value") + .HasColumnType("nvarchar(max)"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens", (string)null); + }); + + modelBuilder.Entity("Hutopy.Domain.Entities.UserTransaction", b => + { + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("ApplicationUserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Infrastructure/Migrations/20240924044131_AddGoogleId.cs b/src/Infrastructure/Migrations/20240924044131_AddGoogleId.cs new file mode 100644 index 0000000..9e71d45 --- /dev/null +++ b/src/Infrastructure/Migrations/20240924044131_AddGoogleId.cs @@ -0,0 +1,29 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Hutopy.Infrastructure.Migrations +{ + /// + public partial class AddGoogleId : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "GoogleId", + table: "AspNetUsers", + type: "nvarchar(255)", + maxLength: 255, + nullable: true); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "GoogleId", + table: "AspNetUsers"); + } + } +} diff --git a/src/Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs b/src/Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs index b3d38bc..7d39e2d 100644 --- a/src/Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs +++ b/src/Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs @@ -189,7 +189,6 @@ namespace Hutopy.Infrastructure.Migrations .HasColumnType("nvarchar(255)"); b.Property("BirthDate") - .HasMaxLength(255) .HasColumnType("datetime2"); b.Property("ConcurrencyStamp") @@ -207,6 +206,10 @@ namespace Hutopy.Infrastructure.Migrations .HasMaxLength(255) .HasColumnType("nvarchar(255)"); + b.Property("GoogleId") + .HasMaxLength(255) + .HasColumnType("nvarchar(255)"); + b.Property("Lastname") .HasMaxLength(255) .HasColumnType("nvarchar(255)"); diff --git a/src/Infrastructure/Utils/PasswordGenerator.cs b/src/Infrastructure/Utils/PasswordGenerator.cs new file mode 100644 index 0000000..7901a7f --- /dev/null +++ b/src/Infrastructure/Utils/PasswordGenerator.cs @@ -0,0 +1,70 @@ +using System.Text; + +namespace Hutopy.Infrastructure.Utils; + +// If we need to add special characters we can alternate between 2 pools. +public class PasswordGenerator +{ + private const string LowerLetters = "abcdefghijklmnopqrstuvwxyz"; + private const string UpperLetters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + private const string Numbers = "0123456789"; + private const string SpecialCharacters = "!@#$%^&*()_+-=[];',./`~{}|:\"<>?"; + + private static readonly Random Random = new(); + + public static string GeneratePassword( + int minLength, + int maxLength, + bool requireNumber = true, + bool requireCapital = true, + bool requireSpecialCharacter = true) + { + // Create pools based on the requirements + var characterPool = new StringBuilder(LowerLetters); + + if (requireCapital) + characterPool.Append(UpperLetters); + + if (requireNumber) + characterPool.Append(Numbers); + + if (requireSpecialCharacter) + characterPool.Append(SpecialCharacters); + + // Ensure that the length is within the specified bounds + int length = Random.Next(minLength, maxLength + 1); + var password = new char[length]; + + // Ensure at least one character from each required category is included + int index = 0; + + if (requireCapital) + password[index++] = UpperLetters[Random.Next(UpperLetters.Length)]; + + if (requireNumber) + password[index++] = Numbers[Random.Next(Numbers.Length)]; + + if (requireSpecialCharacter) + password[index++] = SpecialCharacters[Random.Next(SpecialCharacters.Length)]; + + // Fill the rest of the password + for (int i = index; i < length; i++) + { + password[i] = characterPool[Random.Next(characterPool.Length)]; + } + + // Shuffle the password to randomize the placement of the required characters + Shuffle(password); + return new string(password); + } + + private static void Shuffle( + char[] array) + { + for (int i = array.Length - 1; i > 0; i--) + { + int j = Random.Next(i + 1); + (array[i], array[j]) = (array[j], array[i]); // Swap elements + } + } +} diff --git a/src/Infrastructure/Utils/RandomGenerator.cs b/src/Infrastructure/Utils/RandomGenerator.cs deleted file mode 100644 index 1e5a9a2..0000000 --- a/src/Infrastructure/Utils/RandomGenerator.cs +++ /dev/null @@ -1,58 +0,0 @@ -using System.Text; - -namespace Hutopy.Infrastructure.Utils; - -// If we need to add special characters we can alternate between 2 pools. -public class RandomGenerator -{ - // For the moment, numbers and special characters don't work because - // the random generator is designed to handle a single integer. - // We can modify this in the future. - private const string LetterBytes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" - + "0123456789" - + "!@#$%^&*()_+" - + "-=[];',./`~{}|:\"<>?"; - private const int LetterIdxBits = 6; - private const int LetterIdxMask = 1 << LetterIdxBits; - private const int LetterIdxMax = 64 / LetterIdxBits; - - private static readonly Random Src = new(); - - public static byte[] RandBytesMaskSrc(int n) - { - var b = new byte[n]; - - for (var i = n - 1; i >= 0;) - { - long cache = Src.NextInt64(); - int remain = LetterIdxMax; - - while (remain != 0) - { - if (i < 0) - break; - - if (cache == 0) - cache = Src.NextInt64(); - - var idx = (int)(cache & LetterIdxMask); - if (idx < LetterBytes.Length) - { - b[i] = (byte)LetterBytes[idx]; - i--; - } - - cache >>= LetterIdxBits; - remain--; - } - } - - return b; - } - - public static string RandomString(int length) - { - var bytes = RandBytesMaskSrc(length); - return Encoding.UTF8.GetString(bytes); // Equivalent for *(string*)(&bytes[0]) - } -} diff --git a/src/Web/Controllers/FacebookController.cs b/src/Web/Controllers/FacebookController.cs index 9efee0b..b8b52d9 100644 --- a/src/Web/Controllers/FacebookController.cs +++ b/src/Web/Controllers/FacebookController.cs @@ -49,7 +49,7 @@ public class FacebookController(IIdentityService identityService) : Controller } await identityService.CreateUserAsync(email, givenName, givenName, familyName, - RandomGenerator.RandomString(24)); + PasswordGenerator.GeneratePassword(8, 10)); await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, new ClaimsPrincipal(claimsIdentity)); return Redirect("/"); diff --git a/src/Web/Controllers/GoogleController.cs b/src/Web/Controllers/GoogleController.cs deleted file mode 100644 index fd48001..0000000 --- a/src/Web/Controllers/GoogleController.cs +++ /dev/null @@ -1,89 +0,0 @@ -using System.Security.Claims; -using Hutopy.Application.Common.Interfaces; -using Hutopy.Infrastructure.Identity; -using Hutopy.Infrastructure.Utils; -using Microsoft.AspNetCore.Authentication; -using Microsoft.AspNetCore.Authentication.Cookies; -using Microsoft.AspNetCore.Mvc; -using Microsoft.Extensions.Options; -using Newtonsoft.Json.Linq; - -namespace Hutopy.Web.Controllers; - -public class GoogleController( - IIdentityService identityService, - IHttpClientFactory httpClientFactory, - IOptionsSnapshot jwtOptions) - : Controller -{ - [Microsoft.AspNetCore.Mvc.HttpPost("/api/google/sign-in")] - public async Task SignIn([Microsoft.AspNetCore.Mvc.FromBody] GoogleSignInRequest request) - { - using var httpClient = httpClientFactory.CreateClient(); - - // Verify the token with Google - var response = await httpClient.GetAsync($"https://www.googleapis.com/oauth2/v1/userinfo?access_token={request.AccessToken}"); - if (!response.IsSuccessStatusCode) - { - return BadRequest("Invalid Google token."); - } - - var userInfo = JObject.Parse(await response.Content.ReadAsStringAsync()); - var email = userInfo["email"]?.ToString() ?? ""; - var name = userInfo["name"]?.ToString() ?? ""; - var givenName = userInfo["given_name"]?.ToString() ?? ""; - var familyName = userInfo["family_name"]?.ToString() ?? ""; - - if (string.IsNullOrEmpty(email)) - { - return BadRequest("Google token did not contain an email."); - } - - // Check if user exists or create a new one - var user = await identityService.FindUserByEmailAsync(email); - if (user == null) - { - await identityService.CreateUserAsync(email, email, givenName, familyName, RandomGenerator.RandomString(24)); - user = await identityService.FindUserByEmailAsync(email); - } - - if (user?.Id is null) - { - return BadRequest("Unable to find or create the user."); - } - - // Sign in the user - var claimsIdentity = new ClaimsIdentity( - new List - { - new(ClaimTypes.Name, name), - new(ClaimTypes.Email, email), - new(ClaimTypes.GivenName, givenName), - new(ClaimTypes.Surname, familyName) - }, - CookieAuthenticationDefaults.AuthenticationScheme); - - await HttpContext.SignInAsync( - CookieAuthenticationDefaults.AuthenticationScheme, - new ClaimsPrincipal(claimsIdentity)); - - var token = JwtTokenHelper.GenerateJwtToken( - jwtOptions.Value.Lifetime, - jwtOptions.Value.Issuer, - jwtOptions.Value.Audience, - jwtOptions.Value.Key, - user.Id.ToString(), - user.Email, - user.Alias, - user.Firstname, - user.Lastname, - user.PortraitUrl); - - return Ok(new { accessToken = token, email }); - } - - public class GoogleSignInRequest - { - public required string AccessToken { get; set; } - } -} diff --git a/src/Web/Features/Users/Handlers/LoginWithGoogle.cs b/src/Web/Features/Users/Handlers/LoginWithGoogle.cs new file mode 100644 index 0000000..bdb814d --- /dev/null +++ b/src/Web/Features/Users/Handlers/LoginWithGoogle.cs @@ -0,0 +1,140 @@ +using System.Text.Json; +using System.Text.Json.Serialization; +using Hutopy.Infrastructure.Identity; +using Hutopy.Infrastructure.Utils; +using Microsoft.AspNetCore.Identity; +using Microsoft.Extensions.Options; + +namespace Hutopy.Web.Features.Users.Handlers; + +class GoogleToken +{ + [JsonPropertyName("access_token")] public required string AccessToken { get; init; } + [JsonPropertyName("token_type")] public required string TokenType { get; init; } + [JsonPropertyName("expires_in")] public required int ExpiresIn { get; init; } + [JsonPropertyName("scope")] public required string Scope { get; init; } + [JsonPropertyName("authuser")] public required string AuthUser { get; init; } + [JsonPropertyName("prompt")] public required string Prompt { get; init; } +} + +public class GoogleUserInfo +{ + [JsonPropertyName("id")] public required string Id { get; init; } + [JsonPropertyName("email")] public required string Email { get; init; } + [JsonPropertyName("verified_email")] public required bool VerifiedEmail { get; init; } + [JsonPropertyName("name")] public required string Name { get; init; } + [JsonPropertyName("given_name")] public required string GivenName { get; init; } + [JsonPropertyName("family_name")] public required string FamilyName { get; init; } + [JsonPropertyName("picture")] public required string Picture { get; init; } +} + +[PublicAPI] +public record LoginWithGoogleRequest( + string Token) + : IRequest; + +public record LoginWithGoogleResponse( + string AccessToken, + string RefreshToken); + +[PublicAPI] +public class LoginWithGoogleHandler( + IHttpClientFactory httpClientFactory, + ApplicationUserManager userManager, + SignInManager signInManager, + IOptionsSnapshot jwtOptions) + : Endpoint +{ + public override void Configure() + { + AllowAnonymous(); + Post("/api/users/login-with-google"); + Options(o => o.WithTags("Users")); + } + + public override async Task HandleAsync( + LoginWithGoogleRequest request, + CancellationToken ct) + { + var googleToken = JsonSerializer.Deserialize(request.Token)!; + + // Verify the token with Google + using var httpClient = httpClientFactory.CreateClient(); + var response = await httpClient.GetAsync( + $"https://www.googleapis.com/oauth2/v1/userinfo?access_token={googleToken.AccessToken}", + ct); + if (!response.IsSuccessStatusCode) + { + await SendStringAsync( + "The token is not valid", + 400, + cancellation: ct); + return; + } + + // Extract the user info (email, name, etc.). + var content = await response.Content.ReadAsStringAsync(ct); + var userInfo = JsonSerializer.Deserialize(content); + if (userInfo is null + || !userInfo.VerifiedEmail + || string.IsNullOrEmpty(userInfo.Email)) + { + await SendStringAsync( + "The token does not contain an email", + 400, + cancellation: ct); + return; + } + + // Check if user exists or create a new one + var user = await userManager.FindByEmailAsync(userInfo.Email); + + if (user is null) + { + var generatedPassword = PasswordGenerator.GeneratePassword(8, 10); + var generatedUser = new ApplicationUser + { + UserName = userInfo.Email, + Email = userInfo.Email, + Firstname = userInfo.GivenName, + Lastname = userInfo.FamilyName, + Alias = userInfo.Name, + PortraitUrl = userInfo.Picture, + GoogleId = userInfo.Id, + }; + + var result = await userManager.CreateAsync( + generatedUser, + generatedPassword); + + if (!result.Succeeded) + { + await SendStringAsync( + result.Errors.First().Description, + 400, + cancellation: ct); + return; + } + + user = generatedUser; + } + + await signInManager.SignInAsync(user, isPersistent: false); + + var accessToken = JwtTokenHelper.GenerateJwtToken( + expiresIn: jwtOptions.Value.Lifetime, + issuer: jwtOptions.Value.Issuer, + audience: jwtOptions.Value.Audience, + key: jwtOptions.Value.Key, + userId: user.Id.ToString(), + email: user.Email, + alias: user.Alias, + firstname: user.Firstname, + lastname: user.Lastname, + portraitUrl: user.PortraitUrl); + + await SendOkAsync( + new LoginWithGoogleResponse(accessToken, string.Empty), + cancellation: ct); + } +} From 130925eceb7d67fab1bdd1b96e13d52069ca892e Mon Sep 17 00:00:00 2001 From: Jonathan Bourdon Date: Sun, 6 Oct 2024 01:09:09 -0400 Subject: [PATCH 192/229] Fix typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a3820fe..170ea30 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ ## Tools - Install Docker : https://www.docker.com/get-started/ -- Install sql server management ( or preffered tool ) : https://learn.microsoft.com/en-us/sql/ssms/download-sql-server-management-studio-ssms?view=sql-server-ver16#download-ssms +- Install sql server management ( or preferred tool ) : https://learn.microsoft.com/en-us/sql/ssms/download-sql-server-management-studio-ssms?view=sql-server-ver16#download-ssms ## Database setup in docker for local dev ``` From a7835670c697da9bd1a5c23634cbb0f66225acab Mon Sep 17 00:00:00 2001 From: Jonathan Bourdon Date: Sun, 6 Oct 2024 01:09:28 -0400 Subject: [PATCH 193/229] Fix ChangeColorsHandler to support the new material palette --- .../Features/Contents/Handlers/CreateCreator.cs | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/Web/Features/Contents/Handlers/CreateCreator.cs b/src/Web/Features/Contents/Handlers/CreateCreator.cs index 1e3cca2..12cf41d 100644 --- a/src/Web/Features/Contents/Handlers/CreateCreator.cs +++ b/src/Web/Features/Contents/Handlers/CreateCreator.cs @@ -39,11 +39,24 @@ public sealed class CreateCreatorHandler( CancellationToken ct) { await context.Creators.AddAsync( - new() + new Creator { Id = req.CreatorId, CreatedBy = User.GetUserId(), - Name = req.Name + Name = req.Name, + Colors = + { + Primary = "#6200EE", + OnPrimary = "#FFFFFF", + Secondary = "#03DAC6", + OnSecondary = "#000000", + Surface = "#FFFFFF", + OnSurface = "#000000", + Error = "#B00020", + OnError = "#FFFFFF", + Background = "#FFFFFF", + OnBackground = "#000000", + } }, ct); From deae0f75ba02add66e8d5b40c15a0c7822ce573c Mon Sep 17 00:00:00 2001 From: Dominic Villemure Date: Sat, 12 Oct 2024 18:14:02 -0400 Subject: [PATCH 194/229] ContentEditor possibility to upload image in html post --- .../AzureBlob/AzureBlobStorage.cs | 4 +- src/Infrastructure/AzureBlob/ContentTypes.cs | 16 +- src/Web/Features/Contents/Data/Content.cs | 3 +- .../Handlers/CreateContentFromHtml.cs | 116 +++++++ .../Features/Contents/Handlers/GetContent.cs | 1 + .../Contents/Handlers/GetContentsByCreator.cs | 1 + .../Features/Contents/Handlers/InsertImage.cs | 84 +++++ .../Contents/Handlers/Models/ContentModel.cs | 1 + .../20241012183354_AddHtmlFileUrl.Designer.cs | 313 ++++++++++++++++++ .../20241012183354_AddHtmlFileUrl.cs | 30 ++ .../ContentDbContextModelSnapshot.cs | 3 + 11 files changed, 566 insertions(+), 6 deletions(-) create mode 100644 src/Web/Features/Contents/Handlers/CreateContentFromHtml.cs create mode 100644 src/Web/Features/Contents/Handlers/InsertImage.cs create mode 100644 src/Web/Features/Contents/Migrations/20241012183354_AddHtmlFileUrl.Designer.cs create mode 100644 src/Web/Features/Contents/Migrations/20241012183354_AddHtmlFileUrl.cs diff --git a/src/Infrastructure/AzureBlob/AzureBlobStorage.cs b/src/Infrastructure/AzureBlob/AzureBlobStorage.cs index 53b4342..fab5301 100644 --- a/src/Infrastructure/AzureBlob/AzureBlobStorage.cs +++ b/src/Infrastructure/AzureBlob/AzureBlobStorage.cs @@ -50,8 +50,8 @@ public class AzureBlobStorage : IBlobStorage if (!ContentTypes.IsAllowed(contentType, stream)) { _logger.LogError( - $"Blob storage: Unsupported file type {contentType}. Only PNG and JPEG are allowed."); - throw new InvalidOperationException("Unsupported file type. Only PNG and JPEG are allowed."); + $"Blob storage: Unsupported file type {contentType}."); + throw new InvalidOperationException("Unsupported file type."); } try diff --git a/src/Infrastructure/AzureBlob/ContentTypes.cs b/src/Infrastructure/AzureBlob/ContentTypes.cs index 2637fc9..e7f2da3 100644 --- a/src/Infrastructure/AzureBlob/ContentTypes.cs +++ b/src/Infrastructure/AzureBlob/ContentTypes.cs @@ -1,12 +1,15 @@ -namespace Hutopy.Infrastructure.AzureBlob; +using System.Text; + +namespace Hutopy.Infrastructure.AzureBlob; public static class ContentTypes { private static string ImagePng = "image/png"; private static string ImageJpeg = "image/jpeg"; private static string ImageJpg = "image/jpg"; + private static string TextHtml = "text/html"; - public static HashSet AllowedContentTypes = new HashSet { ImagePng, ImageJpeg, ImageJpg }; + public static HashSet AllowedContentTypes = new HashSet { ImagePng, ImageJpeg, ImageJpg, TextHtml }; public static bool IsAllowed(string contentType, Stream fileStream) { @@ -15,7 +18,7 @@ public static class ContentTypes private static bool IsValidFileType(Stream fileStream) { - byte[] buffer = new byte[4]; + byte[] buffer = new byte[512]; fileStream.Read(buffer, 0, buffer.Length); fileStream.Position = 0; @@ -30,6 +33,13 @@ public static class ContentTypes { return true; } + + // Check for HTML content by looking for "" or "" tags + string content = Encoding.UTF8.GetString(buffer); + if (content.Contains("")) + { + return true; + } return false; } diff --git a/src/Web/Features/Contents/Data/Content.cs b/src/Web/Features/Contents/Data/Content.cs index f782698..fcccd4b 100644 --- a/src/Web/Features/Contents/Data/Content.cs +++ b/src/Web/Features/Contents/Data/Content.cs @@ -11,7 +11,8 @@ public class Content public Guid? DeletedBy { get; set; } public DateTimeOffset? DeletedAt { get; set; } [MaxLength(128)] public required string Title { get; set; } - [MaxLength(2048)] public required string Description { get; set; } + [MaxLength(2048)] public string Description { get; set; } = ""; + public string? HtmlFileUrl { get; set; } = ""; public IList Reactions { get; set; } = new List(); public string[]? Urls { get; init; } } diff --git a/src/Web/Features/Contents/Handlers/CreateContentFromHtml.cs b/src/Web/Features/Contents/Handlers/CreateContentFromHtml.cs new file mode 100644 index 0000000..22a055c --- /dev/null +++ b/src/Web/Features/Contents/Handlers/CreateContentFromHtml.cs @@ -0,0 +1,116 @@ +using System.Text; +using Hutopy.Application.AzureBlobStorage.Constants; +using Hutopy.Application.Common.Interfaces; +using Hutopy.Web.Common; +using Hutopy.Web.Features.Contents.Data; +using Hutopy.Web.Features.Contents.Handlers.Models; + +namespace Hutopy.Web.Features.Contents.Handlers; + +[PublicAPI] +public record PostContentFromHtmlRequest( + Guid Id, + Guid CreatorId, + string Title, + string HtmlContent + ); + +[PublicAPI] +public sealed class PostContentFromHtmlRequestValidator : Validator +{ + public PostContentFromHtmlRequestValidator() + { + RuleFor(r => r.Id) + .NotNull().WithMessage("You should specify the Id") + .NotEmpty().WithMessage("You should specify a valid/not empty Id"); + + RuleFor(r => r.CreatorId) + .NotNull().WithMessage("You should specify the CreatorId") + .NotEmpty().WithMessage("You should specify a valid/not empty CreatorId"); + + RuleFor(r => r.Title) + .NotNull().WithMessage("You should specify the Title") + .NotEmpty().WithMessage("You should specify a valid/not empty Title"); + } +} + +public sealed class PostContentHtml( + IBlobStorage blobStorage, + ContentDbContext context) + : Endpoint +{ + public override void Configure() + { + Post("/api/contents/html"); + Options(o => o.WithTags("Contents")); + AllowFileUploads(); + } + + public override async Task HandleAsync( + PostContentFromHtmlRequest req, + CancellationToken ct) + { + var htmlFileUrl = await SaveHtmlContentAsHtmlFileAsync( + req.CreatorId, + req.Id, + req.HtmlContent, + ct); + + await context.Contents.AddAsync( + new Content + { + Id = req.Id, + CreatedBy = User.GetUserId(), + Title = req.Title, + HtmlFileUrl = htmlFileUrl + }, + ct); + + await context.SaveChangesAsync(ct); + + var content = await context + .Contents + .Select(c => new ContentModel + { + Id = c.Id, + CreatedBy = c.CreatedBy, + CreatedByName = c.Creator!.Name, + CreatedByPortraitUrl = c.Creator.Images.Logo, + CreatedAt = c.CreatedAt, + DeletedBy = c.DeletedBy, + DeletedAt = c.DeletedAt, + Title = c.Title, + Description = c.Description, + Urls = c.Urls, + HtmlFileUrl = htmlFileUrl + }) + .SingleOrDefaultAsync( + c => c.Id == req.Id, + cancellationToken: ct); + + await SendOkAsync(content, ct); + } + + private async Task SaveHtmlContentAsHtmlFileAsync( + Guid creatorId, + Guid contentId, + string htmlContent, + CancellationToken ct = default) + { + var fileName = $"{contentId}.html"; + var filePath = $"{creatorId}/{SubDirectoryNames.Contents}/{fileName}"; + + // Convert the HTML string into a stream + using var stream = new MemoryStream(Encoding.UTF8.GetBytes(htmlContent)); + + // Upload the stream as an HTML file + var url = await blobStorage.UploadFileAsync( + ContainerNames.Creators, + filePath, + stream, + "text/html", + ct: ct); + + return url; + } +} diff --git a/src/Web/Features/Contents/Handlers/GetContent.cs b/src/Web/Features/Contents/Handlers/GetContent.cs index fddba07..5bae8b6 100644 --- a/src/Web/Features/Contents/Handlers/GetContent.cs +++ b/src/Web/Features/Contents/Handlers/GetContent.cs @@ -40,6 +40,7 @@ public class GetContent( Title = c.Title, Description = c.Description, Urls = c.Urls, + HtmlFileUrl = c.HtmlFileUrl ?? "", Reactions = c.Reactions.Select(x => new ReactionModel { Reaction = x.Reaction.FromEnum(), UserId = x.UserId, UserName = x.UserName diff --git a/src/Web/Features/Contents/Handlers/GetContentsByCreator.cs b/src/Web/Features/Contents/Handlers/GetContentsByCreator.cs index 9689808..5a48d0c 100644 --- a/src/Web/Features/Contents/Handlers/GetContentsByCreator.cs +++ b/src/Web/Features/Contents/Handlers/GetContentsByCreator.cs @@ -51,6 +51,7 @@ public class GetContentsByCreatorHandler( Title = c.Title, Description = c.Description, Urls = c.Urls, + HtmlFileUrl = c.HtmlFileUrl ?? "", Reactions = c.Reactions.Select(x => new ReactionModel { Reaction = x.Reaction.FromEnum(), diff --git a/src/Web/Features/Contents/Handlers/InsertImage.cs b/src/Web/Features/Contents/Handlers/InsertImage.cs new file mode 100644 index 0000000..5db7d5c --- /dev/null +++ b/src/Web/Features/Contents/Handlers/InsertImage.cs @@ -0,0 +1,84 @@ +using Hutopy.Application.AzureBlobStorage.Constants; +using Hutopy.Application.Common.Interfaces; + +namespace Hutopy.Web.Features.Contents.Handlers; + +[PublicAPI] +public record InsertImagesRequest( + Guid Id, + Guid CreatorId, + IFormFileCollection? Files + ); + +[PublicAPI] +public sealed class InsertImagesRequestValidator : Validator +{ + public InsertImagesRequestValidator() + { + RuleFor(r => r.Id) + .NotNull().WithMessage("You should specify the Id") + .NotEmpty().WithMessage("You should specify a valid/not empty Id"); + + RuleFor(r => r.CreatorId) + .NotNull().WithMessage("You should specify the CreatorId") + .NotEmpty().WithMessage("You should specify a valid/not empty CreatorId"); + } +} + +public sealed class InsertImages(IBlobStorage blobStorage) : Endpoint +{ + public override void Configure() + { + Post("/api/content/insert-image/"); + Options(o => o.WithTags("Contents")); + AllowFileUploads(); + } + + public override async Task HandleAsync( + InsertImagesRequest req, + CancellationToken ct) + { + var urls = new List(); + if (req.Files is not null) + { + await Parallel.ForEachAsync( + req.Files, + ct, + async ( + file, + ict) => + { + try + { + var contentUrl = await SaveFileAsync( + req.CreatorId, + req.Id, + file, + ict); + urls.Add(contentUrl); + } + catch (Exception ex) + { + Logger.LogError("{ErrorMessage}", ex.Message); + } + }); + } + await SendOkAsync(urls, ct); + } + + private async Task SaveFileAsync( + Guid creatorId, + Guid contentId, + IFormFile file, + CancellationToken ct = default) + { + var url = await blobStorage.UploadFileAsync( + ContainerNames.Creators, + $"{creatorId}/{SubDirectoryNames.Contents}/{contentId}/{file.FileName}", + file.OpenReadStream(), + file.ContentType, + ct: ct); + + return url; + } +} diff --git a/src/Web/Features/Contents/Handlers/Models/ContentModel.cs b/src/Web/Features/Contents/Handlers/Models/ContentModel.cs index d91b23f..e053c53 100644 --- a/src/Web/Features/Contents/Handlers/Models/ContentModel.cs +++ b/src/Web/Features/Contents/Handlers/Models/ContentModel.cs @@ -12,6 +12,7 @@ public class ContentModel public DateTimeOffset? DeletedAt { get; init; } public required string Title { get; init; } public required string Description { get; init; } + public string HtmlFileUrl { get; init; } = ""; public required string[]? Urls { get; init; } public IList? Reactions { get; set; } = new List(); } diff --git a/src/Web/Features/Contents/Migrations/20241012183354_AddHtmlFileUrl.Designer.cs b/src/Web/Features/Contents/Migrations/20241012183354_AddHtmlFileUrl.Designer.cs new file mode 100644 index 0000000..40fc57e --- /dev/null +++ b/src/Web/Features/Contents/Migrations/20241012183354_AddHtmlFileUrl.Designer.cs @@ -0,0 +1,313 @@ +// +using System; +using Hutopy.Web.Features.Contents.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace Hutopy.Web.Features.Contents.Migrations +{ + [DbContext(typeof(ContentDbContext))] + [Migration("20241012183354_AddHtmlFileUrl")] + partial class AddHtmlFileUrl + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasDefaultSchema("Content") + .HasAnnotation("ProductVersion", "8.0.4") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("Hutopy.Web.Features.Contents.Data.Content", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("CURRENT_TIMESTAMP"); + + b.Property("CreatedBy") + .HasColumnType("uuid"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("DeletedBy") + .HasColumnType("uuid"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(2048) + .HasColumnType("character varying(2048)"); + + b.Property("HtmlFileUrl") + .HasColumnType("text"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("Urls") + .HasColumnType("text[]"); + + b.HasKey("Id"); + + b.HasIndex("CreatedBy"); + + b.ToTable("Contents", "Content"); + }); + + modelBuilder.Entity("Hutopy.Web.Features.Contents.Data.Creator", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("uuid"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("Title") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.HasKey("Id"); + + b.ToTable("Creators", "Content"); + }); + + modelBuilder.Entity("Hutopy.Web.Features.Contents.Data.Subscription", b => + { + b.Property("CreatedBy") + .HasColumnType("uuid"); + + b.Property("CreatorId") + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("CreatedBy", "CreatorId"); + + b.HasIndex("CreatorId"); + + b.ToTable("Subscriptions", "Content"); + }); + + modelBuilder.Entity("Hutopy.Web.Features.Contents.Data.Content", b => + { + b.HasOne("Hutopy.Web.Features.Contents.Data.Creator", "Creator") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.OwnsMany("Hutopy.Web.Features.Contents.Data.ContentReaction", "Reactions", b1 => + { + b1.Property("ContentId") + .HasColumnType("uuid"); + + b1.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b1.Property("Id")); + + b1.Property("Reaction") + .HasColumnType("integer"); + + b1.Property("UserId") + .HasColumnType("uuid"); + + b1.Property("UserName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b1.HasKey("ContentId", "Id"); + + b1.ToTable("ContentReactions", "Content"); + + b1.WithOwner() + .HasForeignKey("ContentId"); + }); + + b.Navigation("Creator"); + + b.Navigation("Reactions"); + }); + + modelBuilder.Entity("Hutopy.Web.Features.Contents.Data.Creator", b => + { + b.OwnsOne("Hutopy.Web.Features.Contents.Data.Colors", "Colors", b1 => + { + b1.Property("CreatorId") + .HasColumnType("uuid"); + + b1.Property("Background") + .IsRequired() + .HasMaxLength(9) + .HasColumnType("character varying(9)"); + + b1.Property("Error") + .IsRequired() + .HasMaxLength(9) + .HasColumnType("character varying(9)"); + + b1.Property("OnBackground") + .IsRequired() + .HasMaxLength(9) + .HasColumnType("character varying(9)"); + + b1.Property("OnError") + .IsRequired() + .HasMaxLength(9) + .HasColumnType("character varying(9)"); + + b1.Property("OnPrimary") + .IsRequired() + .HasMaxLength(9) + .HasColumnType("character varying(9)"); + + b1.Property("OnSecondary") + .IsRequired() + .HasMaxLength(9) + .HasColumnType("character varying(9)"); + + b1.Property("OnSurface") + .IsRequired() + .HasMaxLength(9) + .HasColumnType("character varying(9)"); + + b1.Property("Primary") + .IsRequired() + .HasMaxLength(9) + .HasColumnType("character varying(9)"); + + b1.Property("Secondary") + .IsRequired() + .HasMaxLength(9) + .HasColumnType("character varying(9)"); + + b1.Property("Surface") + .IsRequired() + .HasMaxLength(9) + .HasColumnType("character varying(9)"); + + b1.HasKey("CreatorId"); + + b1.ToTable("Colors", "Content"); + + b1.WithOwner() + .HasForeignKey("CreatorId"); + }); + + b.OwnsOne("Hutopy.Web.Features.Contents.Data.Images", "Images", b1 => + { + b1.Property("CreatorId") + .HasColumnType("uuid"); + + b1.Property("Banner") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.Property("Logo") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.HasKey("CreatorId"); + + b1.ToTable("Images", "Content"); + + b1.WithOwner() + .HasForeignKey("CreatorId"); + }); + + b.OwnsOne("Hutopy.Web.Features.Contents.Data.Socials", "Socials", b1 => + { + b1.Property("CreatorId") + .HasColumnType("uuid"); + + b1.Property("FacebookUrl") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.Property("InstagramUrl") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.Property("LinkedInUrl") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.Property("RedditUrl") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.Property("TikTokUrl") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.Property("WebsiteUrl") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.Property("XUrl") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.Property("YoutubeUrl") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.HasKey("CreatorId"); + + b1.ToTable("Socials", "Content"); + + b1.WithOwner() + .HasForeignKey("CreatorId"); + }); + + b.Navigation("Colors") + .IsRequired(); + + b.Navigation("Images") + .IsRequired(); + + b.Navigation("Socials") + .IsRequired(); + }); + + modelBuilder.Entity("Hutopy.Web.Features.Contents.Data.Subscription", b => + { + b.HasOne("Hutopy.Web.Features.Contents.Data.Creator", "Creator") + .WithMany() + .HasForeignKey("CreatorId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Creator"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Web/Features/Contents/Migrations/20241012183354_AddHtmlFileUrl.cs b/src/Web/Features/Contents/Migrations/20241012183354_AddHtmlFileUrl.cs new file mode 100644 index 0000000..25593d2 --- /dev/null +++ b/src/Web/Features/Contents/Migrations/20241012183354_AddHtmlFileUrl.cs @@ -0,0 +1,30 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Hutopy.Web.Features.Contents.Migrations +{ + /// + public partial class AddHtmlFileUrl : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "HtmlFileUrl", + schema: "Content", + table: "Contents", + type: "text", + nullable: true); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "HtmlFileUrl", + schema: "Content", + table: "Contents"); + } + } +} diff --git a/src/Web/Features/Contents/Migrations/ContentDbContextModelSnapshot.cs b/src/Web/Features/Contents/Migrations/ContentDbContextModelSnapshot.cs index f67224a..c38d421 100644 --- a/src/Web/Features/Contents/Migrations/ContentDbContextModelSnapshot.cs +++ b/src/Web/Features/Contents/Migrations/ContentDbContextModelSnapshot.cs @@ -48,6 +48,9 @@ namespace Hutopy.Web.Features.Contents.Migrations .HasMaxLength(2048) .HasColumnType("character varying(2048)"); + b.Property("HtmlFileUrl") + .HasColumnType("text"); + b.Property("Title") .IsRequired() .HasMaxLength(128) From 28d74503dfe2f247d9a3f2246dc960bc48dc4e26 Mon Sep 17 00:00:00 2001 From: Jonathan Bourdon Date: Sun, 20 Oct 2024 14:01:58 -0400 Subject: [PATCH 195/229] + Tips + Memberships - DDD - FutureCreator - UserTransactions --- Directory.Packages.props | 2 +- Hutopy.sln | 7 - global.json | 6 +- .../Behaviours/AuthorizationBehaviour.cs | 84 ----- .../Common/Behaviours/LoggingBehaviour.cs | 30 -- .../Common/Behaviours/PerformanceBehaviour.cs | 38 --- .../Behaviours/UnhandledExceptionBehaviour.cs | 25 -- .../Common/Behaviours/ValidationBehaviour.cs | 28 -- .../Exceptions/ForbiddenAccessException.cs | 6 - .../Common/Exceptions/ValidationException.cs | 17 - .../Interfaces/IApplicationDbContext.cs | 10 - .../Common/Interfaces/IBlobStorage.cs | 8 - .../Common/Interfaces/IIdentityService.cs | 28 -- .../Common/Interfaces/IRoleService.cs | 10 - .../Common/Interfaces/IStripeService.cs | 11 - src/Application/Common/Interfaces/IUser.cs | 6 - .../Common/Mappings/MappingExtensions.cs | 12 - .../Common/Models/PaginatedList.cs | 25 -- .../Common/Security/AuthorizeAttribute.cs | 23 -- src/Application/DependencyInjection.cs | 26 -- .../Commands/CreateFutureCreator.cs | 38 --- .../Queries/FutureCreatorListDto.cs | 20 -- .../Queries/GetFutureCreatorList.cs | 28 -- src/Application/GlobalUsings.cs | 6 - .../Commands/ConfirmStripeTransaction.cs | 73 ----- .../Commands/CreateSessionCheckoutCommand.cs | 44 --- .../Stripe/Queries/GetMyLastReceipt.cs | 27 -- .../Stripe/Queries/MyLastReceiptDto.cs | 6 - src/Application/Users/Commands/CreateUser.cs | 37 --- src/Application/Users/Commands/Login.cs | 27 -- .../Commands/UpdateCurrentUserCommand.cs | 50 --- .../Users/Queries/GetUser/GetUserById.cs | 23 -- .../Queries/GetUser/GetUserByUserName.cs | 23 -- .../Users/Queries/GetUser/UserDto.cs | 24 -- src/Domain/Entities/FutureCreator.cs | 11 - src/Domain/Entities/UserTransaction.cs | 20 -- src/Domain/GlobalUsings.cs | 3 - .../AzureBlob/AzureBlobStorage.cs | 3 +- src/Infrastructure/AzureBlob/ContentTypes.cs | 33 +- .../Data/ApplicationDbContext.cs | 22 +- .../UserTransactionConfiguration.cs | 21 -- .../AuditableEntityInterceptor.cs | 55 ---- .../DispatchDomainEventsInterceptor.cs | 45 --- src/Infrastructure/DependencyInjection.cs | 17 +- .../Identity/IdentityResultExtensions.cs | 2 +- .../Identity/IdentityService.cs | 195 +---------- .../Identity}/Models/Result.cs | 2 +- .../Identity}/Models/RoleModel.cs | 2 +- .../Identity}/Models/UserModel.cs | 2 +- src/Infrastructure/Identity/RoleService.cs | 49 --- src/Infrastructure/Stripe/StripeService.cs | 74 ----- src/Web/Controllers/FacebookController.cs | 8 +- src/Web/DependencyInjection.cs | 7 - src/Web/Endpoints/JoinUs.cs | 26 -- src/Web/Endpoints/Stripe.cs | 31 -- src/Web/Endpoints/UpdateMyUser.cs | 19 -- src/Web/Endpoints/Users.cs | 39 --- .../Contents/Data/ContentDbContext.cs | 8 +- .../Data/{Subscription.cs => Follower.cs} | 2 +- .../Contents/Handlers/ChangeBanner.cs | 4 +- .../Features/Contents/Handlers/ChangeLogo.cs | 4 +- .../Contents/Handlers/CreateContent.cs | 4 +- ...SubscribeToCreator.cs => FollowCreator.cs} | 24 +- .../Contents/Handlers/GetCreatorByAlias.cs | 4 +- .../Contents/Handlers/GetFollowedContents.cs | 75 ----- ...ubscriptions.cs => GetFollowedCreators.cs} | 12 +- .../Contents/Handlers/Models/CreatorModel.cs | 2 +- .../{SubscriptionModel.cs => FollowModel.cs} | 2 +- ...cribeFromCreator.cs => UnfollowCreator.cs} | 15 +- ...653_FromSubscribersToFollowers.Designer.cs | 310 ++++++++++++++++++ ...241011103653_FromSubscribersToFollowers.cs | 81 +++++ .../ContentDbContextModelSnapshot.cs | 6 +- src/Web/Features/Memberships/Data/Creator.cs | 8 + .../Memberships/Data/MembershipDbContext.cs | 58 ++++ .../Data/MembershipDbContextInitializer.cs | 34 ++ .../Features/Memberships/Data/Subscription.cs | 18 + src/Web/Features/Memberships/Data/Tier.cs | 14 + src/Web/Features/Memberships/Data/Tip.cs | 15 + .../Features/Memberships/Data/Transaction.cs | 11 + .../Memberships/DependencyInjection.cs | 27 ++ .../Memberships/Events/SubscriptionPaid.cs | 7 + .../Features/Memberships/Events/TipPaid.cs | 8 + .../Handlers/CancelSubscription.cs | 48 +++ .../Handlers/CreateMembershipTier.cs | 36 ++ .../Handlers/GetActiveSubscriptions.cs | 32 ++ .../Memberships/Handlers/GetMembershipTier.cs | 47 +++ .../Memberships/Handlers/GetReceivedTips.cs | 45 +++ .../Memberships/Handlers/GetSentTips.cs | 45 +++ .../Memberships/Handlers/HandleStripe.cs | 71 ++++ .../Features/Memberships/Handlers/SendTip.cs | 117 +++++++ .../Handlers/SubscribeToCreator.cs | 110 +++++++ .../20241011100852_Initial.Designer.cs | 233 +++++++++++++ .../Migrations/20241011100852_Initial.cs | 170 ++++++++++ .../MembershipDbContextModelSnapshot.cs | 230 +++++++++++++ .../Services/PushNotificationService.cs | 13 + .../Memberships/Services/StripeService.cs | 224 +++++++++++++ .../Features/Users/Handlers/ChangePortrait.cs | 4 +- .../Features/Users/Handlers/GetCurrentUser.cs | 5 +- .../Handlers/GetCurrentUserProfilePicture.cs | 7 +- .../Features/Wallets/UserTransactionDto.cs | 14 - .../Infrastructure/CustomExceptionHandler.cs | 87 ----- src/Web/Infrastructure/EndpointGroupBase.cs | 6 - .../IEndpointRouteBuilderExtensions.cs | 46 --- .../Infrastructure/MethodInfoExtensions.cs | 18 - .../WebApplicationExtensions.cs | 37 --- src/Web/Program.cs | 17 +- src/Web/Services/CurrentUser.cs | 11 - src/Web/TestDataSeeder.cs | 2 +- src/Web/Web.http | 34 +- src/Web/appsettings.Development.json | 4 +- stripe.exe | Bin 0 -> 22229504 bytes .../CustomWebApplicationFactory.cs | 18 +- .../Application.UnitTests.csproj | 26 -- .../Common/Behaviours/RequestLoggerTests.cs | 18 - .../Exceptions/ValidationExceptionTests.cs | 63 ---- .../Common/Mappings/MappingTests.cs | 36 -- update-databases.sh | 7 + 117 files changed, 2149 insertions(+), 1999 deletions(-) delete mode 100644 src/Application/Common/Behaviours/AuthorizationBehaviour.cs delete mode 100644 src/Application/Common/Behaviours/LoggingBehaviour.cs delete mode 100644 src/Application/Common/Behaviours/PerformanceBehaviour.cs delete mode 100644 src/Application/Common/Behaviours/UnhandledExceptionBehaviour.cs delete mode 100644 src/Application/Common/Behaviours/ValidationBehaviour.cs delete mode 100644 src/Application/Common/Exceptions/ForbiddenAccessException.cs delete mode 100644 src/Application/Common/Exceptions/ValidationException.cs delete mode 100644 src/Application/Common/Interfaces/IApplicationDbContext.cs delete mode 100644 src/Application/Common/Interfaces/IBlobStorage.cs delete mode 100644 src/Application/Common/Interfaces/IIdentityService.cs delete mode 100644 src/Application/Common/Interfaces/IRoleService.cs delete mode 100644 src/Application/Common/Interfaces/IStripeService.cs delete mode 100644 src/Application/Common/Interfaces/IUser.cs delete mode 100644 src/Application/Common/Mappings/MappingExtensions.cs delete mode 100644 src/Application/Common/Models/PaginatedList.cs delete mode 100644 src/Application/Common/Security/AuthorizeAttribute.cs delete mode 100644 src/Application/DependencyInjection.cs delete mode 100644 src/Application/FutureCreators/Commands/CreateFutureCreator.cs delete mode 100644 src/Application/FutureCreators/Queries/FutureCreatorListDto.cs delete mode 100644 src/Application/FutureCreators/Queries/GetFutureCreatorList.cs delete mode 100644 src/Application/GlobalUsings.cs delete mode 100644 src/Application/Stripe/Commands/ConfirmStripeTransaction.cs delete mode 100644 src/Application/Stripe/Commands/CreateSessionCheckoutCommand.cs delete mode 100644 src/Application/Stripe/Queries/GetMyLastReceipt.cs delete mode 100644 src/Application/Stripe/Queries/MyLastReceiptDto.cs delete mode 100644 src/Application/Users/Commands/CreateUser.cs delete mode 100644 src/Application/Users/Commands/Login.cs delete mode 100644 src/Application/Users/Commands/UpdateCurrentUserCommand.cs delete mode 100644 src/Application/Users/Queries/GetUser/GetUserById.cs delete mode 100644 src/Application/Users/Queries/GetUser/GetUserByUserName.cs delete mode 100644 src/Application/Users/Queries/GetUser/UserDto.cs delete mode 100644 src/Domain/Entities/FutureCreator.cs delete mode 100644 src/Domain/Entities/UserTransaction.cs delete mode 100644 src/Infrastructure/Data/Configurations/UserTransactionConfiguration.cs delete mode 100644 src/Infrastructure/Data/Interceptors/AuditableEntityInterceptor.cs delete mode 100644 src/Infrastructure/Data/Interceptors/DispatchDomainEventsInterceptor.cs rename src/{Application/Common => Infrastructure/Identity}/Models/Result.cs (95%) rename src/{Application/Common => Infrastructure/Identity}/Models/RoleModel.cs (66%) rename src/{Application/Common => Infrastructure/Identity}/Models/UserModel.cs (90%) delete mode 100644 src/Infrastructure/Identity/RoleService.cs delete mode 100644 src/Infrastructure/Stripe/StripeService.cs delete mode 100644 src/Web/Endpoints/JoinUs.cs delete mode 100644 src/Web/Endpoints/Stripe.cs delete mode 100644 src/Web/Endpoints/UpdateMyUser.cs delete mode 100644 src/Web/Endpoints/Users.cs rename src/Web/Features/Contents/Data/{Subscription.cs => Follower.cs} (89%) rename src/Web/Features/Contents/Handlers/{SubscribeToCreator.cs => FollowCreator.cs} (59%) delete mode 100644 src/Web/Features/Contents/Handlers/GetFollowedContents.cs rename src/Web/Features/Contents/Handlers/{GetSubscriptions.cs => GetFollowedCreators.cs} (73%) rename src/Web/Features/Contents/Handlers/Models/{SubscriptionModel.cs => FollowModel.cs} (81%) rename src/Web/Features/Contents/Handlers/{UnsubscribeFromCreator.cs => UnfollowCreator.cs} (75%) create mode 100644 src/Web/Features/Contents/Migrations/20241011103653_FromSubscribersToFollowers.Designer.cs create mode 100644 src/Web/Features/Contents/Migrations/20241011103653_FromSubscribersToFollowers.cs create mode 100644 src/Web/Features/Memberships/Data/Creator.cs create mode 100644 src/Web/Features/Memberships/Data/MembershipDbContext.cs create mode 100644 src/Web/Features/Memberships/Data/MembershipDbContextInitializer.cs create mode 100644 src/Web/Features/Memberships/Data/Subscription.cs create mode 100644 src/Web/Features/Memberships/Data/Tier.cs create mode 100644 src/Web/Features/Memberships/Data/Tip.cs create mode 100644 src/Web/Features/Memberships/Data/Transaction.cs create mode 100644 src/Web/Features/Memberships/DependencyInjection.cs create mode 100644 src/Web/Features/Memberships/Events/SubscriptionPaid.cs create mode 100644 src/Web/Features/Memberships/Events/TipPaid.cs create mode 100644 src/Web/Features/Memberships/Handlers/CancelSubscription.cs create mode 100644 src/Web/Features/Memberships/Handlers/CreateMembershipTier.cs create mode 100644 src/Web/Features/Memberships/Handlers/GetActiveSubscriptions.cs create mode 100644 src/Web/Features/Memberships/Handlers/GetMembershipTier.cs create mode 100644 src/Web/Features/Memberships/Handlers/GetReceivedTips.cs create mode 100644 src/Web/Features/Memberships/Handlers/GetSentTips.cs create mode 100644 src/Web/Features/Memberships/Handlers/HandleStripe.cs create mode 100644 src/Web/Features/Memberships/Handlers/SendTip.cs create mode 100644 src/Web/Features/Memberships/Handlers/SubscribeToCreator.cs create mode 100644 src/Web/Features/Memberships/Migrations/20241011100852_Initial.Designer.cs create mode 100644 src/Web/Features/Memberships/Migrations/20241011100852_Initial.cs create mode 100644 src/Web/Features/Memberships/Migrations/MembershipDbContextModelSnapshot.cs create mode 100644 src/Web/Features/Memberships/Services/PushNotificationService.cs create mode 100644 src/Web/Features/Memberships/Services/StripeService.cs delete mode 100644 src/Web/Features/Wallets/UserTransactionDto.cs delete mode 100644 src/Web/Infrastructure/CustomExceptionHandler.cs delete mode 100644 src/Web/Infrastructure/EndpointGroupBase.cs delete mode 100644 src/Web/Infrastructure/IEndpointRouteBuilderExtensions.cs delete mode 100644 src/Web/Infrastructure/MethodInfoExtensions.cs delete mode 100644 src/Web/Infrastructure/WebApplicationExtensions.cs delete mode 100644 src/Web/Services/CurrentUser.cs create mode 100644 stripe.exe delete mode 100644 tests/Application.UnitTests/Application.UnitTests.csproj delete mode 100644 tests/Application.UnitTests/Common/Behaviours/RequestLoggerTests.cs delete mode 100644 tests/Application.UnitTests/Common/Exceptions/ValidationExceptionTests.cs delete mode 100644 tests/Application.UnitTests/Common/Mappings/MappingTests.cs diff --git a/Directory.Packages.props b/Directory.Packages.props index 438dfe2..ada3c11 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -46,7 +46,7 @@ - + \ No newline at end of file diff --git a/Hutopy.sln b/Hutopy.sln index cf13057..451a7bc 100644 --- a/Hutopy.sln +++ b/Hutopy.sln @@ -13,8 +13,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{6ED356A7-8B4 EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{664D406C-2F83-48F0-BFC3-408D5CB53C65}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Application.UnitTests", "tests\Application.UnitTests\Application.UnitTests.csproj", "{DEFF4009-1FAB-4392-80B6-707E2DC5C00B}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Domain.UnitTests", "tests\Domain.UnitTests\Domain.UnitTests.csproj", "{DC37FD87-552C-4613-9F16-1537CA522898}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{E2DA20AA-28D1-455C-BF50-C49A8F831633}" @@ -54,10 +52,6 @@ Global {117DA02F-5274-4565-ACC6-DA9B6E568B09}.Debug|Any CPU.Build.0 = Debug|Any CPU {117DA02F-5274-4565-ACC6-DA9B6E568B09}.Release|Any CPU.ActiveCfg = Release|Any CPU {117DA02F-5274-4565-ACC6-DA9B6E568B09}.Release|Any CPU.Build.0 = Release|Any CPU - {DEFF4009-1FAB-4392-80B6-707E2DC5C00B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {DEFF4009-1FAB-4392-80B6-707E2DC5C00B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {DEFF4009-1FAB-4392-80B6-707E2DC5C00B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {DEFF4009-1FAB-4392-80B6-707E2DC5C00B}.Release|Any CPU.Build.0 = Release|Any CPU {DC37FD87-552C-4613-9F16-1537CA522898}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {DC37FD87-552C-4613-9F16-1537CA522898}.Debug|Any CPU.Build.0 = Debug|Any CPU {DC37FD87-552C-4613-9F16-1537CA522898}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -82,7 +76,6 @@ Global {C7E89A3E-A631-4760-8D61-BD1EAB1C4E69} = {6ED356A7-8B47-4613-AD01-C85CF28491BD} {34C0FACD-F3D9-400C-8945-554DD6B0819A} = {6ED356A7-8B47-4613-AD01-C85CF28491BD} {117DA02F-5274-4565-ACC6-DA9B6E568B09} = {6ED356A7-8B47-4613-AD01-C85CF28491BD} - {DEFF4009-1FAB-4392-80B6-707E2DC5C00B} = {664D406C-2F83-48F0-BFC3-408D5CB53C65} {DC37FD87-552C-4613-9F16-1537CA522898} = {664D406C-2F83-48F0-BFC3-408D5CB53C65} {4E4EE20C-F06A-4A1B-851F-C5577796941C} = {6ED356A7-8B47-4613-AD01-C85CF28491BD} {EA6127A5-94C9-4C31-AD11-E6811B92B520} = {664D406C-2F83-48F0-BFC3-408D5CB53C65} diff --git a/global.json b/global.json index 05cf0d8..b5b37b6 100644 --- a/global.json +++ b/global.json @@ -1,7 +1,7 @@ { "sdk": { - "version": "8.0.203", - "rollForward": "latestFeature", - "allowPrerelease": true + "version": "8.0.0", + "rollForward": "latestMajor", + "allowPrerelease": false } } \ No newline at end of file diff --git a/src/Application/Common/Behaviours/AuthorizationBehaviour.cs b/src/Application/Common/Behaviours/AuthorizationBehaviour.cs deleted file mode 100644 index 8012cce..0000000 --- a/src/Application/Common/Behaviours/AuthorizationBehaviour.cs +++ /dev/null @@ -1,84 +0,0 @@ -using System.Reflection; -using Hutopy.Application.Common.Exceptions; -using Hutopy.Application.Common.Interfaces; -using Hutopy.Application.Common.Security; - -namespace Hutopy.Application.Common.Behaviours; - -public class AuthorizationBehaviour( - IUser user, - IIdentityService identityService) - : IPipelineBehavior - where TRequest : notnull -{ - public async Task Handle(TRequest request, RequestHandlerDelegate next, - CancellationToken cancellationToken) - { - var authorizeAttributes = request - .GetType() - .GetCustomAttributes() - .ToArray(); - - if (authorizeAttributes.Length == 0) - { - return await next(); - } - - if (user.Id is null) - { - throw new UnauthorizedAccessException(); - } - - // Role-based authorization - var authorizeAttributesWithRoles = authorizeAttributes - .Where(a => !string.IsNullOrWhiteSpace(a.Roles)) - .ToArray(); - - if (authorizeAttributesWithRoles.Length != 0) - { - var authorized = false; - - foreach (var roles in authorizeAttributesWithRoles.Select(a => a.Roles.Split(','))) - { - foreach (var role in roles) - { - var isInRole = await identityService.IsInRoleAsync(user.Id.Value, role.Trim()); - if (isInRole) - { - authorized = true; - break; - } - } - } - - // Must be a member of at least one role in roles - if (!authorized) - { - throw new ForbiddenAccessException(); - } - } - - // Policy-based authorization - var authorizeAttributesWithPolicies = authorizeAttributes - .Where(a => !string.IsNullOrWhiteSpace(a.Policy)) - .ToArray(); - - if (authorizeAttributesWithPolicies.Length == 0) - { - return await next(); - } - - foreach (var policy in authorizeAttributesWithPolicies.Select(a => a.Policy)) - { - var authorized = await identityService.AuthorizeAsync(user.Id.Value, policy); - - if (!authorized) - { - throw new ForbiddenAccessException(); - } - } - - // User is authorized / authorization not required - return await next(); - } -} diff --git a/src/Application/Common/Behaviours/LoggingBehaviour.cs b/src/Application/Common/Behaviours/LoggingBehaviour.cs deleted file mode 100644 index def9dca..0000000 --- a/src/Application/Common/Behaviours/LoggingBehaviour.cs +++ /dev/null @@ -1,30 +0,0 @@ -using Hutopy.Application.Common.Interfaces; -using MediatR.Pipeline; -using Microsoft.Extensions.Logging; - -namespace Hutopy.Application.Common.Behaviours; - -public class LoggingBehaviour( - ILogger logger, - IUser user, - IIdentityService identityService) - : IRequestPreProcessor - where TRequest : notnull -{ - private readonly ILogger _logger = logger; - - public async Task Process(TRequest request, CancellationToken cancellationToken) - { - var requestName = typeof(TRequest).Name; - string? userName = string.Empty; - - if (user.Id.HasValue) - { - userName = await identityService.GetUserNameAsync(user.Id.Value); - } - - _logger.LogInformation( - "Hutopy Request: {Name} {@UserId} {@UserName} {@Request}", - requestName, user.Id ?? Guid.Empty, userName, request); - } -} diff --git a/src/Application/Common/Behaviours/PerformanceBehaviour.cs b/src/Application/Common/Behaviours/PerformanceBehaviour.cs deleted file mode 100644 index 20a82a2..0000000 --- a/src/Application/Common/Behaviours/PerformanceBehaviour.cs +++ /dev/null @@ -1,38 +0,0 @@ -using System.Diagnostics; -using Hutopy.Application.Common.Interfaces; -using Microsoft.Extensions.Logging; - -namespace Hutopy.Application.Common.Behaviours; - -public class PerformanceBehaviour( - ILogger logger, - IUser user, - IIdentityService identityService) - : IPipelineBehavior - where TRequest : notnull -{ - private readonly Stopwatch _timer = new(); - - public async Task Handle(TRequest request, RequestHandlerDelegate next, CancellationToken cancellationToken) - { - _timer.Start(); - - var response = await next(); - - _timer.Stop(); - - var elapsedMilliseconds = _timer.ElapsedMilliseconds; - - if (elapsedMilliseconds <= 500) return response; - - var requestName = typeof(TRequest).Name; - var userName = string.Empty; - - if (user.Id.HasValue) userName = await identityService.GetUserNameAsync(user.Id.Value); - - logger.LogWarning("Hutopy Long Running Request: {Name} ({ElapsedMilliseconds} milliseconds) {@UserId} {@UserName} {@Request}", - requestName, elapsedMilliseconds, user.Id ?? Guid.Empty, userName, request); - - return response; - } -} diff --git a/src/Application/Common/Behaviours/UnhandledExceptionBehaviour.cs b/src/Application/Common/Behaviours/UnhandledExceptionBehaviour.cs deleted file mode 100644 index 28d2a94..0000000 --- a/src/Application/Common/Behaviours/UnhandledExceptionBehaviour.cs +++ /dev/null @@ -1,25 +0,0 @@ -using Microsoft.Extensions.Logging; - -namespace Hutopy.Application.Common.Behaviours; - -public class UnhandledExceptionBehaviour( - ILogger logger) - : IPipelineBehavior - where TRequest : notnull -{ - public async Task Handle(TRequest request, RequestHandlerDelegate next, CancellationToken cancellationToken) - { - try - { - return await next(); - } - catch (Exception ex) - { - var requestName = typeof(TRequest).Name; - - logger.LogError(ex, "Hutopy Request: Unhandled Exception for Request {Name} {@Request}", requestName, request); - - throw; - } - } -} diff --git a/src/Application/Common/Behaviours/ValidationBehaviour.cs b/src/Application/Common/Behaviours/ValidationBehaviour.cs deleted file mode 100644 index a564099..0000000 --- a/src/Application/Common/Behaviours/ValidationBehaviour.cs +++ /dev/null @@ -1,28 +0,0 @@ -using ValidationException = Hutopy.Application.Common.Exceptions.ValidationException; - -namespace Hutopy.Application.Common.Behaviours; - -public class ValidationBehaviour(IEnumerable> validators) - : IPipelineBehavior - where TRequest : notnull -{ - public async Task Handle(TRequest request, RequestHandlerDelegate next, CancellationToken cancellationToken) - { - if (!validators.Any()) return await next(); - - var context = new ValidationContext(request); - - var validationResults = await Task.WhenAll( - validators.Select(v => - v.ValidateAsync(context, cancellationToken))); - - var failures = validationResults - .Where(r => r.Errors.Any()) - .SelectMany(r => r.Errors) - .ToList(); - - if (failures.Count != 0) throw new ValidationException(failures); - - return await next(); - } -} diff --git a/src/Application/Common/Exceptions/ForbiddenAccessException.cs b/src/Application/Common/Exceptions/ForbiddenAccessException.cs deleted file mode 100644 index 41f91eb..0000000 --- a/src/Application/Common/Exceptions/ForbiddenAccessException.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace Hutopy.Application.Common.Exceptions; - -public class ForbiddenAccessException : Exception -{ - public ForbiddenAccessException() : base() { } -} diff --git a/src/Application/Common/Exceptions/ValidationException.cs b/src/Application/Common/Exceptions/ValidationException.cs deleted file mode 100644 index f167275..0000000 --- a/src/Application/Common/Exceptions/ValidationException.cs +++ /dev/null @@ -1,17 +0,0 @@ -using FluentValidation.Results; - -namespace Hutopy.Application.Common.Exceptions; - -public class ValidationException() - : Exception("One or more validation failures have occurred.") -{ - public ValidationException(IEnumerable failures) - : this() - { - Errors = failures - .GroupBy(e => e.PropertyName, e => e.ErrorMessage) - .ToDictionary(failureGroup => failureGroup.Key, failureGroup => failureGroup.ToArray()); - } - - public IDictionary Errors { get; } = new Dictionary(); -} diff --git a/src/Application/Common/Interfaces/IApplicationDbContext.cs b/src/Application/Common/Interfaces/IApplicationDbContext.cs deleted file mode 100644 index 75eabb6..0000000 --- a/src/Application/Common/Interfaces/IApplicationDbContext.cs +++ /dev/null @@ -1,10 +0,0 @@ -using Hutopy.Domain.Entities; - -namespace Hutopy.Application.Common.Interfaces; - -public interface IApplicationDbContext -{ - DbSet FutureCreators { get; } - DbSet UserTransactions { get; } - Task SaveChangesAsync(CancellationToken cancellationToken); -} diff --git a/src/Application/Common/Interfaces/IBlobStorage.cs b/src/Application/Common/Interfaces/IBlobStorage.cs deleted file mode 100644 index 7dac254..0000000 --- a/src/Application/Common/Interfaces/IBlobStorage.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace Hutopy.Application.Common.Interfaces; - -public interface IBlobStorage -{ - Task UploadFileAsync(string containerName, string blobName, Stream stream, string contentType, - CancellationToken ct = default); - Task DownloadFileAsync(string containerName, string blobName, CancellationToken ct = default); -} diff --git a/src/Application/Common/Interfaces/IIdentityService.cs b/src/Application/Common/Interfaces/IIdentityService.cs deleted file mode 100644 index 3ebbfb3..0000000 --- a/src/Application/Common/Interfaces/IIdentityService.cs +++ /dev/null @@ -1,28 +0,0 @@ -using Hutopy.Application.Common.Models; - -namespace Hutopy.Application.Common.Interfaces; - -public interface IIdentityService -{ - Task> CreateUserAsync( - string email, - string userName, - string firstName, - string lastName, - string password); - - Task GetCurrentUserAsync(); - Task UpdateCurrentUserPortraitUrlAsync(string url); - Task> UpdateCurrentUserAsync(UserModel userModel); - Task> GetCurrentUserRolesAsync(); - Task FindUserByIdAsync(string id); - Task FindUserByEmailAsync(string email); - Task GetUserByUserNameAsync(string userName); - Task LoginAsync(string email, string password); - Task IsInRoleAsync(Guid userId, string role); - Task AuthorizeAsync(Guid userId, string policyName); - Task GetUserNameAsync(Guid userId); - - Task AddRoleAsync(string userId, string role); - Task DeleteUserAsync(string userId); -} diff --git a/src/Application/Common/Interfaces/IRoleService.cs b/src/Application/Common/Interfaces/IRoleService.cs deleted file mode 100644 index 96ed4d2..0000000 --- a/src/Application/Common/Interfaces/IRoleService.cs +++ /dev/null @@ -1,10 +0,0 @@ -using Hutopy.Application.Common.Models; - -namespace Hutopy.Application.Common.Interfaces; - -public interface IRoleService -{ - public Task CreateRoleAsync(string roleName); - public Task DeleteRoleAsync(string roleName); - public Task FindRoleByIdAsync(string roleId); -} diff --git a/src/Application/Common/Interfaces/IStripeService.cs b/src/Application/Common/Interfaces/IStripeService.cs deleted file mode 100644 index 6737a3d..0000000 --- a/src/Application/Common/Interfaces/IStripeService.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Hutopy.Application.Common.Models; -using Hutopy.Application.Stripe.Commands; - -namespace Hutopy.Application.Common.Interfaces; - - -public interface IStripeService -{ - public Task CreateCheckoutSession(int amount, string creatorId, string currency); - public Result ValidateTransaction(ConfirmStripeTransactionCommand request); -} diff --git a/src/Application/Common/Interfaces/IUser.cs b/src/Application/Common/Interfaces/IUser.cs deleted file mode 100644 index ede555b..0000000 --- a/src/Application/Common/Interfaces/IUser.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace Hutopy.Application.Common.Interfaces; - -public interface IUser -{ - Guid? Id { get; } -} diff --git a/src/Application/Common/Mappings/MappingExtensions.cs b/src/Application/Common/Mappings/MappingExtensions.cs deleted file mode 100644 index bdbb707..0000000 --- a/src/Application/Common/Mappings/MappingExtensions.cs +++ /dev/null @@ -1,12 +0,0 @@ -using Hutopy.Application.Common.Models; - -namespace Hutopy.Application.Common.Mappings; - -public static class MappingExtensions -{ - public static Task> PaginatedListAsync(this IQueryable queryable, int pageNumber, int pageSize) where TDestination : class - => PaginatedList.CreateAsync(queryable.AsNoTracking(), pageNumber, pageSize); - - public static Task> ProjectToListAsync(this IQueryable queryable, IConfigurationProvider configuration) where TDestination : class - => queryable.ProjectTo(configuration).AsNoTracking().ToListAsync(); -} diff --git a/src/Application/Common/Models/PaginatedList.cs b/src/Application/Common/Models/PaginatedList.cs deleted file mode 100644 index e0a4e59..0000000 --- a/src/Application/Common/Models/PaginatedList.cs +++ /dev/null @@ -1,25 +0,0 @@ -namespace Hutopy.Application.Common.Models; - -public class PaginatedList( - IReadOnlyCollection items, - int count, - int pageNumber, - int pageSize) -{ - public IReadOnlyCollection Items { get; } = items; - public int PageNumber { get; } = pageNumber; - public int TotalPages { get; } = (int)Math.Ceiling(count / (double)pageSize); - public int TotalCount { get; } = count; - - public bool HasPreviousPage => PageNumber > 1; - - public bool HasNextPage => PageNumber < TotalPages; - - public static async Task> CreateAsync(IQueryable source, int pageNumber, int pageSize) - { - var count = await source.CountAsync(); - var items = await source.Skip((pageNumber - 1) * pageSize).Take(pageSize).ToListAsync(); - - return new PaginatedList(items, count, pageNumber, pageSize); - } -} diff --git a/src/Application/Common/Security/AuthorizeAttribute.cs b/src/Application/Common/Security/AuthorizeAttribute.cs deleted file mode 100644 index ad2e1e1..0000000 --- a/src/Application/Common/Security/AuthorizeAttribute.cs +++ /dev/null @@ -1,23 +0,0 @@ -namespace Hutopy.Application.Common.Security; - -/// -/// Specifies the class this attribute is applied to requires authorization. -/// -[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] -public class AuthorizeAttribute : Attribute -{ - /// - /// Initializes a new instance of the class. - /// - public AuthorizeAttribute() { } - - /// - /// Gets or sets a comma delimited list of roles that are allowed to access the resource. - /// - public string Roles { get; set; } = string.Empty; - - /// - /// Gets or sets the policy name that determines access to the resource. - /// - public string Policy { get; set; } = string.Empty; -} diff --git a/src/Application/DependencyInjection.cs b/src/Application/DependencyInjection.cs deleted file mode 100644 index 41c71da..0000000 --- a/src/Application/DependencyInjection.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System.Reflection; -using Hutopy.Application.Common.Behaviours; -using Microsoft.Extensions.DependencyInjection; - -namespace Hutopy.Application; - -public static class DependencyInjection -{ - public static IServiceCollection AddApplicationServices(this IServiceCollection services) - { - services.AddAutoMapper(Assembly.GetExecutingAssembly()); - - services.AddValidatorsFromAssembly(Assembly.GetExecutingAssembly()); - - services.AddMediatR(cfg => - { - cfg.RegisterServicesFromAssembly(Assembly.GetExecutingAssembly()); - //cfg.AddBehavior(typeof(IPipelineBehavior<,>), typeof(UnhandledExceptionBehaviour<,>)); - cfg.AddBehavior(typeof(IPipelineBehavior<,>), typeof(AuthorizationBehaviour<,>)); - //cfg.AddBehavior(typeof(IPipelineBehavior<,>), typeof(ValidationBehaviour<,>)); - //cfg.AddBehavior(typeof(IPipelineBehavior<,>), typeof(PerformanceBehaviour<,>)); - }); - - return services; - } -} diff --git a/src/Application/FutureCreators/Commands/CreateFutureCreator.cs b/src/Application/FutureCreators/Commands/CreateFutureCreator.cs deleted file mode 100644 index 7aa7f50..0000000 --- a/src/Application/FutureCreators/Commands/CreateFutureCreator.cs +++ /dev/null @@ -1,38 +0,0 @@ -using Hutopy.Application.Common.Interfaces; -using Hutopy.Domain.Entities; - -namespace Hutopy.Application.FutureCreators.Commands; - -public record CreateFutureCreatorCommand : IRequest -{ - public required string FirstName { get; init; } - public required string LastName { get; init; } - public required string EmailAddress { get; init; } - public required string PhoneNumber { get; init; } - public required string SocialNetworkAccount { get; init; } - public required string ReasonToJoin { get; init; } -} - -public class CreateFutureCreatorCommandHandler( - IApplicationDbContext context) - : IRequestHandler -{ - public async Task Handle(CreateFutureCreatorCommand request, CancellationToken cancellationToken) - { - var entity = new FutureCreator - { - FirstName = request.FirstName, - LastName = request.LastName, - EmailAddress = request.EmailAddress, - PhoneNumber = request.PhoneNumber, - SocialNetworkAccount = request.SocialNetworkAccount, - ReasonToJoin = request.ReasonToJoin, - }; - - context.FutureCreators.Add(entity); - - await context.SaveChangesAsync(cancellationToken); - - return entity.Id; - } -} diff --git a/src/Application/FutureCreators/Queries/FutureCreatorListDto.cs b/src/Application/FutureCreators/Queries/FutureCreatorListDto.cs deleted file mode 100644 index 13d95ba..0000000 --- a/src/Application/FutureCreators/Queries/FutureCreatorListDto.cs +++ /dev/null @@ -1,20 +0,0 @@ -using Hutopy.Domain.Entities; - -namespace Hutopy.Application.FutureCreators.Queries; - -public class FutureCreatorListDto -{ - public Guid Id { get; init; } - - public required string FirstName { get; init; } - - public required string LastName { get; init; } - - private class Mapping : Profile - { - public Mapping() - { - CreateMap(); - } - } -} diff --git a/src/Application/FutureCreators/Queries/GetFutureCreatorList.cs b/src/Application/FutureCreators/Queries/GetFutureCreatorList.cs deleted file mode 100644 index 0281518..0000000 --- a/src/Application/FutureCreators/Queries/GetFutureCreatorList.cs +++ /dev/null @@ -1,28 +0,0 @@ - -using Hutopy.Application.Common.Interfaces; -using Hutopy.Application.Common.Mappings; -using Hutopy.Application.Common.Models; -using Hutopy.Application.Common.Security; - -namespace Hutopy.Application.FutureCreators.Queries; - -[Authorize(Roles = "Administrator")] -public record GetFutureCreatorListQuery : IRequest> -{ - public int PageNumber { get; init; } = 1; - public int PageSize { get; init; } = 10; -} - -public class GetFutureCreatorListQueryHandler( - IApplicationDbContext context, - IMapper mapper) - : IRequestHandler> -{ - public async Task> Handle(GetFutureCreatorListQuery request, CancellationToken cancellationToken) - { - return await context.FutureCreators - .OrderBy(x => x.FirstName) - .ProjectTo(mapper.ConfigurationProvider) - .PaginatedListAsync(request.PageNumber, request.PageSize); - } -} diff --git a/src/Application/GlobalUsings.cs b/src/Application/GlobalUsings.cs deleted file mode 100644 index fa904ba..0000000 --- a/src/Application/GlobalUsings.cs +++ /dev/null @@ -1,6 +0,0 @@ -global using Ardalis.GuardClauses; -global using AutoMapper; -global using AutoMapper.QueryableExtensions; -global using Microsoft.EntityFrameworkCore; -global using FluentValidation; -global using MediatR; \ No newline at end of file diff --git a/src/Application/Stripe/Commands/ConfirmStripeTransaction.cs b/src/Application/Stripe/Commands/ConfirmStripeTransaction.cs deleted file mode 100644 index e287b45..0000000 --- a/src/Application/Stripe/Commands/ConfirmStripeTransaction.cs +++ /dev/null @@ -1,73 +0,0 @@ -using Hutopy.Application.Common.Interfaces; - -namespace Hutopy.Application.Stripe.Commands; -public class ConfirmStripeTransactionCommand : IRequest -{ - public string Id { get; set; } - public string Object { get; set; } - public int Created { get; set; } - public Data Data { get; set; } - public Request Request { get; set; } -} - -public class Data -{ - public Object Object { get; set; } -} - -public class Object -{ - public string Id { get; set; } = string.Empty; - public int Amount { get; set; } - public BillingDetails Billing_details { get; set; } = new(); - public string Calculated_statement_descriptor { get; set; } = string.Empty; - public string Currency { get; set; } = string.Empty; - public bool Paid { get; set; } - public string Payment_intent { get; set; } = string.Empty; - public string Payment_method { get; set; } = string.Empty; - public string Receipt_url { get; set; } = string.Empty; - public string Status { get; set; } = string.Empty; - public string Failure_message { get; set; } = string.Empty; -} - -public class BillingDetails -{ - public string Email { get; set; } = string.Empty; - public string Name { get; set; } = string.Empty; - public string Phone { get; set; } = string.Empty; -} - -public class Request -{ - public string Id { get; set; } = string.Empty; -} - -public class ConfirmStripeTransactionCommandHandler( - IApplicationDbContext dbContext, - IStripeService stripeService - ) - : IRequestHandler -{ - public async Task Handle(ConfirmStripeTransactionCommand request, CancellationToken cancellationToken) - { - var lastTransaction = await dbContext.UserTransactions.OrderBy(x => x.CreatedAt).LastAsync(cancellationToken); - var stripeConfirmation = stripeService.ValidateTransaction(request); - - if (stripeConfirmation.Succeeded) - { - lastTransaction.IsConfirmed = true; - } - lastTransaction.Paid = request.Data.Object.Paid; - lastTransaction.StripeChargeId = request.Data.Object.Id; - lastTransaction.StripeEventId = request.Id; - lastTransaction.StripeReceiptUrl = request.Data.Object.Receipt_url; - lastTransaction.StripePaymentIntent = request.Data.Object.Payment_intent; - lastTransaction.StripePaymentMethod = request.Data.Object.Payment_method; - lastTransaction.StripeBillingDetailEmail = request.Data.Object.Billing_details.Email; - lastTransaction.StripeBillingDetailName = request.Data.Object.Billing_details.Name; - - await dbContext.SaveChangesAsync(cancellationToken); - - return ""; - } -} diff --git a/src/Application/Stripe/Commands/CreateSessionCheckoutCommand.cs b/src/Application/Stripe/Commands/CreateSessionCheckoutCommand.cs deleted file mode 100644 index 80249d3..0000000 --- a/src/Application/Stripe/Commands/CreateSessionCheckoutCommand.cs +++ /dev/null @@ -1,44 +0,0 @@ -using Hutopy.Application.Common.Interfaces; -using Hutopy.Domain.Entities; - -namespace Hutopy.Application.Stripe.Commands; - -public record CreateSessionCheckoutCommand : IRequest -{ - public required Guid CreatorId { get; init; } - public required int Amount { get; init; } - public string Currency { get; init; } = "CAD"; - public string TipMessage { get; init; } = string.Empty; -} - -public class CreateSessionCheckoutCommandHandler( - IApplicationDbContext dbContext, - IStripeService stripeService -) - : IRequestHandler -{ - public async Task Handle(CreateSessionCheckoutCommand request, CancellationToken cancellationToken) - { - var stripeSecret = await stripeService.CreateCheckoutSession( - request.Amount, - request.CreatorId.ToString(), - request.Currency); - - // ReSharper disable once PossibleLossOfFraction - decimal priceInDollars = (request.Amount / 100); - - var userTransaction = new UserTransaction - { - Currency = request.Currency, - Amount = priceInDollars, - TipMessage = request.TipMessage, - ApplicationUserId = request.CreatorId - }; - - await dbContext.UserTransactions.AddAsync(userTransaction, cancellationToken); - - await dbContext.SaveChangesAsync(cancellationToken); - - return stripeSecret; - } -} diff --git a/src/Application/Stripe/Queries/GetMyLastReceipt.cs b/src/Application/Stripe/Queries/GetMyLastReceipt.cs deleted file mode 100644 index c4feb05..0000000 --- a/src/Application/Stripe/Queries/GetMyLastReceipt.cs +++ /dev/null @@ -1,27 +0,0 @@ -using Hutopy.Application.Common.Interfaces; - -namespace Hutopy.Application.Stripe.Queries; - -public record GetMyLastReceiptQuery : IRequest -{ - public Guid CreatorId { get; set; } - public string Email { get; set; } = string.Empty; -}; - -public class GetMyLastReceiptQueryHandler( - IApplicationDbContext dbContext -) - : IRequestHandler -{ - public async Task Handle(GetMyLastReceiptQuery request, CancellationToken cancellationToken) - { - var lastTransaction = await dbContext.UserTransactions.OrderBy(x => x.CreatedAt) - .LastOrDefaultAsync( - x => x.ApplicationUserId == request.CreatorId && x.StripeBillingDetailEmail == request.Email, - cancellationToken); - - var receiptUrl = new MyLastReceiptDto { ReceiptUrl = lastTransaction?.StripeReceiptUrl ?? "", }; - - return receiptUrl; - } -} diff --git a/src/Application/Stripe/Queries/MyLastReceiptDto.cs b/src/Application/Stripe/Queries/MyLastReceiptDto.cs deleted file mode 100644 index 5ce1645..0000000 --- a/src/Application/Stripe/Queries/MyLastReceiptDto.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace Hutopy.Application.Stripe.Queries; - -public class MyLastReceiptDto -{ - public string ReceiptUrl { get; set; } -} diff --git a/src/Application/Users/Commands/CreateUser.cs b/src/Application/Users/Commands/CreateUser.cs deleted file mode 100644 index d84b69b..0000000 --- a/src/Application/Users/Commands/CreateUser.cs +++ /dev/null @@ -1,37 +0,0 @@ -using Hutopy.Application.Common.Interfaces; -using Microsoft.AspNetCore.Http; - -namespace Hutopy.Application.Users.Commands; -public record CreateUserCommand : IRequest -{ - public required string FirstName { get; init; } - public required string LastName { get; init; } - public required string EmailAddress { get; init; } - public required string UserName { get; init; } - public required string Password { get; init; } -} - -public class CreateUserCommandHandler : IRequestHandler -{ - private readonly IApplicationDbContext _context; - private readonly IIdentityService _identityService; - - public CreateUserCommandHandler(IApplicationDbContext context, IIdentityService identityService) - { - _context = context; - _identityService = identityService; - } - - public async Task Handle(CreateUserCommand request, CancellationToken cancellationToken) - { - await _identityService.CreateUserAsync(request.EmailAddress, request.UserName, request.FirstName, request.LastName, request.Password); - - var user = await _identityService.FindUserByEmailAsync(request.EmailAddress); - - if (user is null) throw new InvalidOperationException("This should never happen, we just created the user."); - - await _context.SaveChangesAsync(cancellationToken); - - return Results.Ok(user.Id); - } -} diff --git a/src/Application/Users/Commands/Login.cs b/src/Application/Users/Commands/Login.cs deleted file mode 100644 index 8f232b5..0000000 --- a/src/Application/Users/Commands/Login.cs +++ /dev/null @@ -1,27 +0,0 @@ -using Hutopy.Application.Common.Interfaces; - -namespace Hutopy.Application.Users.Commands; - -public record LoginCommand( - string Email, - string Password) - : IRequest; - -public record LoginResponse( - string AccessToken, - string RefreshToken); - -public class LoginCommandHandler( - IApplicationDbContext Context, - IIdentityService identityService) - : IRequestHandler -{ - public async Task Handle(LoginCommand request, CancellationToken cancellationToken) - { - var accessToken = await identityService.LoginAsync(request.Email, request.Password); - - if (string.IsNullOrWhiteSpace(accessToken)) throw new InvalidOperationException("Invalid login credentials"); - - return new LoginResponse(accessToken, string.Empty); - } -} diff --git a/src/Application/Users/Commands/UpdateCurrentUserCommand.cs b/src/Application/Users/Commands/UpdateCurrentUserCommand.cs deleted file mode 100644 index 4836544..0000000 --- a/src/Application/Users/Commands/UpdateCurrentUserCommand.cs +++ /dev/null @@ -1,50 +0,0 @@ -using System.ComponentModel.DataAnnotations.Schema; -using Hutopy.Application.Common.Interfaces; -using Hutopy.Application.Common.Models; -using Microsoft.AspNetCore.Http; - -namespace Hutopy.Application.Users.Commands; - -public class UpdateCurrentUserCommand : IRequest -{ - public required string? Alias { get; init; } - public required string? FirstName { get; init; } - public required string? LastName { get; init; } - public required string? Occupation { get; init; } - public required string? BirthDate { get; init; } - public required string? Country { get; init; } - public required string? City { get; init; } - public required string? Address { get; init; } - - [NotMapped] - private class Mapping : Profile - { - public Mapping() - { - CreateMap(); - } - } -} - -public class UpdateCurrentUserCommandHandler( - IApplicationDbContext context, - IIdentityService identityService, - IMapper mapper) - : IRequestHandler -{ - public async Task Handle(UpdateCurrentUserCommand request, CancellationToken cancellationToken) - { - var identityUser = await identityService.GetCurrentUserAsync(); - - if (identityUser?.Id is null) return Results.Problem("Current user not found."); - - var userModel = mapper.Map(request); - userModel.Id = identityUser.Id; - - var result = await identityService.UpdateCurrentUserAsync(userModel); - - await context.SaveChangesAsync(cancellationToken); - - return result.Succeeded ? Results.Ok(result.GetValueOrDefault()) : Results.Problem(result.GetErrorsAsString()); - } -} diff --git a/src/Application/Users/Queries/GetUser/GetUserById.cs b/src/Application/Users/Queries/GetUser/GetUserById.cs deleted file mode 100644 index 1128cfc..0000000 --- a/src/Application/Users/Queries/GetUser/GetUserById.cs +++ /dev/null @@ -1,23 +0,0 @@ -using Hutopy.Application.Common.Interfaces; - -namespace Hutopy.Application.Users.Queries.GetUser; - -public record GetUserByIdQuery : IRequest -{ - public required string UserId { get; init; } -} - -public class GetUserByIdHandler( - IIdentityService identityService - ) - : IRequestHandler -{ - public async Task Handle(GetUserByIdQuery query, CancellationToken cancellationToken) - { - var user = await identityService.FindUserByIdAsync(query.UserId); - - if (user is null) throw new InvalidOperationException(); - - return user.ToDto(); - } -} diff --git a/src/Application/Users/Queries/GetUser/GetUserByUserName.cs b/src/Application/Users/Queries/GetUser/GetUserByUserName.cs deleted file mode 100644 index 131ac8b..0000000 --- a/src/Application/Users/Queries/GetUser/GetUserByUserName.cs +++ /dev/null @@ -1,23 +0,0 @@ -using Hutopy.Application.Common.Interfaces; - -namespace Hutopy.Application.Users.Queries.GetUser; - -public record GetUserByUserNameQuery : IRequest -{ - public required string UserName { get; init; } -}; - -public class GetUserByUserNameQueryHandler( - IIdentityService identityService -) - : IRequestHandler -{ - public async Task Handle(GetUserByUserNameQuery query, CancellationToken cancellationToken) - { - var user = await identityService.GetUserByUserNameAsync(query.UserName); - - if (user is null) throw new InvalidOperationException(); - - return user.ToDto(); - } -} diff --git a/src/Application/Users/Queries/GetUser/UserDto.cs b/src/Application/Users/Queries/GetUser/UserDto.cs deleted file mode 100644 index c64bb21..0000000 --- a/src/Application/Users/Queries/GetUser/UserDto.cs +++ /dev/null @@ -1,24 +0,0 @@ -using Hutopy.Application.Common.Models; - -namespace Hutopy.Application.Users.Queries.GetUser; - -public class UserDto -{ - public required Guid Id { get; init; } - public required string UserName { get; init; } - public string? FirstName { get; init; } - public string? LastName { get; init; } - public string? Occupation { get; init; } -} - -public static class UserDtoExtensions -{ - public static UserDto ToDto(this UserModel model) => - new() - { - Id = model.Id, - FirstName = model.Firstname, - LastName = model.Lastname, - UserName = model.Username - }; -} diff --git a/src/Domain/Entities/FutureCreator.cs b/src/Domain/Entities/FutureCreator.cs deleted file mode 100644 index b0ebde5..0000000 --- a/src/Domain/Entities/FutureCreator.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace Hutopy.Domain.Entities; - -public class FutureCreator : BaseAuditableEntity -{ - public required string FirstName { get; init; } - public required string LastName { get; init; } - public required string EmailAddress { get; init; } - public required string PhoneNumber { get; init; } - public required string SocialNetworkAccount { get; init; } - public required string ReasonToJoin { get; init; } -} diff --git a/src/Domain/Entities/UserTransaction.cs b/src/Domain/Entities/UserTransaction.cs deleted file mode 100644 index b7df7da..0000000 --- a/src/Domain/Entities/UserTransaction.cs +++ /dev/null @@ -1,20 +0,0 @@ -namespace Hutopy.Domain.Entities; - -public class UserTransaction : BaseAuditableEntity -{ - public decimal Amount { get; set; } - public string Currency { get; set; } = "CAD"; - public string TipMessage { get; set; } = string.Empty; - - // Foreign key to ApplicationUser - public required Guid ApplicationUserId { get; set; } - public bool IsConfirmed { get; set; } - public string StripeEventId { get; set; } = string.Empty; - public string StripeChargeId { get; set; } = string.Empty; - public string StripePaymentIntent { get; set; } = string.Empty; - public string StripePaymentMethod { get; set; } = string.Empty; - public string StripeReceiptUrl { get; set; } = string.Empty; - public string StripeBillingDetailEmail { get; set; } = string.Empty; - public string StripeBillingDetailName { get; set; } = string.Empty; - public bool Paid { get; set; } -} diff --git a/src/Domain/GlobalUsings.cs b/src/Domain/GlobalUsings.cs index e312629..d6161ca 100644 --- a/src/Domain/GlobalUsings.cs +++ b/src/Domain/GlobalUsings.cs @@ -1,5 +1,2 @@ global using Hutopy.Domain.Common; -global using Hutopy.Domain.Entities; -global using Hutopy.Domain.Enums; global using Hutopy.Domain.Exceptions; -global using Hutopy.Domain.ValueObjects; \ No newline at end of file diff --git a/src/Infrastructure/AzureBlob/AzureBlobStorage.cs b/src/Infrastructure/AzureBlob/AzureBlobStorage.cs index fab5301..c2f3c72 100644 --- a/src/Infrastructure/AzureBlob/AzureBlobStorage.cs +++ b/src/Infrastructure/AzureBlob/AzureBlobStorage.cs @@ -1,13 +1,12 @@ using Azure; using Azure.Storage.Blobs; using Azure.Storage.Blobs.Models; -using Hutopy.Application.Common.Interfaces; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; namespace Hutopy.Infrastructure.AzureBlob; -public class AzureBlobStorage : IBlobStorage +public class AzureBlobStorage { private const long MaxUploadSize = 10 * 1024 * 1024; // 10 MB in bytes diff --git a/src/Infrastructure/AzureBlob/ContentTypes.cs b/src/Infrastructure/AzureBlob/ContentTypes.cs index e7f2da3..8af77a1 100644 --- a/src/Infrastructure/AzureBlob/ContentTypes.cs +++ b/src/Infrastructure/AzureBlob/ContentTypes.cs @@ -1,24 +1,24 @@ -using System.Text; - -namespace Hutopy.Infrastructure.AzureBlob; +namespace Hutopy.Infrastructure.AzureBlob; public static class ContentTypes { - private static string ImagePng = "image/png"; - private static string ImageJpeg = "image/jpeg"; - private static string ImageJpg = "image/jpg"; - private static string TextHtml = "text/html"; - - public static HashSet AllowedContentTypes = new HashSet { ImagePng, ImageJpeg, ImageJpg, TextHtml }; + private const string ImagePng = "image/png"; + private const string ImageJpeg = "image/jpeg"; + private const string ImageJpg = "image/jpg"; - public static bool IsAllowed(string contentType, Stream fileStream) + private static readonly HashSet AllowedContentTypes = [ImagePng, ImageJpeg, ImageJpg]; + + public static bool IsAllowed( + string contentType, + Stream fileStream) { return IsValidFileType(fileStream) && AllowedContentTypes.Contains(contentType); } - - private static bool IsValidFileType(Stream fileStream) + + private static bool IsValidFileType( + Stream fileStream) { - byte[] buffer = new byte[512]; + byte[] buffer = new byte[4]; fileStream.Read(buffer, 0, buffer.Length); fileStream.Position = 0; @@ -33,13 +33,6 @@ public static class ContentTypes { return true; } - - // Check for HTML content by looking for "" or "" tags - string content = Encoding.UTF8.GetString(buffer); - if (content.Contains("")) - { - return true; - } return false; } diff --git a/src/Infrastructure/Data/ApplicationDbContext.cs b/src/Infrastructure/Data/ApplicationDbContext.cs index a8a5d4f..ae691cb 100644 --- a/src/Infrastructure/Data/ApplicationDbContext.cs +++ b/src/Infrastructure/Data/ApplicationDbContext.cs @@ -1,24 +1,10 @@ -using System.Reflection; -using Hutopy.Application.Common.Interfaces; -using Hutopy.Domain.Entities; -using Hutopy.Infrastructure.Identity; +using Hutopy.Infrastructure.Identity; using Microsoft.AspNetCore.Identity.EntityFrameworkCore; using Microsoft.EntityFrameworkCore; namespace Hutopy.Infrastructure.Data { - public class ApplicationDbContext(DbContextOptions options) - : IdentityDbContext(options), IApplicationDbContext - { - public DbSet FutureCreators => Set(); - public DbSet UserTransactions => Set(); - - protected override void OnModelCreating(ModelBuilder builder) - { - base.OnModelCreating(builder); - - // Apply configurations - builder.ApplyConfigurationsFromAssembly(Assembly.GetExecutingAssembly()); - } - } + public class ApplicationDbContext( + DbContextOptions options) + : IdentityDbContext(options); } diff --git a/src/Infrastructure/Data/Configurations/UserTransactionConfiguration.cs b/src/Infrastructure/Data/Configurations/UserTransactionConfiguration.cs deleted file mode 100644 index f659e55..0000000 --- a/src/Infrastructure/Data/Configurations/UserTransactionConfiguration.cs +++ /dev/null @@ -1,21 +0,0 @@ -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Metadata.Builders; -using Hutopy.Domain.Entities; -using Hutopy.Infrastructure.Identity; - -namespace Hutopy.Infrastructure.Data.Configurations -{ - public class UserTransactionConfiguration : IEntityTypeConfiguration - { - public void Configure(EntityTypeBuilder builder) - { - // Relationship between ApplicationUser and UserTransaction - builder.HasOne() - .WithMany() - .HasForeignKey(ut => ut.ApplicationUserId) - .IsRequired(); - - builder.Property(x => x.Amount).HasPrecision(18, 2); - } - } -} diff --git a/src/Infrastructure/Data/Interceptors/AuditableEntityInterceptor.cs b/src/Infrastructure/Data/Interceptors/AuditableEntityInterceptor.cs deleted file mode 100644 index b1d7157..0000000 --- a/src/Infrastructure/Data/Interceptors/AuditableEntityInterceptor.cs +++ /dev/null @@ -1,55 +0,0 @@ -using Hutopy.Application.Common.Interfaces; -using Hutopy.Domain.Common; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.ChangeTracking; -using Microsoft.EntityFrameworkCore.Diagnostics; - -namespace Hutopy.Infrastructure.Data.Interceptors; - -public class AuditableEntityInterceptor( - IUser user, - TimeProvider dateTime) : SaveChangesInterceptor -{ - public override InterceptionResult SavingChanges(DbContextEventData eventData, InterceptionResult result) - { - UpdateEntities(eventData.Context); - - return base.SavingChanges(eventData, result); - } - - public override ValueTask> SavingChangesAsync(DbContextEventData eventData, InterceptionResult result, CancellationToken cancellationToken = default) - { - UpdateEntities(eventData.Context); - - return base.SavingChangesAsync(eventData, result, cancellationToken); - } - - public void UpdateEntities(DbContext? context) - { - if (context == null) return; - - foreach (var entry in context.ChangeTracker.Entries()) - { - if (entry.State is EntityState.Added or EntityState.Modified || entry.HasChangedOwnedEntities()) - { - var utcNow = dateTime.GetUtcNow(); - if (entry.State == EntityState.Added) - { - entry.Entity.CreatedBy = user.Id; - entry.Entity.CreatedAt = utcNow; - } - entry.Entity.LastModifiedBy = user.Id; - entry.Entity.LastModifiedAt = utcNow; - } - } - } -} - -public static class Extensions -{ - public static bool HasChangedOwnedEntities(this EntityEntry entry) => - entry.References.Any(r => - r.TargetEntry != null && - r.TargetEntry.Metadata.IsOwned() && - (r.TargetEntry.State == EntityState.Added || r.TargetEntry.State == EntityState.Modified)); -} diff --git a/src/Infrastructure/Data/Interceptors/DispatchDomainEventsInterceptor.cs b/src/Infrastructure/Data/Interceptors/DispatchDomainEventsInterceptor.cs deleted file mode 100644 index 3123ee7..0000000 --- a/src/Infrastructure/Data/Interceptors/DispatchDomainEventsInterceptor.cs +++ /dev/null @@ -1,45 +0,0 @@ -using Hutopy.Domain.Common; -using MediatR; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Diagnostics; - -namespace Hutopy.Infrastructure.Data.Interceptors; - -public class DispatchDomainEventsInterceptor( - IPublisher mediator) - : SaveChangesInterceptor -{ - public override InterceptionResult SavingChanges(DbContextEventData eventData, InterceptionResult result) - { - DispatchDomainEvents(eventData.Context).GetAwaiter().GetResult(); - - return base.SavingChanges(eventData, result); - - } - - public override async ValueTask> SavingChangesAsync(DbContextEventData eventData, InterceptionResult result, CancellationToken cancellationToken = default) - { - await DispatchDomainEvents(eventData.Context); - - return await base.SavingChangesAsync(eventData, result, cancellationToken); - } - - public async Task DispatchDomainEvents(DbContext? context) - { - if (context == null) return; - - var entities = context.ChangeTracker - .Entries() - .Where(e => e.Entity.DomainEvents.Any()) - .Select(e => e.Entity); - - var domainEvents = entities - .SelectMany(e => e.DomainEvents) - .ToList(); - - entities.ToList().ForEach(e => e.ClearDomainEvents()); - - foreach (var domainEvent in domainEvents) - await mediator.Publish(domainEvent); - } -} diff --git a/src/Infrastructure/DependencyInjection.cs b/src/Infrastructure/DependencyInjection.cs index f816daa..0a328f5 100644 --- a/src/Infrastructure/DependencyInjection.cs +++ b/src/Infrastructure/DependencyInjection.cs @@ -1,10 +1,7 @@ -using Hutopy.Application.Common.Interfaces; -using Hutopy.Domain.Constants; +using Hutopy.Domain.Constants; using Hutopy.Infrastructure.AzureBlob; using Hutopy.Infrastructure.Data; -using Hutopy.Infrastructure.Data.Interceptors; using Hutopy.Infrastructure.Identity; -using Hutopy.Infrastructure.Stripe; using Microsoft.AspNetCore.Identity; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Diagnostics; @@ -23,17 +20,12 @@ public static class DependencyInjection var connectionString = configuration.GetConnectionString("MssqlConnection") ?? throw new InvalidOperationException("Missing ConnectionStrings:MssqlConnection"); - services.AddScoped(); - services.AddScoped(); - services.AddDbContext((sp, options) => { options.AddInterceptors(sp.GetServices()); options.UseSqlServer(connectionString); }); - services.AddScoped(provider => provider.GetRequiredService()); - services.AddScoped(); services.AddAuthentication() @@ -52,14 +44,11 @@ public static class DependencyInjection // Singleton services services.AddSingleton(TimeProvider.System); - services.AddSingleton(); + services.AddSingleton(); // Scoped services - services.AddScoped(); + services.AddScoped(); - // Transient services - services.AddTransient(); - services.AddAuthorization(options => options.AddPolicy(Policies.CanPurge, policy => policy.RequireRole(Roles.Administrator))); diff --git a/src/Infrastructure/Identity/IdentityResultExtensions.cs b/src/Infrastructure/Identity/IdentityResultExtensions.cs index 630c372..8ab92c1 100644 --- a/src/Infrastructure/Identity/IdentityResultExtensions.cs +++ b/src/Infrastructure/Identity/IdentityResultExtensions.cs @@ -1,4 +1,4 @@ -using Hutopy.Application.Common.Models; +using Hutopy.Infrastructure.Identity.Models; using Microsoft.AspNetCore.Identity; namespace Hutopy.Infrastructure.Identity; diff --git a/src/Infrastructure/Identity/IdentityService.cs b/src/Infrastructure/Identity/IdentityService.cs index 6195a70..66ce6f8 100644 --- a/src/Infrastructure/Identity/IdentityService.cs +++ b/src/Infrastructure/Identity/IdentityService.cs @@ -1,74 +1,14 @@ -using Google.Apis.Oauth2.v2.Data; using System.Security.Claims; -using Hutopy.Application.Common.Interfaces; -using Hutopy.Application.Common.Models; -using Hutopy.Infrastructure.Utils; -using Microsoft.AspNetCore.Authorization; +using Hutopy.Infrastructure.Identity.Models; using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Identity; -using Microsoft.Extensions.Options; namespace Hutopy.Infrastructure.Identity; public class IdentityService( ApplicationUserManager userManager, - SignInManager signInManager, - IUserClaimsPrincipalFactory userClaimsPrincipalFactory, - IAuthorizationService authorizationService, - IHttpContextAccessor contextAccessor, - IOptionsSnapshot jwtOptions + IHttpContextAccessor contextAccessor ) - : IIdentityService { - public async Task GetUserNameAsync(Guid userId) - { - var user = await userManager.FindByIdAsync(userId.ToString()); - - return user?.UserName; - } - - public async Task GetUserByUserNameAsync(string userName) - { - var user = await userManager.FindByNameAsync(userName); - - if (user == null) return null; - - return new() - { - Id = user.Id, - Username = user.UserName!, - PhoneNumber = user.PhoneNumber, - Email = user.Email, - Alias = user.Alias, - Firstname = user.Firstname, - Lastname = user.Lastname, - BirthDate = user.BirthDate, - Address = user.Address, - PortraitUrl = user.PortraitUrl - }; - } - - public async Task> CreateUserAsync(Userinfo userInfo) - { - var applicationUser = new ApplicationUser - { - UserName = userInfo.Name, - Email = userInfo.Email, - Firstname = userInfo.GivenName, - Lastname = userInfo.FamilyName - }; - - var password = Guid.NewGuid().ToString("N")[..32]; - - var identityResult = await userManager.CreateAsync(applicationUser, password); - - var applicationResult = identityResult.ToApplicationResult(); - - var result = new Result(applicationUser.Id, applicationResult.Succeeded, applicationResult.Errors); - - return result; - } - public async Task> CreateUserAsync(string email, string userName, string firstName, string lastName, string password) { @@ -89,35 +29,6 @@ public class IdentityService( return result; } - public async Task> UpdateCurrentUserAsync(UserModel userModel) - { - var applicationUser = await userManager.FindByIdAsync(userModel.Id.ToString()); - - if (applicationUser is null) return Result.Failure(Guid.Empty, new[] { "User not found." }); - - applicationUser.Id = userModel.Id; - applicationUser.Email = userModel.Email; - applicationUser.PhoneNumber = userModel.PhoneNumber; - applicationUser.Alias = userModel.Alias; - applicationUser.Firstname = userModel.Firstname; - applicationUser.Lastname = userModel.Lastname; - applicationUser.BirthDate = userModel.BirthDate; - applicationUser.Address = userModel.Address; - applicationUser.PortraitUrl = userModel.PortraitUrl; - - var response = await userManager.UpdateAsync(applicationUser); - - var applicationResult = response.ToApplicationResult(); - - var result = new Result( - userModel.Id, - applicationResult.Succeeded, - applicationResult.Errors); - - return result; - } - - private static UserModel BuildModelFrom(ApplicationUser response) { var userModel = new UserModel @@ -168,80 +79,6 @@ public class IdentityService( return await FindUserByIdAsync(currentUserId); } - public async Task UpdateCurrentUserPortraitUrlAsync(string url) - { - var userModel = await GetCurrentUserAsync(); - - var applicationUser = await userManager.FindByIdAsync(userModel.Id.ToString()); - if (applicationUser is null) return Result.Failure(["ApplicationUser not found."]); - - applicationUser.PortraitUrl = url; - - var response = await userManager.UpdateAsync(applicationUser); - - return response.ToApplicationResult(); - } - - public async Task IsInRoleAsync(Guid userId, string role) - { - var user = await userManager.FindByIdAsync(userId.ToString()); - - return user != null && await userManager.IsInRoleAsync(user, role); - } - - public async Task CurrentUserIsInRoleAsync(string role) - { - var currentUserModel = await GetCurrentUserAsync(); - var currentUser = await userManager.FindByIdAsync(currentUserModel.Id.ToString()); - - return currentUser != null && await userManager.IsInRoleAsync(currentUser, role); - } - - public async Task AuthorizeAsync(Guid userId, string policyName) - { - var user = await userManager.FindByIdAsync(userId.ToString()); - - if (user == null) - { - return false; - } - - var principal = await userClaimsPrincipalFactory.CreateAsync(user); - - var result = await authorizationService.AuthorizeAsync(principal, policyName); - - return result.Succeeded; - } - - public async Task DeleteUserAsync(string userId) - { - var user = await userManager.FindByIdAsync(userId); - - return user != null ? await DeleteUserAsync(user) : Result.Success(); - } - - public async Task DeleteUserAsync(ApplicationUser user) - { - var result = await userManager.DeleteAsync(user); - - return result.ToApplicationResult(); - } - - public async Task AddRoleAsync(string userId, string role) - { - var hasAdminAccess = await CurrentUserIsInRoleAsync("Administrator"); - - if (!hasAdminAccess) return Result.Failure(new[] { "Only administrator can assign new roles to a user." }); - - var user = await userManager.FindByIdAsync(userId); - - if (user is null) return Result.Failure(new[] { "User not found." }); - - var result = await userManager.AddToRoleAsync(user, role); - - return result.ToApplicationResult(); - } - public async Task> GetCurrentUserRolesAsync() { var currentUserModel = await GetCurrentUserAsync(); @@ -255,32 +92,4 @@ public class IdentityService( return userRoles; } - public async Task LoginAsync(string userName, string password) - { - var result = - await signInManager.PasswordSignInAsync(userName, password, isPersistent: false, lockoutOnFailure: false); - - if (!result.Succeeded) - { - return null; - } - - var user = await GetUserByUserNameAsync(userName); - - if (user is null) throw new InvalidOperationException(); - - var token = JwtTokenHelper.GenerateJwtToken( - expiresIn: jwtOptions.Value.Lifetime, - issuer: jwtOptions.Value.Issuer, - audience: jwtOptions.Value.Audience, - key: jwtOptions.Value.Key, - userId: user.Id.ToString(), - email: user.Email, - alias: user.Alias, - firstname: user.Firstname, - lastname: user.Lastname, - portraitUrl: user.PortraitUrl); - - return token; - } } diff --git a/src/Application/Common/Models/Result.cs b/src/Infrastructure/Identity/Models/Result.cs similarity index 95% rename from src/Application/Common/Models/Result.cs rename to src/Infrastructure/Identity/Models/Result.cs index 8c30b4a..9d26a1d 100644 --- a/src/Application/Common/Models/Result.cs +++ b/src/Infrastructure/Identity/Models/Result.cs @@ -1,4 +1,4 @@ -namespace Hutopy.Application.Common.Models; +namespace Hutopy.Infrastructure.Identity.Models; public class Result( bool succeeded, diff --git a/src/Application/Common/Models/RoleModel.cs b/src/Infrastructure/Identity/Models/RoleModel.cs similarity index 66% rename from src/Application/Common/Models/RoleModel.cs rename to src/Infrastructure/Identity/Models/RoleModel.cs index 5c1c786..051a272 100644 --- a/src/Application/Common/Models/RoleModel.cs +++ b/src/Infrastructure/Identity/Models/RoleModel.cs @@ -1,4 +1,4 @@ -namespace Hutopy.Application.Common.Models; +namespace Hutopy.Infrastructure.Identity.Models; public class RoleModel { diff --git a/src/Application/Common/Models/UserModel.cs b/src/Infrastructure/Identity/Models/UserModel.cs similarity index 90% rename from src/Application/Common/Models/UserModel.cs rename to src/Infrastructure/Identity/Models/UserModel.cs index 2a28ec7..b43bc71 100644 --- a/src/Application/Common/Models/UserModel.cs +++ b/src/Infrastructure/Identity/Models/UserModel.cs @@ -1,4 +1,4 @@ -namespace Hutopy.Application.Common.Models; +namespace Hutopy.Infrastructure.Identity.Models; public class UserModel { diff --git a/src/Infrastructure/Identity/RoleService.cs b/src/Infrastructure/Identity/RoleService.cs deleted file mode 100644 index ef8749a..0000000 --- a/src/Infrastructure/Identity/RoleService.cs +++ /dev/null @@ -1,49 +0,0 @@ -using Hutopy.Application.Common.Interfaces; -using Hutopy.Application.Common.Models; -using Microsoft.AspNetCore.Identity; - -namespace Hutopy.Infrastructure.Identity; - -public class RoleService( - RoleManager roleManager - ) - : IRoleService -{ - public async Task CreateRoleAsync(string roleName) - { - var role = new ApplicationRole { Name = roleName, Id = Guid.NewGuid()}; - var result = await roleManager.CreateAsync(role); - - return result.ToApplicationResult(); - } - - public async Task DeleteRoleAsync(string roleName) - { - var role = new ApplicationRole { Name = roleName }; - var result = await roleManager.DeleteAsync(role); - - return result.ToApplicationResult(); - } - - public async Task FindRoleByIdAsync(string roleId) - { - var result = await roleManager.FindByIdAsync(roleId); - - if (result is null) return null; - - var roleModel = new RoleModel { Id = result.Id, Name = result.Name }; - - return roleModel; - } - - public async Task FindRoleByNameAsync(string roleName) - { - var result = await roleManager.FindByNameAsync(roleName); - - if (result is null) return null; - - var roleModel = new RoleModel { Id = result.Id, Name = result.Name }; - - return roleModel; - } -} diff --git a/src/Infrastructure/Stripe/StripeService.cs b/src/Infrastructure/Stripe/StripeService.cs deleted file mode 100644 index 863db7c..0000000 --- a/src/Infrastructure/Stripe/StripeService.cs +++ /dev/null @@ -1,74 +0,0 @@ -using Stripe; -using Stripe.Checkout; -using Hutopy.Application.Common.Interfaces; -using Microsoft.AspNetCore.Http; -using Hutopy.Application.Common.Models; -using Hutopy.Application.Stripe.Commands; -using Microsoft.Extensions.Configuration; - -namespace Hutopy.Infrastructure.Stripe; - -public class StripeService : IStripeService -{ - private readonly IHttpContextAccessor _httpContextAccessor; - - public StripeService(IHttpContextAccessor httpContextAccessor, IConfiguration configuration) - { - _httpContextAccessor = httpContextAccessor; - var stripeKey = configuration["Stripe:apiKey"] ?? ""; - StripeConfiguration.ApiKey = stripeKey; - } - - public async Task CreateCheckoutSession(int amount, string creatorId, string currency = "cad") - { - var options = new SessionCreateOptions - { - LineItems = - [ - new SessionLineItemOptions - { - PriceData = new SessionLineItemPriceDataOptions - { - UnitAmount = amount, - Currency = currency, - ProductData = new SessionLineItemPriceDataProductDataOptions { Name = "Tip", }, - }, - Quantity = 1, - } - - ], - Mode = "payment", - UiMode = "embedded", - ReturnUrl = $"https://hutopy.ca/paymentcompleted?creatorId={creatorId}", - InvoiceCreation = new SessionInvoiceCreationOptions(){ Enabled = true}, - ClientReferenceId = creatorId - }; - - var service = new SessionService(); - Session session = await service.CreateAsync(options); - - return session.ClientSecret; - } - - public Result ValidateTransaction(ConfirmStripeTransactionCommand request) - { - try - { - if (request.Data.Object.Status is "succeeded") - { - return new Result(true, new List()); - } - - return new Result(false, new List()); - } - catch (StripeException e) - { - Console.WriteLine("Error: {0}", e.Message); - return new Result(false, new List{e.Message}); - } - catch (Exception e) - { - return new Result(false, new List{e.Message}); - } - } -} diff --git a/src/Web/Controllers/FacebookController.cs b/src/Web/Controllers/FacebookController.cs index b8b52d9..bae7799 100644 --- a/src/Web/Controllers/FacebookController.cs +++ b/src/Web/Controllers/FacebookController.cs @@ -1,5 +1,5 @@ using System.Security.Claims; -using Hutopy.Application.Common.Interfaces; +using Hutopy.Infrastructure.Identity; using Hutopy.Infrastructure.Utils; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authentication.Cookies; @@ -8,7 +8,9 @@ using Microsoft.AspNetCore.Mvc; namespace Hutopy.Web.Controllers; -public class FacebookController(IIdentityService identityService) : Controller +public class FacebookController( + IdentityService identityService) + : Controller { [Microsoft.AspNetCore.Mvc.HttpGet("/api/facebook/sign-in")] public async Task SignIn() @@ -33,7 +35,7 @@ public class FacebookController(IIdentityService identityService) : Controller var claimsIdentity = new ClaimsIdentity( new List { - new(ClaimTypes.Name, name), + new(ClaimTypes.Name, name), new(ClaimTypes.Email, email), new(ClaimTypes.GivenName, givenName), new(ClaimTypes.Surname, familyName) diff --git a/src/Web/DependencyInjection.cs b/src/Web/DependencyInjection.cs index 4161aad..1ce13a2 100644 --- a/src/Web/DependencyInjection.cs +++ b/src/Web/DependencyInjection.cs @@ -1,9 +1,6 @@ using System.Text; using Azure.Identity; -using Hutopy.Application.Common.Interfaces; using Hutopy.Infrastructure.Data; -using Hutopy.Web.Infrastructure; -using Hutopy.Web.Services; using Microsoft.AspNetCore.Authentication.Cookies; using Microsoft.AspNetCore.Authentication.Facebook; using Microsoft.AspNetCore.Authentication.Google; @@ -19,15 +16,11 @@ public static class DependencyInjection { services.AddDatabaseDeveloperPageExceptionFilter(); - services.AddScoped(); - services.AddHttpContextAccessor(); services.AddHealthChecks() .AddDbContextCheck(); - services.AddExceptionHandler(); - services.AddRazorPages(); services.AddHttpClient(); diff --git a/src/Web/Endpoints/JoinUs.cs b/src/Web/Endpoints/JoinUs.cs deleted file mode 100644 index 8353ba1..0000000 --- a/src/Web/Endpoints/JoinUs.cs +++ /dev/null @@ -1,26 +0,0 @@ -using Hutopy.Application.Common.Models; -using Hutopy.Application.FutureCreators.Commands; -using Hutopy.Application.FutureCreators.Queries; -using Hutopy.Web.Infrastructure; - -namespace Hutopy.Web.Endpoints; - -public class JoinUs : EndpointGroupBase -{ - public override void Map(WebApplication app) - { - app.MapGroup(this) - .MapGet(GetFutureCreators) - .MapPost(CreateFutureCreator); - } - - private static Task CreateFutureCreator(ISender sender, CreateFutureCreatorCommand command) - { - return sender.Send(command); - } - - private static Task> GetFutureCreators(ISender sender, [AsParameters] GetFutureCreatorListQuery query) - { - return sender.Send(query); - } -} diff --git a/src/Web/Endpoints/Stripe.cs b/src/Web/Endpoints/Stripe.cs deleted file mode 100644 index be76a0b..0000000 --- a/src/Web/Endpoints/Stripe.cs +++ /dev/null @@ -1,31 +0,0 @@ -using Hutopy.Application.Stripe.Commands; -using Hutopy.Application.Stripe.Queries; -using Hutopy.Web.Infrastructure; - -namespace Hutopy.Web.Endpoints; - -public class Stripe : EndpointGroupBase -{ - public override void Map(WebApplication app) - { - app.MapGroup(this) - .MapPost(ConfirmTransaction, "/confirmTransaction") - .MapGet(GetMyLastReceipt, "/getMyLastReceipt") - .MapPost(CreateSessionCheckout); - } - - private static Task CreateSessionCheckout(ISender sender, CreateSessionCheckoutCommand command) - { - return sender.Send(command); - } - - private async static Task ConfirmTransaction(ISender sender, ConfirmStripeTransactionCommand command) - { - return await sender.Send(command); - } - - private static async Task GetMyLastReceipt(ISender sender, [AsParameters] GetMyLastReceiptQuery query) - { - return await sender.Send(query); - } -} diff --git a/src/Web/Endpoints/UpdateMyUser.cs b/src/Web/Endpoints/UpdateMyUser.cs deleted file mode 100644 index 7118e4e..0000000 --- a/src/Web/Endpoints/UpdateMyUser.cs +++ /dev/null @@ -1,19 +0,0 @@ -using Hutopy.Application.Users.Commands; -using Hutopy.Web.Infrastructure; - -namespace Hutopy.Web.Endpoints; - -public class UpdateMyUser : EndpointGroupBase -{ - public override void Map(WebApplication app) - { - app.MapGroup(this) - .RequireAuthorization() - .MapPatch("/profile", UpdateCurrentUser); - } - - private static async Task UpdateCurrentUser(ISender sender, UpdateCurrentUserCommand command) - { - return await sender.Send(command); - } -} diff --git a/src/Web/Endpoints/Users.cs b/src/Web/Endpoints/Users.cs deleted file mode 100644 index 820aa37..0000000 --- a/src/Web/Endpoints/Users.cs +++ /dev/null @@ -1,39 +0,0 @@ -using Hutopy.Application.Users.Commands; -using Hutopy.Application.Users.Queries.GetUser; -using Hutopy.Web.Infrastructure; - -namespace Hutopy.Web.Endpoints; - -public class Users : EndpointGroupBase -{ - public override void Map(WebApplication app) - { - app.MapGroup(this) - .MapPost(CreateUser) - .MapPost(Login, "/login") - .MapGet(GetUserById, "/id") - .MapGet(GetUserByUserName, "/user-name"); - } - - private static async Task CreateUser(ISender sender, CreateUserCommand command) - { - return await sender.Send(command); - } - - private static async Task GetUserById(ISender sender, - [AsParameters] GetUserByIdQuery query) - { - return await sender.Send(query); - } - - private static async Task GetUserByUserName(ISender sender, - [AsParameters] GetUserByUserNameQuery query) - { - return await sender.Send(query); - } - - private static async Task Login(ISender sender, LoginCommand command) - { - return await sender.Send(command); - } -} diff --git a/src/Web/Features/Contents/Data/ContentDbContext.cs b/src/Web/Features/Contents/Data/ContentDbContext.cs index 11edff0..94b88ea 100644 --- a/src/Web/Features/Contents/Data/ContentDbContext.cs +++ b/src/Web/Features/Contents/Data/ContentDbContext.cs @@ -10,11 +10,11 @@ public class ContentDbContext( public DbSet Contents => Set(); public DbSet Creators => Set(); - public DbSet Subscriptions => Set(); + public DbSet Followers => Set(); protected override void OnModelCreating(ModelBuilder modelBuilder) { - modelBuilder.HasDefaultSchema("Content"); + modelBuilder.HasDefaultSchema(SchemaName); modelBuilder .Entity() @@ -34,13 +34,13 @@ public class ContentDbContext( .ToTable(nameof(ContentReaction).Pluralize()); modelBuilder - .Entity() + .Entity() .HasOne(c => c.Creator) .WithMany() .HasForeignKey(c => c.CreatorId); modelBuilder - .Entity() + .Entity() .HasKey(s => new { s.CreatedBy, s.CreatorId }); modelBuilder diff --git a/src/Web/Features/Contents/Data/Subscription.cs b/src/Web/Features/Contents/Data/Follower.cs similarity index 89% rename from src/Web/Features/Contents/Data/Subscription.cs rename to src/Web/Features/Contents/Data/Follower.cs index 4875fd9..c7368f1 100644 --- a/src/Web/Features/Contents/Data/Subscription.cs +++ b/src/Web/Features/Contents/Data/Follower.cs @@ -1,6 +1,6 @@ namespace Hutopy.Web.Features.Contents.Data; -public class Subscription +public class Follower { public Guid CreatedBy { get; init; } public DateTimeOffset CreatedAt { get; init; } diff --git a/src/Web/Features/Contents/Handlers/ChangeBanner.cs b/src/Web/Features/Contents/Handlers/ChangeBanner.cs index c13aa95..950d1b6 100644 --- a/src/Web/Features/Contents/Handlers/ChangeBanner.cs +++ b/src/Web/Features/Contents/Handlers/ChangeBanner.cs @@ -1,5 +1,5 @@ using Hutopy.Application.AzureBlobStorage.Constants; -using Hutopy.Application.Common.Interfaces; +using Hutopy.Infrastructure.AzureBlob; using Hutopy.Web.Features.Contents.Data; namespace Hutopy.Web.Features.Contents.Handlers; @@ -16,7 +16,7 @@ public record ChangeBannerResponse( [PublicAPI] public class ChangeBannerHandler( ContentDbContext context, - IBlobStorage blobStorage) + AzureBlobStorage blobStorage) : Endpoint { public override void Configure() diff --git a/src/Web/Features/Contents/Handlers/ChangeLogo.cs b/src/Web/Features/Contents/Handlers/ChangeLogo.cs index 0caf367..5bbc6b9 100644 --- a/src/Web/Features/Contents/Handlers/ChangeLogo.cs +++ b/src/Web/Features/Contents/Handlers/ChangeLogo.cs @@ -1,5 +1,5 @@ using Hutopy.Application.AzureBlobStorage.Constants; -using Hutopy.Application.Common.Interfaces; +using Hutopy.Infrastructure.AzureBlob; using Hutopy.Web.Features.Contents.Data; namespace Hutopy.Web.Features.Contents.Handlers; @@ -27,7 +27,7 @@ public sealed class ChangeLogoRequestValidator : Validator [PublicAPI] public class ChangeLogoHandler( ContentDbContext context, - IBlobStorage blobStorage) + AzureBlobStorage blobStorage) : Endpoint { public override void Configure() diff --git a/src/Web/Features/Contents/Handlers/CreateContent.cs b/src/Web/Features/Contents/Handlers/CreateContent.cs index e98f7f1..46e9bb9 100644 --- a/src/Web/Features/Contents/Handlers/CreateContent.cs +++ b/src/Web/Features/Contents/Handlers/CreateContent.cs @@ -1,6 +1,6 @@ using System.Collections.Concurrent; using Hutopy.Application.AzureBlobStorage.Constants; -using Hutopy.Application.Common.Interfaces; +using Hutopy.Infrastructure.AzureBlob; using Hutopy.Web.Common; using Hutopy.Web.Features.Contents.Data; using Hutopy.Web.Features.Contents.Handlers.Models; @@ -44,7 +44,7 @@ public sealed class PostContentRequestValidator : Validator } public sealed class PostContent( - IBlobStorage blobStorage, + AzureBlobStorage blobStorage, ContentDbContext context) : Endpoint { diff --git a/src/Web/Features/Contents/Handlers/SubscribeToCreator.cs b/src/Web/Features/Contents/Handlers/FollowCreator.cs similarity index 59% rename from src/Web/Features/Contents/Handlers/SubscribeToCreator.cs rename to src/Web/Features/Contents/Handlers/FollowCreator.cs index 39352ff..3386046 100644 --- a/src/Web/Features/Contents/Handlers/SubscribeToCreator.cs +++ b/src/Web/Features/Contents/Handlers/FollowCreator.cs @@ -5,40 +5,40 @@ using Hutopy.Web.Features.Contents.Handlers.Models; namespace Hutopy.Web.Features.Contents.Handlers; [PublicAPI] -public sealed class SubscribeToCreatorRequest +public sealed class FollowCreatorRequest { public Guid CreatorId { get; set; } } [PublicAPI] -public sealed class SubscribeToCreatorHandler( +public sealed class FollowCreatorHandler( ContentDbContext context) - : Endpoint + : Endpoint { public override void Configure() { - Post("/api/creators/{CreatorId}/subscribe"); - Options((o => o.WithTags("Subscriptions"))); + Post("/api/creators/{CreatorId}/follow"); + Options((o => o.WithTags("creators"))); Description(x => x.Accepts("*/*")); } public override async Task HandleAsync( - SubscribeToCreatorRequest req, + FollowCreatorRequest req, CancellationToken ct) { - await context.Subscriptions.AddAsync( - new() { CreatedBy = HttpContext.User.GetUserId(), CreatorId = req.CreatorId }, + await context.Followers.AddAsync( + new Follower { CreatedBy = User.GetUserId(), CreatorId = req.CreatorId }, ct); await context.SaveChangesAsync(ct); var creator = await context .Creators - .Where(c => c.Id == req.CreatorId) - .Select(c => new SubscriptionModel( + .Where(creator => creator.Id == req.CreatorId) + .Select(creator => new FollowModel( req.CreatorId, - c.Name, - c.Images.Logo + creator.Name, + creator.Images.Logo )) .FirstOrDefaultAsync(cancellationToken: ct); diff --git a/src/Web/Features/Contents/Handlers/GetCreatorByAlias.cs b/src/Web/Features/Contents/Handlers/GetCreatorByAlias.cs index 2a2b161..c53d2a6 100644 --- a/src/Web/Features/Contents/Handlers/GetCreatorByAlias.cs +++ b/src/Web/Features/Contents/Handlers/GetCreatorByAlias.cs @@ -50,7 +50,7 @@ public class GetCreatorByAliasHandler( } else { - var subscriberCount = await context.Subscriptions.CountAsync( + var followerCount = await context.Followers.CountAsync( s => s.CreatorId == creator.Id, cancellationToken: ct); @@ -63,7 +63,7 @@ public class GetCreatorByAliasHandler( creator.Socials, creator.Colors, creator.Images, - subscriberCount); + followerCount); await SendAsync(model, cancellation: ct); } diff --git a/src/Web/Features/Contents/Handlers/GetFollowedContents.cs b/src/Web/Features/Contents/Handlers/GetFollowedContents.cs deleted file mode 100644 index 39de093..0000000 --- a/src/Web/Features/Contents/Handlers/GetFollowedContents.cs +++ /dev/null @@ -1,75 +0,0 @@ -using Hutopy.Web.Common; -using Hutopy.Web.Extensions; -using Hutopy.Web.Features.Contents.Data; -using Hutopy.Web.Features.Contents.Handlers.Models; - -namespace Hutopy.Web.Features.Contents.Handlers; - -[PublicAPI] -public sealed class GetFollowedContentsRequest -{ - [BindFrom("page_size")] public int PageSize { get; set; } = 10; - [BindFrom("last_id")] public Guid? LastId { get; set; } -} - -[PublicAPI] -public class GetFollowedContentsHandler( - ContentDbContext context) - : Endpoint> -{ - public override void Configure() - { - Get("/api/contents/followed"); - Options(o => o.WithTags("Contents")); - AllowAnonymous(); - } - - public override async Task HandleAsync( - GetFollowedContentsRequest req, - CancellationToken ct) - { - - var userId = HttpContext.User.GetUserId(); - - var userSubscriptionIds = await context - .Subscriptions - .Where(s => s.CreatedBy == userId) - .Select(s => s.CreatorId) - .ToListAsync(cancellationToken: ct); - - var query = context.Contents - .Where(c => c.DeletedAt == null) - .Where(x => userSubscriptionIds.Contains(x.CreatedBy)); - if (req.LastId.HasValue) - { - query = query.Where(c => c.Id > req.LastId.Value); - } - - query = query.OrderByDescending(c => c.CreatedAt); - - var content = await query - .Select(c => new ContentModel - { - Id = c.Id, - CreatedBy = c.CreatedBy, - CreatedByName = c.Creator!.Name, - CreatedByPortraitUrl = c.Creator.Images.Logo, - CreatedAt = c.CreatedAt, - DeletedBy = c.DeletedBy, - DeletedAt = c.DeletedAt, - Title = c.Title, - Description = c.Description, - Urls = c.Urls, - Reactions = c.Reactions.Select(x => new ReactionModel - { - Reaction = x.Reaction.FromEnum(), - UserId = x.UserId, - UserName = x.UserName - }).ToList() - }) - .Take(req.PageSize) - .ToListAsync(ct); - - await SendAsync(content, cancellation: ct); - } -} diff --git a/src/Web/Features/Contents/Handlers/GetSubscriptions.cs b/src/Web/Features/Contents/Handlers/GetFollowedCreators.cs similarity index 73% rename from src/Web/Features/Contents/Handlers/GetSubscriptions.cs rename to src/Web/Features/Contents/Handlers/GetFollowedCreators.cs index 02c320e..6ab7f52 100644 --- a/src/Web/Features/Contents/Handlers/GetSubscriptions.cs +++ b/src/Web/Features/Contents/Handlers/GetFollowedCreators.cs @@ -5,14 +5,14 @@ using Hutopy.Web.Features.Contents.Handlers.Models; namespace Hutopy.Web.Features.Contents.Handlers; [PublicAPI] -public class GetSubscriptionsHandler( +public class GetFollowedCreatorsHandler( ContentDbContext context) - : EndpointWithoutRequest> + : EndpointWithoutRequest> { public override void Configure() { - Get("/api/subscriptions"); - Options((o => o.WithTags("Subscriptions"))); + Get("/api/creators/followed"); + Options((o => o.WithTags("Creators"))); } public override async Task HandleAsync( @@ -21,9 +21,9 @@ public class GetSubscriptionsHandler( var userId = HttpContext.User.GetUserId(); var subscriptions = await context - .Subscriptions + .Followers .Where(s => s.CreatedBy == userId) - .Select(s => new SubscriptionModel( + .Select(s => new FollowModel( s.CreatorId, s.Creator!.Name, s.Creator.Images.Logo)) diff --git a/src/Web/Features/Contents/Handlers/Models/CreatorModel.cs b/src/Web/Features/Contents/Handlers/Models/CreatorModel.cs index 83b7bd6..00abe19 100644 --- a/src/Web/Features/Contents/Handlers/Models/CreatorModel.cs +++ b/src/Web/Features/Contents/Handlers/Models/CreatorModel.cs @@ -12,4 +12,4 @@ public record struct CreatorModel( Socials Socials, Colors Colors, Images Images, - int SubscriberCount); + int FollowerCount); diff --git a/src/Web/Features/Contents/Handlers/Models/SubscriptionModel.cs b/src/Web/Features/Contents/Handlers/Models/FollowModel.cs similarity index 81% rename from src/Web/Features/Contents/Handlers/Models/SubscriptionModel.cs rename to src/Web/Features/Contents/Handlers/Models/FollowModel.cs index 7c748aa..7f722f1 100644 --- a/src/Web/Features/Contents/Handlers/Models/SubscriptionModel.cs +++ b/src/Web/Features/Contents/Handlers/Models/FollowModel.cs @@ -1,7 +1,7 @@ namespace Hutopy.Web.Features.Contents.Handlers.Models; [PublicAPI] -public record SubscriptionModel( +public record FollowModel( Guid CreatorId, string CreatorName, string? CreatorPortraitUrl); diff --git a/src/Web/Features/Contents/Handlers/UnsubscribeFromCreator.cs b/src/Web/Features/Contents/Handlers/UnfollowCreator.cs similarity index 75% rename from src/Web/Features/Contents/Handlers/UnsubscribeFromCreator.cs rename to src/Web/Features/Contents/Handlers/UnfollowCreator.cs index 69ac37e..a4d9669 100644 --- a/src/Web/Features/Contents/Handlers/UnsubscribeFromCreator.cs +++ b/src/Web/Features/Contents/Handlers/UnfollowCreator.cs @@ -16,8 +16,8 @@ public class UnsubscribeFromCreatorHandler( { public override void Configure() { - Post("/api/creators/{CreatorId}/unsubscribe"); - Options((o => o.WithTags("Subscriptions"))); + Post("/api/creators/{CreatorId}/unfollow"); + Options((o => o.WithTags("Creators"))); Description(x => x.Accepts("*/*")); } @@ -25,14 +25,15 @@ public class UnsubscribeFromCreatorHandler( UnsubscribeFromCreatorRequest req, CancellationToken ct) { - var subscription = new Subscription { CreatorId = req.CreatorId, CreatedBy = HttpContext.User.GetUserId() }; - - context.Subscriptions.Attach(subscription); - context.Subscriptions.Remove(subscription); - try { + var subscription = new Follower { CreatorId = req.CreatorId, CreatedBy = HttpContext.User.GetUserId() }; + + context.Followers.Attach(subscription); + context.Followers.Remove(subscription); + await context.SaveChangesAsync(ct); + await SendOkAsync(ct); } catch (Exception) diff --git a/src/Web/Features/Contents/Migrations/20241011103653_FromSubscribersToFollowers.Designer.cs b/src/Web/Features/Contents/Migrations/20241011103653_FromSubscribersToFollowers.Designer.cs new file mode 100644 index 0000000..4d4fd2b --- /dev/null +++ b/src/Web/Features/Contents/Migrations/20241011103653_FromSubscribersToFollowers.Designer.cs @@ -0,0 +1,310 @@ +// +using System; +using Hutopy.Web.Features.Contents.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace Hutopy.Web.Features.Contents.Migrations +{ + [DbContext(typeof(ContentDbContext))] + [Migration("20241011103653_FromSubscribersToFollowers")] + partial class FromSubscribersToFollowers + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasDefaultSchema("Content") + .HasAnnotation("ProductVersion", "8.0.4") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("Hutopy.Web.Features.Contents.Data.Content", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("CURRENT_TIMESTAMP"); + + b.Property("CreatedBy") + .HasColumnType("uuid"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("DeletedBy") + .HasColumnType("uuid"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(2048) + .HasColumnType("character varying(2048)"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("Urls") + .HasColumnType("text[]"); + + b.HasKey("Id"); + + b.HasIndex("CreatedBy"); + + b.ToTable("Contents", "Content"); + }); + + modelBuilder.Entity("Hutopy.Web.Features.Contents.Data.Creator", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("uuid"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("Title") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.HasKey("Id"); + + b.ToTable("Creators", "Content"); + }); + + modelBuilder.Entity("Hutopy.Web.Features.Contents.Data.Follower", b => + { + b.Property("CreatedBy") + .HasColumnType("uuid"); + + b.Property("CreatorId") + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("CreatedBy", "CreatorId"); + + b.HasIndex("CreatorId"); + + b.ToTable("Followers", "Content"); + }); + + modelBuilder.Entity("Hutopy.Web.Features.Contents.Data.Content", b => + { + b.HasOne("Hutopy.Web.Features.Contents.Data.Creator", "Creator") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.OwnsMany("Hutopy.Web.Features.Contents.Data.ContentReaction", "Reactions", b1 => + { + b1.Property("ContentId") + .HasColumnType("uuid"); + + b1.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b1.Property("Id")); + + b1.Property("Reaction") + .HasColumnType("integer"); + + b1.Property("UserId") + .HasColumnType("uuid"); + + b1.Property("UserName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b1.HasKey("ContentId", "Id"); + + b1.ToTable("ContentReactions", "Content"); + + b1.WithOwner() + .HasForeignKey("ContentId"); + }); + + b.Navigation("Creator"); + + b.Navigation("Reactions"); + }); + + modelBuilder.Entity("Hutopy.Web.Features.Contents.Data.Creator", b => + { + b.OwnsOne("Hutopy.Web.Features.Contents.Data.Colors", "Colors", b1 => + { + b1.Property("CreatorId") + .HasColumnType("uuid"); + + b1.Property("Background") + .IsRequired() + .HasMaxLength(9) + .HasColumnType("character varying(9)"); + + b1.Property("Error") + .IsRequired() + .HasMaxLength(9) + .HasColumnType("character varying(9)"); + + b1.Property("OnBackground") + .IsRequired() + .HasMaxLength(9) + .HasColumnType("character varying(9)"); + + b1.Property("OnError") + .IsRequired() + .HasMaxLength(9) + .HasColumnType("character varying(9)"); + + b1.Property("OnPrimary") + .IsRequired() + .HasMaxLength(9) + .HasColumnType("character varying(9)"); + + b1.Property("OnSecondary") + .IsRequired() + .HasMaxLength(9) + .HasColumnType("character varying(9)"); + + b1.Property("OnSurface") + .IsRequired() + .HasMaxLength(9) + .HasColumnType("character varying(9)"); + + b1.Property("Primary") + .IsRequired() + .HasMaxLength(9) + .HasColumnType("character varying(9)"); + + b1.Property("Secondary") + .IsRequired() + .HasMaxLength(9) + .HasColumnType("character varying(9)"); + + b1.Property("Surface") + .IsRequired() + .HasMaxLength(9) + .HasColumnType("character varying(9)"); + + b1.HasKey("CreatorId"); + + b1.ToTable("Colors", "Content"); + + b1.WithOwner() + .HasForeignKey("CreatorId"); + }); + + b.OwnsOne("Hutopy.Web.Features.Contents.Data.Images", "Images", b1 => + { + b1.Property("CreatorId") + .HasColumnType("uuid"); + + b1.Property("Banner") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.Property("Logo") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.HasKey("CreatorId"); + + b1.ToTable("Images", "Content"); + + b1.WithOwner() + .HasForeignKey("CreatorId"); + }); + + b.OwnsOne("Hutopy.Web.Features.Contents.Data.Socials", "Socials", b1 => + { + b1.Property("CreatorId") + .HasColumnType("uuid"); + + b1.Property("FacebookUrl") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.Property("InstagramUrl") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.Property("LinkedInUrl") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.Property("RedditUrl") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.Property("TikTokUrl") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.Property("WebsiteUrl") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.Property("XUrl") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.Property("YoutubeUrl") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b1.HasKey("CreatorId"); + + b1.ToTable("Socials", "Content"); + + b1.WithOwner() + .HasForeignKey("CreatorId"); + }); + + b.Navigation("Colors") + .IsRequired(); + + b.Navigation("Images") + .IsRequired(); + + b.Navigation("Socials") + .IsRequired(); + }); + + modelBuilder.Entity("Hutopy.Web.Features.Contents.Data.Follower", b => + { + b.HasOne("Hutopy.Web.Features.Contents.Data.Creator", "Creator") + .WithMany() + .HasForeignKey("CreatorId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Creator"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Web/Features/Contents/Migrations/20241011103653_FromSubscribersToFollowers.cs b/src/Web/Features/Contents/Migrations/20241011103653_FromSubscribersToFollowers.cs new file mode 100644 index 0000000..8f41082 --- /dev/null +++ b/src/Web/Features/Contents/Migrations/20241011103653_FromSubscribersToFollowers.cs @@ -0,0 +1,81 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Hutopy.Web.Features.Contents.Migrations +{ + /// + public partial class FromSubscribersToFollowers : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "Subscriptions", + schema: "Content"); + + migrationBuilder.CreateTable( + name: "Followers", + schema: "Content", + columns: table => new + { + CreatedBy = table.Column(type: "uuid", nullable: false), + CreatorId = table.Column(type: "uuid", nullable: false), + CreatedAt = table.Column(type: "timestamp with time zone", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Followers", x => new { x.CreatedBy, x.CreatorId }); + table.ForeignKey( + name: "FK_Followers_Creators_CreatorId", + column: x => x.CreatorId, + principalSchema: "Content", + principalTable: "Creators", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "IX_Followers_CreatorId", + schema: "Content", + table: "Followers", + column: "CreatorId"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "Followers", + schema: "Content"); + + migrationBuilder.CreateTable( + name: "Subscriptions", + schema: "Content", + columns: table => new + { + CreatedBy = table.Column(type: "uuid", nullable: false), + CreatorId = table.Column(type: "uuid", nullable: false), + CreatedAt = table.Column(type: "timestamp with time zone", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Subscriptions", x => new { x.CreatedBy, x.CreatorId }); + table.ForeignKey( + name: "FK_Subscriptions_Creators_CreatorId", + column: x => x.CreatorId, + principalSchema: "Content", + principalTable: "Creators", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "IX_Subscriptions_CreatorId", + schema: "Content", + table: "Subscriptions", + column: "CreatorId"); + } + } +} diff --git a/src/Web/Features/Contents/Migrations/ContentDbContextModelSnapshot.cs b/src/Web/Features/Contents/Migrations/ContentDbContextModelSnapshot.cs index c38d421..2f630c6 100644 --- a/src/Web/Features/Contents/Migrations/ContentDbContextModelSnapshot.cs +++ b/src/Web/Features/Contents/Migrations/ContentDbContextModelSnapshot.cs @@ -92,7 +92,7 @@ namespace Hutopy.Web.Features.Contents.Migrations b.ToTable("Creators", "Content"); }); - modelBuilder.Entity("Hutopy.Web.Features.Contents.Data.Subscription", b => + modelBuilder.Entity("Hutopy.Web.Features.Contents.Data.Follower", b => { b.Property("CreatedBy") .HasColumnType("uuid"); @@ -107,7 +107,7 @@ namespace Hutopy.Web.Features.Contents.Migrations b.HasIndex("CreatorId"); - b.ToTable("Subscriptions", "Content"); + b.ToTable("Followers", "Content"); }); modelBuilder.Entity("Hutopy.Web.Features.Contents.Data.Content", b => @@ -294,7 +294,7 @@ namespace Hutopy.Web.Features.Contents.Migrations .IsRequired(); }); - modelBuilder.Entity("Hutopy.Web.Features.Contents.Data.Subscription", b => + modelBuilder.Entity("Hutopy.Web.Features.Contents.Data.Follower", b => { b.HasOne("Hutopy.Web.Features.Contents.Data.Creator", "Creator") .WithMany() diff --git a/src/Web/Features/Memberships/Data/Creator.cs b/src/Web/Features/Memberships/Data/Creator.cs new file mode 100644 index 0000000..72ebd31 --- /dev/null +++ b/src/Web/Features/Memberships/Data/Creator.cs @@ -0,0 +1,8 @@ +namespace Hutopy.Web.Features.Memberships.Data; + +public class Creator +{ + public Guid Id { get; set; } + public string Name { get; set; } + public string StripeAccountId { get; set; } +} diff --git a/src/Web/Features/Memberships/Data/MembershipDbContext.cs b/src/Web/Features/Memberships/Data/MembershipDbContext.cs new file mode 100644 index 0000000..f0dcd47 --- /dev/null +++ b/src/Web/Features/Memberships/Data/MembershipDbContext.cs @@ -0,0 +1,58 @@ +namespace Hutopy.Web.Features.Memberships.Data; + +public sealed class MembershipDbContext( + DbContextOptions options) + : DbContext(options) +{ + public const string SchemaName = "Membership"; + + public DbSet Creators => Set(); + public DbSet Subscriptions => Set(); + public DbSet Tiers => Set(); + public DbSet Tips => Set(); + public DbSet Transactions => Set(); + + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + modelBuilder.HasDefaultSchema(SchemaName); + + modelBuilder.Entity(); + + modelBuilder + .Entity() + .Property(c => c.CreatedAt) + .ValueGeneratedOnAdd() + .HasDefaultValueSql("CURRENT_TIMESTAMP"); + + modelBuilder + .Entity() + .HasOne(c => c.Creator) + .WithMany() + .HasForeignKey(c => c.CreatorId); + + modelBuilder + .Entity() + .HasOne(c => c.Creator) + .WithMany() + .HasForeignKey(c => c.CreatorId); + + modelBuilder + .Entity() + .Property(c => c.CreatedAt) + .ValueGeneratedOnAdd() + .HasDefaultValueSql("CURRENT_TIMESTAMP"); + + modelBuilder + .Entity() + .Property(c => c.CreatedAt) + .ValueGeneratedOnAdd() + .HasDefaultValueSql("CURRENT_TIMESTAMP"); + + modelBuilder + .Entity() + .Property(c => c.CreatedAt) + .ValueGeneratedOnAdd() + .HasDefaultValueSql("CURRENT_TIMESTAMP"); + } +} diff --git a/src/Web/Features/Memberships/Data/MembershipDbContextInitializer.cs b/src/Web/Features/Memberships/Data/MembershipDbContextInitializer.cs new file mode 100644 index 0000000..df9705e --- /dev/null +++ b/src/Web/Features/Memberships/Data/MembershipDbContextInitializer.cs @@ -0,0 +1,34 @@ +using Hutopy.Web.Features.Contents.Data; + +namespace Hutopy.Web.Features.Memberships.Data; + +public static class InitializerExtensions +{ + public static async Task InitialiseMembershipDbContextAsync(this WebApplication app) + { + using var scope = app.Services.CreateScope(); + + var initializer = scope.ServiceProvider.GetRequiredService(); + + await initializer.InitialiseAsync(); + } +} + +public class MembershipDbContextInitializer( + ILogger logger, + ContentDbContext context + ) +{ + public async Task InitialiseAsync() + { + try + { + await context.Database.MigrateAsync(); + } + catch (Exception ex) + { + logger.LogError(ex, "An error occurred while initialising the content database."); + throw; + } + } +} diff --git a/src/Web/Features/Memberships/Data/Subscription.cs b/src/Web/Features/Memberships/Data/Subscription.cs new file mode 100644 index 0000000..6bd00d1 --- /dev/null +++ b/src/Web/Features/Memberships/Data/Subscription.cs @@ -0,0 +1,18 @@ +namespace Hutopy.Web.Features.Memberships.Data; + +public class Subscription +{ + public Guid Id { get; set; } + public DateTimeOffset CreatedAt { get; set; } + public Guid UserId { get; set; } + public Guid CreatorId { get; set; } + public Creator Creator { get; set; } + public Guid TierId { get; set; } + public Tier Tier { get; set; } + public DateTimeOffset StartDate { get; set; } + public DateTimeOffset? EndDate { get; set; } + public bool IsActive => EndDate == null || EndDate > DateTime.UtcNow; + public string? StripeSessionId { get; set; } + public string? StripeSubscriptionId { get; set; } + +} diff --git a/src/Web/Features/Memberships/Data/Tier.cs b/src/Web/Features/Memberships/Data/Tier.cs new file mode 100644 index 0000000..9563852 --- /dev/null +++ b/src/Web/Features/Memberships/Data/Tier.cs @@ -0,0 +1,14 @@ +namespace Hutopy.Web.Features.Memberships.Data; + +public class Tier +{ + public Guid Id { get; set; } + public DateTime CreatedAt { get; set; } + public Guid CreatorId { get; set; } + public Creator Creator { get; set; } + public string Name { get; set; } + public decimal Price { get; set; } + public string CurrencyCode { get; set; } + + public ICollection Subscriptions { get; set; } +} diff --git a/src/Web/Features/Memberships/Data/Tip.cs b/src/Web/Features/Memberships/Data/Tip.cs new file mode 100644 index 0000000..57fe7b7 --- /dev/null +++ b/src/Web/Features/Memberships/Data/Tip.cs @@ -0,0 +1,15 @@ +namespace Hutopy.Web.Features.Memberships.Data; + +public class Tip +{ + public Guid Id { get; set; } + public DateTimeOffset CreatedAt { get; set; } + public string StripeSessionId { get; set; } + public Guid TipperId { get; set; } + public string TipperName { get; set; } + public Guid CreatorId { get; set; } + public string CreatorName { get; set; } + public decimal Amount { get; set; } + public string Currency { get; set; } + public string Message { get; set; } +} diff --git a/src/Web/Features/Memberships/Data/Transaction.cs b/src/Web/Features/Memberships/Data/Transaction.cs new file mode 100644 index 0000000..ae28704 --- /dev/null +++ b/src/Web/Features/Memberships/Data/Transaction.cs @@ -0,0 +1,11 @@ +namespace Hutopy.Web.Features.Memberships.Data; + +public class Transaction +{ + public Guid Id { get; set; } + public DateTimeOffset CreatedAt { get; set; } + public string StripeCheckoutSessionId { get; set; } + public decimal Amount { get; set; } + public string Type { get; set; } // Subscription, Tip + public DateTime Timestamp { get; set; } +} diff --git a/src/Web/Features/Memberships/DependencyInjection.cs b/src/Web/Features/Memberships/DependencyInjection.cs new file mode 100644 index 0000000..8203882 --- /dev/null +++ b/src/Web/Features/Memberships/DependencyInjection.cs @@ -0,0 +1,27 @@ +using Hutopy.Web.Features.Memberships.Data; +using Hutopy.Web.Features.Memberships.Services; + +namespace Hutopy.Web.Features.Memberships; + +public static class DependencyInjection +{ + public static WebApplicationBuilder AddMembershipModule( + this WebApplicationBuilder builder, + Action? configureAction = null) + { + builder.Services.AddSingleton(); + + builder.Services.AddDbContext(configureAction); + builder.Services.AddScoped(); + + builder.Services.AddScoped(); + + builder.Services + .AddOptions() + .Bind(builder.Configuration.GetSection("Stripe")) + .ValidateDataAnnotations() + .ValidateOnStart(); + + return builder; + } +} diff --git a/src/Web/Features/Memberships/Events/SubscriptionPaid.cs b/src/Web/Features/Memberships/Events/SubscriptionPaid.cs new file mode 100644 index 0000000..b661b35 --- /dev/null +++ b/src/Web/Features/Memberships/Events/SubscriptionPaid.cs @@ -0,0 +1,7 @@ +namespace Hutopy.Web.Features.Memberships.Events; + +public record struct SubscriptionPaid( + Guid CreatorId, + string CreatorName, + string Tier, + DateTimeOffset Since); diff --git a/src/Web/Features/Memberships/Events/TipPaid.cs b/src/Web/Features/Memberships/Events/TipPaid.cs new file mode 100644 index 0000000..6331757 --- /dev/null +++ b/src/Web/Features/Memberships/Events/TipPaid.cs @@ -0,0 +1,8 @@ +namespace Hutopy.Web.Features.Memberships.Events; + +public record struct TipPaid( + Guid CreatorId, + string CreatorName, + decimal Amount, + string Currency, + string Message); diff --git a/src/Web/Features/Memberships/Handlers/CancelSubscription.cs b/src/Web/Features/Memberships/Handlers/CancelSubscription.cs new file mode 100644 index 0000000..676c3f7 --- /dev/null +++ b/src/Web/Features/Memberships/Handlers/CancelSubscription.cs @@ -0,0 +1,48 @@ +using Hutopy.Web.Features.Memberships.Data; +using Hutopy.Web.Features.Memberships.Services; + +namespace Hutopy.Web.Features.Memberships.Handlers; + +[PublicAPI] +public class CancelSubscriptionRequest +{ + public Guid SubscriptionId { get; set; } +} + +public class CancelSubscriptionHandler( + MembershipDbContext dbDbContext, + StripeService stripeService) + : Endpoint +{ + public override void Configure() + { + Post("/api/membership/unsubscribe"); + Options(o => o.WithTags("Memberships")); + } + + public override async Task HandleAsync( + CancelSubscriptionRequest req, + CancellationToken ct) + { + var subscription = await dbDbContext + .Subscriptions + .FindAsync( + [req.SubscriptionId], + cancellationToken: ct); + + if (subscription is not { EndDate: null }) + { + await SendNotFoundAsync(ct); + return; + } + + // Cancel Stripe subscription + await stripeService.CancelSubscription(subscription.Id); + + // Update subscription in the system + subscription.EndDate = DateTime.UtcNow; + await dbDbContext.SaveChangesAsync(ct); + + await SendOkAsync(subscription.Id, ct); + } +} diff --git a/src/Web/Features/Memberships/Handlers/CreateMembershipTier.cs b/src/Web/Features/Memberships/Handlers/CreateMembershipTier.cs new file mode 100644 index 0000000..d3dc138 --- /dev/null +++ b/src/Web/Features/Memberships/Handlers/CreateMembershipTier.cs @@ -0,0 +1,36 @@ +using Hutopy.Web.Features.Memberships.Data; + +namespace Hutopy.Web.Features.Memberships.Handlers; + +[PublicAPI] +public class CreateMembershipTierRequest +{ + public Guid CreatorId { get; set; } + public string Name { get; set; } + public decimal Price { get; set; } +} + +[PublicAPI] +public class CreateMembershipTierEndpoint( + MembershipDbContext dbDbContext) + : Endpoint +{ + public override void Configure() + { + Post("/api/membership/tiers"); + Options(o => o.WithTags("Memberships")); + } + + public override async Task HandleAsync( + CreateMembershipTierRequest req, + CancellationToken ct) + { + var tier = dbDbContext + .Tiers + .Add(new Tier { CreatorId = req.CreatorId, Price = req.Price, Name = req.Name }); + + await dbDbContext.SaveChangesAsync(ct); + + await SendOkAsync(tier, ct); + } +} diff --git a/src/Web/Features/Memberships/Handlers/GetActiveSubscriptions.cs b/src/Web/Features/Memberships/Handlers/GetActiveSubscriptions.cs new file mode 100644 index 0000000..ddca0c7 --- /dev/null +++ b/src/Web/Features/Memberships/Handlers/GetActiveSubscriptions.cs @@ -0,0 +1,32 @@ +using Hutopy.Web.Common; +using Hutopy.Web.Features.Memberships.Data; + +namespace Hutopy.Web.Features.Memberships.Handlers; + +[PublicAPI] +public class GetActiveSubscriptionsRequest; + +[PublicAPI] +public class GetActiveSubscriptionsHandler( + MembershipDbContext dbDbContext) + : Endpoint +{ + public override void Configure() + { + Get("/api/membership/active"); + Options(o => o.WithTags("Memberships")); + } + + public override async Task HandleAsync( + GetActiveSubscriptionsRequest req, + CancellationToken ct) + { + var subscriptions = await dbDbContext + .Subscriptions + .Where(subscription => subscription.UserId == User.GetUserId()) + .Where(subscription => subscription.IsActive) + .ToListAsync(ct); + + await SendOkAsync(subscriptions, ct); + } +} diff --git a/src/Web/Features/Memberships/Handlers/GetMembershipTier.cs b/src/Web/Features/Memberships/Handlers/GetMembershipTier.cs new file mode 100644 index 0000000..abb40f4 --- /dev/null +++ b/src/Web/Features/Memberships/Handlers/GetMembershipTier.cs @@ -0,0 +1,47 @@ +using Hutopy.Web.Features.Memberships.Data; + +namespace Hutopy.Web.Features.Memberships.Handlers; + +[PublicAPI] +public class GetMembershipTierRequest +{ + public Guid CreatorId { get; set; } +} + +[PublicAPI] +public record struct TierModel( + Guid Id, + DateTime CreatedAt, + string Name, + decimal Price, + string CurrencyCode); + +[PublicAPI] +public class GetMembershipTierEndpoint( + MembershipDbContext dbDbContext) + : Endpoint> +{ + public override void Configure() + { + Get("/api/membership/tiers"); + Options(o => o.WithTags("Memberships")); + } + + public override async Task HandleAsync( + CreateMembershipTierRequest req, + CancellationToken ct) + { + var tiers = await dbDbContext + .Tiers + .Where(tier => tier.CreatorId == req.CreatorId) + .Select(tier => new TierModel( + tier.Id, + tier.CreatedAt, + tier.Name, + tier.Price, + tier.CurrencyCode)) + .ToListAsync(ct); + + await SendOkAsync(tiers, ct); + } +} diff --git a/src/Web/Features/Memberships/Handlers/GetReceivedTips.cs b/src/Web/Features/Memberships/Handlers/GetReceivedTips.cs new file mode 100644 index 0000000..7e5e606 --- /dev/null +++ b/src/Web/Features/Memberships/Handlers/GetReceivedTips.cs @@ -0,0 +1,45 @@ +using Hutopy.Web.Common; +using Hutopy.Web.Features.Memberships.Data; + +namespace Hutopy.Web.Features.Memberships.Handlers; + +[PublicAPI] +public record struct TipReceivedModel( + Guid Id, + DateTimeOffset CreatedAt, + Guid TipperId, + string TipperName, + decimal Amount, + string Currency, + string Message); + +[PublicAPI] +public class GetReceivedTipsHandler( + MembershipDbContext dbDbContext) + : EndpointWithoutRequest> +{ + public override void Configure() + { + Get("/api/tips/received"); + Options(o => o.WithTags("Memberships")); + } + + public override async Task HandleAsync( + CancellationToken ct) + { + var tipsReceived = await dbDbContext + .Tips + .Where(tip => tip.CreatorId == User.GetUserId()) + .Select(tip => new TipReceivedModel( + tip.Id, + tip.CreatedAt, + tip.TipperId, + tip.TipperName, + tip.Amount, + tip.Currency, + tip.Message)) + .ToListAsync(ct); + + await SendOkAsync(tipsReceived, ct); + } +} diff --git a/src/Web/Features/Memberships/Handlers/GetSentTips.cs b/src/Web/Features/Memberships/Handlers/GetSentTips.cs new file mode 100644 index 0000000..a37af32 --- /dev/null +++ b/src/Web/Features/Memberships/Handlers/GetSentTips.cs @@ -0,0 +1,45 @@ +using Hutopy.Web.Common; +using Hutopy.Web.Features.Memberships.Data; + +namespace Hutopy.Web.Features.Memberships.Handlers; + +[PublicAPI] +public record struct TipSentModel( + Guid Id, + DateTimeOffset CreatedAt, + Guid CreatorId, + string CreatorName, + decimal Amount, + string Currency, + string Message); + +[PublicAPI] +public class GetSentTipsHandler( + MembershipDbContext dbContext) + : EndpointWithoutRequest> +{ + public override void Configure() + { + Get("/api/tips/sent"); + Options(o => o.WithTags("Memberships")); + } + + public override async Task HandleAsync( + CancellationToken ct) + { + var tips = await dbContext + .Tips + .Where(t => t.TipperId == User.GetUserId()) + .Select(tip => new TipSentModel( + tip.Id, + tip.CreatedAt, + tip.CreatorId, + tip.CreatorName, + tip.Amount, + tip.Currency, + tip.Message)) + .ToListAsync(ct); + + await SendOkAsync(tips, ct); + } +} diff --git a/src/Web/Features/Memberships/Handlers/HandleStripe.cs b/src/Web/Features/Memberships/Handlers/HandleStripe.cs new file mode 100644 index 0000000..a46dc67 --- /dev/null +++ b/src/Web/Features/Memberships/Handlers/HandleStripe.cs @@ -0,0 +1,71 @@ +using Hutopy.Web.Features.Memberships.Data; +using Hutopy.Web.Features.Memberships.Services; +using Microsoft.Extensions.Options; +using Stripe; + +namespace Hutopy.Web.Features.Memberships.Handlers; + +public static class StripeEvents +{ + public const string SubscriptionCreated = "subscription_created"; + public const string CustomerSubscriptionDeleted = "customer.subscription_deleted"; + public const string InvoicePaymentSucceeded = "invoice.payment_succeeded"; + public const string InvoicePaymentFailed = "invoice.payment_failed"; + public const string CheckoutSessionCompleted = "checkout.session.completed"; +} + +public class StripeWebhookEndpoint( + MembershipDbContext dbContext, + StripeService stripeService, + IOptions options) + : EndpointWithoutRequest +{ + public override void Configure() + { + Post("/api/stripe"); + AllowAnonymous(); + Options(o => o.WithTags("Memberships")); + } + + public override async Task HandleAsync(CancellationToken ct) + { + using var streamReader = new StreamReader(HttpContext.Request.Body); + var json = await streamReader.ReadToEndAsync(ct); + + var signatureHeader = HttpContext.Request.Headers["Stripe-Signature"]; + var stripeEvent = EventUtility.ConstructEvent(json, signatureHeader, options.Value.WebhookSecret); + + switch (stripeEvent.Type) + { + case StripeEvents.InvoicePaymentSucceeded: + await stripeService.HandlePaymentSucceeded(stripeEvent, ct); + break; + case StripeEvents.InvoicePaymentFailed: + await stripeService.HandlePaymentFailed(stripeEvent, ct); + break; + case StripeEvents.CheckoutSessionCompleted: + await stripeService.HandleCheckoutSessionCompleted(stripeEvent, ct); + break; + case StripeEvents.CustomerSubscriptionDeleted: + { + var subscription = stripeEvent.Data.Object as Stripe.Subscription; + var existingSubscription = await dbContext + .Subscriptions + .FirstOrDefaultAsync(x => x.StripeSubscriptionId == subscription!.Id, ct); + + if (existingSubscription != null) + { + var today = DateTime.Today; + int lastDay = DateTime.DaysInMonth(today.Year, today.Month); + var lastDayOfMonth = new DateTime(today.Year, today.Month, lastDay); + existingSubscription.EndDate = new DateTimeOffset(lastDayOfMonth); + await dbContext.SaveChangesAsync(ct); + } + + break; + } + } + + await SendOkAsync(ct); + } +} diff --git a/src/Web/Features/Memberships/Handlers/SendTip.cs b/src/Web/Features/Memberships/Handlers/SendTip.cs new file mode 100644 index 0000000..9b59761 --- /dev/null +++ b/src/Web/Features/Memberships/Handlers/SendTip.cs @@ -0,0 +1,117 @@ +using Hutopy.Web.Common; +using Hutopy.Web.Features.Memberships.Data; +using Hutopy.Web.Features.Memberships.Services; + +namespace Hutopy.Web.Features.Memberships.Handlers; + +[PublicAPI] +public record SendTipRequest +{ + public Guid CreatorId { get; set; } + public required decimal Amount { get; init; } + public required string Currency { get; init; } + public required string Message { get; init; } + public required string CheckoutSuccessUrl { get; init; } + public required string CheckoutCancelledUrl { get; init; } +} + +[PublicAPI] +public class SendTipResponse +{ + public required string Status { get; init; } + public required string StripeCheckoutUrl { get; init; } +} + +[PublicAPI] +public class SendTipRequestValidator : Validator +{ + public SendTipRequestValidator() + { + RuleFor(x => x.Amount) + .GreaterThan(0) + .WithMessage("Tip amount must be greater than 0"); + + RuleFor(x => x.CreatorId) + .NotEmpty() + .WithMessage("Creator ID is required"); + + RuleFor(x => x.CheckoutSuccessUrl) + .NotEmpty() + .WithMessage("CheckoutSuccessUrl is required"); + + RuleFor(x => x.CheckoutCancelledUrl) + .NotEmpty() + .WithMessage("CheckoutCancelledUrl is required"); + } +} + +[PublicAPI] +public class SendTipHandler( + MembershipDbContext dbDbContext, + StripeService stripeService) + : Endpoint +{ + public override void Configure() + { + Post("/api/tips/{CreatorId}"); + Options(o => o.WithTags("Memberships")); + } + + public override async Task HandleAsync( + SendTipRequest req, + CancellationToken ct) + { + var userId = User.GetUserId(); + var userName = User.GetName(); + + var creator = await dbDbContext.Creators.FindAsync( + [req.CreatorId], + cancellationToken: ct); + if (creator == null) + { + await SendNotFoundAsync(ct); + return; + } + + var checkoutSession = await stripeService.CreateTipCheckoutSession( + userId, + req.Amount, + req.Currency, + creator.Id, + creator.Name, + creator.StripeAccountId, + req.CheckoutSuccessUrl, + req.CheckoutCancelledUrl); + + dbDbContext.Tips.Add( + new Tip + { + Id = Guid.NewGuid(), + CreatedAt = DateTimeOffset.UtcNow, + TipperId = userId, + TipperName = userName, + CreatorId = creator.Id, + CreatorName = creator.Name, + Amount = req.Amount, + Currency = req.Currency, + Message = req.Message, + StripeSessionId = checkoutSession.Id + }); + + dbDbContext.Transactions.Add( + new Transaction + { + Id = Guid.NewGuid(), + StripeCheckoutSessionId = checkoutSession.Id, + Amount = req.Amount, + Type = "Tip", + Timestamp = DateTime.UtcNow + }); + + await dbDbContext.SaveChangesAsync(ct); + + await SendAsync( + new SendTipResponse { Status = "Pending", StripeCheckoutUrl = checkoutSession.Url }, + cancellation: ct); + } +} diff --git a/src/Web/Features/Memberships/Handlers/SubscribeToCreator.cs b/src/Web/Features/Memberships/Handlers/SubscribeToCreator.cs new file mode 100644 index 0000000..a006f1a --- /dev/null +++ b/src/Web/Features/Memberships/Handlers/SubscribeToCreator.cs @@ -0,0 +1,110 @@ +using Hutopy.Web.Common; +using Hutopy.Web.Features.Memberships.Data; +using Hutopy.Web.Features.Memberships.Services; + +namespace Hutopy.Web.Features.Memberships.Handlers; + +[PublicAPI] +public class SubscribeRequest +{ + public Guid CreatorId { get; set; } + public Guid TierId { get; set; } +} + +[PublicAPI] +public record struct SubscriptionResponse( + Guid SubscriptionId, + Guid CreatorId, + Guid UserId, + bool IsActive, + string Tier, + DateTimeOffset StartDate, + DateTimeOffset? EndDate); + +[PublicAPI] +public class SubscribeValidator : Validator +{ + public SubscribeValidator() + { + RuleFor(x => x.TierId).NotEmpty(); + } +} + +[PublicAPI] +public class SubscribeHandler( + MembershipDbContext dbDbContext, + StripeService stripeService) + : Endpoint +{ + public override void Configure() + { + Post("/api/membership/subscribe"); + Options(o => o.WithTags("Memberships")); + } + + public override async Task HandleAsync( + SubscribeRequest req, + CancellationToken ct) + { + var tier = await dbDbContext + .Tiers + .Include(tier => tier.Creator) // Include the related table + .Where(tier => tier.Id == req.TierId) + .FirstOrDefaultAsync(ct); + + if (tier == null) + { + await SendNotFoundAsync(ct); + return; + } + + // Process Stripe subscription + var stripeSubscription = await stripeService.CreateSubscriptionCheckoutSession( + User.GetUserId(), + tier.Price, + tier.CurrencyCode, + $"{tier.Name} from {tier.Creator.Name}", + tier.Creator.StripeAccountId, + "", + ""); + + // Record subscription and transaction + var subscription = new Subscription + { + Id = Guid.NewGuid(), + StripeSubscriptionId = stripeSubscription.Id, + CreatorId = tier.CreatorId, + UserId = User.GetUserId(), + Tier = tier, + StartDate = DateTimeOffset.Now, + EndDate = DateTimeOffset.Now.AddMonths(1) + }; + + dbDbContext.Subscriptions.Add(subscription); + + dbDbContext.Transactions.Add( + new Transaction + { + Id = Guid.NewGuid(), + StripeCheckoutSessionId = stripeSubscription.Id, + Amount = tier.Price, + Type = "Subscription", + Timestamp = DateTime.UtcNow + }); + + await dbDbContext.SaveChangesAsync(ct); + + await SendOkAsync( + new SubscriptionResponse + { + UserId = subscription.UserId, + CreatorId = subscription.CreatorId, + SubscriptionId = subscription.Id, + IsActive = subscription.IsActive, + StartDate = subscription.StartDate, + EndDate = subscription.EndDate, + Tier = tier.Name, + }, + ct); + } +} diff --git a/src/Web/Features/Memberships/Migrations/20241011100852_Initial.Designer.cs b/src/Web/Features/Memberships/Migrations/20241011100852_Initial.Designer.cs new file mode 100644 index 0000000..8e61a0b --- /dev/null +++ b/src/Web/Features/Memberships/Migrations/20241011100852_Initial.Designer.cs @@ -0,0 +1,233 @@ +// +using System; +using Hutopy.Web.Features.Memberships.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace Hutopy.Web.Features.Memberships.Migrations +{ + [DbContext(typeof(MembershipDbContext))] + [Migration("20241011100852_Initial")] + partial class Initial + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasDefaultSchema("Membership") + .HasAnnotation("ProductVersion", "8.0.4") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("Hutopy.Web.Features.Membership.Data.Creator", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("StripeAccountId") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("Creators", "Membership"); + }); + + modelBuilder.Entity("Hutopy.Web.Features.Membership.Data.Subscription", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("CURRENT_TIMESTAMP"); + + b.Property("CreatorId") + .HasColumnType("uuid"); + + b.Property("EndDate") + .HasColumnType("timestamp with time zone"); + + b.Property("StartDate") + .HasColumnType("timestamp with time zone"); + + b.Property("StripeSessionId") + .HasColumnType("text"); + + b.Property("StripeSubscriptionId") + .HasColumnType("text"); + + b.Property("TierId") + .HasColumnType("uuid"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("CreatorId"); + + b.HasIndex("TierId"); + + b.ToTable("Subscriptions", "Membership"); + }); + + modelBuilder.Entity("Hutopy.Web.Features.Membership.Data.Tier", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("CURRENT_TIMESTAMP"); + + b.Property("CreatorId") + .HasColumnType("uuid"); + + b.Property("CurrencyCode") + .IsRequired() + .HasColumnType("text"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("Price") + .HasColumnType("numeric"); + + b.HasKey("Id"); + + b.HasIndex("CreatorId"); + + b.ToTable("Tiers", "Membership"); + }); + + modelBuilder.Entity("Hutopy.Web.Features.Membership.Data.Tip", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Amount") + .HasColumnType("numeric"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("CURRENT_TIMESTAMP"); + + b.Property("CreatorId") + .HasColumnType("uuid"); + + b.Property("CreatorName") + .IsRequired() + .HasColumnType("text"); + + b.Property("Currency") + .IsRequired() + .HasColumnType("text"); + + b.Property("Message") + .IsRequired() + .HasColumnType("text"); + + b.Property("StripeSessionId") + .IsRequired() + .HasColumnType("text"); + + b.Property("TipperId") + .HasColumnType("uuid"); + + b.Property("TipperName") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("Tips", "Membership"); + }); + + modelBuilder.Entity("Hutopy.Web.Features.Membership.Data.Transaction", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Amount") + .HasColumnType("numeric"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("CURRENT_TIMESTAMP"); + + b.Property("StripeCheckoutSessionId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Timestamp") + .HasColumnType("timestamp with time zone"); + + b.Property("Type") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("Transactions", "Membership"); + }); + + modelBuilder.Entity("Hutopy.Web.Features.Membership.Data.Subscription", b => + { + b.HasOne("Hutopy.Web.Features.Membership.Data.Creator", "Creator") + .WithMany() + .HasForeignKey("CreatorId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Hutopy.Web.Features.Membership.Data.Tier", "Tier") + .WithMany("Subscriptions") + .HasForeignKey("TierId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Creator"); + + b.Navigation("Tier"); + }); + + modelBuilder.Entity("Hutopy.Web.Features.Membership.Data.Tier", b => + { + b.HasOne("Hutopy.Web.Features.Membership.Data.Creator", "Creator") + .WithMany() + .HasForeignKey("CreatorId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Creator"); + }); + + modelBuilder.Entity("Hutopy.Web.Features.Membership.Data.Tier", b => + { + b.Navigation("Subscriptions"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Web/Features/Memberships/Migrations/20241011100852_Initial.cs b/src/Web/Features/Memberships/Migrations/20241011100852_Initial.cs new file mode 100644 index 0000000..a792a52 --- /dev/null +++ b/src/Web/Features/Memberships/Migrations/20241011100852_Initial.cs @@ -0,0 +1,170 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Hutopy.Web.Features.Memberships.Migrations +{ + /// + public partial class Initial : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.EnsureSchema( + name: "Membership"); + + migrationBuilder.CreateTable( + name: "Creators", + schema: "Membership", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + Name = table.Column(type: "text", nullable: false), + StripeAccountId = table.Column(type: "text", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Creators", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "Tips", + schema: "Membership", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, defaultValueSql: "CURRENT_TIMESTAMP"), + StripeSessionId = table.Column(type: "text", nullable: false), + TipperId = table.Column(type: "uuid", nullable: false), + TipperName = table.Column(type: "text", nullable: false), + CreatorId = table.Column(type: "uuid", nullable: false), + CreatorName = table.Column(type: "text", nullable: false), + Amount = table.Column(type: "numeric", nullable: false), + Currency = table.Column(type: "text", nullable: false), + Message = table.Column(type: "text", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Tips", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "Transactions", + schema: "Membership", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, defaultValueSql: "CURRENT_TIMESTAMP"), + StripeCheckoutSessionId = table.Column(type: "text", nullable: false), + Amount = table.Column(type: "numeric", nullable: false), + Type = table.Column(type: "text", nullable: false), + Timestamp = table.Column(type: "timestamp with time zone", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Transactions", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "Tiers", + schema: "Membership", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, defaultValueSql: "CURRENT_TIMESTAMP"), + CreatorId = table.Column(type: "uuid", nullable: false), + Name = table.Column(type: "text", nullable: false), + Price = table.Column(type: "numeric", nullable: false), + CurrencyCode = table.Column(type: "text", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Tiers", x => x.Id); + table.ForeignKey( + name: "FK_Tiers_Creators_CreatorId", + column: x => x.CreatorId, + principalSchema: "Membership", + principalTable: "Creators", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "Subscriptions", + schema: "Membership", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, defaultValueSql: "CURRENT_TIMESTAMP"), + UserId = table.Column(type: "uuid", nullable: false), + CreatorId = table.Column(type: "uuid", nullable: false), + TierId = table.Column(type: "uuid", nullable: false), + StartDate = table.Column(type: "timestamp with time zone", nullable: false), + EndDate = table.Column(type: "timestamp with time zone", nullable: true), + StripeSessionId = table.Column(type: "text", nullable: true), + StripeSubscriptionId = table.Column(type: "text", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Subscriptions", x => x.Id); + table.ForeignKey( + name: "FK_Subscriptions_Creators_CreatorId", + column: x => x.CreatorId, + principalSchema: "Membership", + principalTable: "Creators", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_Subscriptions_Tiers_TierId", + column: x => x.TierId, + principalSchema: "Membership", + principalTable: "Tiers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "IX_Subscriptions_CreatorId", + schema: "Membership", + table: "Subscriptions", + column: "CreatorId"); + + migrationBuilder.CreateIndex( + name: "IX_Subscriptions_TierId", + schema: "Membership", + table: "Subscriptions", + column: "TierId"); + + migrationBuilder.CreateIndex( + name: "IX_Tiers_CreatorId", + schema: "Membership", + table: "Tiers", + column: "CreatorId"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "Subscriptions", + schema: "Membership"); + + migrationBuilder.DropTable( + name: "Tips", + schema: "Membership"); + + migrationBuilder.DropTable( + name: "Transactions", + schema: "Membership"); + + migrationBuilder.DropTable( + name: "Tiers", + schema: "Membership"); + + migrationBuilder.DropTable( + name: "Creators", + schema: "Membership"); + } + } +} diff --git a/src/Web/Features/Memberships/Migrations/MembershipDbContextModelSnapshot.cs b/src/Web/Features/Memberships/Migrations/MembershipDbContextModelSnapshot.cs new file mode 100644 index 0000000..d0354ae --- /dev/null +++ b/src/Web/Features/Memberships/Migrations/MembershipDbContextModelSnapshot.cs @@ -0,0 +1,230 @@ +// +using System; +using Hutopy.Web.Features.Memberships.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace Hutopy.Web.Features.Memberships.Migrations +{ + [DbContext(typeof(MembershipDbContext))] + partial class MembershipDbContextModelSnapshot : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasDefaultSchema("Membership") + .HasAnnotation("ProductVersion", "8.0.4") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("Hutopy.Web.Features.Membership.Data.Creator", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("StripeAccountId") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("Creators", "Membership"); + }); + + modelBuilder.Entity("Hutopy.Web.Features.Membership.Data.Subscription", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("CURRENT_TIMESTAMP"); + + b.Property("CreatorId") + .HasColumnType("uuid"); + + b.Property("EndDate") + .HasColumnType("timestamp with time zone"); + + b.Property("StartDate") + .HasColumnType("timestamp with time zone"); + + b.Property("StripeSessionId") + .HasColumnType("text"); + + b.Property("StripeSubscriptionId") + .HasColumnType("text"); + + b.Property("TierId") + .HasColumnType("uuid"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("CreatorId"); + + b.HasIndex("TierId"); + + b.ToTable("Subscriptions", "Membership"); + }); + + modelBuilder.Entity("Hutopy.Web.Features.Membership.Data.Tier", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("CURRENT_TIMESTAMP"); + + b.Property("CreatorId") + .HasColumnType("uuid"); + + b.Property("CurrencyCode") + .IsRequired() + .HasColumnType("text"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("Price") + .HasColumnType("numeric"); + + b.HasKey("Id"); + + b.HasIndex("CreatorId"); + + b.ToTable("Tiers", "Membership"); + }); + + modelBuilder.Entity("Hutopy.Web.Features.Membership.Data.Tip", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Amount") + .HasColumnType("numeric"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("CURRENT_TIMESTAMP"); + + b.Property("CreatorId") + .HasColumnType("uuid"); + + b.Property("CreatorName") + .IsRequired() + .HasColumnType("text"); + + b.Property("Currency") + .IsRequired() + .HasColumnType("text"); + + b.Property("Message") + .IsRequired() + .HasColumnType("text"); + + b.Property("StripeSessionId") + .IsRequired() + .HasColumnType("text"); + + b.Property("TipperId") + .HasColumnType("uuid"); + + b.Property("TipperName") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("Tips", "Membership"); + }); + + modelBuilder.Entity("Hutopy.Web.Features.Membership.Data.Transaction", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Amount") + .HasColumnType("numeric"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("CURRENT_TIMESTAMP"); + + b.Property("StripeCheckoutSessionId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Timestamp") + .HasColumnType("timestamp with time zone"); + + b.Property("Type") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("Transactions", "Membership"); + }); + + modelBuilder.Entity("Hutopy.Web.Features.Membership.Data.Subscription", b => + { + b.HasOne("Hutopy.Web.Features.Membership.Data.Creator", "Creator") + .WithMany() + .HasForeignKey("CreatorId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Hutopy.Web.Features.Membership.Data.Tier", "Tier") + .WithMany("Subscriptions") + .HasForeignKey("TierId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Creator"); + + b.Navigation("Tier"); + }); + + modelBuilder.Entity("Hutopy.Web.Features.Membership.Data.Tier", b => + { + b.HasOne("Hutopy.Web.Features.Membership.Data.Creator", "Creator") + .WithMany() + .HasForeignKey("CreatorId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Creator"); + }); + + modelBuilder.Entity("Hutopy.Web.Features.Membership.Data.Tier", b => + { + b.Navigation("Subscriptions"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Web/Features/Memberships/Services/PushNotificationService.cs b/src/Web/Features/Memberships/Services/PushNotificationService.cs new file mode 100644 index 0000000..ab751c1 --- /dev/null +++ b/src/Web/Features/Memberships/Services/PushNotificationService.cs @@ -0,0 +1,13 @@ +namespace Hutopy.Web.Features.Memberships.Services; + +public sealed class PushNotificationService( + ILogger logger) +{ + public void NotifyCreator( + Guid tipCreatorId, + TEvent notification) + where TEvent : struct + { + logger.LogInformation("Notifying creator {CreatorId}, {Notification}", tipCreatorId, notification); + } +} diff --git a/src/Web/Features/Memberships/Services/StripeService.cs b/src/Web/Features/Memberships/Services/StripeService.cs new file mode 100644 index 0000000..12e3769 --- /dev/null +++ b/src/Web/Features/Memberships/Services/StripeService.cs @@ -0,0 +1,224 @@ +using System.ComponentModel.DataAnnotations; +using Hutopy.Web.Features.Memberships.Data; +using Hutopy.Web.Features.Memberships.Events; +using Microsoft.Extensions.Options; +using Stripe; +using Stripe.Checkout; + +namespace Hutopy.Web.Features.Memberships.Services; + +public class StripeOptions +{ + [Required] public required string SecretKey { get; init; } + + [Required] public required string WebhookSecret { get; init; } + + [Range(0, 1)] public required decimal HutopyRate { get; init; } +} + +public sealed class StripeService( + IOptions paymentOptions, + MembershipDbContext dbDbContext, + PushNotificationService notificationService) +{ + public async Task CreateTipCheckoutSession( + Guid userId, + decimal amount, + string currencyCode, + Guid creatorId, + string creatorName, + string creatorAccountId, + string successUrl, + string cancelUrl) + { + StripeConfiguration.ApiKey = paymentOptions.Value.SecretKey; + + // Create Stripe customer for the user if not already created + var customerService = new CustomerService(); + var customer = await customerService.CreateAsync( + new CustomerCreateOptions + { + Metadata = new Dictionary { { "userId", userId.ToString() } } + }); + + // Create paymentIntent for the user + var sessionService = new SessionService(); + return await sessionService.CreateAsync( + new SessionCreateOptions + { + Customer = customer.Id, + PaymentMethodTypes = ["card"], + LineItems = + [ + new SessionLineItemOptions + { + PriceData = new SessionLineItemPriceDataOptions + { + Currency = currencyCode, + UnitAmountDecimal = amount, // Amount in cents + ProductData = new SessionLineItemPriceDataProductDataOptions + { + Name = $"Tip for {creatorName}", // or any descriptive name for the tip + Metadata = new Dictionary { { "creatorId", creatorId.ToString() } } + } + }, + Quantity = 1 + } + ], + Mode = "payment", + PaymentIntentData = new SessionPaymentIntentDataOptions + { + ApplicationFeeAmount = + Convert.ToInt64(amount * 100 * paymentOptions.Value.HutopyRate), // Platform fee + TransferData = new SessionPaymentIntentDataTransferDataOptions + { + Destination = creatorAccountId // Creator's Stripe account ID + } + }, + SuccessUrl = successUrl, // Redirect after successful payment + CancelUrl = cancelUrl // Redirect after canceled payment + }); + } + + public async Task CreateSubscriptionCheckoutSession( + Guid userId, + decimal amount, + string currencyCode, + string productName, + string creatorAccountId, + string successUrl, + string cancelUrl) + { + // Create Stripe customer for the user if not already created + var customerService = new CustomerService(); + var customer = await customerService.CreateAsync( + new CustomerCreateOptions + { + Metadata = new Dictionary { { "userId", userId.ToString() } } + }); + + // Create Checkout Session for the subscription + var sessionService = new SessionService(); + return await sessionService.CreateAsync(new SessionCreateOptions + { + Customer = customer.Id, + PaymentMethodTypes = ["card"], + LineItems = + [ + new SessionLineItemOptions + { + PriceData = new SessionLineItemPriceDataOptions + { + Currency = currencyCode, + Recurring = new SessionLineItemPriceDataRecurringOptions { Interval = "month" }, + UnitAmountDecimal = amount, // Amount in cents + ProductData = new SessionLineItemPriceDataProductDataOptions { Name = productName } + }, + Quantity = 1 + } + ], + Mode = "subscription", + SubscriptionData = new SessionSubscriptionDataOptions + { + ApplicationFeePercent = paymentOptions.Value.HutopyRate, // Platform fee as a percentage + TransferData = new SessionSubscriptionDataTransferDataOptions + { + Destination = creatorAccountId // Creator's Stripe account ID + } + }, + SuccessUrl = successUrl, // Redirect after successful payment + CancelUrl = cancelUrl // Redirect after canceled payment + }); + } + + public async Task CancelSubscription( + Guid subscriptionId) + { + var subscriptionService = new SubscriptionService(); + await subscriptionService.CancelAsync(subscriptionId.ToString()); + } + + public async Task HandlePaymentSucceeded( + Event stripeEvent, + CancellationToken ct = default) + { + var invoice = stripeEvent.Data.Object as Invoice; + var subscriptionId = invoice.SubscriptionId; + + var subscription = await dbDbContext + .Subscriptions + .FirstOrDefaultAsync(x => x.StripeSubscriptionId == subscriptionId, ct); + + if (subscription != null) + { + subscription.EndDate = null; + await dbDbContext.SaveChangesAsync(ct); + } + } + + public async Task HandlePaymentFailed( + Event stripeEvent, + CancellationToken ct = default) + { + var invoice = stripeEvent.Data.Object as Invoice; + var subscriptionId = invoice!.SubscriptionId; + + var subscription = await dbDbContext + .Subscriptions + .FirstOrDefaultAsync(x => x.StripeSubscriptionId == subscriptionId, ct); + + if (subscription != null) + { + var today = DateTime.Today; + var lastDay = DateTime.DaysInMonth(today.Year, today.Month); + var lastDayOfMonth = new DateTime(today.Year, today.Month, lastDay); + subscription.EndDate = lastDayOfMonth; + await dbDbContext.SaveChangesAsync(ct); + } + } + + public async Task HandleCheckoutSessionCompleted( + Event stripeEvent, + CancellationToken ct = default) + { + var session = stripeEvent.Data.Object as Session; + var sessionId = session!.Id; + + var tip = await dbDbContext + .Tips + .Where(tip => tip.StripeSessionId == sessionId) + .SingleOrDefaultAsync(ct); + + if (tip is not null) + { + notificationService.NotifyCreator( + tip.CreatorId, + new TipPaid( + tip.CreatorId, + tip.CreatorName, + tip.Amount, + tip.Currency, + tip.Message)); + } + else + { + var subscription = await dbDbContext + .Subscriptions + .Where(subscription => subscription.StripeSessionId == sessionId) + .Include(subscription => subscription.Tier) + .Include(subscription => subscription.Creator) + .SingleOrDefaultAsync(ct); + + if (subscription is not null) + { + notificationService.NotifyCreator( + subscription.CreatorId, + new SubscriptionPaid( + subscription.CreatorId, + subscription.Creator.Name, + subscription.Tier.Name, + subscription.StartDate)); + } + } + } +} diff --git a/src/Web/Features/Users/Handlers/ChangePortrait.cs b/src/Web/Features/Users/Handlers/ChangePortrait.cs index 1424fb8..ec624bb 100644 --- a/src/Web/Features/Users/Handlers/ChangePortrait.cs +++ b/src/Web/Features/Users/Handlers/ChangePortrait.cs @@ -1,5 +1,5 @@ using Hutopy.Application.AzureBlobStorage.Constants; -using Hutopy.Application.Common.Interfaces; +using Hutopy.Infrastructure.AzureBlob; using Hutopy.Infrastructure.Identity; using Hutopy.Web.Common; @@ -27,7 +27,7 @@ public sealed class ChangePortraitRequestValidator : Validator { public override void Configure() diff --git a/src/Web/Features/Users/Handlers/GetCurrentUser.cs b/src/Web/Features/Users/Handlers/GetCurrentUser.cs index 30981ac..8d8bd4d 100644 --- a/src/Web/Features/Users/Handlers/GetCurrentUser.cs +++ b/src/Web/Features/Users/Handlers/GetCurrentUser.cs @@ -1,12 +1,11 @@ -using Hutopy.Application.Common.Interfaces; +using Hutopy.Infrastructure.Identity; using Hutopy.Web.Features.Users.Handlers.Models; namespace Hutopy.Web.Features.Users.Handlers; [PublicAPI] public class GetCurrentUserQueryHandler( - IIdentityService identityService -) + IdentityService identityService) : EndpointWithoutRequest { public override void Configure() diff --git a/src/Web/Features/Users/Handlers/GetCurrentUserProfilePicture.cs b/src/Web/Features/Users/Handlers/GetCurrentUserProfilePicture.cs index 806fef9..552a881 100644 --- a/src/Web/Features/Users/Handlers/GetCurrentUserProfilePicture.cs +++ b/src/Web/Features/Users/Handlers/GetCurrentUserProfilePicture.cs @@ -1,12 +1,13 @@ using Hutopy.Application.AzureBlobStorage.Constants; -using Hutopy.Application.Common.Interfaces; +using Hutopy.Infrastructure.AzureBlob; +using Hutopy.Infrastructure.Identity; namespace Hutopy.Web.Features.Users.Handlers; [PublicAPI] public class GetCurrentUserPortraitHandler( - IIdentityService identityService, - IBlobStorage blobStorage + IdentityService identityService, + AzureBlobStorage blobStorage ) : EndpointWithoutRequest { diff --git a/src/Web/Features/Wallets/UserTransactionDto.cs b/src/Web/Features/Wallets/UserTransactionDto.cs deleted file mode 100644 index 361dcff..0000000 --- a/src/Web/Features/Wallets/UserTransactionDto.cs +++ /dev/null @@ -1,14 +0,0 @@ -namespace Hutopy.Web.Features.Wallets; - -public class UserTransactionDto -{ - public required decimal Amount { get; init; } - - public string Currency { get; init; } = "cad"; - - public string TipMessage { get; init; } = string.Empty; - - public DateTimeOffset Created { get; init; } - - public bool IsConfirmed { get; init; } -} diff --git a/src/Web/Infrastructure/CustomExceptionHandler.cs b/src/Web/Infrastructure/CustomExceptionHandler.cs deleted file mode 100644 index 6f321cb..0000000 --- a/src/Web/Infrastructure/CustomExceptionHandler.cs +++ /dev/null @@ -1,87 +0,0 @@ -using Hutopy.Application.Common.Exceptions; -using Microsoft.AspNetCore.Diagnostics; -using Microsoft.AspNetCore.Mvc; -using ProblemDetails = Microsoft.AspNetCore.Mvc.ProblemDetails; -using ValidationException = Hutopy.Application.Common.Exceptions.ValidationException; - -namespace Hutopy.Web.Infrastructure; - -public class CustomExceptionHandler : IExceptionHandler -{ - private readonly Dictionary> _exceptionHandlers; - - public CustomExceptionHandler() - { - // Register known exception types and handlers. - _exceptionHandlers = new Dictionary> - { - { typeof(ValidationException), HandleValidationException }, - { typeof(NotFoundException), HandleNotFoundException }, - { typeof(UnauthorizedAccessException), HandleUnauthorizedAccessException }, - { typeof(ForbiddenAccessException), HandleForbiddenAccessException }, - }; - } - - public async ValueTask TryHandleAsync(HttpContext httpContext, Exception exception, CancellationToken cancellationToken) - { - var exceptionType = exception.GetType(); - - if (!_exceptionHandlers.TryGetValue(exceptionType, out Func? value)) return false; - - await value.Invoke(httpContext, exception); - return true; - - } - - private static async Task HandleValidationException(HttpContext httpContext, Exception ex) - { - var exception = (ValidationException)ex; - - httpContext.Response.StatusCode = StatusCodes.Status400BadRequest; - - await httpContext.Response.WriteAsJsonAsync(new ValidationProblemDetails(exception.Errors) - { - Status = StatusCodes.Status400BadRequest, - Type = "https://tools.ietf.org/html/rfc7231#section-6.5.1" - }); - } - - private static async Task HandleNotFoundException(HttpContext httpContext, Exception ex) - { - var exception = (NotFoundException)ex; - - httpContext.Response.StatusCode = StatusCodes.Status404NotFound; - - await httpContext.Response.WriteAsJsonAsync(new ProblemDetails() - { - Status = StatusCodes.Status404NotFound, - Type = "https://tools.ietf.org/html/rfc7231#section-6.5.4", - Title = "The specified resource was not found.", - Detail = exception.Message - }); - } - - private static async Task HandleUnauthorizedAccessException(HttpContext httpContext, Exception ex) - { - httpContext.Response.StatusCode = StatusCodes.Status401Unauthorized; - - await httpContext.Response.WriteAsJsonAsync(new ProblemDetails - { - Status = StatusCodes.Status401Unauthorized, - Title = "Unauthorized", - Type = "https://tools.ietf.org/html/rfc7235#section-3.1" - }); - } - - private static async Task HandleForbiddenAccessException(HttpContext httpContext, Exception ex) - { - httpContext.Response.StatusCode = StatusCodes.Status403Forbidden; - - await httpContext.Response.WriteAsJsonAsync(new ProblemDetails - { - Status = StatusCodes.Status403Forbidden, - Title = "Forbidden", - Type = "https://tools.ietf.org/html/rfc7231#section-6.5.3" - }); - } -} diff --git a/src/Web/Infrastructure/EndpointGroupBase.cs b/src/Web/Infrastructure/EndpointGroupBase.cs deleted file mode 100644 index 00b4ca7..0000000 --- a/src/Web/Infrastructure/EndpointGroupBase.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace Hutopy.Web.Infrastructure; - -public abstract class EndpointGroupBase -{ - public abstract void Map(WebApplication app); -} diff --git a/src/Web/Infrastructure/IEndpointRouteBuilderExtensions.cs b/src/Web/Infrastructure/IEndpointRouteBuilderExtensions.cs deleted file mode 100644 index 08badbc..0000000 --- a/src/Web/Infrastructure/IEndpointRouteBuilderExtensions.cs +++ /dev/null @@ -1,46 +0,0 @@ -using System.Diagnostics.CodeAnalysis; - -namespace Hutopy.Web.Infrastructure; - -public static class IEndpointRouteBuilderExtensions -{ - public static IEndpointRouteBuilder MapGet(this IEndpointRouteBuilder builder, Delegate handler, [StringSyntax("Route")] string pattern = "") - { - Guard.Against.AnonymousMethod(handler); - - builder.MapGet(pattern, handler) - .WithName(handler.Method.Name); - - return builder; - } - - public static IEndpointRouteBuilder MapPost(this IEndpointRouteBuilder builder, Delegate handler, [StringSyntax("Route")] string pattern = "") - { - Guard.Against.AnonymousMethod(handler); - - builder.MapPost(pattern, handler) - .WithName(handler.Method.Name); - - return builder; - } - - public static IEndpointRouteBuilder MapPut(this IEndpointRouteBuilder builder, Delegate handler, [StringSyntax("Route")] string pattern) - { - Guard.Against.AnonymousMethod(handler); - - builder.MapPut(pattern, handler) - .WithName(handler.Method.Name); - - return builder; - } - - public static IEndpointRouteBuilder MapDelete(this IEndpointRouteBuilder builder, Delegate handler, [StringSyntax("Route")] string pattern) - { - Guard.Against.AnonymousMethod(handler); - - builder.MapDelete(pattern, handler) - .WithName(handler.Method.Name); - - return builder; - } -} diff --git a/src/Web/Infrastructure/MethodInfoExtensions.cs b/src/Web/Infrastructure/MethodInfoExtensions.cs deleted file mode 100644 index 342edc4..0000000 --- a/src/Web/Infrastructure/MethodInfoExtensions.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System.Reflection; - -namespace Hutopy.Web.Infrastructure; - -public static class MethodInfoExtensions -{ - private static bool IsAnonymous(this MethodInfo method) - { - var invalidChars = new[] { '<', '>' }; - return method.Name.Any(invalidChars.Contains); - } - - public static void AnonymousMethod(this IGuardClause guardClause, Delegate input) - { - if (input.Method.IsAnonymous()) - throw new ArgumentException("The endpoint name must be specified when using anonymous handlers."); - } -} diff --git a/src/Web/Infrastructure/WebApplicationExtensions.cs b/src/Web/Infrastructure/WebApplicationExtensions.cs deleted file mode 100644 index 7d977fc..0000000 --- a/src/Web/Infrastructure/WebApplicationExtensions.cs +++ /dev/null @@ -1,37 +0,0 @@ -using System.Reflection; - -namespace Hutopy.Web.Infrastructure; - -public static class WebApplicationExtensions -{ - public static RouteGroupBuilder MapGroup(this WebApplication app, EndpointGroupBase group) - { - var groupName = group.GetType().Name; - - return app - .MapGroup($"/api/{groupName}") - .WithGroupName(groupName) - .WithTags(groupName) - .WithOpenApi(); - } - - public static WebApplication MapEndpoints(this WebApplication app) - { - var endpointGroupType = typeof(EndpointGroupBase); - - var assembly = Assembly.GetExecutingAssembly(); - - var endpointGroupTypes = assembly.GetExportedTypes() - .Where(t => t.IsSubclassOf(endpointGroupType)); - - foreach (var type in endpointGroupTypes) - { - if (Activator.CreateInstance(type) is EndpointGroupBase instance) - { - instance.Map(app); - } - } - - return app; - } -} diff --git a/src/Web/Program.cs b/src/Web/Program.cs index 156130f..741415a 100644 --- a/src/Web/Program.cs +++ b/src/Web/Program.cs @@ -6,9 +6,10 @@ using Hutopy.Infrastructure.Identity; using Hutopy.Web; using Hutopy.Web.Features.Contents; using Hutopy.Web.Features.Contents.Data; +using Hutopy.Web.Features.Memberships; +using Hutopy.Web.Features.Memberships.Data; using Hutopy.Web.Features.Messages; using Hutopy.Web.Features.Messages.Data; -using Hutopy.Web.Infrastructure; using Microsoft.AspNetCore.HttpOverrides; using NSwag; using NSwag.Generation.AspNetCore.Processors; @@ -51,7 +52,6 @@ builder.Services.AddCors(options => // Add services to the container. builder.Services.AddKeyVaultIfConfigured(builder.Configuration); -builder.Services.AddApplicationServices(); builder.Services.AddInfrastructureServices(builder.Configuration); builder.Services.AddWebServices(); builder.Services.AddAuthorizationAndAuthentication(builder.Configuration); @@ -59,7 +59,9 @@ builder.Services.AddAuthorizationAndAuthentication(builder.Configuration); // TODO: This old tech should be remove - need to move Facebook / Google controllers to FastEndpoints builder.Services.AddControllers(); -builder.Services.AddOpenApiDocument((configure, sp) => +builder.Services.AddOpenApiDocument(( + configure, + sp) => { configure.Title = "Hutopy API"; @@ -91,6 +93,10 @@ builder.Services.AddMessagingModule(options => options.UseNpgsql( postgresConnectionString, o => o.MigrationsHistoryTable("__EFMigrationsHistory", MessagingDbContext.SchemaName))); +builder.AddMembershipModule( + options => options.UseNpgsql( + postgresConnectionString, + o => o.MigrationsHistoryTable("__EFMigrationsHistory", MembershipDbContext.SchemaName))); builder.Services.Configure(builder.Configuration.GetRequiredSection(JwtOptions.SectionName)); @@ -111,6 +117,7 @@ app.UseAuthorization(); await app.InitialiseApplicationDatabaseAsync(); await app.InitialiseContentDbContextAsync(); await app.InitialiseMessagingDbContextAsync(); +await app.InitialiseMembershipDbContextAsync(); await app.SeedDatabaseWithTestDataOnlyIfNoDataIsPresentAsync(); // Configure the HTTP request pipeline. @@ -134,10 +141,6 @@ app.MapControllerRoute( name: "default", pattern: "{controller}/{action=Index}/{id?}"); -//TODO: validate the behavior -// app.UseExceptionHandler(); -app.MapEndpoints(); - app.UseFastEndpoints(); app.Run(); diff --git a/src/Web/Services/CurrentUser.cs b/src/Web/Services/CurrentUser.cs deleted file mode 100644 index 29003d5..0000000 --- a/src/Web/Services/CurrentUser.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Hutopy.Application.Common.Interfaces; -using Hutopy.Web.Common; - -namespace Hutopy.Web.Services; - -public class CurrentUser( - IHttpContextAccessor httpContextAccessor) - : IUser -{ - public Guid? Id => httpContextAccessor.HttpContext?.User.GetUserId(); -} diff --git a/src/Web/TestDataSeeder.cs b/src/Web/TestDataSeeder.cs index b2f624f..b6b599b 100644 --- a/src/Web/TestDataSeeder.cs +++ b/src/Web/TestDataSeeder.cs @@ -49,7 +49,7 @@ internal class TestDataSeeder( creator.Id = creatorUser.Id; creator.CreatedBy = creator.Id; - await contentContext.Subscriptions.AddAsync(new Subscription + await contentContext.Followers.AddAsync(new Follower { CreatedBy = userA.Id, CreatorId = creator.Id }); diff --git a/src/Web/Web.http b/src/Web/Web.http index acbc0c9..a56ea97 100644 --- a/src/Web/Web.http +++ b/src/Web/Web.http @@ -75,14 +75,28 @@ Authorization: Bearer {{auth_token}} Content-Type: application/json { - "Primary" : "#fffff0", - "Secondary" : "#fffff0", - "Background" : "#fffff0", - "Surface" : "#fffff0", - "Error" : "#fffff0", - "OnPrimary" : "#fffff0", - "OnSecondary" : "#fffff0", - "OnBackground" : "#fffff0", - "OnSurface" : "#fffff0", - "OnError" : "#fffff0" + "Primary": "#fffff0", + "Secondary": "#fffff0", + "Background": "#fffff0", + "Surface": "#fffff0", + "Error": "#fffff0", + "OnPrimary": "#fffff0", + "OnSecondary": "#fffff0", + "OnBackground": "#fffff0", + "OnSurface": "#fffff0", + "OnError": "#fffff0" +} + + +### +# GET /api/tips/{CreatorId} +POST {{base_url}}/api/tips/8590ba59-58a7-4466-bb50-08dcb5e47c6d/ +Authorization: Bearer {{auth_token}} +Content-Type: application/json + +{ + "amount" : 12300, + "creatorId" : "9a150dea-edda-4b85-f17a-08dce560fa5c", + "currency" : "CAD", + "message" : "TEST" } \ No newline at end of file diff --git a/src/Web/appsettings.Development.json b/src/Web/appsettings.Development.json index d23ea44..be6e89a 100644 --- a/src/Web/appsettings.Development.json +++ b/src/Web/appsettings.Development.json @@ -21,6 +21,8 @@ } }, "Stripe": { - "apiKey": "sk_test_51OoveVDrRyqXtNdBaOs1DFFja0XhrQtJoAo83uSySMuqw4Wyt9NsuugrIHRqet9a50cr5GvolpTP8EZuTSttcgYx00gOUPNDoI" + "SecretKey": "sk_test_51OoveVDrRyqXtNdBaOs1DFFja0XhrQtJoAo83uSySMuqw4Wyt9NsuugrIHRqet9a50cr5GvolpTP8EZuTSttcgYx00gOUPNDoI", + "WebhookSecret": "whsec_cee07ef14cf784850cab63567048b5326fec7fd29c03f4659476524f8299aff1", + "HutopyRate": 0.05 } } \ No newline at end of file diff --git a/stripe.exe b/stripe.exe new file mode 100644 index 0000000000000000000000000000000000000000..e7dab0e673806722aea581afee546d9b8de3458b GIT binary patch literal 22229504 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 =Lw=&0GGP>uck&-1i#CXRuMiN)@n=Vq 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�j)fbv6aNN_mH7o1Mba*TzkIUzV5 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

Wz03ti>d=+>fnA~-D-UkI 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

RyIBkkQ?TI>-qW`s{$+A$B8& zJ+I(L)Ah`sBD-_&4hl;S18~6{1P{DokC5eN#%qdH@Fwuxz^Q7uoWGz_0r z)>LaXg(e9Hzq2T5lgQH6NDc#uN~}5jp;xPaWdUonSU|o&B1m>1RvNIZ{u=YTvz!ag zN9Wf3(Vhkq#a>@`4$9J{ z8N^)fYDj4qej{pFSREnf`ugC+%k|U;AS>89=xGt3@Na*T9oeL=`@J3?Z+HnSInY7{ zbJ}iDz|~g%jxtYnKl7Il58)FY)Vy3MTzolP$AVq(2atXJ7$7ry+~t8h8=WaD)Qvi6 zER(L(N$=_;_z1+QemZH1PP!OLq93T!kX}P^o}?PTvu3^Exrgn!j{4UEJ-H2})pzC| zk#eBKUD8wQX-`nVp-=?;gdy8@LfVHWR(Sf9;wn=uF^JuLf-}uLBn>HHCg=HWbL5;U zG)EfnX|+ZjPE51jwY+?W3h9zRx%*8I-{ zk2gRV&Apxnj@Qr)!%RLn)50Y6pB2C*ofzPZeG$AUHilm3(bX$S^TiyESJ(_XxJaJV zY#Gue55DdfU4;2Hhl3#afi#k?`H#fAXLZ9W+-DAH8WvbvaBy1zeA97(TKus1HAp-b z+zN;g&m`lj8XQDOrai0{wFlqFAI;1BDfH)vAEs#WQ-#8IFYQ6Ht8jop5C{rO0>ney z#QiYOx{1HW=oEm&#Wf03#ZDfLUvPWu0a}DYJQ;8$HC&v4w>Kp*J75a6Faudsj6TWX zc%lLJ^;7$VJ3;t65boq49j7=`)*@FJ&W@N9U@<1J1d_lK=wY6<6EEiMkJW(d(FKGU zF0g=j3nAV;jsiz~n#8h<@kd|?4Uvz9d|2=-V|DS{!xOYt-4tFe1X8=lWn4m1h63ct$|Uxrlp_#}ahJSwuzwiIh#%hW1)i$t@8CGiU@d z9=BRzGPM+ZBPusV$TC zpY>%^K~n=FAxu97HwB)K@T%}HuQ=MLEEsB6P+tfA3LblU?~r3|)WncJHPk9<0SZS@ zp4E#5Im665GCTop@fK0{`KrvJToa@Q46~Qvh^& zlie_OLxz4BVwNNacj0Hace<7lW-4lAv*<3nMa4+-!DcE(vMP2x_=u$y)zR}Y@CnyH zJ8mH>=zegeFkZR<1*stLfiG|?Sz(FL^-we41>)X>)1>NIt}xk461$L|FjFg>5bk_T zey}km0xi%Od|yw&H$N-{6v_r^e3H(H3NR^cR4*mtj0i<~b_3}{od!2T^(u7(-SFTWx=Pnj$+Y#x7wfq*`Hs zY`2_)LwXaYa}@?(Hm*(zE8D{VX(yNW0JlEEiahL84&9w`IH<&(zx^n_fW`ZLuGgU` zP7{uQ3Jk0gUmXh{Tm&!y>P87nm@7WB3=L@^^u8YRAN+qpE)oMQYb@l(16~$Mc%dHE9c++2Crdk`F@KY0Vn6hWq{0X`gWQC1BqHtFNEovi(!i;z~>Xxx=L~_*Ht- zfy21aNjOxCL)ogn9r{r3&0?ZIH`B?L>Ez;p;iq&iug;a=Y8o)5%&Qr-MsmepUmd{l_b$>euG-5qO0Uf9?n=(cTCw;8%L8F5`(H@6%()B`#J2db~Wh$QLY#W9ULHh+O~_T-R8 zv&dhdK%@FM8rDoQK%P4Nu^}2xVe_ ziD;zj!2^w^^*Ap)J((xmvhsL(=DSckqkc8@1)a^0tDWHq`J;Q5 zoMeT+daobDM`?_nKjJt`8_uwKs3R5exp0&P&Jc3csx%|5z$`*V*p&&F!SS1dc(}>? zaDKlb$j~Zyq~jqT(!nm0!100ibRTK?5bz*N69g2TwTnpUg=U9FDEPyAt|^GeMVDBH z49?z&;4Lgq)o?nN7Gv`m-4?;*8U~}v;Y^<4Vtfj?Q{!MN=l(2C^KdLk#eLKxvA*lE z;LutP551`-uGxWd&B{(09ttdVsw1y0)40i^Gg+}ghK(~!L5)-)KGHr0`C<- zrDq57{O{q^0Yav|2s_=MWCTKw%0)Tb;Gc>{Ye)u`U>f>aq+qHEKGB+F(ljabeG%w8 zowTRte|4V7M~Xtogts6Q>@#c;)4TfOA2xX(FGRbhZ$IfFstwW`7!whw?u6~w{lAc z!)X7u(G=F8RCl`{oCY8}AbPa|MN6qpOwEj0*FXd3|23x zmxT+HDlYG1oeRXO`xK%Bi+3NU!Y#l1zA1DQls~h_r}yBvJ6eSQzWK z@sU=v1UQGAJx)SdbxE^gl?^zx05#6c-BV&sT$&l~`~z1@4w$BE;Ax<|E%)fzyO2Cw zPSvz@vqiX(s_AQ@*F>qN|L%_B3qH}RDT;Fo4Je0xBSw490ifRT5JDx65Ne;`tPr4I z9*vLU{|Lg)+a4(iA_zM(LL>VBD}zR9MVa@au>*(5{duSShL_SZNK-k&DwtgH-%~WrwaeW_MQ0F5i$@u z1p3T7yd*0AZ|%FK%YGw5%MxGvK(*@dDml~vE09R>=65k}*PrdvL-w80l6MFKHVjIa z^9#8DdCSh$W7L;!jU3GA_|}sqHIuCl?6glKrawfgb-%b5H(;jY2FzF?^s_afP6&O- zLY!#QL92$OsZ;S8Q)z81ajHJv5(VBkM`_dYe+PL!TK+pQ5<+*?Uzo$Wzk8wlDo-c; z)6(5l59+TNi}EZ42+_a1qCa@by|^z(rxfCQp}XoP{6asA_#J&Ma#xMeDWmagw7V)# za+i5t)Kux`^)%rS9N3}=c|aJr+wk*dmMdtu!G)dpKRiqQ&C2p@L>35Nodqw$z3O2ri_E1KsTp<_ybLc?cS{ytjHxNH z*#3-{;p0`I{*0&$`g4i>885@jRkr?ouJzekvIz;yst~yDCn{8XKKMA25D;JP zXoRqdApkUee9!8m;s;R%iTtR-{Zw*15>mHVZ-+Y0WU@IbK04SnHC-iN1~5e0qiU1- zVil!o3&$MzTxrLgFDe|1;hR_Msm!aL4c=T&;oS~_cd$NiDGwb>PQ*3mJ}KAIHRsR) z;>32%QNiA}#3CuBgeA6iTe^R9BnHD`TLvrm0d-3VR}eSHMC7ZxY9~@DV}qaIB?`+T zUkiX+&@Fv)D3@*dKAP=|BidQqb~asozKBF%T|E)VLVldjQ+;EA4f(%gQwwlI_Y*?g zUIG6+k^hg1{C_A4FzbiFcPZcl9(X?>3Oe^QW?Sglg@i+A6#y3Nc?}%NI{dnr{(GFFrFczpsH?#otmyWM{_E#GJ5jK!0{*D*fDt-x6 zoyp%zWJpAjhA#qnq>%W7oP!$TBO$x;8mGcPb?kVIhR9{;O~^<;!~<)|z#S;aii|*t z6Jw-EnRLuCU03b|BA{%glf6(Uwr|vHwWz4RxgX+7c2x`o8sUeSsm}V5h_Nj*s#C9) z<18jx&DC!-wm_q-GBj6{Z8`Q{J@)%7b_V?iziQ6W(Nv)2=d2d=O_XE_O+!}}N3t|- zXlR9;pAa^EMjoBo>OO~$VSf}bA$K%DrrCJ`L za3~QAk~Z!?)`mp{+r;S5Jof%ak=+e4{!KL8_AlZ8V$d%d3fpgT&nd{lVkh}rK47<+ z1RG$_1`cX6Mz7+GC%~>(rG&tP^^{w8BSAg9Uyp}2^hlT`&d&oNd~4LjfG6|^yU~cJ zu{{3l!M6uq`fx8s*I0h+)3+8(8r2uV$VkHOOL<{yc5}N5jsJgS&}lM_+GvcEX;I zZWq-cG=VKUU^;T$2~gxr3c`(Gv5o$%z@TWhpu-H?L8}I;iXVj~xNZ0Vh05(Lu=5;I z28Bq#idB0QVxUGSUp0PU5q)sCqx5L{_`RkNNDzAt7S`nahT9mXC(Rr{swnLT2tyAc zI?U`_v@Eh>B3>Ds52(Rf^g+A-f_0Ex*0c=&XaC{r5lav_03CsRzz^3Qa-z{BR+n~4 zbgvJTBx31{K!GFiocxnx^GeLGM$jzM6};}^f51087LI>+#J7$<6T>dw_k_zD=ILE( z5dR+rKwH>=iD3|cWo)?@0C9d*WB;X*l0_t^X@h||Vu=-y&i}c$#;ERilHo=GI-|({ z`Q>;N+E$!&(LB)SPilaadv4Z9IU7~O3SB!Q0x4zZM<7L8c|{O$@CB%J)pwmWIs_y| z%Q4VWdT{jdB&^7%QO)EN&L3=^i|+CK!45bF*8H3l(IeNmSp%shlzM6{C@1tMTav_n zE+ZQrM+hw=qL1@k(_d$8zbYjCfkXHQVj4oqM@tqhRq;j<%=UBNjMU)Ikyo8n*HgUATbCeh@WmSiOR!x6LEq{KiB;+bSmlOi?_MWT(E-D01 z>{B1@rQm85=2Y+DM~w)s=A4qWrWH>4t0UGNVx@oAR_))_NLXj?d7cmKsW0Nww4Ro` z3B9=1$am`?E8Ip+%5%`=KGNkr^`^K^--)7Frcpj4yE`Q@!+i?1mTK$hw>c3UY}JLi z0IHt$(?pb0(jr8Lzl@Sz!tgIc6>8HJl=D_`Sy)5f!yM>NLA~x%66n>97_HS7z%y5| zAF(BgTHOkM_O_HHn*VhCkyRD!XF2;>F0LJOi3-qlRs~*=GCjk(=1$&=D37!^z`aM ziFjmG4@$x#vwBcRJbDv{>F!hP(-Q2Xe@_J`s~PuT6wDr6Ibpy)=pruoMjwb>Fr%>b}5!(7-O$gX5}iNUR=~ zRQ>CYhUb{O^3O?dwhFAu3;ZK5us$!aCBM3DUSLCBcEcdEGOm2_@3!Ri+?JQUA;0>{ z#QgX*b+zsC0uAw7^Rl-MGUq2;`)0k$>sg1~_@0y>zqanZj(LG?@$cnj*9|h~#qTId z&&cbE+P2|)$Ncz)y1G*kDk>f+8wQzAw)uYj-|O;vHXt{?r{u@4t6SLxt;esk+W)J2 z`ahlaQ(Lxw{^~hbIqj#lY`@c$S-ioaMy}qHYg>N&#=OAxy7$_HD41(r{MBP_JU6fBM!*ePlT3B_ zpoqYGb#*7>$xKhSd9i+JFt6uY0FSCtCD(@h_)UPQZe=RyLxXigN}o?0ureiA46v?A z%};Q^8rT|GGj~6=)duUzl-A%{b9B=;4qO?n!L|Ft&wDy><+KLZC+#j>>A=;oHMr&^ zfBcgJS9)u3eV00Bume~B*5GmlzkI=gE2%ZO4n4j1Uk+TSw+7d?gu8Ed;L2(ZuKRuG zn>Ji}up@_&V+%?mg$?o?X~NHRNCt`viW-pMw)m|iteFSynM0C-SfH$+oH>bdkDT|^w#W|LJ}dpF}_TFfS0 zJ?3H|a%D!$COwUt$>w+x+^m9lP;yV9YiTP5<+m_?Q&4&D*YBvPyc=46{sI4ogN8 z+7m3F)$6Cc_81$We+_CoU4N~s1rjioaC{$aI{%8i_NWH~zZO|?tSs+!K$0Hi=gyx0 zQeJz|28N$PDAmeR=SGqqYtN!T{41|LCqa;W1_s9kZb%FaOA0`3fp(+K+m3qu z0ry|wedtYrD@Lqk9?uUZfh4sGo`Y2gRPb_Ht}V$Z;S(yjJfRs@@V8jES?8$|0oZgs z_Wr%l8#lqdW$%r&rP{~3Z~{p34}k(Eh8i4hb@>+i{x7TI1yoT@SN(@`Y)}Y+_cu7A`zkWZ|pCK zKZ~5}#3eleMuzSxW#F_qUqistpLmzbaa#$)^5f*3^;JF23gB01XHfwr0D95Bk&Do~ zmrls^&MnELFR1ypKJtV^lGuL?uT0+lih3$nCiAQet{Ye3dgbNV{fCL!tdvxBekqWM zYI$r5sUR7bxhRF=C0p?5W`1lr-jt!ti6{|yEk7KNFpLMUy2?xxp?cPygj zSvX7zUIsD})axXb2gjJ2U$%NbG(n6q+w@=F^(uGNzO0?@>a>ah~w z2bMut>Xx6*1Op&*$zX6zcPrmU@eP&$yBloAHB&0_W!$O`j@#9=It~G$wUfE3pTPcD zSArq7=hG1-G4MlD=={!MEvPPs*GLI$Vy-_t1;YKFx69z09(s#0X09T?=%t?OxSXAU z9Xt4ExM?>(pZh1xUqbHz>s%-Ji{)#oI~y-w9FL77nAu#pc*VMBX%Y<6+n%GVYUhz# z`@{=1=xAl2JK(~o?%RxMPI}K~nw!SzF&Aue1SEeHH@>q7oqDXF=0@QkC*K5YpTa)X zto94b?AqH{wJ&0=rmO#2u%vqgS#sH{4ogbYU`a3@T>R(j@hsRu6h(1ll@t+<)Lg7N zQtFQ4NPbmGtia+(W>E*}sRE9y!4IJ|JezT(unsxWHcYiVzkIrQb!z_9*yR8V8akAW{uE_+5eQjf`|;YtF$UcdCVh zHC@Hz;2*Ehqp3$Jd^|o!dA=b&?YPV2;C29;oT+Oj2X}s!0CCCdaPTRwV3=w&3u~k& z1qXy#m`U9Km=G~i5)xw2l{iszFmtIbcQoVR**J928VBn^ z6b^oO0xKa0Ukrn`#lcde>u&Z(pFv_=P~l*!WSE1|b_54+_#=qD_vnip}qh{4(^X16$F0b+#*Hb zwhG*^6Fk~d=)?S?Nkg_qwcw^xub1a*79kt_TlTpTEPyCsRQBrr@6{9_W+so}Yxx1M z;@N8x`CW@m9|V38-Ej>>TyPaskII5UCZVYjqgZ+c&pqx!wKVhNppC?o(6az#s-dL@ zhMi4IG;!Gn;+Zyr89V^{58GKFRm`mbSib6ta(U>A3#uQh!OsFuU;!R-9ZwHzH>k3O zJ8?K&=b`JLt^@R6iMXn4jSb-(9*<}eG*3Nkh8naG{V#v2pNBlwl%j*^J=NzcY|37N z5-e)>jQ%A~13oi#zdv`*5(-S1juZFen#x{<3-3Ur$6dIvo;DRQvU)fBz~C&mzLJO2T%8 z;Xx-O;lT!tt4{Jq!Bej82!jKCj>z+Dm@p&Uca4iyK`ErY+H{SxKp{aWkAPw!5!)rG z*E%=fOo+B3Te0JzKK_Ih(WpL@=RQbam4Mfp@cxH7^{>c6%}@3RgDdqBcFrHq>-pns z@FW&jdWu-0j|D>cqx_c8pL@Bi7+qcUSY zK64K3$RCU3hm{Cj_Bp$sx1^vc93-{j*1|gZ9 z7Yi^@^uK+M+>9XMc1V-LB&@Kk1rkA2Q|RGCF>{*Lfi(gQfk5NsgmFA!tYlNDW|ur= zg8%GydV()kn@8q2ebp_uC>9NeumtN$Q?gC{L>H(cgEfGwzl>OrY5<9_ebpllR zdvVNlP?E2DNE+lzf#>kV3B-CWp~BP#3Zk2k>H6~{e$0ZxYk^~o)U}}(neuIGd`4g) zx&B#8a9@=K9~tvH$h^al8|o@}i`>L4#_>HmjGMH&GK!p)x7okJJr92mGhE2$vh z%StIQ2WAa3JK}!Hvnarb)nUk$7V4~aum2h+M8LFfNV2*_yn~=Wj|7>F zLLV?CF9m8*Oa>TI#;Z;d%>(L&9cHXLjsCG)CJu5q9qaSqmV?75>hnz9-(`XsMp63g z8TQwTICe8&XzA7n1}HR|)2}K_~M?x)=AC(!B2)R&72_=aT4Hftpu5+}3Zor8{#(#&L#;?@sw#AyyHC4j? z7PJ4Mzv$L{>6c8<|j$nzme>qkiepRdJYr{=(2qb1vuQP#C>}pGj?Gu0r zC;+UH9~w~peo_FQZ>{G>VrS=mg+8n{Qi%7uwtH2R#NmiHTi-d=B2}qV;3pB8o43z?9 zRboa6DbW{{@f=bi*vOTUT(b;A92fi$Ti@0peXh?$hnl&H!iKW%wUHwGb~HfHo%?x| zpyL>&iLUSkPyZwiSBr^EAOV9Io4Kuo#Mu$wL z{YTJgbl^U4_U)3ly;0B2|F}>)s4rjF6HRQ(zbb2`IZz zb{HP!5QDX)Z7Gk%m@TM*{bbk_pb6*6a6WQcI{8BmJb(h(AsDGO+}S(8AGn={era5i zTRwGgse3P-Czq=epkzSNz@&`OFxfuy^s&POzO6~a1EaR$WZl56{@i(gA{yEb4X!Za24&bf@u%g12;-_^%1~cMe>H80NaC{R zS^^+k+X5;O24o*x{M_Q7H{j_=h78VY=3+wp@6-ByCl~NLb5D(h|G5_aUZ53R*2LNJ zc|6sM8^gEMNmDad5dun_UAM#QaheC1toJ6RvXGg4w?BMQU`0Iq3GIslBg+mn zc)%Y6ySOX6<8|N}`WjF7Tc5{GDB*gHbOrs9Q31|^)a%w%xeG5?&_L-SV=m06)xsMw1LETt^&ZCr!a(V0%{%*#2t zGpFdz+%q8Dnb+f5>5NE0I8AjvHos)@@iS_>bIo?>gNH_5I1{znOfyk8>Fp z`IzJ_*oW^#=+X0=!;blV4}j;AL(ER76b#-#2SHvX`Oa-X>gY?Okb2=|VWi&Jv^F+{ z#Om0%{6Jz6PsN9C#Psh@FyasL4ry3U5UoKX-x6TN5ojm;1^S71&wdO^IP4#vSGNnZ z*3#?Z2gf)15TR-b=c!_$8PuN7s9}~9X(1)91gp}%v8lu0vfk%(ny7}t;zr5g*jMu1 zZ%Wa%B&nj{C^2$xPoU|J~Z?)T+f} zVs{3h1LS*0XmA^O|62P=-x8Lu(c;Uupv3~K#m?-Wnf&A9;TDG|U|g&wI6 zPaLEy?SbxI{>_XyHKsoh3_cPbtw#>17?k!OE6Z-LxPx_2jTT8(-D$A18S3%IEPzHUc&V zf5I#6@`Mn(kq8VrJieeh4O<&2h)?>_!~#HDx6YhAyIG7{V!@6mU{c* zJDkw0g9^CD>yV}ELg0v5Vi*I5oBgqX$o~-&q3=iNg#&-|=YIYOD?#*))E|T0z(Q)~ zyWHPBncRf-Zvy4G`$gd@v6GFfE=OCzmAwTMi9a!-yhkj8V8G`RMvG=}AeC5&b60*( zLqBlZ$e;KpINgdD12|nI&nM-h9`de_X`D{Sq$F9DU1p#CB1=XTW{n00ggNy3^C4Zf zEtiF8lIj)zNjcvB`PRItVq7qP9q?HIN?>MLdECgKgf1Y#i zJ4-Ty_5byk&nNS4cRkxZ_uO;Om3pnLqJTm77%2mYx#%fXKsD(AlLq;W(VKZ`PO8UM zX5Hoz3H~J0H5`&|CU*ifjr7S^5VI;?DCv~5RmwK(;2e%SSemOgNl|d_wk-NZw2@;^ zAr{3$jEH);%7;8OeJWdihf}mI-$?Jt;!zyNhs_A{vJ4R)>V5g&JxpYu&!~Zf#MS;D z^;a8R>S35l;k=z-E3|h@<~<>Y`@*!~<$C$Wi?8%*$8b0m(%Z02Wc9{eDa!n60lEch zW-4^=u@S5v>A2ie8su7rfVKvoshMA$!k{YHB49Zrh(TR@YZ$h)R~IC$yjY4-3Bsdx zyDvFvE7{I5IEKUw+uECFP`@$94_dqjtc%irkGEMzwO>YQX- zNQTL`SUIzglhehV`v$5y&s90wC0jYaIg+T(uvRKk)cpIxXswj&oDtm8T6S`VK>bwv z*AF8FC-SdX&L>pyIbS8T#UNlPJ+IX|@4?lq{ciM{zW1?fz}v##bdd%&D3}W#P)u+w z3kM&w65%g>;AFk3yrY0+UPfEfRrY3o$4EG4g&*(^VP!}ickz}$HQ6y{EoB2$O< z*AgyX;fg;a^P}Fne5J6Qa2TitS;p29TMqdsZEchGaW$bo@ z(HPzN*6o|7%UA8Y^}li2XX&_*BhWrYKK6V>QDUi*FTh4caCT&$hnjz1EohIn5eTBw zi1$o@5|Dr@0H+TaLeso?r`Ri>$4izk(^79B=&_vPT36hNLa)<>_ECl2@@9fU-N!4m zY@QG&0$_;sMB0K~KGq&UWvf7q4%WCA8_?Met=BEtp)l2^8@mq0?*;_|<=12L75r0z z54M_`ih)4Ee+j$Q*8aii3OI%7b5jq*J45F%0Hxt1lUk9nLo<3xdK^vX^ zdZ+)Wlku()qy`g~u=zut@mcvV5E?Oho|W!ri(x)a#HBUnYY*#=63aj}T8RGtTzt1E z`FA>})`{hxzzFhB#%IXCI>1bcBl(T9vqs*R;a4ql$_m2n_{yMTCCXi;tyr^NHx?w{l&wgtvlMjBP|fl8`+wG)>Tiz+omQI0keW7Z7knjz6BisXE1yF~K!0L>_=`uJrq+X2I<(q6ZVEfmd z=-2uE&{6OzT7?>ANu-l6f75I|wMNZt#MlXooh9y~+!moCgCtQ#YFkAxERm-bcAch$!nx(wUqi$QSD zvm6jy4(2F7JyHW~<3t;Uf3xdEMIDck3k=(nOg~wtCxJe|7kB6vrFb!oFN*bx61;Hz z4yYcfUpRdEp(^6HpD5Tsx@cFVWxjyahRTMU65OPP24g){zUP?Z=?g=bU(DUj8~9)# zB|WM<7!j-G1=n7Y)f~*HFst5M;s{IzyIzAzJT!2sv6Um2hzV#Sc&Qjh^v@wOyq0$q z>J1gLOpHq48zw}&!3AKNBjp5(l|}-TAq@iV=tTcwqOC~eYf8p|Th&W5AQPooi5_C2 zm!u?nC4-Q26hewIShTWusylcp4oBTTk)hyzHq~fx^$92Ifx_bP=luwfI|hCRs1)ZT zkd+fuJDmb<*C^25guaUQvJ~yTl^5ZcDZvD^hrE{#o`|@u%7opDg)334z`v(1T9dVV zY=o>ck5lw;EB~&{7`EsimA}zU)HFtpsr&?;A%C>DSN&7ap~by#a%oceoe0{P=_y1f zKDinIDA%>(hEzjsS~t5* zSHj^op>E3=Nw4XlwgzM}_wPeat`^Fm0Wp(J6};G5Zlb|z2@A(!&2n6^zVPLLmEVL6 z8pu$fW)(QU_niR0{|5NQuz_;0l>7J$iWA|$VoQ1;1KeT2x0s3)WrWUG&Sh9`SM){y zA92)xx@V@UClNEb^8NegDQc_%=j*Q3@$j?F1^oP(Ey0XyfB+|TZ$<<^6TVDDX@+eP z^IoL$W~#h-??tG5@Nx3q%)Cc?t9pN<@_zhKB=1jOB&rvHguvufb;T^oM{5oh3>=PG zTOP$TV2yk26UXo(`bIjiD>RFVA0vHjmJ4*0a;^ zH)=aVZ%#!}fgWMI zBK#b%NWoVCfWtejt*rsz#@BFuc94h#iRU_eu!kjidU^Ab%TH0MF$L^n{_9VQ^Bxuo zu$gCKt!i&iQU#Ch6ZWw3p5@JJSAIIjci^e_up!juFutQ=bI?74DMVA{$3O;+#(k7{ zju8nVtow-hn&Gp*nk-GZC z$rUDSnbl)|o-dlb6?*;&nFJ54d-Sqdtr&X7R>8IZuU2VlWmxd09&4tQ`Na-6nLKE~8>?USqx_*KS9 zW$b@Rv=L7(X&)l{eCi0<>{JeI+^``4XJ-}qn!JVfWpypvpx?pG;=!nj4cpml>N}^Z zrk<&q`eA8QQ#XDV-BcMtA`OoPuUc)ZnArxzY)vNRXYjEItd&Pe>@Vkc`utM~LXznG z(@N!_2RId>$;wJ0(Y12Jj|E|CpU9!?xQk-)sZ@R=mK7`$d_+LNQURq^1_~|;;ST8L zdVn!Mt5y=s&+_t$FPRaQ5tL#sm2Cv{;etTI_62T*0$OC%!QldyU_O?)4X{MR39@UC zaZFk3P$uH7!=uIR|BM5*jH^*+cjk}?AsS#7F;ASKpbd;$rjp>Ygg_>IYn1=U2XJq~ z{JDu8fWgL;j_4~I!F3imE~n9P89qgj0N22O0HU_t^c(S;>^YD3m@69CbW2*kgS(`D!qoP8omg-#;9LXr|B84jBg=>uhUD9?03(V)VC#8*jTS=@ne zM9Qhcn+PCNHBRo1w)gZ18`#mlqiOc4HOTAa87Vlm&mCyzhFa}Jl(!0=NLY(+vFzu*DiK8$6Lmt=2pRtZK5k5s+2t&W)%2?he`vX2CphHQFJIN^=-^cZ9 z?NL%dkCOFZF=c}^|FRz%u914u*<5GTHWm;}9s7r+!&Ta^#9CN$7%C0ok15ZR0*+7^ zlPu2?d(~PH0{mZEFh0`Ztm-5Z1|(CNoT?Eh%BELW25dcCUk88-Dsfz%!TL}P66w`F z5R6*Tg!kvZ^k)<0X71xX5&V!}W8)T^z z4rA&(I>ND9lIqb(Qi za;1!$LwB_$RK#Zr3jm=`nxvzt(*+$d)Jx5;R-R7!pSBj;%DJMq;C}b zy#fFX5`_Qi2>d6Q0{?IO#fATe%Z~&9DeD#dF;YWHsBtI}{Ffw#zXw%E;D5zo1%JsP z@W1@NDEM!9tQGvj{Yn6To8(sTUw~zFvkE0B_|L*4;6HyD;6E@;!C%khzSc{R!Uz}a zXbXSJyc7<)X`<{ZZS2YlG%h@!<0ybh5R!2Kgu`NC6_{?(aAz{L7jErAEtS2U?N z{utUF#!`w?C&(P4D`$H+q<+_+!`M`O1Nyf#AN?C;kD;$CcUr2vene z{D5>Zwg%kWi6|(8|Mq!$>R`L36i(kL4$XqM$u@J(A<&pHCRycGJ0u}Qx-=1G4iU`! zR2sC&6b@RYRe^&Qq{ygI6FLLH-To=f;8+aQMbC~Z8hwY~O|J=5I?}hyF-BK+f!pOU9vqcrf>N;A*P%3;x6||Kq^AeHMCZYoxXRVI5xWj z({O0_QCyM`?e)4ecs=h5^>q4wbQu-NIN$b%>Dz+WvS}?iW%NfUs3-5kY3VNiPwv1_ z>{9>M6*zaNJMTx&?$9Q&@uI9?Hq*y4m-$e68@{6cwlcC-)rPq=e`){iY>b8AFQI7Y z-_;;5hhZ(8YA+J-S1sQ|PZB-@fhxsAPdZ<^SNJPM@mJ_7!28C*fcJkpD|nwSg{Hc` zjldhO3P(PK?C`Hw93}NyPTa&Lbl(P|7QDo|;r=ETJenm40}v4L4CX20R|su5kCAhv zVc?uHj?|_o(yb&%2w{-05n6m%89dWFivucJm*P zl9V?GTNJ&XmIwI#^TZhVb@?U+e*fB<2!5D9g~X5?2S%nrL^3qlbo z+Kxp`jAS>{?`uPR!Kdg2L;0=u|6agZSAzY&(B>KmanP6G2lUk>&#Po>UP1LzHUC38 z&Wku7<2;7*rwm+So*E%CQ6^2W&B`PPlO2BKOs`f7TdD^KZNqIvGB6^ui~N(3Ul<{Q z$Kw^2+oMHZB)D4SG+$6wDojbWx28ug&A``2s7!}0fkW37Z`T6r=A<%`oV7YLAe?MD zilg7x$hV(jvTKmc*OVMe6)9l(Uvs(UF%FEd*i_({m3g@LPR+Ukdy8-x31%54Usa%_ zB<#IJyXsJKl3G8uSN;ayg=xSB7k$md;&X0zvPSR@DmY!xp}7eD1COi8KW3PUzd+nA z+gyRHEP7gCv(HpU^xZ>g4!4WjNd7P;sAwA2I|qg+SKyhfMzq2Sj5{#bb^@bCxcc%Z z-AS&1v9vO)053wlC_If-@_>jPE`N);?;&!?ZYP6xEX}GwDmPMlCHr72`>L!mX7BDa zmdYJBv-yvhFCecQ6tP%xVQF1*wO6^^Xhkh^r8-d~@64X?FLFa1?vV7@{VeG}x`T~8 z$%%p*@PaUMz!f!=&U}1h-YV`o>b1RUA?eTpq#zc6tV91fRj=n2CY%2=AWKj&0a+?- z%#k()AYqApeE=t-px_%}xll^@rc|Q>qcKZ3g|OtE zf~Cwq$00xAStmKMnj$%us+@%9a^@6x^3L2O@P9F@Nz#M8C4Hr&??HH)c)_6?@Z1Xh zL?Fs{W;bG8fAI7bmgk58sZEUpBfX9#ptoDwmnom&!s_{1xyVn`;|R;&x`80q34gXE z3}Oo|fE3NKDIu(llJAWXqok5OM(^|Arx4cu@X_TX`}NFzpuNhj&9AOM#$-SAUZU)= z#3aMX6qpa*-9`p0GbfH%haVIZ15UXdj|zgfX=hoN@k~}T1{%GE z>m-6@f3-+WsA9ZA1&}MKf|7?Kx=yYjTwb{)5NONAy^Q*zQ)ACuoajCM-TrUg{x97A zf4gZ)#H_bT+a<`G(A?mss7ewkg%TmZwg7jO_v8|W-N}*4m3@YeT*6IwpN;o)^jae6 zlyQ%Cz)X2>4F%wDe2*+3>Hu;O^QB0~Kau@qc%Xf@DEehF9)RtUfQg2M@wjAD3dXB< zDAi#lWhhdxKnGH=3?;`|m^nx5A@h+;cFTH?&9qkz!8h-*+2uDA0+Is~mlblQv4mG& za|%PF-TwoQC~Qww0;?ab31Nd&bEds&36(eF{wA&^sfg^peQ7SE{VB`SkP?%fUBTy4 zS;Y){>N1F2H-(-yYks8?%Dc9w)1*J>Sx{dgW7YGdF;q7$I5MR`gC)#$;@3U(QVn^1qWa9lbXj+zBoN)^ri z(o#ir0bniITZj@b%EMrs1H)ogjxRs;Rtos8{K6i%{8>4nUZRHXV~c=OzBV77%P~SG zSHBiH9K?3+FdEE9wh0n8pBNVjTY6%TLykZ~0pCIf$FH9M{8n$6Kucvw1y}wNi;MXV zl(Ga@2q#7kvnKLbjCJy?0)#Ts0&d2-Y9!-g*sHe#>lD+ny6FGOT(E!``>r_ce?%C-TtrK2wv8@<=PlN4T?9- zjU1n24C1Gm?yg~Lcr4M<;PrNJFD8p&thASlUP{!3*JplNeWyErP4nUE|^^|GNaZGK*gM)lro| zPV9UZa^kbol$_Wh(B?G4u)TB^m>k`u*BPMG7uazZ7I$O%51li*+@z@R{n8G(%S z-mCvlasumzT-|&S)wGcmdi`ihN|d;0W>+vHg8vZ2c^E_Hvdw~#fvIsZ(!Dl;tRR1` zd?{L7gewTixs6=kgtV9oX zTgJ*jv-yQznXkfxMKK*|Uy*9x#`s!X(Ob~s@(KIa`a$up-M)nS!Dml{?}H~RzHeY# z=n(?G|K}Ot`=b9UzK2PdehN)v!+fujM);o3<_tKxB;xyiZ~hv5354BPK_f%49agIUUtDgXGDiH|n_Qkp%=w1>QMd*)Q%ls4E(PlQvy?~pdnR)Lo6PVY;?Z8lYrT4elwwW$ahmi9_zOC}X+hcC zZUI)wRW4q$Z)A7*4st1%vc4er`qyz*Z&m#F#bNu>^lm60O90YHnCp0jeMzo?nkEb* zuE0W*x+gZm;v56|y8&X2NT;I8UGQIhN8q-d`!WYR)JeaRg-Lw5Ng zNufRM@)SFQ)^UQx2gFWN8ap4d`A~;1oCGhF>x+_7@rTp*BmC>DI>6fE8=3|8vdMBg zH7ms?{AI7YL%&GtZLj(*?%gzVJALa8%6F&lhg0mchu}SYq&9Eclyq53)?U)ha#Tf< zVbz3pJ+GWm2nzHthgsrsKEo14osNIPog@dEm?SYwO#G;JL7qES8KEBP$YPaRPK+}L zdzitTpc8`BpPc@Aru4b9>a){7 zdk6d6)8+rnZ9K<&S!>v5PMIvc<@CSj^#7|F@7?~{Nw7Hi@*74AxSamCo0t`Gv>TC? z_sW7I_&0}4`2y!quXFn!O+zlX|H%x={IJUG_RmYfbEu2cc$+uoi<11&Y)Sh{j->sA zr0wSRKbMJTE+wKzyF$H@hc5s{u7Dq8Ljf0fL&3>>jlJqWfTGj)HoKcteg^K?dIZJB z9h;I=ZU=sl*jjmNM{9a(Y;Xu@4)$R+i4gL}mI#KcXZ}w5zo--!t^e7p%FvSaGfVIa zuJJ4QDak&6W|^dnPXRCU8wiaIN$yxoYFY-az?FiH)JENk+(XkNsmP3|~+xC4!(nYdA|tMu4n#U`~jU_n0~BMevdci1e0uOAOi4>m^N6q?hxRfg8(-%pu!6l~@T)_YU@Y zWWr013t?ql8^hs+0}Z3aoQ;CCeU$qLHVLv-d6X_JkFu%)R|{W|RSS{K<*%*9#g{+k zYD-ozp1sH_-kAFdsy28BY;Mwp#gkL!BfDZylZ%pongXdQ=(bRk!A$g; z!7KOr@;6__+7P_*+`Xah;)nE=c^AEK{GWtQV26wwfT>UH^NQiw7QB?vjSSmWr(mY> zCH)Dp6)Ow9#EfoDQq=Z_ua;oy&`QbCrr_3ZAqc%J0nIOKo28zMysfh+n{w;7@P9iQ z%^Ibf)lW5R?`cuZ8WXo!%{=zCZE53KTCy(fOjTO&;;7PW@k%pn1DJ2)J_Q_|@73sh z@4wO(IM|us;$lUtUI=$8aX~%g$_v>I6NYV<|5JCM*S|pt&OnddK#T|R7lW(u1!!5C z&i?C~&(Qr>TX~d!>6kb*bCr^MI*9%=76Vc01p)I%8yEvR=LSy!-c;p zPanI=oiwlAb;2pzLqy52` zanF%jYN1_NzL{B_G08>?8|CwBOTdnfz>4L#(52lKn6ntS&_C$a{wM1AUi844jn6(d z3CwRf8{e=ghSOOFbQUC>&Kpi%!0GGDv`~gvw0w}I0%3IHW^nZ)X;Q2k@=qgK zD7HSp4LK8&7V584P*kux7cULlyzU^9v%lCayn6;4Y^1)mM_jQKkqmgLEqNl}SmrzU zc}%`p(fJO)7&l)Z=35b)@9OA$Z^g^U2!{=JgPX|Qfpgcwjc}bi?_1Bl;6?0(e4Tb$ z^p}u@sNgxWOQ;Pp$99TAW<3ENSkZusMrIvvfysLm1}$_Nwl|xjF*$Ez3?^BCFW-NK zg-MnYIvFyXHwu%m-~Z|7Q7H|IMdbymR6*r+;7#*&loPy)Tnc_^1nxk6pkFJxOq`{D z@{VYM;JzY|vEtlKPQ^g~Ci=m&x%k4ru+=2&A;3K3T&7U#|Kjd7=Smjf`GdG;AwJ?= znoT7c*i;hTj#{LB9DmT$MN!|9=i5+G4VN=_q#@&du^G>a z&N#7cM&_$!z9F&s4jqlE@X~nsFeoXeZ#|WOuCkqDAf$ry6?iBh@a&a$fG{Du>{TVC zPyn@w5XGMWwHY_Wg@U6Bpd!MI^9yr`L*c_@D##&b<@ywJ(ZAra4l%TwV&mr(Nw~NI zGt+p%b{KbF{eAbfmO{ygY3;%hQP4LwFtB99`WW(MW?%lhms{k^GU1hMJjxqIzTDq) zmqou;oT$nyue6amhZ057D9|ss=Mt>U_qxQFf1g!s`%8lF0xHxRoBjwAev=?FZ0+qj z{=j36F$6KDISM~dE^b2*7!-$RrI@!n(W(IMg5zM{iRT!s-_bv)7Hjp&Kd2IM)nLDA zY|joVpE%lYcE~eeFIU*%AKYYKv4c*-C;47*)gR zh2`JJWRg6RY>ZAO`Vr!}hv~*YLne{{vjYv{pMbfDt+Z$uVCF{wGx+cO%M^YdPhmOp z)tUkj&OGFnV&=6-!aos~|B+?B{A-6<+)~21|HKly_BQ>29n{Mbz>`!9;IIhu^=APb zT88>cMPY8KLnGB512b(Jjo)w9#EgaoG;m7J-ml<|c@2__HQ^gtWYLWV)W|>S#tz&>cY_~QHzuPSl%mtbkPClirUU|* zg9vDp=difKgnVQ%&c7XMA;2LBz@+(zdCz!-09Ayw3sapvXP*CejevGiQ5XTsiD22} zVa}VP5MZK8{z=Q5a1-5few3CAeVZ!_RP*oUpbI$jGn>zBY<{ymhntVJf{_Kj{2t-v z=ScIhx^cu@ayyz2GL<4MQM(KCc7jLv6j04TbNMH2%VgWF93X6dR8V~e*(~{Ss|iS}~@alX8tUf4OQWaQTm+SO~sIDsz zMD>3Tq`TGrVoASLwJjoeJ`opZia_i?LWOMM5?qOBHpnsw%RX)vfd!R1T)8+{FW0%+ zU*8(&X0T_}(%DjTz>*kd1q{HYW}fEKMT_ywspf0E0hf|!9=jE-2A9%~mqrNsRxH8S zWcveup#0QQZ{-Y5z6WYrk~y>WWhTF*>n}IzPD!g&NhjE=db1?ZUIo7LPeAL%1Lhhq zi0P8p3#M=wuB_>A{|&{8{xD3TWIgg>$}t`4_WBfEgo)HrRs?Z)aJ!xc)dfCo^YyY|cBvIeR6_ zsW$tyYX1P1wULgEpoo)I`=7blYDL3i2_Q144%Q+UcMr6I@xPN%;zV6yhAQ#3N39a? zPh4W0vT9h?IkBzl5N_T1iOPx&!rrRC!&u@@x;93P!8^aQD4=msg8qVm+9Rjv?~m!+ z%KI_(j`uBWKYg6s>yuFL?{v=I3M$>tw(2cCPR_Z^d6v$Zu5zAJXu)&9adKY6oL|#5 z5Pj8gwYJ=E<^1k1iTj$toUg~`d^DVM#c^_e+T!K;oT^UE?W=!p_0xNtoX;Sqz;{S& zZeKX}Wyi@qp7kc{oIMqkz6@G@O*u}^bD48PgKDwP`C>Td2MZHH3C0u-2$1euIS65} zsNp02M4T^-mdO|=_)!Vw?=M#4!|#|4!zjN{^N<`EW^3_mE~D-S(O$$v@USSB>)fmo zTnnmKWtGY^X5P4RtgVpi+$=BOV~ke$uvZh$jH%50cKBUn>SyNXbB=yyem)oA>c;u; zRWC@Zpnc(m=tXjcUWBW;@D3F%w+6js>%4M>-FG(_Wy<9|2@Bgw*^h7fH1d>HOafS* zVY@l%BXtTX0h0}uV19;x#OtwQ4WP(y99YsMwJHad!1883(Gd|xh>k{KuRdRe>SZ(V zvrCnwNb>pTF{LlRc97O1W}A2xlQnO&$+|mzYUuA1bMT({#5n%AE!SaO*d6=drHIR^ z-wGuB7h*>c|0l??6avm}9UMjvyt*cXkQRt`YsXsx)86f}wBTl1c@dvb+Iz@h%$35- z(LB9GcQ*KfO7p}IUc^87K#`*!Q2x2y5;2!Pl7Jj3kg+WvXTr4+$XBt%FX<@=F`(nf zroL>k#@7oHlxQ`~e1S`~R9_o`BTGXS8m|XV>12}(-7M) zlNwxx!{85cXES#W?O#ZSd2zX$z9Tt~yrL9DZ!>Jq9P?`VryC8+AN8}zHmlK>MH4`{z7oFu0QX(osLvmm1{J?+b1L|r zI6~7m9>EFXm74%-^s~5zh?XxFe;fIKXqo_=u2-8BNf2J-G+%uNh^K|197?S9vSr?8|R=9!VQP#4=PM>$TUD zq=zHC0*==8w<cZ_eaXq!Zq9GUNjnj0c`UMy%5(&720(bG+IC>cmw%2`2vz$u3mu%3p0Chhkd71QddwuhT7;dj}CVWuTL`qou&&EziRGCS%# z{XhobnG=7oG>)!u@<`|xI62S_`A;K&ppErJP#dB>xIYfj!hZG?sTT3WH1&s`szUtB z_(gpCb(|v1H&h9plgYGLlpt|9$iCrDJ$e|OI-g}idKIfq4NiUps74U6-g!0g0C6kw z5I^5oRW3TA~(r9;RJx#{LF&6^lFdyc+rn>DnmoEeAL(;K+B| zlqW%NC$kgK`xf&ZNLSKA-l{bD6GN@&ZU@qtg-;$vt8v`QKn~+7E036+49`wm`>)PR zCVU+*zVNo{D#e`VlR4p*SIwH}8U#4zUIwmt_#HH%ZPlxS@v2_`*TZ`KNLc5uEX=Ug z9KgVFRs3=;{3=d4r0*#x3Wa$3%KlQtI3SD?!Vcc4d|JMUdj2q6BQ zd0sO7(=X!HUPY8Z_^ptJUsj6aipvoFy~3Q*+#;i5<#hRiXz%{|maT6L<`a$6D*EHY ze_oJe)_eh}k0GOi!$ASMd&@yI`Pf<_1}@@iSH+?;$szC#6p#GKnGhA`pd!#S&zvv= ziJ%aUbN$ZJ*=^yg`iVo^R6p&sFR`;(*IqOd{{ zxUrb+hZsaGehBAcbmZju)050W>G@v{Q0NY|dl!@=yBtBh2>I;zbm?Z+_FUAAN=X|b!3=K$)xyPCS ziuQm!)0UWUg7j43#UT6!HJZgzRATH zpY2tgpaMl>wpJki=xT+cC9G@%e%MY6+@k^R8vt%+1#tFxLo`488_d@iDL%e2+(S=$ zM_@Yi1?__mp;O253|rG7M3Gcudu)Hq2PPc1GZ1sqG65Z8BVUtN!{`m3l5m~o+(!w? z)OR+~_du0Sn$tCVAH+@@b!uL#ntL3-X0?-IX;v+J02VDlH=f!)DQRVayx3{Ze}-hG zX1dl(&VnQZRI(B|p3qE9<`5d2%xq?x!>oDsikWSwhWPmgWctn9NC_Q6AN=>98X4?_ z=?~3LNRP2|o#(ULj%ybmO)z~>^Pef0|739PkjA+Ker#2PtD&9H{yYv%T3?Wz?8{F& zolJw(INQFF1CzNdl>aGi%t=?G!VR_u$_9ecs8eq5%Y>m{aDUGWUv%0f94BX@=Xbj1C_|Uv-1rGh?BcZ4wQRWsg0Mi=^FL`F z^@&hZ#xt{xt0GmGw(UUbEep0P3y5QKS&|6H**`^>*KDntF0@ zet`{Rc?T%Pge)oRYUqivqx=W{$y2F0 z@5J~9X^kZ2*f;PF3PXWR(}q*}N3a7gSeAu^80sp+D1zPY|1lB#8a2Q_FVd5?boOgh zfw_=iP_w3u75 zKb;#Zf8BxcnFs+_-itcKpk3yUr9`imm}|}ch=?58;DV&i9FO>z=Vp~}clxukLR(@A z)(=wt*(g7a@*UGr{8;5feq5Gfo<@>G=`h!09bXB{7N z6yzM_GnG5ek3?udKFbx;&T&-Uu6NA%J}C*pYIb*|b{UtqxboK8XMGO_zyP`f!9X2p zg_X&Lfg-*C)-eOyB$)nPCIN^`DJhFx+}~=2(+d3_BUbl)7(ZWLuEtNjSn7XWjByx0 zC640~FNe^0VKl)U1>kgs{(=(3@}ZD}UEtjK0ispA{S70~A{X6;Q^~!!@eRTarVFdx z2=L{^q^z>z2&j8btA948v-lKFA)?MpNY15-Au+$*Oy^%V&ir_hG6+@hKq>zw^Y#!| zr-!2mN{p$(z@Ap;H)D=~6$E?=UBHT{vOI9nTyVO@Cyaq^4tZiP&b+@IoPzvfKwnK+ zP=d3Zv0L`s(>PQ!y7__NVR}ybk8wu+>}4QeKjYs88}XJbu^XUJfDCAyhGUR6sUVn$ ze}sixS!5KP>+dfACo73U^T0?Jy2T7$@kNWgk@cfpcq_-V>@*wj0eeGK>a}=Z!+vR= z`mj$7PgTPHP7){mEm!mN-HQI|2`tcG9j~B2xngW;;{E@Mjd?fK3`^ z_j|zxn5Xi*tW-jMRwc@lo^e~5EdM|h6(M6%SR~=5gfA$hu0?WGfHzE*fd?7jv++cA z4sBr=R?tBX-ejj)-<29ruw0Y{4D^`}!^I;*rsAkg@SizO4fgh`%^)aHC`mHk4o zIXOPPet8T($hro{r%If9A*qo_oiUh=8yFbJrBk4F=BF~u>}$ZwFc9#`JTQ!qqLu_# zT}ngJpCfOZeO`ZPOu-)bG4Jk)$w)m!o(5mEd~s7vpRvDQ+TU8fC}+OFnD#W34=1E8 zDWgRXPamyZhrGUHY30TITFZhoVUhbI)Cc~MkB05XA7*3yb{6|;@u+qiG}8NWGY!Ld zD{&UwYL(%&ZfbDDn!+yx_c45;#|q3pe?(0K;@31Wwx-Y@<8Vx?4iU@oI&>~Ow4o|) zhl;pcC(E2VpR3B}^QF z%hLkmx|rAzK~Y~m1^h#$%BXvWCWpNaW&##D5IqH~1%S#)AuH&-3jGiI`R(LXFbERVT~(t1bQ^N0#6I-16O9kTnrYvF~b#@ zjLn-fy^?zl>A)RWP%D=w7UQzMeHJ!-H6pCK>GTrVb>(NsqYM_g_#&Q6lb-DTMHT zF?m76EhHa8#PKS`Sj`uh2``bW@?^z)@p9qAOuXcuq|COmG~ta2;}L|E-aG?_ZpKS% z{SErrUObY|mRPydSiX^d3!4LbpFHAwhP<|(VK%@stA})3rM%~j7#Gmt%zjr^lf%G| z`BVYHb9WN>m!o|VE5#g6`VzRe0B1ktVtR@IbI}a0?~z_fUYDV*7NC_97uwXoVhr1b zy($o~0`3{+^AA!LwfvlkeE%jn2BL%ow*eB3V1yBUE(jKiBPI&#ih_h0>xdI*2?(Lg zL@f|oRuzmu$c3QYj=WFp#&`Ja3iLvB5HIfF-GZIcvX>0@MahamLB!{BeB~Geitl~% zMKVH++Byvi^-go&e##dNL}iE#WUrjXlvRiAvy^8w2^jl|xb#|F)i#X4m-HNnJ^gF))o)UYu{>IVQ908Ydf%&HDtx&AV%z=j*(st7Mar|U#W zLsDQO{t-F+F87)&T!9-A*!cIEPWy__FTL+ngcf#g`P{jBe;?=D-s!JyPeodH@(-aj zeu%t5^kGasySx4S3lYJorRCBQRbLm{=f4x`fL9|1eO>7LZ}N!BuRW7hv65RAJId&F z7I$`k;l5*6(z}a>==|K~f@><1xC9zcFnJf$=owcz+JIG_eCTp52INHcc9Ez!x`Y@kZjT?GpXCsN* zaA3#pd|?~zHO}F?yiNDr&X(?A4sBZF5JjbYL;niUIUI;qgKN0+?)rJuo93z=H^`KU z5~wj$Gc$OuR<5u%BAB5*N=eFvM6ZzAk(VtQWwbB2%74?El&k!%HEE-aE^B=Gow|^$ zJ6z>&zb3q5JBuzVpnG(H0K;@WgMJ7PseUT=y1Mak)wN#=BS=)(Qio|IRCMC@N1ia-?+7L8AB0; z5@Sj%qjnMWA1wPpR;x$)_hIU+mK8<`&@3e^i+;!!YbhCd&Uhi^w!uG zi^zxqV_s;F)?I?PgXu+0`5)|We~YodUDfp$+24M?{K2v1hf;rW`Sw}&6BEAum}9}{ zNNogimd5b_CVa&(7}T3f?@5wad%qDA6Q^_39&-@?MUcoGzIEBO9^Cn%H_5d9eYa@M zz4+Bg4eW|B)OEZ&tTl%-(h_8TfX1`jl;CYZGXc!`ZKG2D`a{A{`D2lOAWDkXS8#Wo zyw^S$pw8v;Y>gbEEMUbE<7GjbE8xh0#|w^?M0~%Nt=!%;N7%tyDutb-5M93}r>14A zGUd}%45ky~M)1k5si#9>-qP%_zq!@1VLe*f;;;|j=2*R#uBV7^eoZolu&oZ`-j0sd zKV9lr{Y}2Z=z?Qtop?Ta0+nF^+17U@*Elzsr&cS4jFJ|M?f^Yt%Ov!MZ8DFYipax& zPA*4>96e{Y{6(;cN_UaV(7J2bB?;OE&)@Cl+B^Qs=!|qfGh`WRdP9`1c@eln_8P%# zRDiCdVtT7VfIE1HYObZ?#Zyvo2iv$_xy3^X9~5xKnyOVLd?{lyDIwz5XomC9_PvZ{8WE zq*f)6o(QotnR{@6&NT1o9L>aHOQFV=8GJ-r8>43)>Ynu1py;o&@()@{UbMtvZgK%U3-d0jyx%4D!7?jsC57LZ`%T&~)KSb&}gNc*k>L+JHf+!gf5f@EvBQ-H zjwm-Kkl_!*86FIN3=IEO8-@oL+H(G-7(Tm_3~wzuV_!aMEC}90JQ}uhK7jaK|D+;% zy{TpVBFic6{XdZ2_10;jz!~dEkmQ&H?<412ol^_mleSsz$`2>XDcXuKU!a|tIsp|M zsaHJDmd;f?33{z1C=J_19il?)GD|qb{eo-h_@S(PWagNrVJZsIAVSFIs;Ejb_x+V9 zYeW7;>*A6BX%&k6E8CMw4ck}m!b|P%@k@AMZM+h8Ow=V*u^S*2hXlw4NtM+ghW?p+ z8}TygiNnFnciyG~!$lWRUoL8${~mxlP-^8t?-C$)a}w!VT)B`g;$>7~jz62E)w|F5 z#MrtV1(LsZJ)uxtEFew|Y_t4B_uQU1a|gEOso0$V2#b3hv0(&KD3&V=^Ul0BCfPJP=3r4&C2b_8JPP?n#;Xml; z|C0=!eYasu?SL}@J-sP8s|8sN=5QIn^fSaw0S7CLSl0kIi1C5#hL#NR<)0-zuro!e z!;i7je`7`nY(Eu`##lVU2Yb8u5d2ge#-t2$BOPpbB2F~GUlzc?zQ*ARgb|}j8EfY zDwjkvwuTd3k3?o}OcJyt<)a6aR(6jmJsvh>{b|Yx2{1Af(+8zr)~fM+ptAorvRsVs zJ9x$TE>}>VDeoWG#<27=-jwx}EL>axFLy?{0@d8lgy90`kG2GF#XXcjwn;w z==meZHP++`JjC#(j=)1HxM25~CylGqrD`=j$emvT<$e1ePExYZ8j3IsVJc?ZX+E4( z_{Lc%it=gPO45%81NQFXHPlnRF+MPJ2Z0t?)F_uZCND<*w1qWEZ=qMj?~o^(T5zV0 zVaxg}Na6~-Y*QL`-{eS>UaDG<^u}e9M30Val9{`rZ4=%QeNdz}ntb`H8Z;UD8G5hu zBO2l0KmdmD^oKkzkJAfIk||D{zPb!21da?}fIrWzRiYo(0V%SbD{v)*CY(LFM!~R* z;-FCE0&=}b!FuwmAJv^UtKWbbQOh4X8o-{899H?_BLI~Ki{i3tcc)qL6i_I`k~In; zeT7+wVkomp^mwIfHQo9wj5W0<+0h;W!Jjy!0&Ei|-9m%iBBHd=G{Lp3!>}rgOo0{0;^!;%J|Z zl!O^_mUmrlDJR3WUs$iqv1`3p^8=c-TNYN2@oD4M}A~D!E z(4*nAyF^#JQFJvf^8*<)#k8ZlF{P`+fGItE!u!3GzHNEqJZVbUZT;h^^RfSW+1{2= z7ahRfwg#^_USJ7$zgI=eYCVn0{)r*Q;tX;FMWn_|qQri2H_9p?ZlOu>2Mu+wP^=GA zbmd}-odI}37n4E9$e%l3^Ae7fcH+z`^6|ve7bKbQqpfURE~uq|O7HLRHat}6w_&2B z{F?G(bYp{efqkMI7@^>`(XYeziau`y86==jtS|oAlIszo-Ram8B(93l#Jm?KVYS3O zzk*FyBE>uS^zySQA}GzFf4OlOS48b{VMP*@Q9Ow8Ill)r%abMiu{?R9T1Mm!U(7nf z$QoYVE5`{7g%d|}L{1-q?VYA%oXAZFAuhL+f&qrxmz~J*vCw<;rth~G!^6$#{0__7E29}|j!IP0~gfY6I(0iuqMPr z7>^wEA_HeGLw4Y2Hj0Xm4h28V$ScOf%7T$kE&~SO5Ij#F^1C{;Nc#tP&S49Le@lcd zYN!anYIB7QqBteeTrlV>c>FiFaFZHsAFWYOc7*mT&OTzp!J=CzQChH^&6`({uq-r2 z*t5i86hoBB*cDAtM*Gf6*7!e!eHHY{LpaU`lR}1-un`WkpYW-uEHDKqpO7$}#_t01 z!wu%eOoof!f`IOT0r-~@ohsi^1l!Jyg?pTw={)j@6VvQM-=1W*k#$m`xA}B?C07x+ zd|$=}JHqlGA8*15!K4Q6imc2>vdeIm&`I87ojvD_ukjx1;>q&DcVi|U|3KLjPWB$_ zYMB1Fiqb<=-0J`s9y-b_gUiva{!M{C4r=<2TcD34Z%}2BH7BneNFhG>Tfh z$2v~vgPViiW8Eg4jGO?`!F}WCbSPLyD-mpgZzZ^6PO*dUa%2ahC=ZI(hvMqgLk4B=Y~3Zx3_z(JnlQKhWb;moU0c zyPP;t&fRyXGkLWuZ|i+m(_gkgd{%fstXHVic4btMLOYM1#6&`7LzbPF7Hc|{DnnB1ufFw|x~#=!Xei%ZIj`zZ#;edGX{plA0fVAJ zEupgseplY==^KNOqK65q^n>H7*Rub|K1+iC`}UVo2ZL1S4@!in z)KmkS&fy!7u547aP&k#REL#)UCPKzY&6=anL{#(7m8+V>COdaCpdJAS0;u2_^S_mc zTUu~Bpl2)xP{ddGP&{ylup%geQ&}(I4XN=g{V$slQDCG z*Mgl|i8gsu`X_|}bm$`D55k8(KpCjAC|d<0pBu*h_WW4v!{)ZGNG))N2@t@>RLp#l znL&Ii33Zl397e)#%yYu6Q2a4OHD&4Jt(sCk8WR_>-+>S#O>xCw!3!c-w4Yocu#Th)Zyn&X&rupt@>pS@DFBA`>C3*}SgvoGrg z4QZhF*nslhT;!-Fz*?Y#{1iTy8wWlgMUV~4Zv~WEq9!L4d56sYsshiYB*|Py-X~N0 z*>QyXzyj}21Ilf9_N2>*y@w^E{sIi0|HVCpu96ID?y4rwqz&K>!?L;Lw?Y;DA5*9( zRWi`9{d9eJS1Fh#Ockq##8O3Usg~(knJ3I^RoU+^YE|~r@yotFZrRHLe@qplI#IK> z?K>gNVu!CTjdByv1GAIG=@5tIGAJ7qDMju;7wlV^nv#N5Ia(E8TiOKK3fPGpRxZ*7 zu)lAc{z_<3YuK^G6ap7@SOU$=`KArkDdYB|aY;{zk^Y;-)N91foxwnkGxm$0hyO+8 z%wy;)mhj8ae-~|Pa)lvJu2w9r`PyL)vhFp&sm7Z>>^^Ks^^9=^o{>*3f4__H#+QHb zK5AIq_`XPr=+_VLL+9flX&CBG#l74A4yWJzYM$DSn$149-?TD>pl_(GbOEbHWjsrb zHZxA(`3#BcITOnBou`cOe_QDLq7P4KDTc$`*BuKFZ^+~^D#dR5@E>bJCyjvj-&UH} zQt%@WWTg_+%;A@Fah};mFG||+*kzg#isczA=yFvcp=wnj-z`wxMr8<7M;;QB>-PUx z=-Y>uU_5mCT23kN=ms66gy3cdo912~4>jPf5M-&Um2^-_qk=RA%qT^JW6M}25=qtQ zFPlVLp)?V5nF^j1lglm^!92quUmAPD35ZMs1#D_JR$fRG8pi+No49}z)w;OcG~x}r z*uX11!*<}Bg8#@z!}i7dvoS(HE@{k)vEWLD}-CpUNL zeoM!w;i`sO4UF{r7j_w};2Zx&_Wx+ z@0;KKHq;`L$^7bfs2AX?7BD`Z<>eJ<%3+oOeBEgq5JgO0D7>|7qsXkH35VV;+yNor zZbD|cNx~PoNt0ZaD(*b6PO2~`6pQ5ib^)auV%4)sG@)6l*2Ialq!{x`m3FO8%YvCU zMatDKAt*!DW9grBwePeo<0`}!IGyDhs-Cy8q<{i`GGDt5;uvH}Vq+ts$p^!mRMIF{ z1iRzausyjcii*y^&Z46FDQ&4J9CYFrRxvcXip|$rRoou8iuuY3oZ4C~S_la?^-q*w zpbq8p?eg31!y8||XOEU(mExX*_qXDG=qwyr4GA_D_vFw5fWn;Ih2m?2+h0$yrP5Pu z)u09nQ>v?^4?a_D^?}&B5@PE;nECp+{qI9)1tGN7WxDOdgCeiKro5`7ysCpcFxRj! zm7{>mp*oA%U(k|xMKw4d@|5xp?m$UO=(j?!bg44e{~?w)N)pQ%6v+8hPFn`Ki}Gci z#TKp;&T#q9aOHhAwL9ySa3bnlum$WGIvPz7t>wvrjZu`4J;p-QTa)5Z0;fPNt10Cm zM}Is;nn$5hLQ#V$eQQw}DyEQzrkvg3b~5an5v4#yxJTDKT7s_1O`Y_)nM&hF#Ho?$eo#p$CLv956e2pjB7L-kTCCFc z)oE2JmC6~*uua?x36#xzkU%Uayn>Qb@{1)_Ai(bW z_Cu2glXHG4Dka(=)-0JmL!rSs*!%AzxJh0Eqa~gIGJwFjD$Nx@P$Z-G)_DMZ-p=wq zj=&{wG=cVrRR^4&yxpwe?iz4Y4yGWvG`s;(pXW{$`>MIiO`vdUx&^Py_wZN~SNnWz zZvyQz59(#xj_EhD{xlJN%Vys)*|*HNkT%l0Ne3Fr^Q3R%QtYxnJ8w(*$&LV43#X@; zuN+hz$wWus>&od08=k?2cMtcY6Cc|r?8jGo67*wqynaagIrBiP?}FI??ayHQ(H-p# z3Z#jXXZq*|h=48SmpB6Oe;WmB<3)d+js4J0ILkCH(r9~ zUgshfbblOtb2;9`M@0Wb9Vm*^0X6@`))3Oy&-dZ$2if3;^7~0#j7Vqn9z4w}baj&} z(9w}MHbtyM-6Ing-Ita+jxWO7cTnr=rE%1yD+fzN*d93(}>&; zJzFrmy}cYVAt|)n%uAua4~cTr#pw8zS6KvEz{eqYj1PytpCv$KN)#M8|M5bes`*d% zE`Y;~{YjjT`(Ko(@eV^@q0(gVy>EFYRURC=Y-6g&v(oUE19^_*f+i)`RT4ayijd^u z^j!(NYmYW#X&ajTHQ;`S!;x23R6blr9(w1Sf%j-)^PEkoC?!FUkP@K3u_n&hGg%|P zvqnrGbV?DqRQcpa^f|POFQ~;+&qITwJ{q<@Yn1e38uK-QE46sXy-NBuQz*|^M`)~d z28uEf93tCIla_tO9&BfFg1NR}*U(peoU5$uOxQ*g>VOX}*w?W>e-_p%3TNyEys?RC zS9wpaD}Y5m>&2Pb!c)=F7j| zxexX+`rp*bXY37Fm@yO)k#}Jlq(do7h5-jq-l_+Fm&x>X)_u=TCAU+$Mc*4JPQa>xVp)^wz1U z$m}+LpG<7j*p0E8Z3j3AcEGz{E^`{Bpg974INeyel{by~{_U!a#mo!d@!~4vy2H9L zaYMq8S~zFHv-t>V(@3}bsXfdOyL>h3v{D+iPcxz|CtME*&+Ck_JJkRV`t z=U@xA|Ge$Euw9~HOLlMsFCI+Iu>A-{8sNN#)pK zH8+Mf@G?fIzPl>YaQaVPVKx20U2&S;s+tl<;K5SV1L-sMTBlLgf`F{ku4-K+8xj%n zIKMNhO7p7`R)yX;6YtarmR;Njf2W5FPPozVS!39kv8)X3zHjf5Nbh-kmvmPcg(r3%%aV@C+ zrjYW2MvA8k)oI6|!@)~{he3zANOhY-V$>eGZy0r~0*Q))Q4?EEZQape^MmWu3V)<3 z)drf!h)pI1BNkwxceOA7m96Xv7EpVw4yC%WZ+Y_%pSOfgkabsh{1fUm=pl3wsGQoM z12qO3d;!UW-x5_6_HTf8XE*45L-A3Kt1Hk2A&VYVef6upZiPeYuAsrXb`5I5j#)wO zay-jTJ+m9>TSylWOngt1WSzW*119Z`Dvc+rgbxjp0@@-5+V35P3J__IzP3eH0xJh% zJPvgxox}du4YuLdETdc(_qqdpX;-a-unW5`*6RmxUEHA`#C6fc1I@Bb!PB#u4ab2$ z_8?H5*Y9y$%6niPcu*UV8MnfzanJNQ!4}SITM#Wo4Y3vh;k@l>X)u-kh`o_L5U*;D z=abM1j;xKSf$9)zrU9b~*WhXt;`F@(*UR-V#<&CAk-kc-SLnkCalgz&IzC7ra`c1r zp#Tp&@tY}NvtbJ|aO=+7UJiwRcvb}$lw=PI?n9SFS_(q7XpEaB-FfTm^CkeyHQ3VL zvWBy~@OLo?TRD|2H1F87UO4)>0pYB+xUqinUg+;=yPfl!;0b~s1rfXyP7F3-QCW2o z?sxT8CyR7fq?5(^K{{EgAEc8Ncwi@)f?Jr;N#=Ct?JhqN+z&T?oJxGaWfWio6W*?y zz94jlbz1cSSKjy2dc*e$s~4ED@TBTbTnJ&iJG2oE3BHC%Yq%~)aY@1F@Bo=Q6%Ha! z--cYgrx2i~2L{0Tmf#1Z10qIBgKPAIG`LnjNQ0N)fvsc;&geiN%qj43=j|xB!(}9k z1W}7>WeuSy*_rq8bblxtfexZRxboId%fwQGE0A>%9YBl&^zSo}6TCq`Vf)=cnYxuO z(7)wPYz!dIQ(CRIL@ggL|0w=MBWn40!J!0mV9q~EQLCDN41p^u<{uf-(HFIvp|9Zh zY`za51~qt`x(hZI!W&3i)({4b(qReS!xOEYecm&W7mVKuud0WbkuR%8!wDPv@cY$3 zP$DNG#*S5(WB#p|4Ns6t^e5=d6=ud|yCt#67=T%-2s~K8!7}g{hg@DQ;)VDq& zbu2uRzF4I%QRzz~>5G{j=_s}w(3FkzVP`BtVLh^N+j9cKKwu!iY*Pogh0O&JxK_=x zGoy7y!UT%Z_7(6>O~E~hrdFI&Zppt5z=1SUtSzPAzJ#(N*Ia^ zwOhjcSAJXs*D8c9RtQ@XLD+KzDt#T>96>N+sDU8rRQmcz`iV>*gW&7>h7mm2^NSI@ z^3(^D-bzK~L@)tI9{2KUq;EoaUkk_JU$ZA>pKwC3SB~ZI*$M+c2hj)-7`A&EH`sz$ z)ll@vNWGcw+LFPs9xzd6qCGTGHsTs4gVf$_$pDPmK^^XZyN>p%m#L`uj<)xdqW!o@ z^V||?hwLm7|EEjYg7hCI5_&ktp0z~?v9SzG<^%bzbqfN$;NaoK9jp~6 ztvxj!9k(5)&B^b@ADx3U;Kzda1@KL1vBuw1)cC7t|3$?Mu>T29_$uH-*@bky5HtXf zsEZtd{M7V;m~dXy6&IOVLE{E-NctJ;SPT}MxLD94%g4+}QB{O19H%{4mm8fHI$^}1 zt**Q+cH=ETw#FH_A66M(TuxhI07fO$obeuME4Z&oX9%Qk_-a5hg`zIqUMZnO>9@l$s-Le{E2-iJBS|^;y|q{Et#KTCb%FEo!1s z`4e1F)@3zS+oIBYv9+zWwijD#5ws?N0%|Q_t0+}btUhZ{qqh9h!teb#^E{i)KT7ZS z{&;ETnP=yjIdjgLGiT16Im4NL6qhqf{Bv>3ij)+TMYuI?0lkToj4d0i%tMw5UXpJP z^7fwmJo2hg(uvxl^xV6RK#a)sW?uOxT=V9x$m1n=>rLmU4~SXem&>;jKHbRgyt{ER z?}qX&QT^2N?AqM`%vrlD?~ngLVu z+g-#z_`{8M{_%u*I=fO5mLW3RImrM@GcO$UZkb`v3`NYqA#qeceQo7SiT@^wm>xmO zvgLJN_c4UTN5K&-X2)*heYZc_;FDtKrHbD!(NG<>NeT0=y@hAD>DP4O*nW!p8t7*S zjDAx$k04yq)kjRkiWCM>?mG6m37&A!UAPDi?*^rUEmy6Yj!B>URv1tp5&AR?7ucoJ zbm41n+(3h`azd))6ec+>Wi?_6!7|Tqhsk0~=EuU;Y6eT=Wb30i#vYFjsB8c)9K z{~GzA9r_m4kDX|$-M@(AQxlgkx;S@g8gJfo;VrL&SLBR?#ja(H2*H@n+^33bH~4xx z%``rF?ke_jaYfKm$@uipRf+13r!|=Okz#zg=BkvtFfz4BhA+uqv64<>UrgSe#$IgSJNTt)wpt$N zXIAd zqF&0~xt+St6*pG_oN7Pb^$OJ-9F~#QkAvUpyh6bYK+bHU-q6BmUGEb>vyWkbVkjFh zVZa0H31fJWe64R5La)%%rOZ3@ka$I@2~n@gD{mZv(&!(t$Xxi36iECWx?qG@$w7$e zmzmq)gT?SUaCdFDCnUWV<4!wvz_)p+<3*;*NXf}qdoaQBfTf2GCmyi!m=iGjEZoa)tB+e1k0soM1$ds*Up*0o9;j3#oz3^^3$5Auy ziF?yjm3duHiD#)3Lob_nk&@F4fF>Ty)HIjA@obi+`8*4PCa3hKhP^&b*2}^-NOT5! zLwiI9%BmeRA89`@wrjc0UoW4&|Cy<>S2=_IT5Z+eIDh^6sCAiRWVK5()-s3bsTcc^ zf6KBy^wM8^o?|PDr>`h$amJxb#Wk}wcZe3rM}mnpNEs)Z?lc2#Qy)l8@?t2Gq}BH2 z1l~*BPAjXozn=ZA)KAgir{GXO(SNWR3l|>oQ03Rq;idWG|987Up2F*6%LELyo1~+4 zD~<46sIQpDj6=~;taaX-R7l6=G82aW3U3Y4;gLY>dX$J}#W9^&Z$Rh_10^<+iP=$P z`F8mEgB@loB*aVM56*tYF%6}Luad3EAWJ*HI&GZg;bV!wD=}SM<1@uq_*Xwalj8Fn zx>95K+(o7If4sM=zC5gcbl=r$d~~gzp+)uRkJP`?OMrBCY8~EPuJJ0RUS8wn_I4_N zpDb&p9s#pWDV>=rh$}TzYm{vgW?h*8Phwu?lKp?8nN!Qo%}2bc<j2Yb5p znpEmk-y}&o&(36MO#7;0)(Wu|XzjUx$}x2Q>FM5CHpkEzhuw3XeZ;>({EiC?)zIdR zY7hQ(qzzI?ZE(Oz0tB&Dm)*!nom?({Ud4OjJRr{<1I1Hk*T`w0)!tv^X_jW(US6R+ z3nRYW<$%f;PhEx8_Yvbk;xIF@hnT*pR6+^nS|3k-=2u|ql|R93TV@A5o2bfbBs5&% zOZ8~cFXE$`sJ>xwphX8olKJd_p&l#(62E;TI8uC@A>J<3f4l;YzhcHkRPafnInPha z$#rE-(RhkNrpYthzJI#-o)Ov{eA0U9B_oOIebva7obR)+T(}RcEb{ME-H^;smyPui z+7$w2@r;A18u@>js#~mf5+~&~o`Tkn{{MSHejuU0iX{3Ss+}6=(TguyE8jN1nI{dg zVJUxTA5FU|0*_uew^-EWv@k$>(zYQ8&tJzDrWWJ@ zwehd|@HnTz+Bon`|3K|YJg(2vC$33UFL+!CLZ@=bi6;xz5WyY|Oa1h}YDfspPuCKC z>@;*Wu5r1kM8P*Gf3Ajd({Nt<@C_6ysOP_c{RJE~6 z*foMpU^58JnihAHm=@`w*E5=5D$<`4AblxO{mJhf{x~aJ@KWYcP~uOeqRh{El9*U% zgvdcj4N!f!rUyzk9GioZ8c*o>Z&hLFNUIT{!>v!^$-!&57d$|R&A3!we`9ah2ptZlXUWQ;fd>RV76QC|M_d`M)wKy64+ISWo%%*mVq$2IxBb>C z;JBFN%6u~8(nDj4uW;CQ(d@9bUfbLK6=@+p@;QP%C?aaQaNXJ)6tRE}C~jzpCtvnw zEoLkunt?AQu42XM)JF0Gs9g7$kVpSq8(KDJGyaOd_BNEe5ACjbJ97H5pV9cl0m}T_ zNDn06(kZ$9n&V>V`s`w%R8KhXL2Mqst*| z)g~*Pq5ZoZ3;f}kEqVU(pT2=zA`}ReRty!&W2h)mIEy#|mItx_d=^bpxy)h5YN3`c zp1|j3avHTIIOpxZJYI)bH#B@n?N&q{ceCKA)$q@krH4+27ZMyc4K&a&>&{?(tT^Oe zO2OG1D%HG}sce7mM5Sv!>2S_PhZ7|eL4%YL#FrfGi4=Mb`sSxIf8YMI+*UYVO?0;D zZ|O+zfHAYSH^V{G_o_|T<+qQKj#*>E>{IqRS%2Mpsi?u|4xyG{WJ;$E4Uw8LgcgCT zc$^@5Rh*i>@W00-K0EOGdwE*Z!sEc}@8I!idpUbdV*62zgLEo+P9tVZe&2p+WcF1& z=0a#k%3hOv^G{$@<#5N`cv-1GU~w*o5b1(DOFr#3aR-yQ=I>yAH%?Nruk~HHH4v;L zpw(EXpL2c`G!s%|G*+I5uX>4H%2$1*p-kIWHr7MsFT2=tm0?obSDos*?BIm*jLRdB zk1lcNS7+@s>=&}jF8yzLYNf>4LMmnHTlLC}3+dOO+#Xe!&+ljI*D)9GreCVU6wX;Y zyL9Jax-yXe3#~i!S5k9EU;H4Sg#vggGm}@rgaZd<`cU)0} zM~M=@nCK|6k)I{{RdG0q!@YP{J^klXan5Q$&!O`^3{{BDDW>T~X#J1VK!8Cb^5Tb@ANvZ^(&zP#CMh2IE&?T{FC` z^_wp0M3@%V$UHe*gq4eNJ-!X`vzkC^Q%;2N$1 z#q4sZ>TpWXW2RP&THVtA6(_=4X*~ofYbVKliH)Mf)(tZ-^zEf7s>JkD$;-XQG*=$p zaCVG?!ghN2+#=?);cOAr5FBntgxzXdY- zv@H$NH!{KPn0ZS^J}5mQ)mr&q40IT9{gh44soRG5L+YtWYVspfkNw4_qaFUD^7H}emjkqH>uY@(tScG++XNqk5{Dzd6WjYw8_|5i#Kuy> z0v$*cpNkv0ESFV8`kI|6gQ$BF7S<`S4EwEz1N~)lDUCUB z!ucdHkJwy_fBDsJ=RjrAKQ)f}Hf zEwimu>i8ILMzxA(o_yKO4@)okTp>Zeq@kclh|Z{7wRYx%VfQmf8E>(H(XDaJk<6cM zGtNPH^bg~_$iuV!upmI6%|m|W`A&X_a*`Zx$VSsa2L2Aj#^A)VrzJEVL2Vn%|3x;& zjQ=rvrqMh7b(1AAGXEpOIGNx=1GG4jj#}+^{N1foL^BM!E@tKui=c_>SWL*KuL&KK zkk8lVQbV9*Em$Edz-a+NF1)IfAb$J{AvwN0rYAWxoh(vqiIpXa{6u@UvNDJOx?Vby z3h1m2fr54ZL3YX2?c>6wjN}*RCt6LmL;r)UQ~EUEMp2gaFZ~Ex(`t7+#bo|Ikm3Cxtv7`7j^*$Fs~++tv&?RVb?cuo zVv26@eKB9yN94CfjCRNu<^}B5 zXOLHgyriy<_K4HgU0h&qmv+vk)gaS36SK4uJtm$?RFLTVT`+KBX&t$|Mu?6w)c&F< zeu#T!j^>q?D~D!RKdxGKcCKuRVIP0}OxefTA^4#Ec^$;BYMn7}d}{DYn?DlUcQw2p zPu;EN;;H-9xPl?&5mJ1RSlc`s?(+Vd^H-=pP$DYJap#H@YI- z6gr`+Tx+5V|E^#5pn-ud#FT3(RFU~Er0XW)CEtVl6UR9DK3D9Me59;dDf*qI2+>v0y(voxy3gHIX?N z^Ru(eda1o7Fj(e~lL3ZxZ@TcAyX6cfgX_)v+khr=8FtsgU-91ezhm*t8>h3q``7=J zr+eY+mK481BFUjq6%N?&AP-T@@NT=pbyS$~a^pTCXQhwBFPirMq6%e(8&9 z+m*m(>RcwU`d~lz@89bmHonkiZALPC_^?y20FkLYtv1clK+*iQz4s z*dM>soCo|T(H<7xLseh8c*M`_evCdSQ?)LaGU@6W17yYzZcJ`g4V~5hcuKS8_Y;Ep zqptpwJ_s%p=yd?Ry0&ZmU+k;?Svwwl=hfE6iHwLHA50U;8_#q{KF2|}{@{GmXPORUG@KcyQS9O3>*F*d07*sf8Rqbh}T@DwS97YRNTvu|j6$<`-1>!0#72YpfILT1qdHQ8w+5{8}>!+q=xeUH}VyLXU z6c%CM3)*jAkZr7&2g&aaw|_a>$#1cU4zwZYe67Pk)1!!;~5;#>A@GZpFk%k=#bd_T+yI%_z* zJloaCv1C^xHs*$QXgh^(pzS3}6yfwu#2s4w$C7&K!b6|n64hmLTm%&e2DddSt<*^i zw_Sj<&KsBI-glt`5NrMShq~J?<~%R((uEh@$&}F;R8}J)MUCHkNI$0TmFV|Uk1n>N z)n|V5dM0OresI_VJ$Mc46B(lCyBZs>cIrjy47l@ToOD*p@nFPj>O)oW1`;#y4D!oc zwBSb*Np$F5lvcF5L8d!oUbW_QIQgb}#`u>m(Wl2oNx~Aprv#`h?}^HuZy*=?eaG~n zag+`7G~%Sl`_>W)G}Au4wbgDsHOQ;Fsin-FE- zMB*70JR7Up*3jNQh}v4IEvh?xjy>8{bBwAvo@z=L7xSCeJiRbnA2n4p45y|dstD~* zP%d9J9!QOcFW#q@8hgdNhDof@^&sxV%tsO$Y_oq)>1*iS-v+ zoo@2=&`Ikfwmz;xv}=jd${t^O0_^na%%8X4jT#!OT0cF48v5+`)X4k*>pF`g4cIex#Tjayji~rC%AvnkjcC&c zgQ$P-Vsy$pOm^WnP$=h{_IDQ}A@i1Zk)m#WvQP>~R~e4viPFk~iwvkAk-#IEG5do4 zZddRg6+DxIRV}IF1HO+p?dnF>CxwG~#GCf}AKshi7u_ju+7XA{yJfaaCnVxVaDr^-rPpRW=~>j>JI zF1*x%XmIZS9ip;UgK0}p4l@9Bybdam` zZdJNh_eu|Om0tOKh((PD`43W~#+Pc%7kB2?`t)5{P#@zF>{YAQMe~Hc98h1WHc*=Z z)xkMFfYXd%*^Wp?O2V2)fsPet z#-hZe3Kw4h7^x9YSW>)%#HpUSWg1+WMpx$gUdvRtGNW9XqkAp0`Fv~Z151iOBL&Gj(_f!BYxhIcn z-HEa-Cka+&@v?H$!z=yY4n&<|ph!UnHJN;k7FL;gMGQ(5|HuOQjR%HI{m*!f9_yRUa|klFs^Cq*cdL z^%U`!1( zYOL`@V>&35E`0Hu42N?C5Cg6}8=mB)cUS~>9a$zN3_1R>^K+@>CYzD!s@7i*x%Jl% z3aN9}=Jl$Y_179}B1kcKbdcAQU4EkqFHkOOU`){=5SBs{&((VWkT{8Kn)?%ZkYK6& zRp3F7H1jOli$zjZ#Cx3)XgnPIW8(9I$ZX&0D17=&W8PLvf|h5k5I`)Fcl6_;AgYjL zs*@$gH-P4u3#qtC#{y*F6QHt#=ULwEya;e{n*eVn&6)_Pw|`{L&w0fbIEmM_sUu&hokJ9#e@JP-|L4NDGqw3qdA%6cqoqhEwbufL@;EQK) z=KlT2oC8e&vhnme_t)IQk1g?Z{ikI6-Ec-=8p1Pq5CHiXFa%;5z>`D?u%XuKX^xPg*V2N?HuLs-(|7Uy()U*OrduOr1Y>a55Eoj zTdZnbWKJ!_1oHlk6KKyrY}poVlw|iiy6_A8a~C!f|4DATSOue2SMe{_JFA`XS@P4> zJ@_o1+{nBp(8l!+n#^^PIV&7!r@yA)ea&Rp9|k^&x7yUzY~0<<*~0!BlZ{hqlgnz8 z&l6IDU=QY?@uGEpyMI{2*4@E>xZr>0a0maFsTr+dN3pYN8vLt2=?#AHy50XyKR!#3 z`1z}t6y*@YYR{K{T6bJC(cQhlWW_y}bR{akHo9N0@8wrNlSd;4$(x7tGGaC9W&DCA z5||Ab^Ape3n81o9{~iul<(mjh;g0LI&_^;d-C>Mh80N6uIn%uTh5;||XRmTr(8hfg zV`CMi<0)dOkhT}v0FUi@hOs>JmUwap`fKJ->ORu}s|Fm#CC#In>X;%LTs&7Co|zad z7LHt;>-^YVPS%%bVNohsAC(%$l&>$qDN~)kU?_7MhA%Q(al!1S*MwQk4~yLV@F_4d zKN!0*KL~U$9i)g~H*Yw@_-tJMerxhBjTdE(4ffSP2sUm55$#{@+{K2EaO~;)K0m?!AfrgX4Jy7!h?A z@=I;%-iJs~ZqPD_|H3^Kn3wrJCY=NSU-mG?Yu2|}E7Vn|q}o*Kf7FsYi<NC^&Q+&hD62Uj&(lQ-5gv_tLJ6zitBx5JDr@ zlaKm?4$ToVB)ReMheVa<)6r zO~)%$4xsg+h8u3?=c5Zw0}0{zzE(c5^L=05#iid$T$U&i8>kZZjLr zrPRYa64hmM6)TQiGyoQWC*)}4i=tkFyoKz;A-n~y%a!^ zA$#djeTfV?tt2x7wiEDq0yeuB6CUg-yk(~@eRrCO|BvLG42+;G!)&2|Mt;pF&HR}) zrvxgx#;-nyc-i~mPug@tp1F;(?&n-apFdFC!mVb(FqNzmm^$!jl7Kw`&7d$!>-hBWWr^xH=7@{% zD_&sWj86_8(f>7T=w^;SwQ4v4(64R z&_O1aSYATBDm5)}8Y0g)1{cOR6~bIo%-bP1XlbDj0|7VBtzsEJzV*NYS83vi<9}l( zgK?M098A^5EJYv!{}|BXzqQQ--9^XsD(Jqxx-UVOd08vHpj~LKb|sTF3usIVI0*^| zM7M4+-`CTnSn_q_jgWWR_p-|^KB%4ZPGpYG?u`OOhUu&R($fPu`4Es>7Z!yNt>MF( z@L?klVs;hbKYP}9R0zIMfb=_Za+Rg?%JgB5oP5&ZG8C2Sn2E}*+nuPio=O{i*)Q0u ztEhy@x15n4-kPZ1eoMgQxWQ5V_~c-?e{gGUI%Z5R(BRvAF}c9ud5oBx0*=WAQ^@4% zk7M$$3;d1NjeE+PEuChb9uox{9Im$f7iT*$xlsimO|zvG6g?gyBlj9eCsH~7tgUK` z+&L8)X5syCpNXWeg*#7&w+l4>SyiZ#>4iAgv|r*lhim!#v0s%c^8dgDW0KFrl7H>O z1Y;8aoEf>JiG@_A4v4xB3DW^2<(XnLYqo}BmxJx^#giZQ5b1{D1>@`akU_gw zYPuIo49+x#dd)`7phA{Vt}3+R_ardql98|!AH-8p$;wssIEj%qxoiRkhm1}k?AB(PjWiWe$6i1sKvAVBIAM0>%LvLJ5R11%_A< zc-scOqnvcL_Mv7kVG-+G_{gFE*DCbIiTtbqxk)RN!^Z{#vICB@o^A^tio(8^h7aXD zXh5n6kM^wZ>=}&e3jtJODU-d@PQ|6K0eR(?9s}~aetiwdNi(wpQcZUskOD0nkOHU2 zfD}yOfK-3nfUFjGtXG%dj;UG_$wTCi|8S#G4Mog8e!?s_B&{g)n<{l|Qn&FqiE3>m zo~Ds_ukn-{S*aCfjePSMdraCc+yzDI{r3`X9Te3HlXa!O0IQYaoEoh#Sy$={&^V%y{_l5D1l`I?Q7M+PX>vZ$ zYWn`)s;`O*LiOrkg_k~&a~{^+i+~BMF)s4g;(E!4g!2@J1OmE$;m!&q4%JX0vlh0f zSNw5mOE__LDayIZ%2KWVOz`qqW_9>w)~xcBtyCG{5nd82rn)7mf7vaL3PqXU!=K&O zoncn%%lRzt-TLyCk>GjOX5ZpPVeM3!4pIqQd;eHj2}-Mku#{I>PRlKwR~EIDC5Zjb zdX0209+g&2;WdAsooBXglyJY`pXw%#F8VF8WFrGCui>j0h_60DcH*NZTe74GgC)~h zJoV!|o+RvM&x&gGnVGKyPp#P&O@#{s2e48+4L)%q4?WHv6tmtQO2UUI4_@jPwW$5S z6S$IGwOGJ7BwdS{knunxt(nWwQp-P9_7JJ&m_?Rygk0}6!P@U=)}+!I^nCs$}9(1yZ+~=>s?6sI1j7lg@ZoDT|B7AOFO{)^QKA41(kz#m6eQXB9&+F1=>{My~yFBEG3r6l{b&5 zAc-aBJZ#kYRh3ca*Omm-*_2D2QD1~CTQXynY-k^ul`Pz%i+4uAO0!mo!*IW1|Cg(I z7YJ}hgo|MyJnWuyay9l+_X$3tnb%md#Ixi#0+nF$6G$Q^-#-iJTPO5_tqGR0;vf}$ zCt3cnvZpUMvEph#k$5mbNm zMn?v@2wME`k4e-|rmPeyO#@msV(3JWOIdF1ii zr;_;BR*Ap}9}p=*M=hOKR!%BHS6KeBvPx1By2esWPkK*J-FKaY*7qW0NN9bpd`M`0 zue>8P<;XVw7#s#X*LE}ALMS);6JAuy~P_6N zTqwGaKF;WVtR(^6-_0HPi%TK+uFUgFwzQAfE!8d1?0ZNToYgiQtBMQ%YDw|yB)FC` zU@o8{%`w|37QcEeR_uEW#p9D>ONz!P<0U1r^oiUUU%>x0Q4w?!1V~hWp;2fqIwLu{ zqkW?ga?KEsvj}Wq8)J3;v&rmf|ye$cFHA~;6SM6LfKxA0h#X|W61O^=?$3+ z_7^gR|I8viZfVzfnsD;$E=LWWg<`+dvGc6X!n7sDcaS)AR#T18Db4ZULFe<=soQ%Q zIt%?@tE)niIs-xGt5L?efP*d&syyb*)PZ$ z#3B1)A=@nPw$;V($jul3AvarjGsR zDC6FpmK5(Iap>NMT7>4V+?uGKcCFAk$j~{^){o|&17S?t4|trzW9ovJTJn$*4v!I3 z{V`*#Q5&2CFR`Q|n%^?74-vewNa_w1igQ}9l|pe>A-2z0tJ6k{3MXDF56v+#s}Rj$nH* z6l_B!*oGq5GT#j;IyBl|nj_eZzx;{v3~{tQPqZ}@X~1oiAPCfV&4G@3lfP=iY>Fkl zQSW^Y`9QsYDlz?ln)(uK0sUG)mZ-CyM)pKMK)WvmAoK$_H{V`P&i~|S)q;^uSVm?U z(j^heOFt0WHOdU{lrzNhyD+b=y6-ym1AQOK(GT>!@}Yj9@0Abr13~ZfgV#Ca(Nh<^ z>^q{v|B)_;e$crvkY2~a;Ny3@>IY+{I{m-^V}{at>UmXz#%i*)o&rWCr8mUrbVS^6fpl! z7I~NmhewIIH0KBJV2FD#9OMsI(u33HPL7ruf6f&K(?_))pxPdBVLsDGwJp2XvSMdx z{8oyei!8sShAL#+lW2f-gt1q^NQxos!GtuY@< z&6z;evDA<1ElE$ZVUk>jPPD>Xi{zl>sYUAEt~XiKR#qOOYf>)9kPU)6xo9Ny{z);O{@d z&8`MDTQLSTyXk{$GGE7O+*2f5JwBA~S!3zEvO0B+{3NAZ8-3fmJj4!b^A2lMw5hGH zx)@WdV)?D3))5q$Dm3eaYr8X&@x99l__}umEKKx^natmxeOqii5WQsYsMC+{M!vHM zs1pFvswmK{+{+I;+WGxnsqRrmatzzqKsJ(XJ_!2H7G}>3G zx2fN#f2dk{N>H_!0(+=hnYEzRX;~TF_Lp@JbnV~vZcvjjk}en}waXD=iLeu6Rd~aI zB|6&Ier8y^$55YOtfr&E$>mS$XEvM>)ZSaOxu3IL1~LbUmKrK6-mrR|Rd6cuiwoIr zFb?B)@~ztz5#RmS+14 z3^krYv9$S%zW>fH>xF+MPo_)aEb*zo{;#>}oa{QNWXU=fZ zPYZu``HgvgTYspqvZjcl?7QU20xJ3A>a3&F;jJ8X<%#N3t`ws7(M#8OT`4z4re*YY zZ~S$Jwb^9`0$Vx)0WfV#XF~XleY(l{oIF|9%#WOp3F1l%2ez3yXoIsKI;7ZU>hFDc zG4MNSLK%#I``P(?EUrpa|KdLd8755R7tOGJlQ%wHfXS++$V=l1#5-Fiu(35c3NK8AGC9IDKHy8LkFQC>}0xd=4*<4;p+A8`j%r_D@$XGfk2&awe+!ICHSnyipE0L ze`IUq&TZNkQ7jPrKUQW=vD~UBG~kGDflwH=A@ON`=5Cw^*zL#Cz|Ca`Yj$4*Sa|1Q zfJKj69Aqr$@2VhUQGeHykp)*JG(qaK+Nu{Ci$-l}!E=N)QgB7t1MT0(J3%k1-krW* zZED&-V6#7QlT=4-)%J#W+W+h>JpV3xIsPf~(n~rh{p-IM0(m6+s(34K8`iGcH==-|%}g?`Xe;U=X#*zw!=9rw^-5zE2Q`7iyE6#;3}judUk51zvx0z+V9HhFZT3 zZ#ak9ud&Cp8=#{hU^dxU<+To)OFotw5=+I3oRG^LqMcf{b~Pb(4S?|~d}typ zHEeklTSw~H6_!*#qXgB+zENZPmd58RMHoFqiXgD(g*?-7erHfwIh@=qManB>))P>n zoD$$!F{R!R-X~qye>@R1n7dr}OiY!$6N;&z0!6?txIWglvCxUCo%Iq`2TLqDK)0LY za#k!&yvKE~{WQT=V~7jFlG2xl45q@{YZbbKjUPajeerT9maH^nuu_PnMJi2Cgl@Sc z1!9Twh><&MnX`;QkZEP+TOW#myP2f|{{d*F&YEMVDh+5UG>i6KCaOcq91VTpvnvgU znUm@i$`AX}myCu{OR7gIfrj=CH0&^%AWfA*Lrqj64fPPxu#{&36SWiztI|E9;Yslx zG>pIfFKBrDrCAy}K)ccKhvwZpCC^PPl>rSG8p5)^i_ea8G*k_Km99HMv$C>KP*a;G z7W<|T3dW^%P$tjn4@Vo7G#e%6xmlb7S}bKQ-<%^{9!>>f(djS$gERAPWTSk}ItBXt zFlX}Rp)hCiWidI)7nKR*i$2cEmoMZB^vq32jejj-UU0%u=kBt?@%`I@e@kKutLL%w zZ6^2M#L_ob)+SfhCg0-rM9pZrIMYo?t3nt}KCTIK2LHw|XYhBB6Z|SeO`4GOvEWB> zd(iw^x#_4qTAO@5p8gh&e;a4s+LF1(IzremSArjFxejyR+GIO3)SsE2Ue@&Vdi!d3 z^X1r_u9*Gxps+g`uBYBzPo&9rQbLO#%UMrK!<_Y`oSb^1GC@ylkrehM3XiBK2j})A zb3&J4Kd2x2*p6wTF1a*R8yai__jN0GC5Uy*Yf@`!rPfs~CruEHr5PN^_U z2N!0m^E4#u&&<--`}8f5kBRf&c~K%Yv7%W^0M;M+qiaZ0H&NrsML6bQ8$X*S&aTi3 z{1O?mfzALsS1w1>%4ArZRyM)@;sG>lHljhrCJ6p|^<IIF1A{^E#p?0GgnG;s9AIoeEfE;n^c9|)?e^v|~H1bSj~vvaYb z|Ng{F0(@nLP*h#+^3V1ENzDpf&$#Mx0U}kkU_q$Ni_E#nN;FmQc%vR&uQsRdvznI0O`4r#ANq+C0v+ znY{X*pv_@j+Wf%^CL1jT)- z@V&inWC(!cwZx}-O?D8y7ldIzc0)$j}A5O+2J)vMr>B3AAPFd*@pUhk>{chq9-wNVi`%}LWlKMZg z4pslZ(09O>!S#?c60n|Hv@0;F@z5@psefOPV^u77}S^BnI z)RVq;{)&O^{Nwi0zW1!nH8w&yvZ6E{q^ua~?LD6Mq^71@8g7#_A?bI!XBlrkWKVEW z9=-%=mhLvDX0FNF7EQm(F`8U9Ti~I%<3$jW!aa%VaJjfs2G`ciUHV=!(@TxUg3H*l z7FOvs+WUG^{X^JIV((2WLi`w=k(ke zYL&rKzIxPZX-#9)wk$lVMXRf)~9@@{2 zxy9w8{=5Yh#x0GdSwKM!AMyEef0aZdvH^+E%5=F_XWE!sDui8}Rw1p#NNNJ26!%u; zCfH^P+nR3xkD-0B086%FUs}m9=6;p}m=2So-fMB$sx)2L^uu0!%T>ld_^0wKH@DQ# z=HwG z>385*P%y;sH)~rnpH2t=7v{Ggt`5fjDdg)&L@u=4Oc&#j#6k4bEsIb%^vW}{(V zJN(HvTtLrm$TyC&kr0k~3`~8Dc-!nTPi5xjF2g0xaM5We8!o77L>k~k5%#se1AUf0 zu#ZkYy|>&*RG;4~iN@a37l}T4z@5eDA(^BTaJ0FrctV#5FakR|X{uvRgvZ-p_hWn> zLiP|35cAO@M@*Mh{9}k|W}fb&N+tX+n@3G2F(s{yn7;($?M;e=dzT&K>2ieUJcj}u z;hFWB=-7*#4SItR>fR+e)0cOi+{yM!CwFF~GxyMPuQhhBC-Vp{;lX}fJh?LP-K|s) z0wF2lMos<&qS2<0hCU7i9CwbBs8M6RKr-kH78NzU9tfDtNoy(6(yy*R8QmFnnv9yt z+5uhl>>^kOeV)ne1QCbXu2e%my7bmSUnhRn@fu7jo>);4xWxbZ>|lm(|9POLJN+%V zzlPyCnaw!bm?|0Ftg1C#E6ktn6BQP^h)FNvF^yHD4n*j)Ij zXK_;+%U>U_T0Y|vgndP6bDsZvri)s)tRqzG);%h2);t^Z_(@QP5zZ)BWYrP^Y`BdxLL|>s0F=R^Jn-?GtG&vp_jk zXRe(uH5mGri8g?M3NyfEB9ig4Cu1R&p#h$8v3GdMFZ` z?L#QD#y{VVDwy&fBA|=@eyTxc`W>S#SAU=6FS$-M70D7SnxwxU_D?P?Pmegd!SuWP zQ(66PQC&d&%w7xx#{mB>f6dDB*U6PV`D=XG!vCJXuHNT=&0lMVLGG*H>%w1`e;D%D zwg1zNzdB;Q^Vhep-BbR$R1NNU*EJaMSL4MYf8}>?aHcirmW5gV`s|uL=dV9OS=NRA zp)dTK{I$i_czyHN-#nqBcmBEv0K4$l>K(>k>#i~WIw6_mue$Ml@R#CSRZ6z7xYZxC zePm@AVQR`5U+`@8cqOuSm@v~wD_?qBmgCkO>o~3gPOo$ljr$pDgGSr$2}D|#q>Fr; zAQ%t~`Xl+okS@szIOwu!*Gq`DI6rV}p{E89sQY3-`U#9&+E`AIV*`HlE%)>wWm$EbGw*F4hulH)52y+zT5!D?0r=T6<^T zW?NtQHwP^S?6>8jko|7y(qeyW(ed7|gk@x#^e6vjn#|mU!l|KRGJWowR{1MJW&!Od@-60X5kp~itd%@bFimSsP$t9bML4c~F> zmo-nEvCY`;obRp%0o;#tYnK1kjO&B{{*C$bmMphjeoRmK_MNbW|Gj)m5tZP7Ie&JP zz+tJkyKvYonUKTodbpc>D>=1yCQDAqGFkoZ=g*mH@C!kM0fT*iLdakvyEpjXW7S|c z`F0Sk?dkma5u}xTJALK9Dc|+1bBlXZdSt ztS5iP(^r(Oa>kL#TG`LqtktW6(>TpINP`uxX>B$3*IgeR7mBSlzi5OPa&O*-YFBzo138s+Qz)t!)L# z=UX%V5^o*Twy9rY(+dM%O+LRSlX&aAwVM)~9v=AW+#;`SM^Wptg5=uP_xmN@KBnz0 z3coP$x#Ze4?eM2#MNXTSrADg33Ln ziVC%;o>$VtH}0ClwDFCys6YBKx|t2E@+|ND2L>~MLA)(K!OlYaFx;Uw)NyK5hsc`w zMQ6x7WrTNS2-EDMRVgz`+GdU9F@_J;z(DJ6XGO=wS5$U&F3aS~!fZIk9nSC1xM0=_ zF$KEWjrlQR$B#`u*V+HXuA)d{J^GlO){@)DB-gHcf6KD`1|p1pg40>%6RlY=Qe#z^ ziYQ#7?)yLEsYO#*k$>~)AyZz1Ur(30PZ{xNaR1;|K7~IGBKXrS6mqc@}t> zr3W7)g0i?NO#hneL%0g#Z*7tQoz6`H0;in*a?Y%JZU&lu!HX@pVji;VNIWu!?N7qJ zP?6bZz)AREzDlBHRe1~kfsw?A%BBa$#wWkA3ZLdHR+XHQK5YZKf_lv?9XPRk~73*`6+cxU~keLIAo~^aN!_mjy);Dz1sn@piByZ#=UV1p% zM2I*YpMLsRGxGfVPI;5Agk}ew{e7qlukN@Hf5CqYbi69&llf-8rD0HiFebEBDu`N> z*wMIFxK@T6;2o1IgHB^1^=;E6u3IzDmCX)z7Nf$g`0)11sKySnR){-nNwQpGkpPc_ zm;w%vgCkolQ9+e1{w(RD?NK3cF%tI-E)7`*5Tgj&OyqF|ePa0wTtMwcQF_=Pf3iAH z!7eP+zn2QQGXM)0#wg~ITCP5+Oa;Z=vr_XC+3vGc(<|4**qtmQ|4(g4SdVlXkIW6IDm z#9ZUC%Zlhz#d46pFA0kj0;O z@;ijW(kqe5UA@|rUCs6oei0c)b7vYd|baNu#C>6E8K_FUt&ZSzX z>`28JcXf^4rcq<+zlAyx2{1Y9r~anl5Q0M6qE>Gey) z`||;P7ImS|_YoGW3Pm48L1^feVcm!YLTL^=kcd++;*|G6CQ&9T9F~hRTnUVL5oKyL z5}^@NqgTopwq~sm5_K^PLkVN((ZMb@7ZVSih->{C9Z+2(A-g6~ojl%zEJyyQG()gMDI~Tu zH34~3$Mo$@&<@f8*j++jZ~J}L3Vp@~!`#L8d9cZnUes!}JZZj8*?Bvwzp$e0(2BCd z|8G+yj{g&+5#Uy)G!r{_33VyZj&gI+w_ElhgA2P5mJ<0RRE($0#>Gj<)d;>8B{*@0(S8#rWT;BC0*@(Q5fs*V~L3WkP{vpV&ciE?dtWOpz?mF{Z`9mSO%)x-- z?&NB?Som`nHAUvUEafOYtai3t))blZtn#U0)jMoRf8CPmlaz$p8Qnm(cG!2);l4k( z%4(ju75zc|x61lE6(Tj!#90kd`CmEO;`|?iPzL39{jW?DuP3&!P^pn`dVAOV$L#p12oy&rpTP{>JinnUK>rU?G!GA z(Qbke0kse);|R=$1g$m#mCo7HIEL`&1q~;tSEucondiT?#`Wqe`aNB|^*M*{^ay{x zI@H$7#Y2gmXtTeu@;82J@NwUJzw3(x;B39tDnMc+YPL~1YvJZIB61czGneo}-9B?C-G2X1uG@!NH;R`W7k2yOA6mENr%M~%871I{!K&itK@}&v zDi%K(n4CuZ+EpQl&|A7!p=G)@R;5HV`IlF^X>yXZoT<`snlg%CoSho&LHa}8mQa7# zYac+HwYh?$G14E(l`=&t)oOK;rT3IgwcqiWw)C;G36^r|$$p<*R&ROE?O3{?tVU_N zu%&z^)!=xs)-QZm*T0PAwXV`UvzQ0Qp_Na4&*r$$KBAL_A1Ul{;--?kM%_ZbU-R*K z4FkQE%cSQASJM;qp3qRUDcAgjoL2K1zS;bQyG4VT9N(Ly378@cwL0oJu=xr3gXT4y z1W@;X4#JOn(a|gr4SDTGGq)X{uCDxn2p8OTer!#&W}I8G=y%pqiAY@QPN+0yZC)a2wqHa^WP2a1D)TG2pb2! za_f8#_;y?#G@(=F3yeGFIYS|sl=F=+>Ez06<0kxPxEmOW8<}%{P<)#P1;sinoo!xF z=0L>n{s+3PSfz&qrENe{d3{j%Mt#Ln!?D_LTErNsCC+2`mWAZB6|Sn|RnIqY?by2Z z?@0Ddu+N=sL$XgY19O{vh|qR5$NT$^gopUpiIA{`;380@iB%DpN93}kD#FHep*^nz zgNgG=oV#_;wW<4>fv-08WAkfHJuIhZ&gXAv7+9P1i9{PuzS{{}Xohj^ zay(q$60b+!#@)9z{`kJ}vgRc=R2n8Q9-b%Mtp6X+(-*qgtZu^wjwAu8092&%+ZO2x zgu!L;)Pq(qmK;n-svaEL{|E z+#qYv(Va8;?l{KntqcS%ZeOHC^O33ov07qDqPCK@w8Xf;=cMZ@YB`v?_U%~P`(KJZ z(LD3fSCEQ%wfWEKJCz?ZYa;^hBz>-G+6Q%(l7pYB(mz3L%>b-5le$kwDxm#(OCHv# z3K3*JALu~XLQC;BCpB39cG7iaoS%rT{adWiHV`Z9&=k z;J1z8Zy>r}U4|f~1*GIR+BdT;_?Yq%2Kv36-&Jn~ss5Rbt5PrNooDG|CNy(;*Q|m$ z{d+2lA2$G1??Zg5b~Fr(F)Z%}s$gGCp7U@0^_vdnYfu-lE|CB&v2R(w zgKn&GPOR?I8s-+>qV7}Ib8I^3-kJaa`tPP>x0|H4Dy*_K{@Mjjz`Lm*aB{GEeG?;INJ+xp*vH{9mcnd0aJ_E*{p3 zilG5ZrSa57QFX$!D<%wUp9y5H{pL1k>;SvX8Iqc+RXWy~T`w7`&ob1apBdzV6&-BO zrv_1Wf<#q%<{H^AI>*mJ7liXaX8^4RG(9W%WLcA?ju&!Rv?lla+b#?lgR_#vXOVuQ z0h`mr4)d_aL?kw}85$B>3L7eI+k}+>hSD>PIi1O7VI znwsq*A40}b%M*CbQmzx}CO+uK*e<|b902Ff#pOZ}=IKjNE26+Sos$$xuwb}AGUH>& zBtEu_Lm-t9uVE>KYmQ$?%9Xq3ZWxAe;5hnP=C}Lr(frZcaIuMmxqR4A;H5Y_4*<#u z9W6@Jg`X_qD!r2hOnRRE7T$5;Z)y6FBT07P_YEE5H4oZyAu-fc0cNUdfv*f903`&4 z7Qo!Hf#09j7ysw4>BZq6qi{d7Ohclk=y>Z*@pq=$3MW*!SKi*2!ksQ`@8I)WgU?TK zpO1U2%ja|Z`uu;_vt;Nb-W40>s{CTsWj6OmdN~#_jXyWExt^9ePPIQ8_gpVlNLZSsAggP~PpLkwwT zgCl48HeV93>+)@bd5=zEBi8>Zr(PvVtyJ>e91(ZG`JGa*((1r+qO?=c{{1{x#PlEZ zZwrB8;);887r5vf272;U^xvPbQGzU(U;y6Z`ouJOwd6}H9punNzLM5%3~91+)(YWL zUXj23fN?YaX~&EKGyEdmg&FE@%VEYYpCi(Q>)CsGsaqEZ80*k{p1!qJSunB9ruS!a zCWmHFoZIc0=LVPoaQir!vp?WI&ng+`1Z6q@HHCZi5VMnLUlyI_01q}ZkvAF1?@ht) zl9e2)cyd2ZN6E-$Fm-^qS9>9sk23-uBkHXMNpk&xf-;E01ZlI zoD}5e26>5D{oWGfo5;7YSMN$XRsV~Do?n~4M*M1$88B3pz);irO#ejYun8;2Z`4 zRC?un<$+`&ss5=KrdxxMMZs^2gWp68<6eGi)o^)t>pPun(r1FR#0uMjm<6QuEOnRb zuv?%>E;ufC3p6bi7XgL;(cKK6tdq@Uf0KMYA%p%wtx;=bfwO#op$hW0KZNRgiuLX> z7edf(ddnsQO=akQy`^B)(l!21zw6ckQOjqoZtab;{B;6Af;fNFB<0Q<%+ zuXHwt?&|;p0MzGM-Juq}AlM*WU3}bQ za_caCy~b*_{fUS8h@}VH2?yk8Cb@#w*nMNL96sllW4H$7WHGau1~OEKOm4fOXqJ>&m#x8gTp z0s{*Fu5>N~JjhR`AAR;W=#Q$I+wDHE(Z_4{KRC9%x;DiDqj|RC(1wSZ{MUeNWz6Qk zG02$Fze9w9h$JkW*m9T3^mWi*1i>M%X}%eG@Mat^SM7G zG?Tn7DXz&u)i9}KOG##`D*aRQ)(p+NW&&{dPT;7lz_GGdudXD9O;Muy_%CRnpCXu7 z@#Fa9(4z62rKnAxZ6V`bkB9UlVlVGvHquoIHo1I_di9%U#`<^-<`S}!iFKq9><%NC zL!v)&xCVZxdAPEn>=tk9o6era(=kF5JQulh3Y#IB=VZ=Cg=Div9#3pYc=7?Sy|0$W&^?s0aVcR>V z|2_`evC=pgG_ufs;kRyYEnR#$=YPFq@y*}*N`9jHol;>H*WJSF$a6eAU40b~I{!Te z;L?Q+ROUy5x`-sJx~6^}Z0!{9@9H|q>YAUe>uaiOFm-)}2Y(1P`A13}r~jo4ZM0wh>ir?VNFPx?IW_7%?Y_z{^pZ{GD{Ct9e%!y`l`CsT=SKxl zorkm31aorcq275r7yd{$twNR3Cm6z<|KG}HE-~MJcYx6K6_JXMVLbMuxKhv_*hgc$ z@y6r9+;1lEP}x3|nbS+_1NH~+;C{Nc1K-pQi@V3d=VLHO|46-I91b4c9~`v&n@AXzgM=~Zx#$l|OZNZ^TWY|<_kPH#C-AG4^tXRq;$g(`e@2~47ajpM zSb$yehc|X5s*kePHEf4d+=kkIJorDWwn6*!Mh5LgzX5FsfWUu0d9)zhge$7%YJW*wroOF-&k1kt! ztjqU5_@2D>bC!;Ax%MBBJ9X*lF88CS$bHS4>3Ey!&f&HH0M)hV3KtrG(dX^?dYe)s zgO~2-KD^}p7UaWZcB2y|j>bRvlRune!>x7$J!> z@ADAEhxxH;>k=QO3;xWZ3L9CIm!h@el9#3C56dSp`)dK=W{0;}5OII=)xMD{I4+Y| z21|b$Dd{Ko2e|WO^Nqkg@MLq1z=`u@^NgtRs`$NO@6a{x+4lbt@DS-6WzqIu`{!Mg z?bx8OW2V1mPGG86@9JIe6phb%7v}*UvGaxBrf+OcO~yV#Nt}1DjKUX+&5`W?)r@tRm@Ww6--mQY96iA}%iif5n?T>9ZAb>@vENQ>9vuS&>_D`ez za5Z?2}M!iFH`4>WtFJ zJ#CCX_5z?(FUaxR_Rqyk=32)v-9R+>bbc#`J|TWi4Dd4|7eC;p2%pl<7X5p_lf}*W zu*vqH3peFg;y(^o{NAwhXt$;#8LFfvanxK*~5n+!VYb@D{twSB^y$dNUSJY?!PdF&ItArmND1| z4E{eE{Hyzfzkybe1Bf8;S7q4FwE_Ol^ir-5b5=L*6N*p23X#YVh?VYI`-Bsz)qnZr zoq6(YWG&YkOTKE7v6XWE{&wJ5^(R);a6VN)+Ax4Wh6X*hNOgkTGnf;CnenOXG{uJG7+%)yruyCEf7p699O}B@Kb~!2&+#9*^+_k+ z>qG-jH1I@&?ELtse%AbWhqc92u&sZ?-bP;@2R82W#8>r0df2@`y*n?su$$!rBaxwI zDrBX9%q*sP^!tma=V`gY!ecCJiFD!oedxnz`<%Dg9h0$l5Gn#!1J)T8W~!E5r`7+} z^KwfUkcky_Tu{dOv8zK``X&2?r2LOSs7|o)gGU&7;W~3%cWOo+FRI+TaWF$gL!>Bj zPb@> zt_0D^Je*P5;@`~gyOYl+?3+6xGrC8z6S@~(NEKD>-8eku6;zEYXdFr}1dqC-d7z|6 zcXB_qXZ0^~>q_B2vAIO_XWvtQAWvxv@^h(N&fHYXFK6wCo%R^7KNF8jOM+08E;60*WUG}WWmoiB{O=XdKnQEU2h&KL?IJo}#oFaV_Kwf|Xw zP^b5$JOdd%EwV86ABXt&qW&G`DAxs)&OI7`YDq3BH6fL{`M(pK9#00}&E4VK&pTp> z_lMUEkC8ktpQt+y*dqY;59n?D3*HBi9|7bl765;Qj)p5MwIS*qaTYWC;Qg%+&&ioD zL}yEmwxD5K>i;s*qZ646Xs!q3?uGmp7Xgqv|8Qv$b)bOD>EbI>dHN)jrQmz5^&=Edt3m=NY zZ{@*YW!8ib8^ec%;lo4WgLa^;aB28?G<>KCA6mi(*_5pCLp*qCTmzIQ2XjBrH#jhP zI0Np~$OXIpGoBiKNI4bPrXJ@nCEb39m(;dQ_*I-Qw!wA(@(U?_{)>H<)UqfPs@J$2uv?+N;)Z};ELx2`$YCs&X9RJI#Pn|eZ;<~)#Q zn-c$*?5g(#W@l5u>DnUX8|>a&`BAOyCd`=*bMS6hoZH7IUJ9d%x2u&ov0xgu6s&oo zTMx7XEL{Lt&0n9frP^EjU7Cg5t}3BsU?0tg5HqWGhxp~b@DIc_4&s3hVzGTM5W7fj z4#TlMgxFOjh%e})`BAMc4$0_!-9bLMk8eCcu5=*p=RnRq5YnCxCIi!wHDKW}Zu<eXV7}h(wey*i<@@jv`t{U zagwoVj@5vFZhqI+LkTF7+A^)ooicX%SG_=qss>L_<$9{qQ-z+uo2~RX*srG=y_=-1 zS+&eyBKAhB7I}$nh117*SFa(=!plVWIEghxwbawL9sL!tP$3Ksd)Z6utnm(9hs)9m zPabs1k7F-wjE%%W1K_l%D$(>*N)(18X0yGrYH5^4Yze9ECWt+zpp3_i8MtQb+=62W z)DWy+w--gy4bqn%KX)(#dvt_`qLK7vyqev=MVV`#<%HN1s?JXz(dD$h_J0bx@Yg&U zO>_QvGL0SMje6PJ`l>hbMQ@a;>Z6WvwyW!k^h@v>O??zE%#4RYi;^Rs)6Yp|WZRRn zeqCwq7i4&ms)MDji{}17=DMhsv8+=$13?f~%n)1O_EI+&S!s}Lo_>bd0l4bGa zsu<_il%H4{ORk6~*T=A3Zhgy3O^n8p&*;7}mv4K!ShmeJ{}^xJvUvK$b!Vi9-V}Q} z92&JFSH|;qcu9<;?-j==6&tv%bKt~Bt~0-$^NV6_Z}Ic{$J7p7oBQ+IabjpE&o7C! zZQ|$6{Jbgm=lA18vr3-NP}0vI91|bd-ubh}RzC6S#>0&roeOwRrX#I^*nBgieiJLy zkB*5g4ngMjt$2FyF3y6V8PDfJmP%WzrkaX6i^NB+^zymJf>EwTFKg@g$TnNsvRrLz z*PBv%L-QDGf|`E9Ww%7pbrvv0!s2#Oe# z3F|8f->5!VW_c`$Pc}fR_Wb3sAM}=MeV`QVO`Yj-l#6v?HS!8=<1@GXJSK? zqb}7PCa~U*;(w3Tv>bdmi^-STVo^JV)-A(MlP?VA0wZs&Hqb`-}2w{k~>BFS_TuG zUz>c*I6S%8I61j9CcgOBm7p&mk#U&taF>`+5>HMljVGJ>VSy%DMP2G((J^1Zbi$va`d1%TNSAhp#SqBj8nF9VnEP4JBbhNOjIni}$# z#fB)S^44njCMYj~B59)XSGV?~Rp_xIW^e_hyo^@eo8TL$$u(Sm$@vB-o{bIB8#qHX zST2`rpBBd>53Urk*6PnD{rLxEd$#uK4RvT zsRl7&R3#W{lWXxCA=wn;Wo_~w5;S{Ii6dJ@JXr(T>L6P^WSbgYF8ha{wSV-J+s>@b z^G&@Ww1-mcA5JA?g+Sh>*ubnYyT8X;aRRZa8iqtl`fGlkz;$P~M>a_zF(xG5-Zqy+ z&o?CAp2_nKiRWsR{3~;W){|DIr|Dy1_|rq-L)N~rDtxmheAwt7rUe0(n#1=k;e&KJ zYiMft&>TL<@L@lB;ll(Tn7z?ro!H)Ix)@zR{R z(=d+ue+pik`Wt?ROGcCb4{jmS2f~;tR4rcG9bE9&2S3_N=Nb6_G50RuQ5DJG@B}gt zlz4&?3_>($)I?De5lzIn6AgL>CmK=Lc-b|&8l%g)5fX@ikT3~k9FB}GDu@?$brlsA z6(L+i0xSejxvAV%1=014gD&VQHU-db2NhW~*@BhBf$D=uOPT#7ls;jH3tE*YD z(trC{iTn}{vufUqPp=TOHDsa&dr0u3d^esZv*LiGymf?gX{$=|j`Jnqe$CLe7R z2iu6)uB1~6Tz0B>f5)vU5XCW*1(|*Z`zuH4CoTo?y{$5cwVe zk%#qgEzS;WQQpXw(?$)>=ZYtMn9BB`u*jugW6wr__l`>CSi~rgX=N0;sH5V3F@v;F zLC5M~1GbUIp2AQG&HFoxf4z5qhBo1CM6U{NlOA$8VGR?TUCsGCHQa8vDE^)iorc(q ze(7%%F>TI_bhQyEjoVd-jG4fGeJ2PdM8B55dIXx=GxN;ZKL8Z(p$sLLG!IVls6q&& z0`~-rK5X!wEoUw)xsG5&sB^g#FpJ?z7ob?c9M9tzSP-R|rTZC3oZtNR5slyqj2A5>W-O2=Q-en0` zq7@~k6y>h!hE>EKS%2@(7`ro|&0E&m(rlgJm;czHr1_Bz8 zCmdY)G?M>&B7LpYd;;>!y#gEi{Uk{hd7r!LP;kxuSHwBVHj9Z?5WMzaU}iK2DkvT} zG8Cg?p(we-b}xYVCg5QxUMf5a6gIBv9kv<3K1ml1tH&rL$8}G_pBuYp4bI(A)D6eE zo5>PmzXa25Y+Zw6DewVHsD2%2S#|~h$^alB40fjvbN=abG*H0*m}72)Us~INFQy$U zPzt1^9NIFk`A<7xAeJ841dp883U*e}G}ZWALITA2P_Wtx%9s*mh`~%=#vm|76h1mv z#lB^TgW-2&iLVl4Vjux85MT@fm-x3DOh7K|PdxCYT&t0Vbq!Y-kW)HTW?%^y2||7h zDn*n5(R0vP4%XUv)MYS2B#iPFinJ1*-<2!AaDN!e=fI;MHi>ooZ2M%ik%@6plk?-T zp@#alEyEOklBli4_^%N)6@V6iR>G7u&y`cSZ_8k9-ck>i_r=Y7>+8oV*sE9zaErk!b}-mUel)YrP$nVEI0g)$CFGGvJ#O3+KS4tA z8YQ3&Mh*AkiYz(L=gwZOXSWpl)>^mFyZfz%8~Oq#;8FGGwU? zh@bjH4dOR8qBG2_&AUFQF-6CAJMV`d3vStLI?xyS6^PthK2 z@C(=;H8U5B>!7{&ci_%Y8SYdo1*;+SX-OIHh%W;Dv3M+XXF~v$l)3l8dT39b+xP>`=~>=_HzS2B@Fh(OgC#Ko zo0%xQ(v<`8-=oF__v1YDfHP-JDPBtWA}X}=GTbuv>!j2p-^WK~TLHdIq?E$nbhhW+ ztduq6i#ZnG~qsUX?C>ZoOWb;!uYG zd@m^KRMtqzlo`V z0Zz@i-|bRyO@l*h)k`>l@Q+Lf>?sl7A@gixA<~pbj+C#m%ZEO+MRT~kHt}X9pFzN3 zkd^2^=+!33FxLBX0QY5IYLjRru;W`^wo_}E!u}YkkIjW^S^lPKc+IzPkhCnocSrSQ z_@z!4%S|~SQ3^v8PtL4GDv#+aUXg#D<=0rm=DuM%4ZP~adRZs#9P0*3SQ z+rnB2=DD!L+DZAm+sG~lFdIr(laYGxow#8AUaHo)wW8P!KXe+Uj|E&0RY0}=8Fa`3 zTo$Qe0OA1NaBEz^Z_SGVe3#a+5C{R_{YFfL8Kpf!%LPJ910YueoAsHsC?v;k@ie>i z{+S`v;s1$HKMfz@6A-sy4kof;6Vya@ihN6+RIVm6S}mNFL)2L75cMM`qX(H%G8*;M zE{W;ES6ag-k|*`FT%3tO2M|oChsS?slE;5vN~lNSdq{N@(&y2^t~#p0ck4aAT^?Uh z=Pj{}kscFIh(U9NOTJ(8GoATPkdtm-#BX; z&MTIpZ)X7-4)riw!9V5V=*}VIBW&tSt0`3=x$6pbYD&ALegtW^#(kp{|lg zVeF!8)+w7y%q>ARwjn#2kHVGH6$A|PQQ;#tN`fVErUE6up2LW2tA9pRPtim$h~|y<^!xu^^Xb%^o|EppwGZ}bGbHQJ)z28sb@n4 zR-w}wHhqttus$*Ym>*okgRNnl`jf}Zl*0~Vk54?4%x}3kO1_vp= z@gcG5JglGaEwL(>xvNeMUanHQj5-CMomHnudO{bi;Y=hf*a_hnx&SF%s=F>=psUd7 zM&K7Lf6G;9A0FxqY2^i7leC8afR+nz%XTX(8g(g~8`W2!=z=eus*@IC#&Lum0DJ)C z!q7wbnpky?z;PkVRP_(tL;b(JATf#HBy_1d8{fNB_2ZXnw*-$3osaU)r0T8ZT@~Cqyi6_d|`_sMQ;)NS?0>2Qrj1eZEDMkU)#+c)K*TW zF&BId@h~61f?9iCQ1rLXSGhQU!*PIrP*f+smB_665_%Ahz>JeCM(VEF4`ULCct-qT z%GM^5cTp04#UN<83Wi(_(^qO>*hJ>9zP*XmmteAO^S=1i)}@&7jnvF@$IAMZ`TGNp zn@)wBdA?mc3>kmOJrV{9J|rgP4K5r;B-=%&p=>M-`gKr4WT??TFy^c1;T8O#4GL+$ zvf}ff4euY=uV%3!ILFSE2Gz4178`0m68V5nIw1SubZj`cf6N;xHkmj479^(v^IuV5 zun)~ZmpFfgPn+;5jD34PPQCNBhdI9k|L;hVlLGd|SGq9{b+ux};=l2S{krzvMt#*v zpuAPrir}E}O&2(KU#c5JasC#r>(Jl1iuEVw&44Hb^OgauyC;rD058}F7X6;uXlh@k z`3EM;0~LFWtGn{vS8SCQxQ)xeG~>H6sz5eFC)Bcw&8?j&rLZ`kZ*`thK6g7J`vz~P zz9_F7gL(L^m_%!!9t+~%d;dfbpS39dqIlBgBX|Tpl-C_h?5s81&zyd=K&!iiyjJ=q z0zdEEJRkv4NQvA}@e`-(?#M-0<&7KE$`08r)zqK-{RH&NNWI_}Oip05Q_Mf@q_@A; z5Mt9*H0{i&*B7aGoT|4g>m41Z-se=kS0A$LO||N+jZ<%Kq~5bsy>I5A-qYjMd#$SX z606=*NuM2ZJ^^N8XXPhYoUg6aXJ_XwopC-oX#u>u91Hm;bcYIcUY!kumY+?< zZGCk*D&F=nDjujR?wS;-ICOpo@OAK+N-E8&ZZB_9M|k~u%NPoED|aKN&!2N!Lw(h( zt^2LC9&Q+M7X>49=DA`;rVdGXZqK|*tcNgW zQRn%?gwe1ltv36#>z_nBR%NNjMFu#vOzeEmM@{8d`TFXi&c(hp9^)Dnx8V1H*W=q5 zIon#GLd z!dmMzbovbikOj7(PgUY>U5fjImXCY;D)6JLyfFVj^={vO+ax4;0?Q+)Vjs~_cny*# zv&@~JMPrVzV@_czI4~=?TuoF8e;P(8@K;0pS^k6mQgqOTV`1C1`ZWL+ZfkW1=biHM zaX4&lq@Hklu1-M} zf4juT_>I_q=@lAQckue_*8aQtZhT+!4Yhzx)yhW#+=CT*87!4)FsY$uI0(R{O)0)) z;0qX9Y_~VcAbesFASe)Mu!;z8C)^wZ10_Q(^T3Gp=)xrkBZQB;${mD+8ffmYC3&HH^4)_npt-nFl|A1A05B6a1R`#H}nt}j$g3<8G zBrcCyAXvet>x}UzlgQK~Kc@oXA}<3|ghG8qUu?hN^cq0mO)Qh1Kng&yFRM zsF@Fg8Q;rL6V-!Z@$DUr*@dJy3o#QH4USOT+0q2n@q_2DubKP>(X4!#d*v z?d*0yycMTB;YK-FgHWzvCV)S)UAc$im9u7>xa~i8J0QQJT|K!m^@x@W{b9ydOTP_n zfcr+Y=#}3}esqQZKIBIRoA7bnbQsm1i6I3qab)jAW&C@2&j7NBB1rC1}g}zQV?7n13?qShoc&p)j|J|f?;47hNmSpjD?H{3}B*lW_Ja{-*<5Z0r_n% z!dY>kqEj>=?g$`@9~D%*Cy(?ce1uVPfi$JqQGxLWYFDT@DHe>Z2pCxeqk%3VhVxW_ zVdg6ca3VD_AeI-UgmJ)kq<=IZog#qz@`wQPUwNb-<|7Qq6lp4Ye4Y>nV?-<%Wf3sS2*%g+ z(lDIkz5ptw-zTWJKp;@lZ*p@(7!{)x1Y;BgV`CslZU@0+^iLsT@7mb$SrGxDf*{}M@<`vo2e*uUB~Tvfq!n;OskKq8`Zp*H zMww(tp#?i+adccv?{B@gn+;dH;I&uYC;{ z#3=pfhQv7fQNLE|M}zK-=tmm6cn&^51UVf7J6*MX=*4i`>m~_$*UKY)10P{N zJ3Xpx#b4KBrVKmZS|uX1wju&&|g7tnLuFaNA)|y5F{%IPEZhNF%ZmbiS$0A zAN2`CQ7h?TDB9{rKkN}a__qU!m+lcfbd~Xzq403ep)eGyCJG)}$aH@i!ctse3!3u(_6a-htKrl^OiIu;pVHifo z!q8Sf+D%6hEH$>-@^{AFf{GIb5VcW}+)x~rev2Cf74OL-eF-07RA|yvwETS(JyfXp zab*lD+UiI5C@>Ch1uA+g2+j})tf}bj`C$kS)(ZrO_VK~PSgeT$Nh%tG#fM87l)8&>p5q#qn2(=1?`ve4A>>Ou<0I{R^VKw@uknsIK zEF_4;xgsxwC|0s=usxfwzPXKHC|SeJ6PlXBvWDyPLu(;!o{YCNi;_R>?PIj+l_`q@ z7H3chtFV&;+Y#KZtXr8#~`H9#YP90UpfX?YPc;G^&N?1f0KCP?Re?x9Auv1_l zEXq8=hD5z_!zeTf2uu7Qzz=|c{4IBtNs$LM_J+k z7sdi?hi&X*T$1My4SDALHNY_-!1|N?5EoXq zW6U-E_VKK2W(6+7I-9r2vM}l8VD~*X+rJ)+pY4dWP+dQF z_0eddx*j|oL|6FNCjOfK-M=K%asQH!t$$tq=l#2;G%I!})SA zG=Jie8ZvK;)65HKrinr=a-28Pu=PvYKMU<+_|oAFwk3>G`UARPSaWC5Z`F20laXb9 zyVB}Vh}9lT{o2HXYJ60(4Q%G{5B$^Aj_h1Hnp4ly14#=Bty}Y~_ZTIKqCa}_KdnL} zXLSQqq|oBbrK}Pj_uP{5NU%bjjxoREA`crqvI*?BuePz8Li}5dj7$2J+4ChiIY9Xb?C%_ z?!&j!0BsL3L||CJ!Dse|FCM}#$cyX`_rZt2v5deImmM32+#fRn)%g2gr_VMb#*%tR zpwIu^@ulcPx+wZQBa)iitv#;R=G~nF0)23GBc9ku_2e%b$FJSfij6W5=$Cc`+Mx*K zhr3*aK=ALu`!UgH_|pG5eNI*52l96qW^T+su#bv=6}LXUhZD61QxJ|<^VN5$Tdl4_ z^efn}wTAbR5|jf%D3U`lo)Iv=emWHQ2xLGMZOZTr>F)a}WXe(FrAlnS+ErvhsYrOC z4)%!|^gDuRN6mVQw_wnM@VX6CO0>^?mO1B3Vu0(4{FbUje>aAPr2gBq2D^k93d)6z zx}zH@EpU>cesW+33fUjbVSF{5U*9k12gmJfao~LNjwARtiW+bJw8Rox9cu8w$79BY zEy~pR;Gu8GFJOHbItu)wx3cj@=Wy@g?pi~Oh5u6XoVl_1r*DWv2@gbJ^vrQkGG%`l zF>U`SL}86Y>p3shIn2Q~DXbEQ!0OlY!&uFT#cGCm>rRDLgb8S=LgddLf~*vp+yuK% zuU6PqXD_3%tK`f682onUE7te-34TxA0sJ1=cXa$d@!nDK`}Ps=dx7HbBjERdjb9$V zt;z`i#<~f-Kcdf#z!V%NGMK?g{^C2@K%fUEpWb)1gT85q=Nc+dP6*Ra_cz{XXVrA;^F36@nO_gCG_7Bq9eC?qJ<&CN4fI zLF!15`1&(cXoQT$-g%(C{`~49t7e)1k6b=2PWk(PMft2a<QcIFhH|_C8QY@G+`KS8vJn4T`gi2|GmcvSsH4>X0N@7~4da$D|BxNcE1rliqQQP= zKMF2B{d#b*k$jsBj3k`@ekaU-lo3%!r83Nm;p#&Pn*to9!MzeP@#LIptqj?9= zQbCzIPsEGIL_2`8!lhXF5Hy2o`L>Av{bW^>|9UKL)SaR9>Xh7Al8NNUQjN8e6XNBj ze+E`VrR;Y}$C=8Qsgjv0Vlw4Kw>y(iqTM<2#N~=syA1IF2imK-MuPyt3{E(cm7H3!__R(^0l}=ud}O}j zs}fctJ(g}&a3xq7_wZHllDJcYOu=BI2j2rT80kN}HXxzBAwc+ZQ0(}j%UcEt&OECT z_Rr$a;k^!aE4S4R_dANY)L;<*IP;TvmM>iB4SVKSPpSVm@#}Z7{u!u$rK?jyY#U#{ z-M)RpcQ`8G=OVk;JFp>Q~*0nW#e~Zlzf{R}r8x_^&X-lm6O7dO(8*Fv^C3@{qB* zd(}Ts5aMcBrV9Zzps2v%G=rbSJoX)bR;lcXh~9PFEt>N0Oqsk*n| z>2OJ1(sVOlrImOK#)Z>L#DA;=>yJJvwbWZs7EUeY{X;dSqCX${L^@vPEpUa?%Ot%_ z(zmO0h`$k#epl9@^AMb_8gD^LIDdseQenO+dH+&ND*N9dlj^=XeBk~gNI$s%Ex=UP z-^3qSAE`0{yy(7wJp6x|hBusl4wvCOZ(nNS4^u}GZQfsI;&)?!e|7&~X3687Ie2*d z-X^~J=E$3`mT%sIJHxdxuhhmL=E0AF0I*^fs$7Z>jRF3}OS8Q2FF10UJl^4BK?Z-@ z_p=<5HfF(Fu}jj#Dfz>mfP3F-&p^=D!q66<}gc0a~niQ!~N9grQA==r!iY@x0Q)RmxOwWbcW84Qq#*cFpDIUpLrvu;#Md$OYuQBl*!y? zTXXf(;%9sZoKau8hkMKEPw|16G2`L*k4v9X$b1o*IR0^3SmQ?`Ue2x{Ad~f~dz(mc zhxSBs{pu=6M+GR3*${s0nW<8X(7RSh_-O*XEwRBqp#a-eRspB~p03S^xGuR%A-{2U+d}E}D8#c>izK^3 zP8f#`f5%rXrIrH5n(J#f%J0Z*k2xL60pk8OTA5NH-*1zMOR^kMSISZq$l~muBsF3i zlrL%4i_VuU>qXRuJiK7Gyy34r|8ym9y}RTkj=KV4%)vxnz-Uz`cQ9JD$u*2tWpWc^ zysE;jIrAfoGI+{QmC_zROwmJ=ig~}12j}>H{t-KqQs~9>NZU6Rs=-w-hP5)IETIspZS6ETiulq_T4{t=J&1Uz}{Sz z(%AUgZ$YQCzJ>)w>~H4wEtF@m&51T`Hos~Mw5Os3T10i1Uq_d32VakoZ);!qRr2lV z^^blvrv5+vy80zPDMCpp`8n%2AQSOPJK^C&{5n1%KjjIAoXL0GdTWxo@K2G2MB^!- zar^gk2<&N2pr?HTU ziMFQd4^U+4{%ML;=8)5&m234+p-|v`OH?*Vt8h?sIT~6YzLY1`D3mA%1M-AKXF*?! z?~r+^;Ll0{ERupnvnqkxu_Y%03d$2#N8@S!{Zn!cxR4()I{1;WN@j4AU<{G}0Q&Mk zj06{v4GwNGn_nT}6cR#3aq$ZIH0W2fWMkc03`qYsKHR6xf?)N-5#$R6TL`?7{1^{u zU__}`Yh{4NJyY>{z2t%wMc%F9Yt%~+Rr98GJ6drPs^NU6!UH*_wy7D&20=GtRyJ=y z2Q^D+@8w)2KX;|7sUQCS5=OU#DILIAYm+^JQ!PZDM0a z^7HHk+Ll*#lE`lsSafm z8jfi~ff$0t%z50~YNRRb;XwaN^OAI);lC0kP!yPts@1sYXWi(#$6Ijv(Hy!g9-TQNrIS6bOtF%)_)R*ilGz6h$sruW$5I9uBu2TU;a)~9pN8|E zw*Vy94eaRt8EP;xZxm?23v)Bp081lcqI4Kbc#KkuCV*CG)r#e)wU3bhxi;l^*e^k1 z65672@J=X^qD^c;D-kuFZf1$&Y@SwBS%q8?p;zV&Z0`t!NZ{V(h1+n$T5 zf9 zmAL)~J9uhG5W{bux8RRYa@bx=pjorWm$=VkB;Ioz-?T# zPd7%&z?F7-bYVJM(Ry5!66%M6u;O(!Kv}7I^E3`nYjz~Q;QPk$mWJLTOoTS2h2zcY zE)7&+<$M}5V=a*?OlHvp9UxwG-;`4ID8mEu{}b#A6eP80h~yG{5B0Qc0`_;a+xu#L zz`8O23VT^>P`85I!DaN_SBpPF@)GzXZ26=Ee+25sV`fB;O)4y~bdAl-2u_dy#vGs8 z#5)LQYplsXtDyyWu2 zx`UlN4`0JCotbL@&J#S(Y~_OyFywd~EZ8(^b~rVashms#lH7&K!wrvdTS9UE))BX| z8w{CpBSWUhUf)&(Q}+097YT9O0^FLr&@UDsU!YU6gB-6*XbIK0eHdY?(w=b3-5yNG zQW)V^XjrX;HMd4>`ZvN|#0*ZiC<1p&L`)eS-ivBu+KAXUhJ!X~wBLfY#Xn&z9ni2} z#PzALCijj2XdZ%}be7mAKa2~Qb~if~;QSO9}C#z%qR zvK_Pyj!{ud&W(XS!cUxgvx3Fwc1$-Ee=VkH^X{%-AIjK=GR_{Ds^Q(MGh{V3&M(ou zH5rbouDW*&9@#oxpj?mQ^ka z1;~MEk5LX_Hz+mb@fNg_64DqA)<{jjt9dTnYm9<-&cjve%x@mN2+&eEAyx!n#DeGx z09Zd|EQH~5?2p;-RbPP5-~E6s@y7EBvg#F3a|=;ZRZ8C}7rR}W`*YBXn(aU}3XQRE z2<SgFij@3$EspFT_LbNZ9yC{6_CX8IF-B#1>Jy!uI#b?Tka`T@G4HWEh!lK9!lL zikys8oc|0EEoXWBojpE?*qS70bV<9x&~FzZJ2?iY-1y{`;gtZ^Z~4l3~8G>o7MT>d_*bfz@g^%n3Yl76wY%tr2y$7MbJ+yW}xa z{|Ix12c52AOg<)3qZh;hfzo@+%IE>nA&RG3Yv0jjXuK2=_9{4ioNNB!U0gXR_H(Ua zNZa=9I;9Q-ob0UCpGcF3|JE$j0+BH~4>h?kB60j~2m&6hH&0s9iNSX3UlKY@wP>lj z41~?CM--zAx`0m^u&7irSuq0TOCNlRgb1wPjiE36Ye&|*3m+gNlKVhyVaUJ`-~AFl z&!tTAw`Z0i$lZ&L5d^~CYqDo)x9S>L9)CJ@mPlu(F9 z>d;$o3K7`qDGk{zzz!pqheG+3p}G5==pK}de`ahSsHaNS=9sMQI}50n{1#B(lBJ-& zLP5PmQz6eVfz*gTMAH}c*Y>nH+Sj2}i?#q%vE&v8w-YqOwJkPBM6AF;6v7B%g+b{I z=e%dJJiS=pfDc|+tX%S09I;|J9fW?y*$Voz74$Dnh^bX`)^Hh`-h}>eBXF{-xvF~cnnXbZl1IPgu}_qo^erz_>4E9GasF$ zI>W}GRis`LmlQ4E$0G$4YES;whldPCjKLx0Mfqm+B^ZC`RMjcP;T6dyH#nDTh++sq z29D(BV(Q6P@%(T>8Xiy}F%u%H{Tzvj_w0>;D$jx{OF?ybY7~ku11xRHi@Pa>vxSj^ zek!P~xK8jFPyXSDPXbz?GG`8lO1``L8+;03zW=6Bdj_|hZbPObUno=?HQz3JGP$yVMGt~A3OV9<$I_*j!M<9uI?poBf23+ zrxBg;O+bZ{I{%BVS^ZY}>+dLSJJer?V_qAbfyp2RP$Z##&KDUdLYBB(PU=}__H3Qk zjp%)D72dATI7|$^9H2WVhEIuNCNOv`IH2Gr3WXM};T1`^5yAERkCSyh{-?>hy8m&- zx*N&5sn;fvbBj9DLnY|7@i^qC8Q)L!}nw-d3pMe+#EV3SiK3d34U? z7=n*E;_~PNAd9q5(iZM?43E%uXB*nKC#>~__7_trXMg5Qfz4N-M>b#igmOl`g9_G6 zd19{=Pi=k)lmN`%{+bM|J+e6ezfSaQuP&s%BYC}}lN^DnbQ%&^M)!}y!O$+UcqKdN zI2UoBEexa)>{lWmR*E7zAv0sX8qSpKF&JMvJx1QW@KDrXeDhm17^BO%y-U-?ivV5~ zbULai_Jh2o_#fBk`hQyqwySm)L)*Lnxy%o5IxM~TZMYX<=m9bH=L%duN?Kx)9fJOx z0+Vl54=QBPg1{!2afLk%JwfyrPyRY>N)2>uxhPu}-XwF5OaYZ)4Nqz`r|ka>YoFwn z{;+L`q6v6wsHS7ZwYsVcx0bNH<=xZIWY!8wMfp{Z&ye>`1H#r#sHx%blKVeZ(?={? zmIEz2-Tpqs{=0ya`^$>+|BwXxFxt)I>D)4p&qN0Ewvpm(1hS&fgaw+PMc{U*p?L#J zp^Q@2VB86N!_M)434RAAj!)_^+i$YmL?O*+6}a14Rw()NvXVb#TnLov2LF(hkZr%Bi zVhvO*jU|HD>%i7`zyVBzkN0#oj|OpFY)g&Y@{Ab`W-qqCoq93&ehxFZu=J?mF!DE6 z;=%HmXNuq@v;)~3)t9od3aHUJpjLD3SlGA5AhK{hR>c!05Ol2T8G{jPVjK!uB`;?0 z*|69mwks20WB`IEvNqj6ZwnrBeNqk>Ob(i%V~Ei~{CHQC$xTcp*c3^@au)j{gfNTZ zxJ373dvY959f4*5pfSH6rGWXVE*2PEJ7fVfnV6)h15+A@LykLt&-kZ;j67lPf$N-F zDw@tlONa$&pXpHgeDDF~&weF;l9l{vBmuBEtmPB(N1kAKC6|`VEwjO zNTkkOM9x|~6F!(b2e~|uVw^3)rLD6UG8U~su4-H=5hV7#F+a(e{Lh7IOqLLdrPMK% zOtX*1tF3DDJC%Fo`J>PWk23Rs-pYfFtEv{XPfO=|LVcPG@%>bZsaAwACv$cJf_Tc}KX<9JKNfvSq%VWD!5H{t&42{a8uw^#UGCDRt_ry7 zTVWUh&x5JLmvG=7A7m8yWDa_e>kP|&1_qP6A=Fk27>(G~{S$NWaMQ+QT>-JF_0zyY z@EoMoz|&C`+yi^Hu7Q>1bdeuy%7s33MG^v|ZW*DPfaH)f{I+_!oge{km(c2)@ynPaw^|5(%Dsm>j~cGc{~6A8 zPR%zm`k+f0d213s8QV*HR#iCS{I}Ms_>0bPxOwt zF=~VZH%7gC8LjYkVX)rsjeuiOFBXgbS`xyb(%OFQ8#ixi+`QW+$E$bSxAE$|X9d0{ zw{7kHmF>U6pK%1d{T7~&%w`ZCbaIoHjPDtEgZNfgYdwmWfI2bs!UX!AV}Jy=9*Kh$ z|B%+P{9{xGZTfZ^b+@8#qUQa8&>989^KAOMzO{&p#J?kv#D#ZkA8nF>H^#@_JA7Om ziuOyx+CPS(<=*}2)xAKP#6lndR;(z}gsENpF{quyH2Z$AmrstN_BHoSahR(vjiENM zHxP(f*azjz*Jc5GF!DLfJMoK{lb0LuVqxySItz2eZ*cpO=O=}~mk3eJ_#?ZIa6$aF z3aT#af`|(_^c%iw)Ps8dx>0xN+0Z;9T)qxm{^{?qoHY{jBP^*{ymS*fEnI1L`t4pZ zonG`6I=wMJw$uA9`HhY(yo>#P>*cUWnOJLylz^z6?Zry?i^#Wj@i!pIqmuu^EiuK?ct}VAyz9;HsdVLLB%7}FYftgyRiuV2ezHxFvaosJ{G|k zuhYMM*kOMB9n>Id=44)bW&;t;KH=)-hM6kr$C2TScfNYf!xl0GzPLt-HuY;0=d1CV z$2l6RHU9wk5;BWR_sL16@JXiLqpUT8Uc)s)NsXJgR%|vOpUG1xxak6_fwctX;$fe; zwWKpdm1y5Xv1B~15SEEZh_SJ3;pz;We;#Sodq)=Qy)H{n4m|UPc{`TOL;JGmuTA{Ey?pYQX3#dk{kQrzk*w9f%S>nuy^GQW z7yT2|ee!!y7Ykv8ly|;*0!~sZH4s{%ImSx57D-bs9UqmX8IBnq8V@@|KPa5CT(6-TB~oLp8a|A;nNUfaDY-sS;osF z>u|)}x4F6XG;HPH*txaPcc`e}s=@uX73FT;x4GY8+*(ou66bGt_~b%RJ$s!SDth)> z+^f=BoWEgIbLbr3kIlOh`~B$K+Pte%zqP)t8+P?uyYx`keqXq>d8=d zme{#EtM*{e>N8+F!LGl@x8Z$WPLlgG{3of+3xIVi2rn4DUXEOtZs;pq0_kkse@h1T zp2?=w`EG=f#8OEXdPo;@1#Au6HqPC?gv$+J{~3Ya&3#~Cd3~_ON#6b*Is+TvvWjl@ zT(HnevY+p`M`Sn0$V2dqWk+FJ$qncZ6tutZw<9*0-{{Dy{<+h@) zyc4P%dIp;MD8t1zu|>5|JHLMFYn>EYX4NY6=&plD5~14HnnpSb^t59D2U zb~CISha&9i?$^wqa%6LNHq0L{3U!MUcDlXG4~0(RrV_c!4OT@Jq&#f}vj_#4Wu`nQ zTgR=Z3UoM^lwm`MQSR|!EWnx7Vh_kS;9H#?Cp}pMal;zTI&3-fMSWE6XTHyEevz$u zWkm>{3$74(mR~Z=^+Y+6J^Ol$2E$j;5q^enY9N`9*9{g&&A5aAGM?* z6Gv>8JnJ)eAl>bEyWBoEbiv6|i8jB7Ht)esI9PjqNnzuILotdYJg+KVqh~jh5;}o0 zZooZnw}3zX>25xhG`R8B;|Dk11veU1JF`h^U_^liyF^WBm25)-x_zG%%JOXi*Kox+ zFbwn%OrlA3x+cTp>zV2H{sV}bojH?*G1tIr<8E#r6hTpf8iG7B-)`~n@F>A`;?l{NMmka8>*{ba^!Oh9wI3{Qc?n+~YCaxXyfDPyXrK zV{q=aqHgeUTCL}=9sgATYR;#vYns2M0ySA^Hdvdt+TCvhVi6`(!&^bIw6GQ_O93U6 z2L?E@i6)MXCd?d;&^gf{ZS5=|ofrosy|o2u?bv~Z(Aqk=ij2Dw1~=Z_$yIx>wdyO6 zZz&?Y0l*?$Vj5RrF`S3{irP8IzCl@9S!Zd3fi92+as`WF?~MQi7RsBqJ!M-3+E`M}J1gU_FM^Fx{_E5~ zXF{=7`seK@fRXEV?+|{TEe`b5Kex!cIvc|ofqq?_Q0f2V0pF*{P@XGCDL9n(Ge5l@ z%L7`2A3zT=dO{6RlaHRidBl0>U8hrNasSl3b@xs%s46U6AeBLb!L(&ng{IaE2#aMB z(v8I49x8}G!at`EmtSBW$pDGZ`Hclj@yu<_{h1T2z+bn5-C9mnH%*$b&iX)4<|&4@ z{o;5wQNSGi0|rpT((wa0pYV$sWAy!HIkqkRMHluUb#U%RD2&h-dAx{~q~RF|cg5%n zMA(W11|e(6-!?Wyo3I)2If(~W61orw+DY2})0MRM@z+4xvBTG^^f}@06yAHBiAr9`w@J?K- z)xRddb45X={T7^vVAo~}jMkwkyD{{i@R2dH@Kp6uny|ePj#XMMBb{6+b3UKk+lNoa ze#Ec;hC9Am!@XQ1{g0Xu@uJnM^N%11(d0dd_1#O-7 z%t{%pIXuB|#(+%&dNPnA(ebItalFbz!}*7Uf%8w6Y>nlxs0$54ySfwFRiP`lH9VvY~+;)c1XXtAKyw?sv$Y@MAG{h$r=wWF@Rf*;#^Ar4n;w1lVb` zUc&GGyI@Ph%rAMiLn?9k0Ol2ZgF?h^Ve7}tBT^Ed2z6M0p!3V5XOki|VnKo$t+jjh zstAO7zy0hRp>Z31JKL?24R)YLt6g>yOIuE_#FDIEti4r$pg>nEqu_~Lq#4eqf2oyW zLq=w0WMuQ6e=@uX<`;}_tv(4VCdXU`lITi-EojAi(7s&~le|#=h5)(ElvC9R0K^>E zv>WkSWE_N(QL|Ja#tCD2KBHnx0M|RRN3O^78Y2C}3rPW1pJ&$^cPOW8(38!_V5pd)X-PLomZQu)ts0`DCJ9<3s3RJxO_^mPgb^(kM(asI_o!SF8YpOcstDBo%leX@m>V1#$(# z&IM}{`Tb6p$9E^zhL-H~wn7kIgvxAc5BB%ZgpxTnGqK2bUrABpLpOT-70@(sI!Oq4 z8G_bh_K@FW8MHnk>ry<%Lpp_?f{>asLCumM@Mxsi`5Y@kw@(%tVK^(! zRMwrC5irP}m9wN}JhLMhfwW{GxmqOZk97G>dqo2;6}w&9YCm zvoGn{uyH}mAaAje*qw7_3(HwU2_`4hrHmgo8a??NIYlI+8L~|+APbdZwawEapeo-n z@ZUNK1IzP;nj%;|+1ehZY=Ybzkf-Vh8Hpg{)@N&qAfY{+1D*!gaPo2pg667Yu=&f2 zegE)ip5+QDM2c*8I$bcW95^5hHM_Ysd~ zVD@gKfE%~8Ue(w)19ygFeOjEq;^D5tL&1}*1~d4CGn^ciaLLEvA~S8Efv94}kVI=sk5M$P6({DkqB6gu}2e%)Z6 zVLi7a$sF0ZL%9@~A227*cd0hMugB7HI$BU7*LTpIjdZ&?S>N{I2i4>T^8~!e+R{u6 z|2o)+2HwRhkcg3D-Y-7^%T6gjLtb}!eBYWS_^JFDuEH-`n9++d@^h;>0M9^&n_=-h zel%I%&bX5t342MKz0(feeuCM1qdd}Nf0Fy3Iou_}+J}GO44B9AF7(w%zYP8+3hXy~ zt1WmH7Ff042knOzMD0k%{^a`EfejC}eqNjf($(#*rJ(Z7&aB}R>t}iT8_R^v0u^{f z$DF!1~x9rm}#v z6PRfUtu!WvBxnX$<)cPi-@X6}&bneIK zen<)K6i?2q!6y_Lb{gEdUtWi~jz`hd=l5lXw@RC9&Ot`b3Li*!lb3yTUV@(Qd>aM&X-o;-wBmZ${M;v<>4F1>>Qc3FGmAS=cZDWGK+g;k9a@p}Q9R5ZuDKbt}lwAh*RI{yD-7{zj4n zyxJ&_CPk+M+Jx87#OLgTl%M;yL4?A3u-Q%bu?b$Jz=C*r5y;$M`d{eXpHS7U_F%16 zKeHd1bH3;Dg!01X<|J)?)#aVFc{NwS#Zjw&4{ab3Ay;uyn&%H*zz579IA*b?Itf{V zPv8T5{XLoIEV>FfG$-JKQ1JRKhlJ0>NA-_ z(ldd?Q~dsz!s=TJ#|sp4>lAXAX%q4?kvV%A^~ypq2tpx2IFx02_I|y2KTwV1y?x<^ zh4m(?#rkMV6%_Jj^G7*$fH_VY#eNH(j2ghkHN+?=wcZIF-z)G$2gepn!~ss^6~lL@{p=(7UL z?6Ja~%-e82TC6>oTIH-g z*sHobIQW1A>TDW&LNBPwB;k)Oc$XhL>>qoW!zeiPBhNrA&SVA#1Y-IHf)2#g;WsRb z_wyMZku~x*r|rP}4@MaM*5ES`=ACA0McMn54dlQOqwjIL0Tl-o$oPbDvI^1yE(^`( z9H<;bv%rC2W3v$9iDn_f6vaaMgQ8ey@;_o&=(CW`LMP1wAs^+q1PlEZq*=zKw&Lru z8{)DM9bm##ie@34Z>N_{6#wK9HQ?bbihug{MzfdfQT!v{$UmP9Wi!G*Dt|Qp@QYc* zYH@yPUK}8wlF}XV&vA5UIV%4&uf(i7S8Shf#BgC3FjcQR>?p*xU+-WA5qw%LdVq=L zutUe&qc`H4IK-MhCer;z0m4h@xN2XL7gl(l&v5>voN750VaejQWHJDhLfWX*(70zEr4yFLE3MGvqDZyUI!VB)=nSp{*~NO&Q1ojj-YF zG|ott8nLo=8u|eA&LJ;){Ivl-vSF&VJT&q@(h=u1Fob45rDS;gjWx)m=l`HhI4PY7 zz-H|pZPG7&@zFOℜ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

^it&b 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

    k+E z(W#8r@jLegI3BD4oXf!IQUC6!i=bTimGWf~m}OU2cRU?`@bQiDp$anVUh z8&C7@Zt=kTMEG;d+4Ot*sYH1yh>8G$v5Ui#Y>a3?+zjYZSZV?ZRg>%G)Jy#COb8+l zd}=In2WEfW4t!j(*N#ZOvs88u(;B=ZdX|WOmL;WBU7y_B5PYUB+9c@MUNVt0NSDDR1rhV5k|NW6 zZi|2tiBGCJgqrGSwpn%xA`YrmsPKX`&BZIk7WI@`4S(*IYEG<%?eO&$l4e^)Ah?Qp~M zltx$>+Xp6Raw8Rp1wTW!-d9zqfx=(r<4tj2gTCjjzJMNw-Ixq^$erHdHUZ#01vVs> z>bNlo|94w{qj90#?hx$)uM{PJxxRnOrc`$E(PCL*xTeZX^%YB*0m+XOSt{?9H#;Y} zMDD#0yuvwJ?w4mR;fU$mkuvbbc}Z@=nY#regvhZOF6L{{f_PkVHo4oQrz8HO3el2~ zn9&&$uNw#$d)o34QczsD;dhj{*2%k*N1EyO;yiThaEi&@;qaM=G+ zgWAiQ*db^`VWqYdHD93!fXnVK*Ed2vh%af3sQup^#4!V=0u1MB07yq_e%WF)AHFQI zHCd-$R0ak^E;L%>gqynb2qZh|1?rMVrN$h{r}Y0qmvH_u`jn0tjU?!vK0> zA@^}S6W*T3+Azt5w)hL4haAFH~qJQT$DfyLK^eriZwu5u zjUTO-qJ%^dorDsF=V|wm27=_B=rwts-+I>>okE%63uJ+hdjS&5}BHat!{iqga;mEc$#3 z7zG-vVF@gilx)usP*d$Qp6%gOq%2TkAUC?7e{o3KkTR4IwU!jzIAdK5Tq4T}UBxSN zApjtrxD=Je(brEkeYx2?4+ACIs>XQy3HZHC=A~V(R{RQJ7yRZx1i#g~P`YymY!LM1 zT-EX^P8;1JsR=x9Je+3=AmTx^Wimmew`UzIwFjkOtL8ZZEz8>#FU-n&y|)a2CRuAOmeEm%gH zVbyy{1xWz?4zO2nV*6^a$=lH2XYNh60D6$zpnWV?0B{CF6rS@-!VJ<|w;io1ZpwOE zSIOV#UveCAQ=O|PSKSJ$c)?jxLDaAXK;m#>ZPsGeW9A+t?R!tjt_0OMC{gutc1 zLVhMoIKn>ANAy!9iqINW{8DAzmO!b{xZFRc1K>{DheMgmQc)o(0n;XhK6n-=^m3U{ zI|>bc+L1!pfXl)lDPf&JCh~kmN>5cNJW+4dnFdP(Pb5Syh9})OFHCZGPEaVaRT`vk zwv+Ps4cb0GD5%h+T%k$JgIp#-6IDEhCcJmezYw{JCZ{KNf+kK{>lb$I*Ls$c+Kxm|maL#w9(DO#^x zr?)P+nRBIT7?%qz(|t8dzkXC+vj!n5P1pI4vT-nkM^!hAS>C-GOd0r4Rm9s&w`ab3 zdy%?r5hQM^gcX?P?+6k=iWTzYO0QDf8^58Wenzu|d)pF%8NZ@W ziD)VIKE@yHRQkn|o*4M-kA$|Yr?ZxDzA)~|6-%{D<_~GjlZ8_DoQLEleJ^2hlXdqK zEhJVz%2{4=6S<2eH#v6=(c`7E4WW##U2*b{B~+#(rL?}VSUN#&hR6%0SW5WUz+dLh zV#Em`jH-2*Izrm`GXUI4Nxpst@&iA3G4K=TNAQiuaMPN)#+@HM{Pkb3$a)I1*KuYz z&uW$&P;+p@Gp$iNLgxdz@*>$K4!7K{YC%(SwIuoBEf4YDj)9GZ-UTqM9~9n#1! z9XF_kGx<6&)igaC9ij8qPvWdy$9Faw=Ap3fEH@%|RwP%Y)Le%6ZZ*lhH_IeXWveR( zsyXJVIgZ&H*J|Teoy^fmS!c#&fLVDm2wabv(c>L6z;s)zxi7v=qB6iln&=m&*18CG zq9Xg0BKWu!0nrhh*Kg5#XTjO7&%JUPfn%Wp7~sP=5V{R#G0@*|a8cVyCXgp;%o+%62$qDp#|5y>z8g^ba(hRGK~ zuF8X0MCX#Ln~77{sm5onA2J3D-shNcjLjREic3xYTMnuPYCk6I;MIl3U^PG{9XLel z_`Ig*3li0?jhMHfqfADR-D>0_+OoXU!#i(Dmz8BG?p!W za-nKTC*WB0&$xyB{BS2Nf!OM0;7nuXHCxO9uDuBZ1U2KaXSQsI=ysp}V+9VGxairbzxf_i79ol|x~B zcn^Kvda_QX~R zReYd0%oy)n_u zMQ}m=3i1Jt4x`18Uvf8T{iKXOtBdePhC>DVGC=?{YU=&-I=qkZ52hq|Rz?$P zze9d!vjT>Q^}u394X!*I*Y!K6HbC{lZBA`>Qz$ z>^Z0pX1?l*IIwR&&>7g5E5%$~o{vFpEHJ1hGN_dOdk|Y_=l=s2oW}rJk(p!RWHih4 znd1pdECTerp*$jn^R(oLh~tqmmojVR5)P%Ee81yv(gO9@rFa_)sTkGB9d;aB9FtA) zmT)laAEg@h$aJuI01kFz&b9#oJboyvhV8ZA zo7>$h2D!)MzeIqnXzjhai9aqT^_kx5)Sx07IyQjL$s;EsM-=7<4_% z4<0QCs`f?)Q}+@t4wztuq@n;cUM5MIkPfE^nCwg7-%y+p$!}>8Hi%q>sbqr&44a3j z)V+>ng8GY!Y;s>El=$KFe>a0`XFVCcQdGMw~-zTUZ&k^7hWA-^+{`29FXH!tRZ@>yhog2lZx9dz~+2|DRH~y zxIk)(kK6s7dh>hr<_14*_txAdCRNyhq!iJ$_#=_PZ%f?nX7m^rw|g<-cAxr_#O>Cs zm!hSvo-aMV2T&ssXzuxEDPcNZ+`RtE`qe8?LCI%5#t_dNwRfr#|!1B*s z3Ql3#KVOCmKzWi!KvHA&IyOX!(!>WNokxL_$gb8qwV>uua#a+SH>%1_yaea&!KEsX zhhY7w`YgsR?QmOB&D8QWQU#EzJM9IB=R%<`T`T0!bpk0A{zGRgia0}2#0O`_2`3Nl zR}>LH+RoY*Qyc2zJBDP0wAIt;_rtJ#G6cHRF!gDEbCm6yK|YTEG7f z_zB+IKQ0y*WX@TdAZyMt`g2x?Ez@N+XVxC>FERUN-JiLtI8*RXdK?wx;@$x^i;PO& z)bxdH8id7uL?A%l`($(~*+&E9oOH;9=UhTDV7XX=<@`aLj29f|nT%mEe!-7O2BSvb zNk;OQwAQYY1`i?p7{>^69%~nOO!l5QVazZ30O|x*DkmcZ_MQ_aX`Xv7F0_y)MRC@J zT^V+Yw#rE&FUdrPz(=MO3CLhSydk4%qzAzwdnN?&7aL?8ud#Rri`Q*Ox)KS#-QL;* zKf6^S7G--?YHMZ#?RRBtyiaSac}VAaN!SE2j)^(2UoGQLd_8gDhw$j@3{xbc8Gg(o zK#MqFUB~>nCn0-4KJFXB&bTaa(L>(}L{>vKf$TMGxX50Y;9>^f4$OT}9&1-6NI4>> z0miAA#SoCr>4w!C?xO=6mM%ytSOt9)pxIQIyB%Mlb1#6hr?lbAG39xj~Esh5w<`MO9(zdR3ZHYtl^_gcx2kY*@#P# zJrTCCJ(9;}m%A1s6Y-y}s>jP{bucB`twCuDfiepU$vYnTnifYd)4J!r0LOHnR)C&O zsMfZ_8-M|ydLrabuQ9nkuLrq2s|NQ(>Ly&>e_j_GIn;7;zMUMD{d00HqK04zJ~kQI z!Us;T+i|eI5v-xtMi|AadO)CVi#~`~5HM-Z_M@614hXtx+EnhL-G4+$z{>~_OJx|( zs61*`HD3RraJ{rEAp|V_o?>}o%W~2dt%_rLPk+*p*o-#=w)=K2RgjxoG|@K z=|giY{+ya2J~W8+L+XspGsK5xL)%7pZ3HO)M0aCzG^~B@g@2*|v&X#xS2Wx0QdlXS zeqSy7OOji?@$a59>bXBB3}{1oOeM%w_PKv@V3ChX$<0d)hkvk9L$;NK1SY>ku?CI) zVK%e2y(J${{mgCt`b{)T{1+A*OVS2B7i@#J1}Yy)mHiri=3;18p8N7HsEc?8%Dx72 zw(rpZHO z>QG-j`Sv@JM>v#p>XsR9nxo+pJI#&midow_3M#a}H7WbsiO{qmoHP-Z5Kd&Xfp8*M zJH4iQ08AxY_>#FkA}?@vOKJ$zJ}l*HwVNjnd*$BCfQ7G)XbMD1BFM2=6^JvXKy#!w zEs@Kw%5lLtR-mp9RpaxTJ~dS7%aJCHxQstoxIUsoV5quDYwY5lbF<$ z`y0QO4i?(@Gqmj`$SY}b%y%~RaDsd5psRD)atFo&-FP? zRZ;`$JlE%wekCu{XQ8U(szGrn5lwM`cb1n3{WexoKD$c|N%mPIV^GOHnOIW@5%A`7_f~1e+vgHJTxNrV8rq?Hq zCIJ9?CfR7-op;r@%|sF=%KjJpZ02pyYVoav#N6#n+&-F2uL8Q9$(&)=kSW7mKK7Y} zSp(rS@IW^&ahS(0SP)90Visr{wIx}iYO7aCYfYG6Mc7qjt!;>Y2LEK?vhE+}d3(#yKj7fjRjjog=p{U-D?-E7yWDcA`u1xb(P)Nt~bYLRC9BrIs5h;x-~;s zgLnoOjD3q68o-v*t_D8*p=)HqYK78H%B8;s5dYLqg5Rb5|_&*?M7ZK1g=^}P9%TzEX^P*Bv!vV)4l)KTsP!!v2V*mavbcl$em#s zA=Cj^nD3WoavY~R&%Kf50VND=1bPh@msti@3cpu`$J84*b?0M?>sqGL6$e(T4FR_Y zIBOe5$V$@b15I+fI(|_{M5iUWDgVTZI{kiyMI>7Uz+g_Uq{$Za?SB8qasKHze~xsC zEp5#-I#bTpybi8gT=E z^PP?Zk87rJw3@%c`Risb<}{qNIfNA z?S6FGwwJnmfKE$MQho;;_u*01O_KRl<$$%9rlM0+OX3Br8C^E=H|J*tf6KR3LB23h zD8xd+MqaAm{|&jHO@TRGM?C@u^fU<%r3*fOLq7WcDwM`Zae+?eZf*-akNWKrIh))DjpDBes67_JJy=`WH?4sR9aho2A z0X0{;ozw*1MS@UW$qYtkei!|WWJPZ62P&iO>i|mC^e?Fq_#kc!brH8kZi!wo7HnSL zTNcGQaC*Be5AZb9I?%omJQ#=!6&+xU(foEdc>N!jYS&u^)X53Gs!4GL6{e^xF*o1DlSV1KAomhV@~m8fATkt+2h~Kh->&flP_ccogS>nAH@^Ly(s098xjZYE zpv{K~?H|7J+uP3oqU7Dfzwzy73!*h-%H>(P1Z_S{X#c^ZXulYh^6uf^`1Y%%;f4yi zJS&%=&4&r?4?1G|t57tl6^9)4%cO~#rEWp^ehT(o<0P*O%F#aYwnHE(_-+Y|KO8a zG-uD9$!~95t>iZu8RfU@Q2}Rv*iWv-W^+>sy8>Rcj z6)dilLmWoe5JuL*dR!v;;mRC{Wjs2rmWT-OY{|K@<{=`C7`9D&VH3*2hgW9k3|#+v zj;9x%b#CDP9)|~+B7`c1x zzo^hEz$jbvglc>Vw1!REtJyNbkDBCiw;tBSKY7D)9}lx<2CAWZgWW>~P~D?*_uD#u z?{KVhz!zKi<1+LxSUp^ur^8WcN;Wd$z~g5Rt?&IcZ*eeWP$S81Jfs?x} zVe3nz*eJ3NxGfKp{Gfb%ENwoYRl}<_DKnBEnCxMW#L|q)(CM@5A0Xzu;Sa>RzZlI& z@^|0H@-Xqp*Y{cj#_VR*?-ut;R_TnkH9cFh!jO%ZvUextFD>+t9}01M`UgVPuS(5GD2ve8|D+c1r|&n{>(Kj79Zi%lrVgdR``t%w*K9v}Qar~`v@w(aFH!c9@#^q< z55Wfe$WC5iACaq_s_e_}$V)G`-~w%Y9*s=Rk<~=X?H@k1_drMf2dasi4`SInb|B~!Hr~^m0u5k79PG4l| zv)AoGvph=KHz$(hUeQaD;xg&W`>xS#d9~dm`ET9ADd1a*hz^9|D6&44^N2gbKIhT@ z$J?8LM^R;MzzL)w0)7#vQj2H&(|<*l`W02%@rxT5WK|<&#ax|Gwwms_srYi1Ypb&-0L~uDW%Xv)yyf zJ@;IqWO7`?8HPCq?DQjQ9a~?C^|d0@3M!1Qb$F_Ms1F=`!!walE=14U}{Osq{3f8&26tLZc`~A(1p=kF?*i4M;L9S&buc)QH)kA z)hG?XI+rKCa?)&|(vG-v0_9@FYZFN|D7g-}CaYVxr&F^akk^@4_%LsqM_CD3W8&MY z0cnHCOb}RV^&3*Z7T;ixpz7XMh{^cv5R<3lsr8q8@NLADGlodcC!ZEsckKEM;U%Ne z29+J!T?{8tQXAJgfw61WFi6iw+M##rnFR$fhO~uq35ZF$t{#p9)F@CwWtd#;jxeLw zwUDUOfIJ6ECrrQ^(q2Ldqgy6D z1NNp3m}uPIj7bE|asw0l!2A_l!+l$-)(f$L{{edp1AEM#q}c-zxNgHluq1XI!M}5O zzLKm2cPv~xl2!U)x^CG5T%WaDaNX9UG^HAT+Z@;8AGmC&609d{pEyKK1Y1-)k~QKX z<`}K6iGfp}R*GGw zBU%|*@7x79mkI$R_W$1!s?^^TRR>4!pLNy*jZvVMAiyEIjzrWGN&AkaO;XCfA@ zT8uF(`8KjD7suzQ#c@oAUSHUZhsej&&n)|JR6GbrIB zMZiR?z*^-c|HxEx4W}ANNd*Fitu!?iU_*U?YW5>^)LPaBRNdV}d)gn^}#tos3hlPT%vJ;1{M-AIev! zR%JS=T4R|`SIyT|aQ2Keo$9}$dV%@`oKf`hm;%&23Q#L*&;jTfwYcaNHS43k#CX?< zguSeEvjZ??w&H@2YkTT0U(W|trAex{nKBW=9GTN)1A6?-HdK|1+grO(kntO$fO{0AXzseTRCk+(uf2)eH9T z*(#S6JLS?;gq3J6l^Oz%69;f`?8L>NU3i1dFZK9MAIE*X(fZN$Ao_2*iU&i~-500S zR7C~zbbs!b(!oci(%`GC6c&jGkrohu?WJ;fPn;l-7v>QlT9dwigOpZLx@acpeMq+r zTdB?1VSja`9cjXJU5n(5)=k)kL9zh<&X+DA-5Fy4jOxB+E9+2QT*+Bvt=!;KivWw< z;DW`t!2NeN(Jr7YUqc8xs#oMQ3BcSsYYzgAdnQ0X>|6GGe93ppzY>E9nz>j`zng+f z7P|Uo5)ff0PmXO?Em{kUrGFy^iMQ1R00y!cSFkyM@)Tae1>uc^v@h^NFiCCqU^(kN02UAPfa4BPxinvx&$iSak zd;)mSa?`@YVb_NtiG6_&EZ?3lF$)iY8fUvE*$CA=s@eRC+x%7URJXX8gJ}<{*9YWi zH6FHS_Ca>WNsY+PIG{0ksF{FmjKAj#sSORJG=?sb8J>Hbas%(<{50zXQd(d~ZXguu zBJa4wjNqz8>?)ErLr5gU`jHG2*e-=R1|>8f35)cG@K){xh=UBYX$|RZ07ByvlE; zJj6?qA$0;n7+05+QQ_q>{SsOh;H!UN+%P$HNm2%8?0h(8falMa8qUHv%1Kh z9+*{Eusf0AuCBsDqUMA)>+dIMa%`f-)uH!+OhPj0q~CokrBG z@0VJ3>2ajQsU5MQ5*i%Z*k%>%R1OCPdc+BhXlf`Hza)lY2`_-dGJY7GmKqV5ffby_ zE!2NX#36aa~-m#$LZ#_u?p&CSI^e;b8kUBAlq zj5rRwlvXOZ)>mdKQ<+)B^Xd4TUVw6_oKrPa69LRBer7L8RBezB&r=yMVE?YC{reGx z7v^C77@$lAd04mhC;Z@`xPn!gN!Omo%mK|KF+i3mPW#whS%lUqTFaRN=wBY58zz<% zL84=LA12KUB6w1Y1tJ2Ao0M(sl+`^;StgT)yYfd?s{4yIM5rCpak|i5)<;Z_fkuVv z0^d0HYq+)Mjo5jkm1s(1?5;(~OD0U-!GYe|L9i=jZH z(jk6)fzGD@zEw%jl;_({Nj5KyFC2seQD;rZqJE4e^>T9gPKx z4d?%tu(<7v3k>Wa~hmCE=CNlcd}Za@vn$Tq~qRJ{+Y;* zSA}!4i#+30O`eG1GJR>Sc9{x%ti#31Vq-rryH=CB{3{;8Mai!@r=cD%4q*;HP{VgY zIfg`XA>oVM;0>PK;4N6Tnt=t&Gz82{V#f8Eh-ZgZt3+#)jO&QSfUnG2UBnFFYX8a# zR*YF+=4=S)dTB_ruk2>%)RUmMPmNQaF_x}wo@RZ?B}lVA@T480eOkKaT3$`p@n-Zf!TicMralP!#`xP>TE<)io5 zDl$k3d5O}mUq8XTfyFl~r9YFb&f2V1KQ$`*SM3vt#I`+8M?PyV5;XksID${kA^e(< zs!iOoE%0@g!1+Yo0in4+M^WE1SV3_1iv(9Thk)88+sp5GvaTGjr*Z7BbX-}{3rqT! ziXU4^phU-yL7Rui3AP{uha~v5-umG(^pR||QPA0GM-R>wO%wXka6)<@5Hp1-R7H{# zqRdheW#++7qgw2eIp0h7$u^u{x2FqUQ#`=yD?ci{c4q}<()UXv z_F})joOreC@R?)ckw7;sk#=IMfxY$)I1W44wqlnsb^y7T)aeaC*k3$UOc|~x4j*gl zZfA#gtdLZDZH#ent;Rq7n+KGCQ%-1V;rw|dB|zw}2MH(Az5WBO-1AI81+ix*7WA!K zmFV@?9?8vG<*pn-SV4ePV}O#Rl}2G6X$Z75G8Iag2UxMZ+(v}(ROm0(_IJsb4B_;z zLfpd^WB+ILrZ&>GPAG5la}xTs>tVBat@kKIvHq4-$yjWWyohjNEB$Y*Jvh}yAWnai*$_7Ov+B0f)ESr zt&~91cSwBs+=tXythN%vv;|j}u_pWMS?KvqpP}KDQ;Gi{6#jEq-b~u}f$%jwo!gM# z^3|oFfWSI1bCW7Do~vX$7hR2u2%qNdqELn^)axjP070nf2s$EE5Dt#82kVqEnrWXd1cnceLC11tX%Me~=v8A0>^UZQAT zYZ|SfD*pR?pvucUHTw{jWBupTJ+$B4l?+l8 zDW|0ZNM*#SJRs_x8hqfc9IxNQpl-+YNBckcLksKNkH z4d43@#=Gb2LSF||jR3UNQzRQq$D3B}+5f^D!(VsAoAr(t`M9wg{fKw}HdJy&U;nOF zgUtlgL@q;0?siuHIixyv610{Ao-(&r|^M!(YQC(0<^W{D*Iz_5QfYMFvWV#i)A1)=qCurTLvhI{$*{S z!AN+-L|L0~S55Foa1hS-8`X?^LW9CQL;0%rxBSc=mhY|M1;#T~Jj0CM-y&07x?v)6 zx%vM3K6kOD$?!X^h(BZCje!^6|ABHa-B@wt^A(Rw8+9R=8k057nahKAcz)K4@gVbk#N?64InuP9O;hUS3n)8nqT^BK`5IjD?mrK?+vmtFA*mu zgV|9Jb;18hrp!ir{pS%1^;)U`+bW@$e+Xm2Q>o*_#2$SlEmXl#2vH%NqhS2$ zJ%_Mvc{pvk^uz7LS-Q%h1^JUzU)-L$Ey6D{puiFIO3ko$I;jy^uY;ygN6K6~? z>M%?!up?s$HpQWqeb#rfVZe5n)!Solj$^&O%wGo_!z36_9P4L@NkQHS$-}5{jQ2lU zi|1k(G0^-*=y+QR3C}Ios^QJ?e10=LN9Z5NQ^>cVf7otXIJgMiK6`MUV&$*JNmM3# zZ3fIC-WV2yAEA9HP*8pl=fIt(L&&yTSN)w?s`R!~9}P5qsHzA8Bt zF?jH+`M~Y{nb)Q1MC`mpN}J|ygLx3wTQy@bOHj0CAYN{$O5h*LbjBw_-|<1az-FgB zQE7N+Yj7|CKOOd-k%`(65y+IR=wn_J=2{%CrlEo>M9ia5-=tCQkETxJUk@bXrOXTx z`7c4CqMYG9(y1l-g6^SaN-G}MmEp_UH1%TYZrFE0of^*!@X`fG=*{QhU*!7o_tYF~ zaA4_@O*gh$-Be$L4^u??f^%zdL0XH31aD(qHMTj-x)_^DQU=o%T-?bQTtExc7kr9-jDl*N zZ|}@v7q{GXE5QXxdqQo|P_NDCA98=WD|~dTLM)MpDY`P{`j+x>f#ma86>xB+?FfUg zcn5h@Nr1+!1P~@wJ)~Gtf~?i5JEx^U>@!?B%tnzfNhG9yU_G zhGPYhyrCKmUhWHC>1ffnJ;*RAR}n5?43HwQ-u`TSMjP;Mt|h|BpgKJ$(Vu%i6AYeLbIMK(Ec5u>Z$}z{C#$nv|WML;u>6icDv`V;?`#NxNqk0 zR_@CE@Th~|`jgdUGjP5r5L?+(9w@uhzTpt$NgTeFn`GSBLq*mtSczlPq4dHbHDA`p zxZcRmx#*IZ^&5W-T#>vo(Ny}&AuKRhngL*Yhw6szTnfsG+^;Q zX{}pVPcd>K!RK(*2b@1XZNR|5=kSR%Bo3_ViUo3{)qvzE;h0JRA^{vxp}o>hNJipM)p08gX>y*tvs2qE{2l%qe06Yl1Yiutkbg1d zA_nwy2Rr}umugTw)S&JxQptwQZvCEZVNhcGVYr%pz$+Xk>_6Pu@2oY>;}v8kOvqDi z#cK*5mVJh0g(dLgk;o5&&WGi=^ER%{&1!Jp`|AG2#z9!Gn1t=0pO%CM1U83u<53ga zDXalm6Rsp$ZRLl&AEEq&&ce4!+fn|LC)h3j-gNqCFqiRfX&Fz7j#w}^JWN{AH4g& z@Yekf2g%n7x$*D&dVFS>(|_a8i!@Aq-M`K4v301K=JuLJzabnN&etsPXGJ9Q+VSLCNPw4=YH6QH2US!08@wF!s0b{36!zLEU z_ZkeDRS+)Fk|-jF9Z-$% zc^L6qSutEE6_3*zqhuXU4bVveaCL4h}(C<6w|GUf{4s#{J8nkYZY9)I)9D8?p zkOlZE>a_T@3SG~sx&&4zY8nQ0juR`y1l@nLPiLV3TeUDdaO@=IH{cF&e2AE09qi=jP|E4Hyq6mvD7`RfR4WB)dU z@m~Sgp`GT=7hlI)QmWTqdx-HJVAWPLPcNveg+yAY7$6w5Pyid#_u(=SzJaY|m!PX} zfF#zfpIn*}?3?Vb7&lJo;$0|X3ptWnDNzjHGTIM)&RZdXLBRM%=^$aR-g49h9Lu zED+VTVvg0ypG8sub`9bv z+vJ!htJty32#VsSWmz-JCbK?mO|V{)B!7GO9NMFZZM)Gj{Squi)1w_t4|duyJ?(AzM{c(eQFSe_QF-Q3i53{>Z}S^eS185N_@Y%IS)T(PMy<~Uu|EV$n5V*# z@8RL$Ae#)Ru+HL(T8{&MuZ_pp4{nZSeJ<5u*Ps zy4T@f(f+vNVWKkNBz%y~B9z^yccbCfZw;Vmmkl)JpLLWjAeuqsK zO!Q#rdcpMF^$}rDwZNGyz!YGO1xAu>3+4vChLl@Fg=s?C<%VAc-eCF|fH|b{J2r-A zlxFyu2@0S>$i7nTQc~$@nKQlqHLajNwsM=5(z@%*M);iW+@#>&MV=)UZ8cFrBB-$J zQ4pS1_c(0nGUi7PpX!bb6H+EmeyibfzLlm?PBpE;gmMG}1B(bQ?v95Ph$~Z~Ew1=x zj&>)yz)m{qPqi=WY4PdI8Vqu|fZctkK8jTa4$@X+(xyjZbvL>@p|{Y2-BPYOGY$T5 zoo^Z)+{%|(jZ^Pngwq(R(|Kt1(Qn0_AjukzSPgGd7y7ef3Y~WAo$T(^wQsXlDq|FYF6vumFmA`A{ z^JXow8ta1rKLL1p`U9m1MPYTT9sJ!)^3@WxQ!3MNC1Fq9Gl3hbI%@%8*h(V zqemUGJA3zU_0}DLAEnl3CSY?XOhQzdB4a5-tL{qbP@(PkLvaW1o;b1?++(`l`Wnau zI!TLM;C|^f&SCJo;&V=kW~W1_g9{Y-?6@NR5vhCtId7AJ%?nxtz%PX*4=loP(E?61 zx&)^V!W1DnQ(zY`g#gB>8vT#~AKOdLbem)Y0O$V zKfCA))QcU+06lt&t||o^V|(nGd*fD~&S$3bJ=vZQtBoH{4;au1FtZb_WvIgHcrApF z>FTK}zv!B^nm!ibrOY46oYFCHUz&&ZV>%5!xL~oWLV)IQUB_T5);ufyVkL;7RqzYI zz(f54(*VD~z%mIJ0Eb_oNM2}KiwO#pf8i}+$G;bBGl?w8Kf%GMer#fOwc*bMilpLm5Vl~vd!al zn|hiL^s{AGr>Hg`I-hNFt7>BC3F6PcKG8Z64Tk>4U##Ekjjfi&T+u4^Ak!LFX!lRW zawOK)I6fdzrTRep*sGLRe9j&sQbFX700vP2#Ge7bUb5AZh9}CQMj1N7G32YjXpcYJ zB^_!{qBPK}WF%0YsOG%3++(!d9~2zxLcj%&_#bybdeZ3%UP%O zA%0<>S{!2_KPF#_CdMyR3E}E1B$)_0V4Rr8{CH0Bq^Z3)QJ()7k0OD}FbND{RX{vA z$j1=@VE$DI%01L()(wQu0pkCiX#8(-@Q*#rVUH$ApzV2K5;!?b0!n_)xGItk&=y)1 zI=IzoHVY&GN#ZJEv+Z@Wngr(L*d%ab(`KuChMSF~yyJ9>AUoAuC@54>1gf|i_OVS6 zpHA(o7FIzgIcR>7?dJZ(iL5KR2pgkX;&@;b%L;LFm1Q?s8##Vq7%MOqo^^O`9TJ@ix4 z89b3D66I%@P!+@CBQoqLc8-yX>SN(qrUeGiswdX!5v)P87xL4i2{Lcb&xLs}8tKUY zn=!v2zEC~yhUZol9?6t|_%>_71*`|QL#P)b8p4XTzEkr1C)6G-zo|a6O{&Kv5Drr~ z9>4*fbnrwzK>#LxBdrW&803Z>P+WoBV0|^?>qajo|G;NBi57CKJ|ZqcCTkp0U|!h> z|4qlK*W+M~?R(O(a(3Q(xOlUEnKl5f)(ID(*)*8LYy;W|+o1o4{m@m@{a;Vy6cQsv z*84xx@^*wBGY{^vGARK~*N>kG=)M~c5KX+v1`)@SOq8S7QSk+wH8FLLLN?U>=W7_U zC7_6f(J2qPQbihY!o;kJ!l4%&*+~#9__h_sikcr42-TpVUbrij{N&UzJ)Hgwvu7jn zU%ZYHBb;^VSIk$Ny$Ba){}9%%=FH=3@F~!tp`@{8W6`~&1M-7V9$|k2DFsP)u793n z9Sv13f{A?Ra5xcxnn64HqHKXDI+=H{B@9!9CshgxlN{^KENV|-xYt{&85alt!ZrbV zNgjZ{@5W;Tx;6K_V}iH%-xfrHy9N5LAb_Iv6M;V_9-nzVi14?LQ-^^Fuih<0I0zSS z*2mL&^+h_9P8e_s4>cKdHMicjM^(iP{q3<}e6 zcu-c=KDtAMoaiJ1-Q*eT6VfC_0jx105c8s~tNA62knoqJ6>zF<6tu)ftt_dIE7_7I zob`f@#*mHjNHcJCNfdtb)gP{3&Nw$VbV98JFp9rMD*h_v_z_FOKNz|ivf2_!`L&3k z&?vY0hp2b^8}SC{AH7r1Z{Xs*&-&Os=M#RYmnr~D=~vr(#KuopHipI=g+&$q)^co3;=9KaiONL%l|zb!TyoXibvMqxtA&~Z`!0a=2&{%^U`6QP7m>*S zK>r5S*T_iq>WW?jBp{dJIn9Ye_{x)20>qm=k(Q|P%(Q$nU4B<6S_`)b1q%uYK5uox^1-B?O6AkuIcxBGA$Z0;Tm%0fku> zY;)1tlWe{U&->_A87iSHDN?AYZ@{5fdizBcU)gHY(UEfJS$~L>Y0*fDm}MgHvzZQ= zW5Z9_e^%f>*v(ye7g1}vKK!^iZl#Akho@uJ6PTaTb3oBXYTdupOROpEqoPQa!5aIV z-ji?|D+wmO^D>uE1vj16$-Nkj-B!sxjcwD_Cc7lg>i#cq2B25ET-6G9SFy^)pzMFm z-{;eHjx7n#O22GUNWJqKxQM61avVBsKQ zgPOllViwNpCf^ibiX=@!bM*p_6*vTUowP4z3H3|J$KFV#*RT=;1zPfXXaT>#=?3Wp zBQ#K*(-w1N4ZnrZEwT>ZwNC~Lj(}|(7z`0K`cy&%u)y{WEU^Zrcp5y6?t|CjeS~%R zOdMQ^`?^6Gs5#wZrDDW9cCa%ChHzTs2W{GY^zH?ouNwGB;L>DpcsoA?I=!3x>8r8g4B|} zs9;LCf*Vx@`))@CH>e8cs|vFFG_OGD8`Ydr(g)R?tE$1~7?(#?^E|3S{!dlUs21xX zQZOfnJ4R_^tvMaR$xCT=9coc_5JK*yIq9n-xyuG6O^>cnsYaaZW1gMiPw=HU5Fl$BoiB6jA%sRXP?5)mJ3go>KGW> zO4UJkav0u@+A@_i&~rf!=Z3s=pEfr0$W_&H4aSSbCw4TfpM7 zZUEg;5J-I!OKcvP#p#$=o0U}XpA!TAVqyyt#Qa4sDJ>a#1q}=mIwzU4Ii-2#C6MML zmnvzFBDCGmX`rTe_Cv)KtDe=`^4hZ)I`72xi&>l zfbcCN2r!@`F4!%`4|*ObUunbE@FfOPD9+s<5nyJuu22dxpvq}TYa0BZNrVr-RhmXR za#4a!K)JT2u>~hRj3mJDYB+F&S1hW21BfJYi1s`UP5?Ii+NlYYcThEeN5$Z|_@9Io zM7}T?!M$79E1(a&Das}H>|v;=_P=V`?wD2!Fx?PdoPId`qx29&KrZvZ&pu@s;g(_a z*o2dd4cSigR$3W8_rjmj;}Eyt`nn@T90cg2W4_*9K^D;NtvN&CMO!11C#?A*e=Oqk zsyQ+c>#?mxKz?;ow3SRirxGH-!%-I_o{!woq4+0_s+WInY1sZF)oj3UNJaIy(gYUb za5QA4KKWo;)XIB1EKF(2w9l&We5l#=L|HWfpJlvDhahHPX6Uw7Jw*SBt{vUZLyl4R zT;(?vE&FMy0E@%k{hxd5e!Ifk{bO(Z8rwYfWqpO+B0NqsWL=W0U{J{6=T&q4liGSN z4B2>Z-S<}vF^kWHemE`O*mQ(VvcqJv~b7yU_#L%h%|oKW}$DS1Xf)%|2MtwG~<%5w?>w1}Ozgm8ZnM$K%56_gcke z-TByX)6u=8_X+MLed2rV&#CH@h%9A{-+uRQi$Yx)v>Kq_^aDU~o;~~r3*;8(v*9YV z2__uRWha>` ziPkvXzr=?55!1SJtN7!5C4Y;;{vq;5t;WX_?G%xiE}_#H>r0bpu- zq3W&YbN(!)SQn@MSt6OB^$CR^$rT=@ADdN;V8ViG*oX1ch8ASEZe21C=@Zi3D|WS> zdMaSN;Km0r0?-erZDku7mO~hb=a;twU>?rkdsoxOAd!{tRaEnmb`z>Asm)>^;E$j*_JOK) z%I`N+)CArOd4TGw@SIH-P-GCH*p=9hTuBq`<+a7=Hwepm>H$)f9dkPqZ?g_g>n`&X zqEcNIEXeq)?W8`cgmw?8siJz!gep+gT24C)EL|k}5*BKwwB^iS+RzpC^g%rwG>WSV ztb25YSS_$C(%YKUcCs3d3x(NrP_8vr%sAK2Yhc@F$g^$MH}|tswgW?rnbtyqwHN3z znC&O2)dzG&c4{q`ZV9-ER$&BsgXE#uQ4LJw9ePommTcEe?MFZfHV{yQ4Ys0LZvaz| zYSA0`#247zxA7DELHJvZw(>Q^;%cJ7a}46r+R{nUhvyiCWN2fgd?fvBQ1r8oi^Ao5 zmkEqsQaX*PuB0D{Rsww#k<8%F%EOg(G)8{gapCjSwmp<1{2e+XL?Y>EB8Xkl(YR_w zM+#<|j!tvvs1FNnv>p_M2^C2}g?#Om1R>R;eyd2fDMS(yJRhn|!)c(UeXG=bY6~IO zWL>6fj;>J)WkpdkLQoVTK#EF~c2vBUv1vCkP7E7n%5+Z0J8=(VsUN4fQZ#!fo5h09 z?e{67t6^F6c@eIP=)5ak(o#-0#G zn(o+W1l`S3XoL*sxnu6RYoz2y-X8Df2DWPvb1#vvzRKQ`VP<70lAHCz9k+8IhQ;#GQupCXx<0_)m>8uVypKb_7;Tow zE1p+L`KNWr@fVK zSIRA%PoG&uatq&Y$a+R@F@1k$jkTZdvhK5=?zRTt7R$Wc+ZR1A zbxp=HvZm0(pl?SbioQ|vFPE{Pqd}jTLkZqFiW#8-v?%FvS=1x8uyRZ5XO zB@msy13l6|)Rjsrs+OIF;vilW(nHr zaO=AoJLAL0^oQwx;=?(q`0zUYq338HVmzf(Nk{RE3-Cpg!pp>(xJ_ATR%`!5z zVuY!qEjO+yy1n6S_Id(->tRpbPZr0zaOD za^*imnt|?YJcI25a3ky^?uZ`80gU`nE2!{D0vfAuE>#{`8ZIWju>8jLlz*p@vu(tp zLbw^#OM7Kny|Zf-_*>iC!xeOOi$Myi|GQXolz)cWuO;o-X(#8YegCFw<8o-q>O6#P z$d5mVS_@r&km_af1#CWWXQE;1NZPOnoUS?4S}VS(`O3%$UI@+RZ*`*C%$G~I2XQe1 z32CJ3L}CRPKpS?mRA$&aDlrFe^#*>SUb7FkvaB9e)b>4uWvtEgw9i(yQ+O^Cp5zo( zhFU^;Pc7SLD;0 zGSWX(TKwUO+B*Trg7QO>#fH}#KKm&vO53X zvel}ZVx#~L2uCgLF|x;e#Tj%hVcF~lC74Zt1#xLohg(EgVN|4?g^xg4yS^k$s|bjt1`{@;=D|%7O5jki$>DGE@kAe-#{&7*ZUoM7 z`7{#?$eI4^e&M1yD9U-oEXBM64bECBF*fir;zb@Gq3^~RoPQJk#=sLpzA;$9u>A6k z4YXsndJ(hj$} zE6Ul06_c-|B%0zeN8vH=X;^J{3$y4e->~>eaA|Kr_>86Rd z7JCXhCO<;~t;a-B5>i~|Y0&w5TaLMYQ(6wDmbCWhnTwfrE?(TsDO zze+Qz8fun>Ue-mx=x&lfqI;PE{Cr2WIlY9aurk?2bE>S1C@v6iNMn%ZNW#hLi~3b{ zi0fB1Dh^3x5-y}HgNBdoaOS}= zx7GL;vlV82wbP>afg5!u8>K2~6Bd4e9JG@f9p;1{6>_#ys?q&pW>QfMtMF75!*CB5 zv0z}E9glW^KOHt}ZV%9EQDK!C`ASgP)E{lz)`LDG^pjmOV@w8IlV#ryRGB(t0RhXOZ}?#nV^@gymavzVU{Uk8 zyK*#}g*5?fW)+gJ9cne}G9WH(EhqRK=)VuC`CV`0dhPG_Hl9`2a%vab61-!pXxMK` zV8#{u!gXdT#eWu)j=Z-9aZESrI`t-y-5o?{!1R4<%sLy22|DPFS39gp&`SOWBkR+t znc|93cBAPU{4z<7dvK)x3ucghXzZa58cHIpls<_m1^b&YrzHG^Re+XkW@7D2^I8#( zJ;QM9X~XeU$`J>SmGN{xMS(CAL*2D{2I7xqJQxMPDGP1*&Hn3u1HXBw)H++&sp0oz zdmDb|$E>qq${)gyrXnCf`PS~GDEN(=uHXkXLJCE~kLpj)fcM3YBpEV2SW;7US4m4VEJb_ajGtDWqcWe|*+B)o@mIguYh^W#UT4B7n~9Hs-Xoan|aKWnWJp^=Kd;Eykm2aVA(3 zf73D|bhu^TCRJpmAItuc==}a%zm;&95y=1aD^4e-t}IdrLq%qQNq~SKarq)}yndCn z6b0ZD#@1-jfyL_p+qxg-C+zlw1cPFR;B{);&X$pj#u7ewm*WG#rGOz&7nlQ8V-pE= zddHYN7$OcKGj|6<)8SH3W8HSh9_t0o-3)4cvG$*Gd`zX|as5X)$9 zL&f~l6{wB14|S~5q~3x0*`W-tR1L5Z6=)vvQj%xtrgQ828GFF?{O2j%#7TC`heItA_!&BQ5#Sze&+CFZ$LfR zg^GlB7}H-|_>7SG?OoSGzHR@DL)7~Y*oY4AKm7yzrecqAvPQ6ARU!C}qarvTeW-X_ z&re;dqwss;!!~|T$Nudwz@Pf51^jm5=#B}$C!k5|rTbKK8oy_^vGM!*=*Z@JOLI-| zyBMJ!$B5s`XC3^0R(x#ueNFZzw1D5Ie{31Qr$_`!1b(ZY68zrZnfN{2%fWB*{^t0l z{<28vFOsIIeD79~7dmMf^p|@1y-<4#m4YR<5cLGPp*A8nHTKP7`=%B*?j?CSRZ6q; zXK&xffn-zvOQk!IH!3vr_9r}%S~Q5osgUkh~0S0p+HEU_p>DnlOI3r^&v^dG?5RMc2xRYGEACcOzHTJ z^41`cqs=3&X0<_^n;W2|tV2V5W8NV*Xi=y5YGuU3;Da!i7O6iXl|y%Fbie2{JR#r< z+_{%tSWveP+9MM3B0;7)@xEenNdjh|Y_Z;p|UG#fnMQuq38%B74F5x8bGKYh? zF>U0i$sLB}OYMJZq@P{^w4l0TV=xDd!)=qwd*%don zv4GChRMRtQsSSnXxq0DKkR7cw(JwE%o$P5R6B!0iQ09L~qKT00>2f}~IXYeM4tV7x z${N^gNRRdu^iGM0QxWI{7g8BXE%1^`X#x?U=5zRC z@mvJKBKFVJ5uIjK5+9k5d5S^-GPN-78tS>eYn?!yoZrIK@v#m3B!%E-HJw)gY%P8{ zhE6undD${Z^(}#@N#uPTqKsfZsGeV7voXCY(jmu6RXv5NL!ibLkBO=n*3Jezoz)MO zf4LNu->ECtQ^qfivTFmCmmQ_@&^&e&c783d+VWw&bUiHN6^741THMwA0S7{r6m$)# z39Ik$Ut0@qC4K5*s85PHR*-`DQUytE2x%ZeNJ@KpIlp>cMVcQ?#M##fSaZis1guX; zU^jI&PzsSkcNRfizXZ^@r78;4*WYJ@dJ47}{~@U5sLooBv~iWtpAiY}+t@%m-GByn zmdSdqr9WVXZCr`SL3Q;8#Wi+{E{R8Ywr+buAME%DyJsdnPB4S}QNRSJ*^&fQ;*K#qx<+v)wO#F z4)7WjtMyTFUJ?BDObYukIj-SCYUx0mtiwq)v}&guo*idR4guS6(L$-_TMRd!dJS3{ zpXT8gXak_4U+`2+g#*&Mfd=UN5XT1qlM$ha_plZ5bXyV6Xr_pJwCcaP_;k_2Hm#>E-0Uwc4|WF67-4@Eoc=@vsG-tY}4ykDBsBFjRj=BG)IH*h*vv% zX*_o};fY6W#e~-=1@UXh`pW6Vz2u~-QE5Dthsu5;?1+S3o1vfMc$0ESiL#j(YRR-F zgN6JG+Z}&yxMx8KLO+rAnKV!h`bpd|=`3>27C-@`7sP3r@Cm9joO zqJMW;DE7y3f;GH8gP4Qmqb(1QlFzU_E^Pc!EDw^*#$vd{VRRH!OO87 zM_^^(ED`9=>Cl~>){$NmG@J>aTFz=)OQ!xj!)@!&w>x(?;?6E(jddR9;Z6y-CYrQ$ zwG~^5E~pM2Zh3Dm-{|JLE{-!iqWyJ9w91ih)q zc!%RdME=_=y=J$AhjDz!;(q}4%I(RxH{_>z5i>?-86M&g5J77>-}Kdas`YJtzW%rGiVOU4U3C; zm}Er$(zBrwy_e}q#Ot9FPN3j;q(#{%SryoT?bH{6?JV6z4v&`Z4kPe^f&8)m2}zc=AxCaw5F=3pCi@APj0bjpgp1@UxpG^Ead-vx1k%RQ*c+JrYUVrxC_ zVhe)YJ+TErD5V84K>mM38P{tS|6A-ejO(4e!nl?zI9$>F!JL`JoF;pGh&jolrz4-) zcc-uWIwSr|um1p;crt6U^;U3NJ|zUdm*oNaj|zRkDsqr7Sk33i99En{CfX;3u)fo) zF?16dYyEl{|BVf&=q<~LZvxPzOXX|W)740jg|l;><#)jd^*rAl_YhJiCgIu)w7)Kr>;BVdglDZ?)Sh3}1Ydn$YJ` zTO>KwfWNMm;tx}s>&9vd<9B8L8~0ZV1)K8cDKumDBm3qX=3V>9B&Cj23T*NQ4hetb z6gbXbmo4}fakW_RL5}yG>@?v5#l<5`ALczZtp;#f$OZ+o9L&x+?#FQ|k=;1=adRU{ zG=f{kym@;(PAy3|0e?E+RJ9EQj)O4$5sH9k=2ti*d9@sp9C{i7N|1@%Gv-E28>bMG zfY-kYN}49?z^9r#^t<4Rv>hKovA#-%tBH<3Ajp+pm_H!Rm1CGcAkuXXW{lcYku!>4 zKYec-U605hOX;JQx$?CB!t?J6LE^^xTA_3o6_FeVYxpAH=_XJD#(|ep(x@nIkqLg8 z2VLb}jPDT}7h5v?WoHYL;m}bR5S9L{^VfkJCUK3Ie=v`rmx;hK{&Uu;M;-^B)A2sK zLaxCh91BRaqntOHvAfkK^BTd`5d0x>dfn zR^SsmK7(?y9`79|CWG5VPC{@AW8u10DzH7qZ>T_JEjwXRTp`}-LKITfkctf)=n3_I z1l68={s1$~4txb1C{2x@!DVGf#Y!PnvF)1XWG%uOh1e0YkrLq7AmZ-2M6Y|ro-3wy zm0jq2ymfm|^ZvW+?pHreLebp#-_SVnk5+ER>)gQSFc4rWTrT*_t=v;`LT+Gh-}0|P z{#OjF{JuD^p*0@h0Mb-nUdsrMiaIq!>vEEr z4XAJqc>M+y1o`=y=nb1_B~6@2FtDh!!t-=GD|S~;EmInpo@!0_oz(&z)b%jRGJIpX zcQZjst-EqAYp^F^sw={f#G8%ZR>f!j0TC$q4tn{&kOKBsi2?#l!dRs1-ko_@hR8>r2c2wT=|K>-Q?$<9{T*LVp3pN}2fLll;4m*zYyH^8GPVY@PLE z9OfSD-L}kkF2rq9ddox(i5#^gMAcA5!O`5yWYl(!b>}vq3N?aiSQz621ZHyXU}3z- zp#Fi3I4B&N=S0RSZy)vBtxCULNu-wVr4*rlOZZT~l`DjUFd*Po%jbIW!Uw|J%HP=e z1P=)kc;jpc=#kn*ME?V3MD0^u$e9TKA>{EgO!URasS&CG?V3&2&&)G`g;yl;k|n%t zum`~Q(t7zCb_%Grvzpy?;ySe1^zG521_fT$(5=S=s?ayiq{a2M4fv%%G>R%WwqVC| zVAwgzD?lVyfFhHx0h&Cy&Py|J70#%Yf>`m8>)rbt2X%D>eD2@`%l(nYi=jqm|0Gk( zJtpmGrvXr*P^1%1VB%prBty1qwZqpuy<|wZW$a`%V>B-Q>o9)ygFY30ekN>XP}mlW zw$)kbnR*a8dJrOCBl^G8`QFK8YIjk08FGY-W8KIaf+^TtG+&)afZnNEv1Q+ZP1E{c zX|4MQ5hi`X*R`ll#wOP{q?U*Za)1tp{%(u-UcTe^dQ1v2Z-}G5rSC6rzK;PMsVExG zP5b{aX9A)BX7F_k3?P>i4CRxO(rVqqdhio|Ya0T(5Wp#gu#`s88_J8Zm67y&z@gt? zpl^VFW$gs?TPCB|SI}=F=!YzwL3+YkT)JG}O7q|<)Ksm(^@vQq7vAOl2aXu!z0%v?m(|W)c`_bh=VfBwQSQq2 zxG$UDZlJp|p54X7rn-GKd}M$Mo>84kmFt*PUohX}3l^pee!W?nr{3xVk>%6PHinzC z>(Ncj!cWeaivH8$!m#K(yFHJVH zY(Ov*s3C4r33q@K2ci)>wOI(~>)r)h89n1$87oxMEmq|) z>?SowLT6T`oxZbb880WM{BWCI?zSK->b^-p)ftICGXWcfeD85AScgf;2yNk>JfvGi za5a!5kHU=AT)bb#c`*+d8R1KLJtJ&Kd&U}a;2`KA2j zKMeoEGaQBni?ZEdYO}tKL7Bh%O2ikz6Eot4g;w_vdTO#-K#7pGteR-qXcj_3OrYs)OsVx#{ z$_3OWT`^r(J%pj|yHO4GB55G$%}>Rz7jvkNjE$)N4!e3VjpP)R+;D~0On?oa^9u;%vO^${4k&3I zTuA~EKDT9*@Vngvj4j}jy~1KprSwj?L>Lf~CofU>&>O{v*HJV=<|y|H;PsaoP5BTq zhxWk`NFCusyYVmws*l41p-_OZiR8pl^1ex(2Zc7i>K2n2QXi8c7qLsazKl_O~HV*rm3ANW#@oIB;mdJvkdXXnr(f9tKYsnn^XI zICuc#Y#Cotby9@_hMls7a-KXzrOgOl3EN^wGPufm?qk^0m9-@jh^Sun1={B6IEQOe ztxA+|tMx~uIu+%}bY(n%vAugk6#ULTuH~^cf!}COUye+C>fD&{d+&au%5MqJ;7M{`um6aL>py>;1rIyz zpR5D!N~P}(fq{0JFW5gB5)m7#L@rhlvT(?{XXk(*eWrJ(7r&N!@EGTpZ}j?Wcj_F0 zef>Kil{&{Q=hC5U+;e%OY2RtMSmK>s+F3sqULmU^$ZKq8v&0P1HO zJdG_5otJwEp?!E(G9DYKr3d2wyKE_av&DmmUg2%3rW`MnJEaC{Z7Hm1w~;vY$#CZ@ z8?KDS?P<$&^{57l)?61w25D`N2}PrRi9}INkC-H|@jlc)LD#QI;GWgTRR1p$Y-zJ- zPVD+`V*Lra{_cb#j&(l!UT_K%q+s(`6m;(17eQk4qw3$8-n{?e8k8|%YuXW&42!6Q ztLD*@akv5pK~Y^e!TDM&?V_3MNe^*TH&Cr?=MYkk0~7V?XJ9!@7}g` zYa{DIcO`WlrCV2*Or>I7G8q!D*S&z-d;g>G?p1JWHBI9CV|H5cPnfJmbEa|l^Qp6& z1JCZFRJW5Yh)$Gw3EDI}op4J`o#^_1K_@Dg?nLWE(!RAIr3J-EjXwe}OMle;YYJ1- zb+L(|Z@N|u{X8{vcmI}2(ov79BkCV**Dv$OQ)e|FzbtcD$NjKFMI0;s{m%}rcxclR z6R3!sCibPRI8mRVtgy~p&#@fc-n12J+DQB;RE?uvn#Pc+^^xny63ugT({jt9=9X#w za{nRG3MyplADvbt#Y`eF$GYTUzQmmWFhPe*@8g4c$qN4EhcZ{~xD*SCW~ci{&w{wE zFYeWlU4H2LPu5={PiG9}Bv)VDrQz)ILzN@H?^kjf%0APk!j{kVCCA(A86K=>q;qnf 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%0DQLjR#N|PWVB`-+Z!-nV9;gOw$0osu4+qU{#y)v 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≤8H7WXArzUrqPcXUr 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

    Nbg!Q3m2`aC2}e-Z{Xz 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

    VW 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

      &TU8Is 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%0Am%wqnO= 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�uroFzVP-nMe4kfpk$g)a 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%0Ansqq z{^%QXt`oC!N{<_J`JjO@6d~7Fs8Oz->HG^-!Ml$f3-5koXE&ngYNq#)OPQN3BUB?E z6wZu`%O(K!M%uX3-k@gF4}?^O@9#S?$$y zK4thx;gY<&+PTKmBpQ-ZQ``Bf4sW}Tpgrm5WNuB8%SRxY3h2qp=GEpS2?D(^SGa;- z4a)wtanxFMptkbQw|+0Rn9ZQw^;&hli#)AWcYRDNp-ZC$pWOgHU8kax6Muia#<}nh z_Hc?!P=AxD(9JA62QPnE-=qpDx2Lw;;;Jk4H_lTFI_p;Aah6MNjzq_acm7qgj=Eq= z8$-N&`&q0{I3EZ&v3P+25}HQ*s+t3?%lVCQ7(|#uf#A?nccZ`M^BlbA30|vROEM?h z6pixsYZ#LZ9FRg66=@lpC1YLJBUyCsI23~0(DZljDZk(o&@AsdI}s8bD@Q*+|BSMW z7`KUs-No7CUp@4gekylAy>}-+-OEp+wm_q8rZ?=iZgC`Pwx5&o8+JF;)g(a?s3NyB zyZD7~ee*v2Q-VjP4N{(LV^`AzwrNwAB=S^D>#zk-& z6ar$i<@sEN0&;D$N?Zt=KKq?*{j)(743G|X-e|-cTUcs?=5&kJTPj2QRBYj9;AyRT z{RFWr=A{S2`WUqkzK>8B%a97Ma${`4HiJI&7H7x>h@8io<~lXrddctBOTX|Y4J-}k z1iu*N$im-X;JU$UotK}}lt=hWcJ@LH4U~N$7L~m*Ec>n1kkhG}A6iw3KQTcTXBR-A zx~3ltBiKmmm3`$V&NrttR}5_-c;yt4n#<3LEw(Nc8O?!#R_$wpk-&yavg}c6B2=h9 zOucEl%WRp0B{n|PxFzg&hb4GxlIG}W7{_66?K?&ysBjYxcQRj-y4q#vp9@wie`ey- zzy>D>$yfo$IWb`r*0xpzhfyIiU1tA^z`fdPFTBPcZrp;uG_UU$2cpL6pg~BZnVN?F z65ROhL7WnN{>E%3Np0VU3$*QToyXouiB=KCp07Vpd$lH5wuW?|LkjGh!HFptm(Gn* z=aeg<(`9fWnl)L2x4t9_%Y49m3Ws>uk&+o{GCF~ zaqi4%O!mQG%UtyGJF}Y{l$QMHcJkvODU@7}OnZ_aEA>Qv*b_yhUYrN(d-e?NrHF_+ zy>tDuHt$LRWX1{F<-~sB;8wh{l+!BlKwy$RSV-{O8Zz?GWb^J<

      6Qy^Rs@Y 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%0A%V5VgVwQ^{SSdVf8J*34r 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

      dTA*Mu+mAll- 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

      s^gW=>R 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%0DMtE}qpS@6m5zPkLALkwN3;b5xaj%S7su9tM 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�S-#J+p=a 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 z%0D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

      7!7)#KILnDkjJelvf?@1Ki+Y_>S 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ð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%0DUzk55{ftjb|R>D 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

      _Vm-5=}J);`}sK2u;d!x%y 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

      |agR@o&qcR*ERc)3aY$#;RNv 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∈|@q8WnXE2ybbk4fFS(hbC zj$={|>N|R&amfRXbi@M@3a92TlcZ>TelGp9<}XYXO@t7yokk$-0rU8-hP;(4t8IJ0 zjCH5~2Hq+OG=kCvv3ZMZrt$mL^5dovMAVWWCHv7EFNz0ISbrv8lni1n>d$1MfIEi_ zHGd}4?V)zFJN-A12zO$J?`ji4PEbVgk+ya42mfEbhP8+p;Jj5dwh%)7blBlgdsXy z#B_Un6uHxX149%}ZUno-jt{v2zVY$zo%FuLA44gBFD8?8vgB{s)##m<#4cg4MkXsT z%7bJ&Gpm0D3ynldEllTGcbrWU*kj^Ke!h+?_e;2P$MU_ITLJ5b0^^e0N?SS$Q1?pr zxIZWHGnei!iT%nNxXu5Af%_vb!Z})w!TM=ZBSc*;ETiR1_2I@B8HnSnBge<7rCs#+ zC>sVyFTKq*DE{^{AT`|lAPe+wWEpRbjd(3R1@6kzn-UnzrPXu z-RpA+lyE5iskP?smfi=sgyuwki?#lUFU9%}+$1x(82ZetE)lq7?*KPhE1Q255KBwc za(#Cq6YtaOil*4+3lFP!q*R86BZ(}9^+_`}($ZUzqI2)*;^x4Qzd=2shnQJ|#UyCU z^Ce74(`9;{=_(`Zli5sdB8{|}c#FTzTRMO%!7kSMbXgG2(<9-*`&rml6Rt-==qIan zTH<1+S?gBSmzBP(Q;yxo6x%@Cg(-BG!#Z(dZ|Wz?|g5BGmzyC*49E!izAcLO28j(*q?+_VV%iHl4s2F6Wn7qr~y|NA|wWau6 zzLlS879_d;$T864ZuxWux%W`?`^lnT!o(3AjL@%}+WK{Zbtc%%I_*5tu&qUsr?w0KzN)EsZxfsK zNUq693(e3elg}VsDCnW<{__X$$_VgE?L8Qe6T5@|JY~m&9*=c%*WDN8Yq3$Ab@M-2 z*d7+=@N+LJ7?>au-4g^U-Ek-L+9YktyrlHQ%iLA$`tny$TJ4<>o5&cyjKAR07aBh5 z`QbB?;!yN|78%IDO(te@emx0KWeALtHPay;$$AdChs^o*={8OIIhCKmoJ~1-itRgM z@+5N}vy0?yk5*XVThfLkdlu0O9CM3Wzs(|9T100q!RMo9PPO9R*d&X2e&B<{(T64- zJ-)F&(1i49TE;z(PnWto*GmLw_P%Z|KXWXC=c;#s=YB@N*A8sNzC-o%?VCsn%f55m zcPLVgB9$WUhKUuy5_k8px@W%lH8gp3d?Pg3+b9!h{t+L7#`&jo1ZflRs1<#I&-XXF z@aapK_pl!wmElz6nI>ie3$GVyk>~x-U3q@J+MwPY*9fLv8Z6Z`e(xQw|9QezkB{*F z5c_}KE$nCu1GN(v90Lq$i;<*cQEux)KmQw_^EpOh*!OVIE$i(YT=Y7Qw5UcOSBeO^ zb%C49o<~(jKOX*ZPa_nmYqakvOOBF0r&4}&TU`v&HW8nD`tSiVMazg5qJG$@#{8@_}QB1W_S8;z;FFszZSn=JwN_MoHuMlyg)?e$1h~J-&WxFZ^37KevDpR za(-;(NJ7q!t66~aV^YND1^i5v;;uB3&tALE#Ak=$kC@+|9@7Z1c1FkpJ^pEsg#M6C z{}(KJ`3H`0d9`Oqm<|bB^PUmd=Y*}M{?9NF4qk*MicakJc@0`R!2Y~YBeJ}HYrNA%NBj|Kw2 zfr3Q*#&nB;8(}o)AyPy~uwwNmlE4K@^fr6gVNCUnhNgk9SnXsDh%0{TW8jxY;-}IZ zvx)$~8?#1!aT%xlE==FX-<;J(jwkz-ui=VR4!$sgDL=i87o302Sznfgso*A?GOz3_j{@ho9W z6+TESG*Oyl0$FmWL*D*GSSjSko$p8Q$Bg zhvj>3uNmg;T2VNMK$(!+QB84-$)1V?5d7d z5GfIX4%c+%r(brNeU?oI;aNNw3kL=!IzI{HjKo^+H-=?;uUS{qZC-+6ny@a{V+~!WEDa`b=lc_y3O>a=8 zO0{56*D!aPle_i=o6KL2mNjG8AYy+lu3)Yr4Do_Nd9X!E_gD zcObTzLhBcU=$CS2=MNwnWi=WsOoOUeiIA>ZVv0YweVOE-G_p4H>5#95IDAx=D*D3~ zaUEBaMr!#msj94%Ryj(ba=^jg^aQ-1)1(A_z5y#a&;HB0#;MWPhY>o&e!{k%BEQs7 zem9eT772ut^L4{^!iQb%Q^X*{kawDj=mi|Tn z@wXYe%Lt53t33rJ@v4*5!z_%e8R=?1Ld}z^rl$LVBSPGkxMaIVd4w;A{pXz&Vh+>u zkJiBIm8Kdin6^Bp-gg1{V>UmTNjd~J;J+{oe^Dg-Me5ZD3BN;RyU{S6iw)j>M5ptd zmZgz&MKKL)zDPe#UOL2Z9_10FGmdRJvWYySO$H1@CbQ9s7! z68|{oI4p?=B@&oQ*Mb$o5tsFR%uubI`f-M!Kdy+zL570h6$q2ZOa6EgrXKf77iQ%1 zJ_(#E`d2|k&HLyjx}u;A$iidv!7K0}ft;ca3dvj9Y6N`wm{2kWCkTj(f0qyIifC$z2vAFIj!jZo1BA9lEGMGqtLb-8=(h`G z;Ta9k4@mK>3NQnc;lK(tA|Epa3$rooHRi$wW9Y*UBSXv0^n8|D| zE-e%xBg9oFz&j9xf7so!u#*dr7_?PQ8X;?FjhmvHe!EB-|E>(uFOBp|Bh;CM8ss9> z;5;LOc*$1RGdebyMNYkMc;|oDQTX9R4o~7(ck86$Ar+^C#&jz~6)N;Om*c4YA9gUq5fW-~T6 z61|Ir0n;$FG8ha9J*S@uP}I=gFg!LNhBmti)_?=K{!%)=drOM&@?A2!1YXjou1xC} z8s}WWR$sA7c3dp)3uRqqoh@6K?vsxaQd(G7m>BfOutuC^V2NRkfzEI|2+YjepeP6j z;wtm}z{-Na`uxDZ3j$x|^ORbsAb|b3Ubuq?$YNwLYMFbGg8|2L?2 z0H1~xQFK3|pmI>+*bawzxi|yr!$%zH7OLedNrA@4yND^Z@}}6tmO(G4p+ZlR?4<8* zP2X}V%;me}_yOoE%NNjBenDSNcienQ66SpFtyuK z$BF`dP<=hfncusr;}fmPTqRjgMV!XwvLL2osThmAH%~(4ymuMVTCw7uw2!S}{qB=r7DjJklx&vcX&cn*&r#~~JFXnN z|1xSsWEl2sG1Xd6w;WvZ(<)P=g0AHyHXKu_TI`$M+fW{34YqG|N6jgw=YMT6>lb~= zi&`a~5xNy&WI0tpAm9&~)J(uZ1q?V1nmSVsRt(nD!dN4K(BdeIyjMeCIq5GP;BwNs z#0VUZ^{qroDp3n9&lbQ-tQb}HGxUFD$j4CyV#{y=v8#wa+G01u#&xt*{BHy5+4S6O zQE}w678PChx81Kv&ok&CW|0u{>kH1)`r9&w3&#i>(SV?cRuhY$FSP+dn{U$ug}gli zf^Lx$1{Og_G$82OYe`T|L=e;_=S`L?4IsA3xdG&)!HtVIGbtVL%al{2mh5-}-5bfB z>PEQViGRR}cu-gIPaFKHj3qf;n!I`aVTbjZIHDC6qOSUKJa5d#qJBn13?V%~F@Qei zr%cXIAT0lY&lA_%<@Y4I%d4lbY)1V~w8GI_rvhzi zGQ1OT2KfyKhL^8&*CBa+^j=dnOtK|A+4@Fg10t%_NqYec0jC-6kJPA5@7pj8bSFw$ z52s+armlia6aJd*l-M)ti@)~BhweIcm%OyW zi^Cr}U1|Q(>F>Jv>q#jhN4#@9bL8c2clz`4sZf`{QC@gx!Kr_Ud`iG4;VFy?XK0Av z#nD)3rwnZY(!l!eNgRDK#y-qdAA^5R+MBVGE=}X*d+dNZDD%eWLTCYX#w)cw#LvtFm#K)Uc^$V5u2;- z(l`k~NG5Z>&i9}K+GHZWZtsDw+y;yI+A|?m-gGa%(nu4Lx4tvJa-${U>($w@>b)@L z*G+J#imqW<%&*@k$AaPGm|tILg1k`}zjz>;I_U4jFx#sZe~#w(lrYDKWiOvJ|4%0Y z8k{c|)q|4-l!CFG?n~5%5Z%(b8Jg4Be_P)Jf0!wQ6ES!-lZkzj%O7ycShY;2cem1o zJM+L159j5_Ejyj`}zo>#unjNfj>XE1siZs1wOuse?N$RI*deL~gvuQ*8 z#tdm}?vVY57Be8NlVw+-nMOR#N4U&tg)rs@aCArx6g<+Y$wx(Vl!NwNs_%4GnS^qH17&rybFlvE5ev*6 z*F=LkDkhjm0ACv$zT}wjos7{a)>KsqCR8uh*i`H&@XekcgN%KT4!-LSNxxo?SoF)o zLz!15y@-CktrZ}oWKiFO!Bq*jQE#nCd(qJ_HQTSRODkU@Xm@*21R!D4YXV<|>;znkH!b@wkU$kpJ{(OhQ-0BEQJDF;^Xu zKiU)esA0A5e;8I2ziLYz0Q>n}8?alT#;9)|iUC#S)iLNhE+$xxBp`oyC(qIJEh2p} zUGfj;TTBv;APGT7YfjgbtB@am#AwZx0p@swH}G`5)t=eaC6EJ<&)hhYz#oO6c#*b_ zSY5$t&DXWmu8 z3LC%Wae`lu2V?Z#j=@KVU%BSb#@1h}O-R^G2!b7aI0Fyg@Zn^_pX1rX=eBs*%?D0o zoAAIjt81?P4?LDM8{UEt1*&4XjmE)xY@Upn76XZnF_0M8kO^HfFvoK>+KsWk9Mc){ zA&p}%m17U`*Oso}|8drl*Hnz3G^|=8L@Lr}|0#-;wJ$isTg#tA>mPxsphhhHWBz_y z1YHHmukNh2Y4Ytapvm=S44NcGL-U*Uk2Zi$x-FT2MhVId-`fnh0Cs=1w#tUG7of!Y zcWMkUhg}gxw9v2CKOPEN@Kxd=8os|Dw5ga(_|9_RdlKt$tbby`w`$N)!FMSBIS6(p zr#HqwL!+B=^G}%JV#nE|eRP4gkM7_Kw0xHsDqtV2;g~h`FSG{B;A~ma{J9VJhv8^g zC8JCyUHpJ`S@`*QP%TP9D)UhI9)v**0 z>fO-{u!Qlimc0dj!2afsx;Aa4wXET&hVTAdk5kP&R)eb^a%ba#<;O`)>StZecUCo1 z2nB4nl@>I7NBpmR8=9MJXs#tR7w9@Nbsf*s4ueT`EGzIy1$go2`kc}i+ojKE=>wyP ziyEa%zi5@lyew-RY!dl%FLjExVo}216c2*GF1--f$bk&sU838@OfOq#1?ffp+~!W{ zN2j1PuExkU@u1h&<8=9-Bg-2sUns^sf9`6-M*A;z`753BJ*0fMt?FD0{yGgoHfzWe zTdqI1!l|JrYasmRNezfUaVN2tNdM|VsUl^>-m^hKF(}Ad4^RHw-gXr!)%T-{R;Xez z9@JJTuNE#7{9oRwTNfD%9T#RA;BOaAn#Q8UzXA^y{wQw*Ep{$nN$y^uPQMI6&*QnK z)%r#B`Phj2nO|ck)6a)TX1t4%eRc6=t#yo7gd@D5Z(QxIK6suUYk#^33;kN$J_q}t z4<5Hp)|2@?PpjaFKE7>4miSxo*2>bd$Z)AcU&HF1XF2rp7RDKn>=$)gjaxw{f6RVn zx@A>Wg##_A6XN=nG1rYseS7l7c$eFg&ySklV#IgPpwia?@jmO#6SF?Aq z?psY~v*EDr?@L(s)!})|e){e74dJY41Nz>c7n{C)`8`Zu-|#Sf+m%MrcmG(>m*;9C z>6^5=A$@zybLhK!z|qr}_>UP8xqh?b=#QrYUPxm1!qzAP*v)T;lB|4N9a#9f{8}3D3PYzb@TOfl?-(!74enS!KZAv)PnvN z{c4|=tI}!zluH5L5bk-+<{9^I?3PQ}?9F<|B-t?Utgmfq)PG=9=vb`hN-Wmz84Gq5 z@PYYp@A!^}*%z@Zt4Ez>bl$@~cSPabx5cPFfS|fHM*MPAz_^_2t#E%Dd>LPmAL@J} zAutQP?2C#lS?j+kZ zrWqUr>bvcgOG_l4tA>Nu89q`1I9_=&0*;wNw@2LcYWOVuHvmwkh4oXr|1P!q4|}!j zJYkPG)lzz}0KDP^OxC)G%4F*l`-$os!|uwzlPnoRmIVTiOL+w_(*8}6?c+Lh-neW8 z2P9S+ImedCRFXjeus~oBsA2u&deu|NuDGgU5b`52`%lSbh_##FCVM~|msfAJZlwC! z;0e=*?qW~H{wMHt1$@b*Pa^gAM4LXaGyupv{LfFNM}U2YwI;##el`h~kp!tif+#t7 zg!QLI*MHydS${@!{ipt(^=C%czr647NFVXYh@}7Zzi0h<(eO9woIf-;q9r z(e?NKJ?k%uu77)<-x2=e==$&bJ?kG4UH_@SXZ#t~^=WAlf_j4Ti9^g7Kio~+Ne6W|@jSItKewAQZWzTPiub<1**!9o;UFx6PX#G77 zU%z+q-%uPh%HtfU_ZY|{qMucKZ8_vYqZuu0pC(w)$c`t1ssC~*JeKqt$NDsZpTau$ z_&0^l?Y)xFgT%i_oQ*(b*jaXI*c_U-8N= z30>82rUzC~ZLn%FyQJHE@2qe9)pGe%to2PFw#pXtwN+8`y3OF^?^yBKBIp;ress}r z2zD^IzG;f}qea64ezMn(3E}nQWnClIH)+>~Y1@5xByCf1WIM+C=Io_z+ETwA`j|uB zcDb6Q#9;H0rCUf99;ew{@`9PI8G-~}0T^K8Ofzan3H$ChtBE&aBGD4bAng9fC)dNt(X!Z{$+qxPI1 z8#ua5$*Hi6(CtvaWa1QKh)-0qLl|Fd{rM>2*PAy-4S%;k4E_sZ&;OUX=l?0P)pU3f z9L$PM<=Pox72r8hg`T7eB=i3fwXb*14m$-L^GCHmS99IrRG?t@qsJfdy4=3qww^!A z(*G_O#g9fu=zuvXLvD+?Uk=NonOnBS-t6tPsh<85ss~KJ`mFD3Utrg~%k7Wh{O?p- zW5oT3=UMQE=)c82$`935B z4fTlb6o5a&rXMb#75jd^=+DrdHT^n|jNT>};w3o5+wm!O%Hv@!)|9*Jb5QQbk)Ygn z4>+(sb*@b~k|<2L2ZXsNS+o-R6al_$!UtPA{@C!1rf7p&!H@u0Y~V0Qasf`I6a)*C z#g63|z~x=4?OU2^nb?`gUZHMqAQ2s0j2q$~s#@59g)JQ78XDsLXM{6P zI`}@qc|`r|ojjSmA4OwleJ$>Bz~EXJp`G(1Db=@V|Adq(Jd`EtAQ0?-%Y{>DANmT6 zD?W&~d;;26JYm!R;J@hqaw}+mXTYKT>D?^aYyUlm_}+>#;7G(mBk^F#7w=@tf3E?L zSn!vXk@{D;V85Z+2=nq=9>e)F zwQPz5bxEepF~e+*vG%X%BqvZuIf49|@m2GF#Q4eyL-74M76eB;zR>H54ebvdNiUoa zg)mA=xEUMOGs3H4wf27C%MMAF{bOOZ4`oQKi6K6;{6EU|@BGaX_zhu;*82CT@%uIO zP23XE{+7v3`_sA}Eq&R(ck+TmkFRH$%>DcO_+U*0Fa}V*<)q{f2dkcohY@_}jECWT zfcXpi_jtRLZ}2}$Dd7YB&r+_&137wq!%=t#qaTPf^YtGvKB*cv(}sG_MnFCCCh*^IzfE!Y zuQ@>fYW?M?=LaHj@CI~1OFkXIQ%w55vC5tw9)(0!ufZg%^@%fx$x}B9{b%226lH`3*|uAnjkFyiQjpC zm;!Eh;g`b(_5ARC#?j)ZqxmP`kNd6{ z{ut+TpwG0S4;}gVJXHT^g;*Pv!~N5e4IW+pG_ro{X6fH;y^G@1$M@+@Nrd{Eyh6>J z=%6*^47*caXS3Q7VWp@HZ__^|O8;>7Kg7SQO-%o;KCEA`5Dnyz`yXSD2>yu?@P9qQ zfq&-dhk*ar%r7;sM)2?5;ikGeO&!(x=vq(_=5x@N>kpi=MbEqZSI%+US=Q5k<=J%c zUy&Ff@L$PCejI<#?w@>Ux0MG^vnU}ek6OQ_e~-EC(Czn*YX5ZIerM}UWpA{9jde^P z@m-9Z-pLXs4fCHm*lBvbcI_i(kv{5N{~k8M+)FTn?)IMjmpyfw5>q6rezmk(uE63agiPqcc4hetd46`p&rx$rjfM7fPzJkYA4y`kzgbnsd`x>;>;w>2mP=&_iBa}#?A)jwP# znyGFjXaG?$)G$NNTEwQ)aY-_j=_NLH$SB>e6U@Z|1Gk9}gQuMq*_ycLcZ%pl*Zt7O z4K;@Mtqt09)%(^@?<50|0`FU^@pX-{T0`&cvjMML4R4=4`2C{5+XwL=E{iu?tugcS zjOtLce6uLtJZY;r6mPY-=DyVcqkg&B?j!RGeAtN(32iFzFNO=c?%!DV6XX17w~s1o zN6Dfb^gl@zf|5&8Nhm;UtX?6M_4fIgqXp-~V1+a~dpvGDj_VwaXR2m#&cI@LQC=js@|hsg91huLCpM! zyWy<=KlDyMz|afy3&o<}0N)i_e5aqSb%_14UnzRO@k;nD7~fm*;$j8u#Bq8@H$P~n z&{1f_8P?8&?w^nze`7iRN+<(M=-IC=nj9idP_&fs8@9(0**qhdHCCQW=~3XR`N)V{ zb{eRoUU>Uypt+Ujcf^65edj-jDEkciQ=Wa-b)#O{PsJ_jvrP&Heu9F zW!}iVjNSI-1{=*4Z#`YVB#UiGU?y~)+2NN{`^Tv>H$PslzA;O}L?KVNB#f21Emkg?9>S5xn6_-u}9Y;#NKa@SKO6-5eK-Lg$q9>9Y{U z@Hz*EP45AQD*yw?TKhy;C=0V_qu9?UM{$fcifwJ|WVmLb0&`xv0%z$XCPNUCo*|CN zP65RG;jd}^A~el>`93v$0eoK5r9h&aooT;tUABuj-TDmz?rux?*ZD z<>RZ-)8K%yh^$(M%gH>~oUjx32dB;E(bqTAQ(2dp^o+!qoNB+Gk38gPeangU8SiYF zEg(9PZqC4w69EIGcPzumY-X$eYy@@v5>M)EIUO`9U1lWHbMo!yBYxvT_Vpxvpk_64 z5zaZ11#4;?|3CyIXiVp{3zA@Fxt?t4{_3%5>>;1V~kKce^%mB+@{LN)j&2!R?-pVr|SJq25}1qY%07ZP)MIq>@8GzN*;pe|sHLI^cb%z_&s zhNf3fDM;_f@IkIC%$@i|>q#OJFeq23u0-qy78Y^`N1>ug(hrD_Cf%9{bX6rxx)}E@ zYB(0Ar}G=ZOy;lY`OkrVamzZ8_~ukev!h6;qH7>{k+F)2zy}h}bK~&yaeyQb`p@gA z6uk|JSBPGjokIF05f+_2xi*<2+cQtPVQd zDyvtDbO@$wcnhL92r)ayVp%(s)d%d=D&$1eIJrMGo&U>U(5rn}t&G}WlX~=|l^bm^w-K~PJR*IeYj7qK z`;av<>6SGi1+3Fu=n1rH;U7HLial$3ZvOFHWco>c8BeZ)Y714I=OzqEjl+!f9|-J3x%8#V_LvXi&py>OXnB{@f zYbKN7gr(MGn4WA+TMMnZuq2V^{5bLHFX|_8T@fviqgum>{nrwTl<+yA)Q=4;QDyz|H#ISg$Lf~@ct42oU_?mu~Q1& ziO)dr?qtKf3a5`YjmA=4i(Viczx-lUvd0K)ROdg;fNpP!;57o5BhcM>ULx!<0?lhZ z>J7Su;1+|x=Q2H@ssJY1>K&L>Yz|8}&oF!9|3u7D`&zTCm%OQaZt!`Dn5C?FKs`?< zm%wMj+Zn=kS$lLQ$$CNotQXfErcUT_c0azUDfH@vis$}P)D+|@l zGTYNW0^UV{KnwLt$O4O*%k(s>c2Mu}kVain1odnIzZp?)hW$T!ZD_<1VjHVYN;8eS zH8}-Zxo|(2WZ`b3^)71Fte5XV*RoJ(0^YgIdyhV5^&i;tOT}LA)JcdefvoLX_wvc*>pNbk2m1=vy7nHs zwJMbWA$rY`24CJ(+9hx}0IO-3G`JWWB#SXw-)86~c<_8@rhaFq77153;Y=+De!<#B zt=L5pp&Bd4aD-|YbkzIe{XrnONgrN`s88CskrDrI!Gq`5YxLscC64s+U7C@s!0%XG zEFf-Ry(;;&?ym^;&)`U$!f(M*K#Qx?;5}(v>=f%@$dl52l8WfZP$&?ZSPVnG=)WQh z&j^9=X-EWu8hC)x02D7wwBoBV^kx%6hDwUKpvojOvg%dwSXR)$5F9j?{Zve?nn6>c z_!!Jog-l4qDAKZ1r(-(DMF_&U9CPw8S8__gRg_it!*~mwBknD&bI8yH1t?kBPzf0# zPhF>T&3a8M98w2z&1Wvtv;9%5WIM^T9^8(?(fM+6rvs?z$-Wjs{^RF}xflZs$e__J z*~w5oxlRfsV+c}7#*1pnE;duXdI(E#h&<_n0ItBh8l`fj6o!63#x1AB+oYD#9fQ|) zAv7}WIN6r^e5a_-&=R1i{1p@jWf}LiSmqP;brEsZ;cc->^5<@Ep}8&qsRc1Lq86~> zN6i+O8JGc#oUF(4p|upja`EWvqLdT_!QnRNd_e(PLxKc;>{Y)WYDrfn3jBIf^XJ|x zjkGjY=OrQ|PqDKN9RB~0I9x>DM&RP^y{#j-`;73Kn&WfKnHZZ`W$^qPY%k9FM6BC- zC#uid&IaM_vvKN0R8_l1HUh*y1AED3n`AR!L&U(hUO0X#_4wJ_6u6b|+AS!)q(u$J zkCOK}TF1!oj5e?#Rq>8|)axi}d7^;$51cTu$nYO%UwST>e-g5wLVU#KEPR4N&g?L3 zIt;TX;8iWJdj$KFAmgymFt#koXWoru+~$G%4Umla73qCLSxomINP~ISe;^(A$w=N^ z3yioW>CAf<@*-o0&_Nk!Z0G7rkeJ5AYb3EOjmr+frF1%4Ee$+;9_jLxZYs=rDaH>`146B zC5vedI&lXQQA--)`)9!GJK@){^)M~r5TB33ZsAiO9} z+Ui_EE0+ixQmg+NaUn{T#hrDIp=aiUec|5{YQvVm?wIB5 zumP(1F>Y~0(V80i7~$1o2oT!$ilIJh5z?|H$XdQDO}P0b%erR$LP}7bblLTi@rw1< zIeHG;2FPSGW7me|2is zX8o#)z4vB-2mXpL-L~R#vzFTsLjk0f$}r1jvr@1+E0y*|mYG@i;Z`-S%&gaAQJ$|H z5r%0mxfY6biAcnAXvbkE?V~A!)4NJVy9I1S75GB#f|YOE_$`>5TLvp-FsUnlpob7; z8qtMs0h`V>$5Qt!0+z2NT~{C)1VR`Tn1jHUALsA;EWf($;)0IrIhPWJ0<&FnjvF>! z09x&r1~t0gMF0(oWdZMTfCh^Grx(ejNzK{(oOB=aY83_3jlQrQ%D-pdHrOXe{mcm- z%LpTJ($=yoD><8IY7>ec-Ju1n#xV zK(v;72!*BoVAjtD1S!W}gl`|KmpM?$67LJBbF3)%qSH7htaP8+@om?7E6$M`ar27q zW!3Lz&Mm|i^NV*z{W(i^NfV zHr7J$8ICM)p`H*#lXEsg9R$lxbRkFjjQdgWtN6yEHTj-nLG!)TqO1Hr#C;1~RaN%? zMY)M4UQ8(}O;jqJ${;mCr7neeuuEZCQaXh-nY~HDD9z9d$&F4@V`XI%)70cl^~=i4 zSA~xhZ8Fqfra4pEYt9WTt;Xk!{J-C|_qq36xPUtK|M~I5Is2adSbM$p+H0@9x7C#% zKDkb7T>~Z_+Pw_b2V=Vl@7VWK{Q~i+$5|mQH zPTAi?7OnFrFYMq>>6p5%fgQ|`#y-65Dcrd&KPV=ZPGdMl5p@mGT-1dbC2GMeNl!1# za#7ya4Du^7!<@)PZLl1)3yt0o90vsbyr;VH6PBwaNSd{?S({hGRL$vXNO&X?;{*p_ z;GdxYjag0Zr{Gy_{oG$Upmq=oU>8fC zw&rS~dN88XtX$w~W>!`Qm*G&wD0Zd&Q`__3Yhxnkzl~2F&HPvSzcx~X`*#&_HZ+m5 zp@|`pEMrH(c8dMfy_g0>lxdDX+eP{7V5DTjuX4a1olQli#8@P$f z-9?)&HG1vIsGY^-fFJ`(Nc40IAQrz!05a4}X{Bo@=a*A;`!HIZ?L%peO0(yEE%h4s zqeiVb*MTb3Q=Sq+l?`4bsyr2PVX{VUQA7!7O6gG35*5I{MnNucrP`Pv`mv?nj-VaE z(Vi+)=wH!T(w8X6S15R|afr*h?+!%(=yV$a)}J}43MK7ZCNy?gu0OdnNp z@TZ7tRc!Io{$aVpFUtL1vhIQEyQi>;ILw0*`dh*8eh+Ojrtv0U)xgtJfxf(|MffY& z$EgtOrsc6k0Lq(v2Fqz{xf~QR1bQoTDo6KT^r??{FVVM zd-97_6Da#>bgIL?m@FEl$$e9q?t=s2oSa@Q(@fmK{ri1E*KW^>6B}1nY`Q;<=BEr$ zrh5uL$V9jIMm5ou-@(E2(IQoM4W80m5u7^nq%np!n2Bj9NjGb$VM@G%iehL!xs?@n ztY5`4xzP=Zt)+?grgkakLLycM| z*wxdkO!tCwL9i(yO`7|oLz4pEp`fa>@j>YI$p=c4*0LUGP}V2n0@qaH)8rlHrb_&N zkJ6yvA(8@aI4WI&6Q*9JFXc4ZNo`WB;DmR$;IH8jRRtHk>HgDUtSEv34C|U#s3DXG zyy0|ezy*ZEzBJv0{9AAR5A!^%*QeGSe$?$M#sZPdH5rD`5vQOQV}TJ-(l}&kglADs z3eVS{&#Al&ZlYCcX=MW~@^v!05=&oD2weLV+aq(A>%Qd=$`}Dwi=LN}Etc zc&^Wo18d#x54fIfkL~w-O76ngZVuY@1Or^sirq`48`UMSzf^nx_PO{{&T#0XGpUcf zA$^oeeWZib?VDbXp@=gI9{g*KO;%dWS$&8*h_56o<3}fp5J^eF9BtIK%^wGUjNp$; z_Z$O%e69GSko-|V{s1N6Xm;>NzTyvRD_LQ{Vn7)%jGb`qn6pC58@BQH#CHzXfS#f4 zfv%QHtzeBw_)gZ~`qo<2dGLj}k{I5KX$>nECV{F-d{Q$B-_Jr(G6~q2)We&A7L7@E z)H#{timf3gSv$wcBqfQ$A_x^j$OwSN$Oa8`1J%G8)zAZ7mHrWSfvG3M7ct~tU5Kfy z{U+Jl%*{(hsiXpjML&shq9s+;#i+V2j=GB-7bR8K_zCz2dP=Sfw)GUYacp?t?S@CC zIi(+4gAe;FdXoQaC`k&Xn1uDzoNMt9&G=8|T(l2@ZN$&F&7arqj^NLizdtJe~FxtrgsCLl%U-8iSe>Vz#V0n9&R3xVq6CYyC6` zJIA#GLPpp>bpQM?7;+G52pQs-PF6}Kf~JBD4EdvJWs-zkfNKuPbKfgujA;!LeFHj? zp_wgo12n83wvmK3fOJuE%@96RxAD{1R(fmL2oK&BWw|?PS2Otxex)ZOj`{t^)RNKX z_aR08N=g~Hh+HgWh1iIg=-D}R{Dn&Eg0feFFYBtwaO2p`_&%rG^DSs83Zb4~Y(zwo zNEhO#{~2^yw|=Lmfkl`r+)tRm6@0%NU-^#dy99mfC^NK)I5Sy?5eC*9rXVP26``Jl z7p5U%NvA+_F%U|8@L%p4BL2l^t_5Dro{Q^-yOz+GB5_>BDF$P$5EN&-6_oqII)?!O zkasUtt!NV2=>fk+aTa?~D6;5SiMlYXll8m>s1b2(GI?ygC`rbv!ec0Gou8zPgcj-s zU=F2i#eLhHAAW9PSK2ma+xmG3=*0md4g(rCZXX{!YW=MJOTRMzJ>REI{_}hd{`>aZ z7Wi+^SHC3x-T1BIzf%i@|K>je{=*V>8~pbwg9v^l{$sH4w3K7wzeR~h!+(|k{3ZEs zDd^?kzp8JJn*Zji;GWmq!0n7(mJs0;6{7$nr>KM9|K{@ab;q5pd~GR`UnFQJgWkq3zhnfKg8L=EKq-l>4@+Tino=~6E7Pui2C(k`h*mYbZ`n*_8 z^1Ono#Q;ZM>hJ=kJItDY1w|r0W?;JXlo>)^3uJ(O4;ZbPS4ysB6)L=!rJ1XqPt)D8 z{Yclc!Sb%+TSDQzBm2@-sRLWl+kE7{It>xNdl=w{E?|IQgzuxD!BbgHsA5$bjk#L&mR_ka27(nxld=xU1KPNn}I&T<+?{sySk25ue0O9Ey9m z-u32954dnX5lN#EXvg;?27Bs_ao3PIr6Jf&cdu_?f52Zuidvh9kE+CF59<9!Lj7sX zj~HULzN7ZT?Iu=$!cw&vt`bQ`d1S#n=6n_OQrmXa_>7?weY#Hi^i#-uh5zPjN848m zEqV_93QDXat0#Jj8ELNY%yCq@iZq+IXp8ImYl|;qmt-*2c7=f97zc68w!Jk{22nfI zTU#Npt9G!_8LKI~m{VyE^xqffDmmY}7w13uvsV6{j%Q4h^vA$OdSj@d1JT(!9Q!Oc zsL6Fp+5Pd(Q{Z^;1bA*5cEDzmeD1ih6={bCu?kOsLiJ2|AW{!6_7qExhQ@Ni6NgVaqdoBlhSk1VI)dRp6>Y5r{6 zzPa|Ri1FntgjXJA{JEZg23nqf`hYrHfz^N)7%QpN-olhxNvruN*M272+TVv!pq?MA z#y}tKR#Q7DFF7p2o_BS1>hB+(RQh|?TJjNC6)rEvM_wpenLZJi*J)sfX(>g*6lGGq z-ZKG3vjAzU<7Fsq#?P!$OG6kkBurT^kYrfFJo(+!;--2UZs@}Z6$YO{fPTp0}1x}5mMHp?I^ht9e}AD zr4T9zTPi|hLVh7s?8|2oV{>F)fckMhS0IW0r|kp@JrMvfiX~2(K}Cv?gcU>~Y7v3} z3AM=CxWy4)`2>sVDh>Y-SIJqH8)r)Svn~^0MdE9i2fNuZhAfx1t(A-x!DjTTQ_$P1 zo=|!wpMYmr$8BJzu^|Lq#QlF#4OEw=H-@LMM3V!oDKYvI!lqM943~w}_2^L3$!Elz zKpZ)o9i@`R(tMnVi+;AY|D%~m5yoU9H`FoAV7KTK2+l9-m3{SZwSG(<;^7GM z`GkEXPbmIcq#brv4U({DBzPKDsW2svLG_ehiFzTM4H zp_gh}Nt0@Y0wmIgz0$}iKIZ>@gWa@=tiNkwheg3myq%rExdSd;kyWcA-pLW!<-hg-|vZ zazumR;(wA^<}^imLGp~%#66+`M4Hq(?ecvCasMYJ8dF$oe7C2t3g5p-b6`I#nZx*- zNhnQsE}9gHrhm{{Ms0z%yDpR2kLmuyjNz`Jh?MER;4J76DNhYx&DMFlER&hK>29|K zm$BS|IzK)$)0uHXD5F>-ru&cEkugWA5^7cx6fm7U#dZVH!~`+j=iEKqwXB`Ms*L5( zD)&cMy`Wa8i>%mOfDQk|gAq#5beD|}Z7ZXCgJMNHhpms3lzM}PrFu5qU!AVk$EPw3 zj}oNx+o}Jn^&4Ce5$ofIwFjXsnjg$T?;lRs1AAz$$1#a)%3RnbquME$I+B`IDxiG(bq>*#87pn`F({)=aYmKWw@SqwVo| z$fptGbJf~)(Y2g1HlYYuV`J>fO>t;Lk(^wp< z(nLQMU_T0CIIqD&GY#Epzm9$yb|z+KPg2#F z2SdRb(oZ)m)cR>q-w6G*CX`X@r9G|^9=zXJVq zhA20uej3!hiGIrIt@YD(3A_vGr>P&csGmk1aOkJ6uKv~Z(@wAGr%ikuiGDh{{juq% zo&Wob=%=SYj?hmHn~zmL-M}3#Gj{#g_7hDZr~MR&Z>FD4tdFjr>;MdHN15&**g^Eu zoWC5Ie)?Oa{q!u#ADMnKcnj{(&>;2q3xo+iux}A0n!ZjKz zxoHen=$`Jw6}mp`*P6Koqkq$DbaQ*x`C?Y7Yjm+o%yd8h5Y^;1Be0Jfw+1eaP?I;q zj7tY>P?P835mil!ece1hu!h2^R*A!dwhX6w*}yqyv+rJxscC>Hp$~NBZ4~@t)0N@o zS~ML)wp@j%5cmDxX|~L58(gho5=_veR=76>Psx?Dtj&z?r2zj5ZI&n!W{J0sAlR?`TvfP zKUyM~FHmbOLAYDB)$Q;TfGcdo9jTSJ{iEhu@aC|U*0z22bbX}$+iqBEI7FDEC7z1VIpa>rbXof-ILD@Qj-a`a&e8M7jzOn=HdVJBvd^xY9JbF6Ln0ko z=W?Alq;OXLRoiEepB$lZ&Io1H3TOO>M{b{ecS8#b$C^DNq-$0W5nYp2+C)sqEE zlYcNKmxkO~2%myCsIL;o48c^YUf-cdi-)CQlAQu)*1y|R8Tr8gA!k-#jYAp1O(3gu zD)>QKfl9amSws!R*C=gWL}y_c*$B8P#dJSK8pXmy;$P924uDHM4do;R&M?LMi;yM4 z8R50Uwk<5)neI2roN6cMb)|Mp_bD@EDI|2=;KA&Rhpz8IH-N{Dc=oaHl(*W4GU z^bsCAL2sq(OBW~n5IQg-gCtBPz+O5i(zvKwh@gUraOn>E3cEvKOnr@q^aOaYot5E= zyEm;E`=9DL=(SjN^(tLkRn|kO8g7rNe1L6J>Gl8&QdmH;p|R@rDuzX^@ZOXd$JZh2BKWro@sLNcKB4&czuF&=8xyfV;L}yYu2J>} zEXNn&(wm=EsK{56fO)EOe?S1)NCAv>zv}*gn13lUCX>7Lv8rE`Bkzm*RC0=5sG zV%HfTgkEnyLxkAQab*Mv=|G~yYqdV%`-T-tpTNT@5!en#cxZPA_6NWbj^Kf5Kzii% zfFTk{dIz1vIrl@`fc{=<$TS?_k1LKNy^e;7P2gM~dIq;2a65q4RXmpZ1gk#S7J!g# z)4gK{eA{CO<2!7V4P2oS1XOiu+=w&g-(d)B|8ShXY&EVShLl2zZ11QtTYvtMtQA>9 z*!^kETJ2N?!K79;;2nYdzaPP0RjZDQzkUh%{}0$Hyg%sE_ga*Hd{OfMRIBojY;DOu z7Cis!{XsE%T9W^jzo`7Lil9%!ild^>uOk14BIW9$=r1JmHe<%M9Y)8re zy&?I>`6;c*|9vgWzpE?e<6{T>U&#OWt;>I{W-zf_|6BQA5y4+o?;RC?{SxwjAX5I9 zwJ87iqU8T^)&Ca8e`IS*{*!+R`TwpZ`F~fF=a(7(-;1D6!#hVspI=4(_eIM8(w5{O zAC&z6o(MUT@qfvGC;t){s^q^UB>y-cr#1O!d`R^1zqTWM6JyW)zmWfLTbKXkzoh)X z6Tx3q%Z`e_l>CpR4d>s5rQT!O-}kw)E4}{$UxoMgZG79oS5fx&y^8O`UImXTbYLpj zY=7V1Sv6*ov@VNKK+P(Zb%~HmSh~&j_sMKEc9L_p`UEdI#?%y{m~LDdAe)Ri$NL5L z=Pk387Qw_dwEZt~_Gisq>Lj;vRFog_{=93KMbP)W{4|{-z6^6f<_o@&V#+ z#MDLnjXdEy=dzGv9>HJ;Vpr`4SKBO?OV~_k?TGOkm`>#W^d(#tjMxadEVjJmAicpU zg<7?;553dp+Tr9%WE374JzJ?5$p_y>EvjQ^E1_b@R2`o7Y%y_`o^qsuDaN7(%^=*m zq{BE`$zS@w};sodQ;3~@}wgPAdnMQ}czI!SL6IDnCdsKr|UygDTn zRUw-?zSJn+RE#OCY*Mm!7DmS732zt5UuWng{bNvCa=i+%vJ%Wb- zw;9^UBqDXUQRR)p`8&5D+uN~f8A05L1y-CcfQ_||0uXF(T*DA#H)7Ocg3i9}45_~a zhh=MLVnIVU6a_3>c|H>w1AV=5A+~}R!?H5ryI>KHK6=VoUU8L_H=32#rBZLeai%w- z6!aTwXJeQ!%gI-^r^`OG$>H~6`w3RVn@-GE2cK!hIRPJ~!vBv%Z{+=jI6vp@Auj00 zk&J}Rd6jI^(FnM^efOmcXP=u{o$!MF+si&idsrWS@&cE2m*h`j1O)f?JHVfN&dLtS$rr<2*KD<8nk5zlgxm;NBLIr0^pSxJdj^ zeUR%5>Byc)&>=sFru83~BDWyr=--(`kx#D2;aE}JVKMmK)qt%j^peU6`Vdn&&7S*t zSRY)=g^XO@kDG)7ABpqLQkqh4|4jy>KA((Xj9SWiyf?8$7*Hj6j1KFV^ZwxIEP;y? z7J=aeZbA-m!COmTcQOo$CrNRURIL9WY7sT!;pX|uUP!VsQF`EHA*gt-ERw#GlEEib zJfGgmq5whFzsBwsskcO;yEKH4bVHTK}dE^<+c2szlc})Q%it#qJFHpDg|Nlnqc-uzj!|3aDR%FR1Oj4u#B9lv9!GqXzY zV*hTW`1kII+*Q7buCPp>Y^8jeLISMhI*Kw=Kw{8_{2YxUQ27}5=0 zar1+jm5x`?2d9`Z7#!P@NFW&E`!%7Mu4awNo<);R$`0)If72@$_vv_+eh-}0Ci^@& z8>+$W7z_g2fUWdRxJ0UhegT}m0MEx5+ARuxrd%Jw&!O7{KTR;wd+qcHjO+#$to#Xc zakz~wh8S#c2i~AVYo-G~N){?F9Z!mX-nre*2)IY4RSv$ zE=RO?F<{}CCNmeOxnn}?Zp_4#{ulu*UoOPPT_Myq@;S54^T-d>Mp|HCAA^4(AJ}Zy zo}xo)KZQmiBfW8~n5&xBw7VBx{aMK`YIURPg&OkUcTqRT;f3&ue(s2fB&r*gWZ&um zBGt}TJ^>5UyhSAi>Sk0c>ZTU<9TW~!4HV8g=p3zZ_zFEF$H-IRbfSI$U*rDEEJzDl zS}aJxhA4Te%a@1{V!@i2guB1Xvby5vmTOE-57RimpDybWD7d+W3rrE1rt@f%RPW2|e7L$qPDaoY9+VYe%Jo%4WS$;z& zQt_KF@Pd3J@X{%WuyhIy?m&LSRCS1Y%nj_e&Z>J3`gXhL!FvcEm-`FiV4y(p*2``O z>)T|aXr8(uPL4S#eOVook#;JCYSA1S#xWtnz@pd^BSSVX4sQ=4P=!oH&FSlM0w1OC z#s0fN51qcnQ2!m&Yza`*E%mklO~!0Clz~O`iWWPZXup zZ%rM~`@^&?G-EYQBi@dT+kAUN4v4}U)JY*$(>tNDmwdretI@zXlS!;|G6M;va1p>5R0kkK0G$=! znI;wD`Uu(uZ;piA0~7dCYn_+bis+kJbMHf5*_H&7NG%{EYbCC{*3TKLbdA)H!`0=f zH}siV#j{a54lR*mnwMUrOIPdCmAZ5tOPE=%8&MjkskczNl%*lZb4ebji;MHauz%}C z@RRtrz|D)L0XU#o1nC7jU8B=G*ce8N`BG)#L$Ju0T)-r>&0;(SZ)8stC1z{!8`+gT zXSzroZc^-P=Y{CkH>ax0RoY6qS~D>WdyPX%U4QS52g>D@X_bnyFrrp@?XI8%d3 z7i5N2#o;M9Mr#TD4Xm0ZPv}HEasAGs@hmbYC6zx@ZQ?12HOo^d3Y1Mno`*GYr!k6Q zp&%-IG5gGmwjazuR$au}c9F}a>>(xYu=C%U?!q-E5M#6F+jzI0_$`IJiINlfZ>H(A zqOvuf={|UQGflTP`DiuW3(tl%-F!s%DoscG`cwwP1oj0V8L8M1Na8B$?1PFNPI43m9ZmGKwy zH?`R?p&UI_`nEX(o#0HlGtPBZM2hf#=bqRCF0_63AsdJK1rlTvhz5So#)S5{S4`gi|1m`NE4O&jozmST5Ky8f&d$mFi?8+slCZstGT95<&UiUzpB{O<-hC!+FwIwtU5*w@3+!z1AO zH?N7#^$UO%&GiN3`g{@(hl50Ly?r{JZJIl{Ka%TNo3Q*4A|7C&PIWpz>kYGfHS$rR z;?cMQOg{%N&6%E`tyAKK0VaQ+2Dq9r{c-2F#PrXfa!iCh>(Xe1{nx3-K-iDwHYcnP z;WuRZ87(or^!bd=(&q=hQ+;+aJ#+z)WwlpX#_23g7~Y2gF)G7bRVTNJmMbVZBE+^% zFx}lpMnMbp^Y&AY0W)ts*&H+HF(?I?;YDjLFuc{};v-}BHCIPx_Qk-QX7)lddqH$& zXSSBCRfmd~Y}D_&nIFuKIu*0CUVU460tCUjx|7iJwT5Us3}XO!7+r}*w^{4kCeWxT z1e$C_ArSp9Cm#cS5}zP_;D3%iFSr_7Enb}coibJ59DZm^iOF0q4Xzv{bBOiz|)Lfaq)NrUP*EBY3e6* za)SJhNduplWriKUm6$=uM<{NNyqsA`dSOZ`o}2~umO{M$4@jW@3kyo{f1QO%Z!cMN zN`6f9RL_&R=yXCh?*q>|p6gCq5Y&^y*@K>9q58!#!0R-eY<+S(i!Q>9cSW{;2WGr0 zG2^u`<6XfSZ+&%cU~5A+{22}>v33*73u~MRN%Ubk*-NOsNQmzk=g4L~{d>$SI|5v5 z&~Gq>gzxDD@v?VTUiP$Hc#+-KlB@8ostSUXuT-PLeb zbNBl~{O)wWCj$oS%ge$3G&BVuF51Fg5uBRtmoB~#$^;AP)a|FlfpL&A2^qzDjf0`7 zOn3Vw8839okOY-;QkbOSP0A1fsXEPqOxI!3=Scv$S*$B&raCRvAiV==mKRFP(XD75 zbv16mMT8YWT<^=Tgh%|Jo{D(D$@a-2yj(YjeS-cb=GhNHI(XI#oX;Dr=knHyRP8d* z3^iAtu)tW#%zA3N!)4H{Cd<##nDnQyQ|1Hpj*0$OgoxS`{Tiusj>-n8RU>m!GBi%4 zG2p~2)g&IiQcd&?CNV$G$5ZCVq!fPx3l+-q;gpGdnu&YvS4E1LM3GWFzX0NVvL+AfS%@y+_eV6T#MvXqR; z={-|%t2L%_m;Nyu;44w2{rOBR#E)+MyFgTeqb4vpROHb)ygpxdQuO=w(_7{8ey<_3 ztg1$<4fK6Rm#@}RQmLgRPDx1`<|o1mQK3QkvATSjE?=t4yHxp07qrp-sk(fTEhc-7 z{0>!qGu@i4!GEeQpQg*F>hfDv`I|07dD}JFOiKa(+xx2iC+qS_x_rGV->a?i&*<_A zx_q22U#H4{b^+Rl1Vk4((qET%>GJzYcSuvMD(`Nq{Zn=M-BJ$HsLRXb#LVj37XG&P zQT^Yc%Wu`?7pV5V^8mku2eiOH&*<{?x_q53KVOyq84k^mTRIy4$LjL6x;*t3`(LBV z$N!A-SSW1~f2Zp53v~JUy8K*K{+ZJ*alMO$+7`=i@2%xum!GT4SF7^tZ)gMlXLR{$ zUA|J6uTac@^dHzbUA`=n~t1P!ZC76 zNu(155ZD2%3F&HKFpRW1U8&O3_-uk+XIw4u{mb=o45k$;Cyd-eDII;|AT zoD>(dIq|VW=a19rG@UhowjtkPNzj7p#FNDRsxTOL!DNF zk1!CO76pL(`*pfr*O$Ps1K_Vtr;~JA1RnX5by^8DEIFN4f(=Vfr)xC)hE6Zg^%d&$ ze4U=C(<0EQzsN4HzgODdb-G%oMSziiuASE37wB}QPA|688lGCFVcu+&=e(31^2DMK zpRgGzZ|UoT`?@pf9_PsdHnf?d%@V7_zY&6q`58i@?Z8Jwj$pw+Ev(uR6tq8rQ%;b2 zMh^~8DZ=KB7v~cmlDa(Q!^BpNZqhu|Uuzkwb5E_#gnO{gC(n@4KIyvF)S0!RhbmpI zOIPaBam1CGmH69MOIPdCWx8~!E-jkE%&Nh`7%dOw))l&RkuE(^mlnNYX6>XQ)#5;E zb=Rc}b?E|KTC@mev5%uP2nSk4!JxI}RMqc%UE0v4MW>iqXB4*z`COK+O5AfQ-v^T9gbZJFN+{L3AO$*rd zIjxpHSC>|FMR18Otp)76^(c)ge)L{gdy*97iprSu>e5=k{)Qt;-vyppDE+1`t!UnC zo?v~C(k zou*5t>bAG4(v|0-bjylmnJ%5IODE~l^{Vt6)hOMfVu5`>mF1xgN`-d^4ZEr=eE1#L zhr{s?-6W7XQZq;?hh`{aElAs%p;D(6KS87DwBjqch;-W43=4ExaS#S^owhYYy-wSj zVXICno`G?o(~5Us9O$&I8C>wz5kAEwFg|tK)(puyZEJ>9omPAS<3Ohse;`;`r!8U| znj~MR6(>Mb>U4%s1;&9+@6h>6bz0FLno_3~4?t7uwD1DzuhD5mZD>lJR#Zn!oK6e% zk-v^<`ax`|4Tg%{@)?>Ccf%bJ|~Mw_?&j*sg!Vd-m{5suGw)RY`aXnn2}b{stp1Rh|#0r15DcKDI>_$zT#iym$(3+F}6qE_*TTI$?l~ zuqcC%b7(c)!;6PCXMhEJGy}X&?rwnre$28NAO?}wLIf`cHhD4ZmjVuT=n%iKL;OI6 zn$M@1_&=zF(k9u^p+fwOKH*b&>n>B)7jofw7@uez>V{suCx~*N8?9HL?$*6}rIlWd zgx^=(2-aCA=w2nEE$LOV{gQ?k_KIKFD}G?FQu#C!kJG+m$%bBK;Aff%ZT5=wg?eTE zh8_Bz%w)O`zZFGJJEB7&J{Q+yt*~Ac!xKZ_U(QC)@ZDvN>e{NnUNuY;HY(+zp&ONNy9}u#9-+!sOd`k(3eAlrChkVyd zjfv%FDTdt2BuKXdPvVSORfl1e>Y}!M@78HszV|b2CUzOBsv_xGRUDr9B2}s0V|3*= zRBexnNjhzhipflyiPv|zM8qVONmP}Fr?{HHgBkn{Jm{4tVo~`t6SH)Yd?rz(08c5> zmSho8;rPBkCx8cUl?kC*=s}pfr~HFf#)XN=;2!WX?icIQDx2lgI}WITfG7-Wy`oFE zz-FJki_$HRDtDr^(nLax5daz^nbEc|9n}7cQ{!7D=OqBDWrEQE-C4O-0fFFEXINPc_E5u=gzsg!aMrcyLr*gmb6S`+WML7`?YlR!-kp6mg&^?d#YY%Y)| zF3aN6Of;9PBDGASNFAO>giV4JTDF7zjY77Dw>EHp9~L?bbmY6~UjEqhh`{#($dEPb zJQe!D2C-M2%kkJ;9Yq{KjTZ(1!5|>^haL}1VvYJy;qcv%PI=jHzr=wR*FLDR!~IG`l`HMJB)Q4_6RU~<{iQTyrG^^8N>wZVl-c+GK6JoZ!sz` z8DBaL)n@A8(n4fZ!KG!a1Klqp7`R`juL_1?2Htn2f=kVxaaOwCBOwJ4lnk)2N5T#+ zmEw`Xr8nOl3`Hv)ho0+brJW4PKrqZt5)3mA_3#pqfjTrs+C`TpB4+9B9-3CQm_`WE z>N%gl#+d<{37I4l;z^oBhEo?+hr_80@otSsQ?Ub53n;yn#UUjYDUMi)t~hi7D9A+Z z%UB)v1TK_ieznO2TmP98fx27y%=~0Bw-rAc0LB!WCj106fpz3Fa4OjYpGjB*cBz1i z7&CwvT(=SPlRxW{A|j{I1fS;=BxK4zAq*y=sll4JZtd`X_;LA z!496;C!$Hb9p|aYLVYua*D1t2555)5qKAC(jkoWVf5OLP+i9#GReyFt9B8{HEGejdoq-jJzghoT4F42t1 zW zQCS&*N(Pa907NTfK?}*tT>E7{)fLECL)?Ju)ku?_gybMMGcrwbll+puts#(=gmu_j zv>v3zG@%;ZiStyDn{$_fE3O`Yd&y0{%o98nw{cw1tWX;Pzpz3latfU81~siAOd943 z)7WdzKg$lpcpkhI>^H27r=pMKldVO$Uh)ozeW6b^M5VwG0jWg_OqvJ^OsH0)I>FX7Ahbe*ICk1}k7YyPRA#Xr zxm9TJc@NOQB2KAayO#9f)@ZZmUH`%Lsho{k4_+%Sj2wguVleRICqdRkFt@xE*)L_n z?%~0JIh=z5Gdc$Y$=}vsz)He{0nbMY4s{S2MyNgNPpAfb<)=A5CWk*pQhW!{A+YZj zyu`1(N>QA@lj0Vhw!ldiP<%hXHK+K9e}m%0lTiF#R&)du-}Hbjbk_iy=HX2tN{)62-5C3LwqdNa1 zn1bNrC}G{);g(GMY3%KsjyDhQ=61nk>`xlHxy9IK1~~J4l?>SA>U@=NIs%3nyJS2L zyrRM_5#Q`30jc2RiD5^c3uTtU-L(BEhP3mzPg5*TWUgg@pfSY`#Bnf1>6>u+5q2s| zZ8KK05zN{as-xfhYoHsD3ES$qysnH#RY_i8t1p24!=pJHQrUe~UAS>G2~~I!E)k11 zS-p!zn?_Ko4C03y;z#CIbtK#IXHK*-_&KnihJyk-+#=gR4uRbUO~678sqU5~HocbI<$*5x7=Jg~hbXi&eWoW>fj{LJ@(u5&?GZh@_qCr%OBj?SvB{hpm@ z%S^2NpNru8D93knII|w+AzuJKix5MsLJbLK){Vcz{2XkD`?U`}*JvZ{>sim)=idNx zWnv5Ka|Ehz=t*Ebwrz7ZTxj?YbiW5Tq~86#;XfQRWeC&7CkB&H!Xy3>|A7;yq~O<+ zO1c~Vp)Rjy&YFgEL(`jTd^rU%*%(VaOTXwisTclsn2a+Z2k<0Y?5hg9+I#hvi^q>|h4x4U3> zLiIg3e?sH7KYuRn9()k$AFn4)>8aX33GLaKy%-;W&l@?c0G|`8C&%I}k#nMAwc$in zJ_*sH`k*R5 z0a^$rZ|S3Gp2L+F)+ws-Vw@_E^-nb5S#)1g`a0{Pw;Fjq&{eF*bPp_MShRh%p9-H; z@y%Nm>^CCQYv1ZsCAJB0Yw)y|>I@el!-i|3WOzzv=#32V&*}vaXAPw)1GbWw?#>g{ zAyDj=w7={Vv|nYUQ9jvTnx&xcI};4xWlXNQ?UL zLEJyuwZGJFWd2xkA2GwajjBm;9Jmal>I6s~by9Mn#Xkvf#Kwr&QB%*5B3 z8Bp^#a)xL%)17)KCwv_&zuDWnMgFX1pZ}?`;YvrFw@NkjWQH2#4mHCnRn_x!)hZp@ zcsOb&YQjL~ob2wmYls8Q$l)9Y=)_TD9F96b25M^;erF5J$Duqy=O@GFR^1(!TXk}7 z)x8Nm%x!&`%kr4Q6;s3@^1%dt0u2ojEW0+wYjxU4Y;L7=tXIIR4kn)sK_<+=~($nhb-qi1+l;uVjlyR18& z#VMzlKeJTt$WnJlE!Bgi2BVZZQ{}_JQ;m5QUwO*O?%AHDUv>1%{Jpg5zNmYdBIZ`4 zg{l@mz&z5YHzH(_KLGhV_=LQXSmXl|%i2^=E{ngk3$c!HM#&3rG@qvXju$R*ErWMF zVuw8Iv#$NepBk;lSy;MxJjz=S&O zC2uRL!r8mpKB?I2DZiO?2nh!~+K3;OYmjhm8}H$m3^e|=$>Q~{C*HBT!43L2>Si&^!)0u`M^6UXW{;Z#8d-6$ zMyN34D{8MrE?RAM^0Y5`=g~kU=w_>wTZmz;Drodf0@6yT)SZ=UCtnykL9z&~eRDjS zY%`kn1=d)L|E{Jx%uh6w$#W&e8KY#8?7EbC@J-qXyZ49T?1;*1s0!5C5pL`FndBFq zON+S-c%;zC+~S$d12BUt#kCKwIP2$urY1re@vaPUX|)MX)tJ1PjDv~8ewGWN6^g;| zuS_QTxMD(=4w!f%dKWi|+C-aYfdf{?SWL8lzxmQGR(gi~fb&7aEKm@I1$YqFFdT$cF~(+r zbPNY^Wn=*k^Nni=F<4-qXZA?FutUWk{1;a(sDi9#eyjCMaAWw^$na)d>W>{tf2=3w zXY3+@ID2m9WWMyP%L}Z} z?YA*^#TV|}6$dWN>%D%Y+5JRnYMhh^7NQCS0drDt7GJ{|xiqdxbKTU8)ip@2qUtNm z_2ZaD9I8Sd6b6Kj0B&d9MFt!P8OL;CX#u%!H07wBah8%U>vZ-7#4STr{8&o)rfhNG zQ*s!V@41O2F8N)$IRw4LKz&&Z?YF$ly2)2+r7{j$&UAN*BVi8-Vb}Ts8?0?xIe1ev zWaQp<6=~IhBX3$Z@~v1NfX_zuY)Sb=%HmG5U$E37y?tA+Y#|IoEI{ktM(nDF{d?N6uq zhW+VjTOBBFhQq?hHXb2J+kta`l6PUrdDN`|HV{I57NH zZ+Ti)1ypWM6}FV-hhpK4s3g`5o;WQ$~@s^=^C-B__B7Kei_Ny2MY zXKbdQb{zDL`xew|#q!#9$V9RcNHENcVhsQOtEXYWu}N!Pe9cqvAh?2Kqd^@e7U7>V z7QB^2-a=LULl~?t&UhB{x2#5hbsC?^!s{=H3j8%2N!igQ(^GT5_J)~;nx1fu$N^ z`L`tB2a?NoU*?+0nLx`Nx7K=C{ocnB?aR$iHu}tq5$-UW%h9$E0a^|>y#Z#T%UBb8 z()B?DJw>h8dn$Nv457aP&<4OYV@ z_WRPvexqt;r;c~@KBqGFq`W{~aD-~&IcYXF+h4mQqL~qBW>C{+%3Ew^M6_la`mv$U zFzVB8!QiyfTG>^pVpwsji&kAy8SBBXd5B&xN5vSKo2PG>atpzZiy3a_1GIxD-?Kaq zpM05HCU2rMvXB;e0r3FU>7LVG@Bmk&(0_~d=sZ!%VKP z;Ao#8poi#y#_Lz%*KK%(Z1dL*c&!dgH1vzLeY8`kgMY(upJDA{pMNhA;r?B)2X3eF z#XpcA3V>~Ir?2BW3Jk&YMxHZ!oG-A^$LVx2n3vKtoCX7o6WmsjlQOY#bjk?yrE^?$ z_KX8%D0lyHKH#Py-8%aa&tS%9j>+JAmH@j?%;tGvpEjMlOsLNGAGp4xleC>1_^F|i z2YnQlZz}n%&%6#C3bX0+$wrPCH>UgCcKzW@fJ%eS_?b1Mo){h*qnop5LufXKvc;); zA#7Df2f?@@l*21Krv>{!+;X5Q`^59$76Pe*k_s4<)IkiLhJom%4`h8O24sb{gTApt zkUF7R6@tXFcIXlM=&Ou9&u)nXSLT!e@d0EheN*ryFgjXuqoK(-e4AWgy01kO(kZ)v zzkEb{i603adXT*~Hf{Kw#gnqvOQm2yt;0h-{;Cy@VyptiC zywkqb_m{{@*OA^|vM{9<2qhQIm*;XdTQs}l>Vzv|d}eGHD6(7}?LsN>V$A`zu@Q%J zU-J6Z`7&2dzjLJ7`2=I*PGW(sw$UzewdH-tzAsOyVWn$F#Nh$_Q-T6x;PrX-QV!tS z>(jfKaB!*1u*D>k@dRfe&1c83FPT z@bJoEtW8RnE2f7VAM*&8^^8G9D!)u7(20Q;5s_mBnJdOZFy>c^mPd=0AhXA-gKFsc~ zwa$@tbOCl4mIQK8=)voR(~LbCdXkt~j7niY%VbN;cDv^zr02-bo@36+1C0Ca_Gf*b ztNUBb{tjk;@n$U{=$Uo*{MP7)nan4~zE6!62QM^wuQXzQB=?jW{V);Ka}|UmQm){n z;e-OPL8l=|kMNY?cfwf2@fE+kq9!u>LKo|bdm?lvizS8KPS)=)Ck1IMh0IQBuVliQ z8vMA4S`A5&vQM6%c5I?wZ9j%RpR)B6+0Gk>BSU@tRx&{p)CK{DPguT*7Vq z=N!15fo1CVq3e}INbejHk)b4_%5X@8=Wa5ANQBJcfD|H&$N%fP2X-Y3q#0GEfI`-9 zGWShBhy4F}Yo^0pGSdxFcd$q?RLGd96GB=ax1=VN(_0I4}YRRQ?z zh!D}i2%6|#Yc)Xyx-&@m(L(u+AS(uvmik`@SVy_6T7*1`Tz&>_;wi=ywnLf_S896#YW;~!`~HBYv=Ui+rR>uJy# zO*0Vj#Z~I|7jzyMnE=xd%^l>jPXCJjQg$DRPE%LF)Lx=71-lyV;nfXP z6%-j~%_UuB{w0wQs5(_4M*bEk@lf-#rQ+6I_&pVg_y{PMgK;_MzS*!V3gcB`7qr)D+1#W|(PGK!hOBozG zeE!aBXj2er<|z0dfFi7!Hm-*QcUpY5XVJi}-m=4;O1{Gp;cHjI3=tOa@+(f^p9HIO z&!o{*IvGa4PmF%3dkk`f72+0O%m%}}rm+F&VCM=UezM}1%F|Z&GXM{r(v-vA9lJA6=iOm zG={?slzy7gZ;jCi{O&XMeP*mUj2`{S-!lZ1yBmXjK|tEeFzk|qmLLQMMk2?*+91-K zr0cB>6l5r9&|wu`9drn@w$(A$NfE-8BqLF9s^X7t-;#B9M-g`&{V7qdOsd=Q`904xpMNFc{kvuwx#pT~_; z=i>|xc3)h*SjVXa>g*5{r5ULbh%7QN2v3*->qP&K?e=VA)_>r|VU)t57*F|*c$bR{ z{Jb7!LbZQ?Cr|mUc+CMn`f@VyVMBtWegFP(o{D}vS_Ff!3^@Kn?K}@xA`eFdLIUa; zF_=4#_skjxKMCFjduDx%PH6u@A5ZxYNa6Q0J>_4kw=~bpdc-8snw3rgBbcJ-0a(Nh zrWg)lKyFOtxiHY~9KEXunni9pTA}p&q1&kP)F{m=`h7~#^&f0M-Mtjhfd589wic>p zGB8V&N_|fJGU}16ld*(*Z%-*P;4sLdp4sJGsc}Q*}Jn<`Y_ifExvHwC}@0GrO z>zJ#SxngATXd>Ov6uu%~=31VHuB_gM8)cLv3$Q6do-AYgP0y|B0k^c$0&^1WE0 z3O0hVkOaTHLZDEykk-HQFrv6Zq-|$}x^|u2wa?i#MC7Ab!wor=zLbldT}xuuO!pf< zHtEu5!rzB#)hwLtNlx^-TG~hV6jSre*NekF{U`_1a47S`EFUa|Weupudnzsj{E<-G z7NP$O2h_Y}MF=8StZ1mOq9?q>4g zyufBC#^6U-9s;0~JhQmV$7W#sGQl%zELz0d4W5cWHbZ@DotRLKUvHMvO;){N03a{1Q0j%U|16b_RvVjf0 zc0lt-#S|Rb@QX0=ZUtyYb3iNJ31d}qwE<|n1JL6DXh;ErYfC({rmAtH_!s40OF@4h zXBGgD+C^017HjSDF!YkE4d^>Mpf~mlnoB$to{sQ80RF2=IxOKK84d0wh<|`Zy3I3t z6o!fr2`~iAI+@IlC`ZrC7`|a5fqC4d!`d|Pf78w|dq64OeVG2?J=Tkdo@`u_fZE`LgKR$7Gz;+LP%~fB>VUdj zvqx9M9NR9vb_s?6m-XF24L3#;kDA{NQxk*y83$dsto;5n&1zQ)n=eOx2Bo=BaB^3` zkEPa59k-acY%vD7TuPgT19vTQ(Iv-bVQRze`LD| ztMOtAo5=6Ed_xOmQe!k*(b{JVFGLIb(=s6e6xi#)>10EjDnba_hnpaBPWzBm(?0aq zV(>q90}*Q_wsmJmZH5fQ-vz^5C&XD}z5X_d!xclFJGy~bz%Ec2m4OHd!v^A6+^nH{ z2o;}${&H&ctq@GHCGRTg_i5N7G5+V+7#VzwHYD?KyEAeq|_PIf)Ay905wNN|Nbizb4U+5*iPpoD+5LDr ztI4O^t=_k`BGC%CC=wlfX%A_jr=Vuf_wp}sEg|>YTMPc$K)(+f`8?Y6S5TZUJy$ak z4xPfNAS(sVTK^IqdWnD9akhwobeS4H&7NO(Gh9o~5TvNE*^rOwH%H$74wRP- z=(h5<@>JtzwBGpNE<)p}(HejC+txY{??8{|#XHawk0V46!<=l~{Lh~SH?ux(6*uR! z2ws=Az`OsC0^W2yju5;i)a$Gu{Q9$2Aq;FE;aZXs4S}}@TSH)odzOh3wbAnAi-MM- z)*JoZ9cVN;TBG}LQ%B1z3#v`15wzTlM>MohqX}PDEv;nzRWr-v@sQHQdYr_ve7}80 z<65hd9LhyNvU1=#DH52?y#B0b&Q<>7z${h)|4&E5|3jITh~N?BFjy=#!y2%5VxK)C zLr_(uhbe?4nZIs-p16tcz7>iCN~Z;J>N60yIgM4DO~h&YKij~~$maw%m*No>H;uJE z#0Z*OG0%a|>udy={3qEn^KVEJKBVBkc~>Su|AGHzp?VwVDgP_p=pXyf1Cy2opGAUh zk~_xH!MN4BNuG$`u*TwTF}cASCBOY>b+mtx{trdU+B=rT>aG6#1gtY;s*le8seHp0 zxOJ8XKPjK3^}B)ENg2Ek)C#%No4s&-xlTDJ#ax)NO9%w#q$o8wC*=tRR!i*43MS%M z-v{kLr)h9~!oi;04zJ)|HWDXgXCbhrNClV5{cxIF}*= z33{an32OvE!x)$RCYPvIQ0_xcchi0Is9e{w!H(7r+|{JDIJWkux`@^;W@}L!`;-AT zX3sa@Xx-I^WmwtiijfjXs3ejW#A6oNb!nJMArIoKmbD(A zq4?`h=nnWRpZsNT{RNx`u9EX1tV}vjQG0<=bvG)%2CdwSsqED;Xd^q92at>+Kn$b$ z{xfPh1PgDmE`F6W9fao~Di`c_@o(6FEV_+DFyaGRBi&B_?n{Kt^-FLUGMJo*Fb*+`ONNvIq90uU(JEoFTn96bI;^-u6ja;3(9O;{w-*GEpDR5l~kEzA9y()YuFt>kvP5U>@`f!Z*|+ zSvM|{mBiCxWSdx+Y)JO+PoCDzzrRm$7p#UAcl7Unz*CXd9`E!zt=6ZL|P znlv?dfsQ@ffDX*2RO{S!LjUy8`Qcf&>ZOE|XvC8ZR$#pJ`n0LBCN_N>*X(8sbiG{u z{T)kkbIl^K(LRaTs$wf#nb+%M+g~ErOqN-FsD3&d2(7T$ii_67#uNuLV5G6;itq7( zHOlzSYSRJyz)-bT;K*vcQ_2T-!Zh*kk1xrwfn;sph_y=~t)WL&+oa%Jsi;q}8$>9{ zQviD5U)VQ!5Nezgt}*!MHhWBrUQ`*2^Ra^2sMZFJyFM=sRix~fXO65k#Ft)fcJ7#m zxaK_1JL`zj(mXS}kxP5IE36AHH)CV+OfS>z^04i~_D|;0r!?z0IDoJQ?Bj|*e2$9v zvOKto73B4<6Y?_NuSgzb>Km`{UOVwo+A^?4rd4bh>!W+7FLP}}3PxU%Az z-4(y1TRD{OGW^nlC}pABf8Nqml&qg#P;z9~Ox>MtSEWD&kU35{qW*(Zoo%1(-~zJK za5f-PWIc_FDL@ewM+y)tj=}&Xtup}o2v75YSkJ5=x~}Q(Ujr?y8NgrrA9&YV=YVHE z4spQlKefmK_PhiRBh3L%!c2E?z``-Y0XeO6K$mIHHU>}ExC-e9BCNX&#tQ2efN^XH zyQ(#W0aJ0FS#Ll~g)r5@fvE#+V(RYy4Pk1{^DSZu7~*(A5zv?_>pa|vsfRH2fvmKF zsju$S%N|-ZR(fXbBHsGdJ4FNgy7hWW%qB5xDN(^Qu|O8)Hm(%WiTWaoBObQjHXK?K z3Ub7`PejpgzRbpvQ(e zFpfid5iO{Rln>|~Kz< z;pNK^jY7?~<&C`skiW-3c;z4PMoP`K|Bo{S6qrssDpvrl_!B zf~S9NNxP}oBr~}^EmZ{RN!%VpO4+fezhX+RT_+|QP3nwAos=JIY_ocAxs&xyh^UvMNio^#8ck<}S%*8pJ%soMYE%^-<&HJ6|;UGrkT!^pr0RubeVi}%2a@7;`z zgbd&#kU01V*xWIB!>jO5NelBg%{fV=PSdHIRH$wy!4x5}m;gr1+R{$}<5X*xfSR_w zc9G(orqed->SQO_!JEU}awPDT3fDH7S~h{Nq#1mVp4<#RPfPGE>eUi_j{V(dzzA$% ze|PTM_W>gmJ3Pq*7HXTeJc3L|V4DiGI=`+_HoY7sQOO_h&u6+1!XgvRUui2wz0(@b z$WjgftdTWgiePxLHy{HsnVyPXAR6?BD|>G(A_RXxo-#xaR(yjOqpB!X8D|CHi_$co zX(V$`3xm`qLnhoEKBRKy3JMM$rhD- zqE+ov!YU!RV!;o}CKYl4xnR7iU1L4R51G8_E$~1OwsInVuww6#U}et-A?Pk?2HnL1 zodYQnV_gLQ*M+TOWpskZipT%FDCkJiV0>FUnUl}raO3NqYKodQCx%g@iIIb5qoO4^ z6wSc4C`XqepXh(Ar(y?~rR-3gr~DHU_51`F60*|++O#yusKU`@n5PY(j{r&;V+a{? zBEb5`dg5fGHArB>SDH(huqz{igAG)8A$3!}Va9gj&a+Okc|!JPsGtzF&qrz=ljP4j zkf_)THW~_!iEB8?Fvnoz+z(rUwHI2J^lhzj;W3==dhpi>u<_-JjdL^W;gK=jUI7kl zjGdBOtjFdyMcZuMQd35byMVYuW8&aY?n<6|J%)S*{KCywg{?`B{ZMHNhB0y66a_TF z>qT4vP3#2xKkL-?s4fBnKd9bC-yj7pLR|4?WnXNk9f91S#6smp30#f#1zlG|8rOFx zx*!m=*aDX%2N_E!;vqj-L$ly^9D(1m_pX2<$WoLp0a5dlpezz{Wj~!~<|X(5X~lS5 z1n(!YYAXjXu*#(YID)yQ@!L8P1E5soZ|IXv(V8I;IYdFTj}0moF|JQ4$dRf3HzC`3Z)-drtDT|8Jp9( z5u2Su*sN~wIB@yH(5D*PRx30GzlK(-7W_;dfuoF?C>|NW>2Kxw+R3CZ26PWSuEAF@ zcW{o-2F}XxEE*YC8Mn&$bLd_9_xn?IMC@;u#V_zo;`Uizx}bgkjt9>Hg2Vd?2oo?s zq7se$Ukjc8g*5>C@Gqx0&A?l1?f@kow$kYqzp!SPuuurNl$-x?A6{;cDB zaGCx6%+UAy9p9(Eitmszm(@YOyHNjc9p6{2!*>k!F6*Div3-8ea(usiwf%jq`tHyA z5Tl3gFZ$ws;Bxf$1ojs%?5`K+D`cX>S1(b>#nb=`YVp^;iJHJNY+-C)ba)CXG~~b$ zmuvq6+*ehNPhNat=P|2@|N0GG#2SgbuqoZ`&YSLn>FHw56CF8s9yi?eUK}b{`s-Ak zeRI0b&ivo#Zn5U;-bT%W*4=JZv&&KQa!1ZTcR|e^iJ&z)=N4V5KWmjIgb8%geg9>e z^2K-|CjK9F?;amjb+rK}z(`Qy1O<&E8Z>A?ut7l*l^QhY3{E5<+6cC9EJ~xIMolm( zYA}gpI*g8pio)CCr7c?9VqZjBP{TzHU^PLD2(2P&J!4RVR^(F6_dILubLNsWA$(u| z`TSwdoU?Chuf1-2?X~wVu+A(Xqs@eN;(mSW;{kfU#;R01GnK_?-)+_P=QGv5qv6KQ zF-!OinpR#Ga^3O_|7q#;q%_K7AMr6 zkMg~$`_C!hoWd^pCl(#@mm)x9-Eaivr?`@ci`sr8{288db8Sil|KQ}-KuKITRx0vP&`Ew{2L4PcQ)7)^9 z7Gfe~DNMX0K8O^#f+q8e3Fzwd7OXtU25Z^|FjElwj6*MQkY_SVVJBuAH$|{rE)nSh zx%&ie>Kb4e)=;d~+dH?4bnJ|GZ#C9g*cYq%AB?}|2o44elSY~`aq9}jah!WKYR3M* z?L0ZwopsxWV&t~@yTi8u{O<_P!63< zvI9P!_Mg|-f7G-v^_U4%1)g9gXs-NdO_ELM7=QRd{nW1d=`iRQ_#Xs!&`*uhYx9J@ zk(sX((6rjThwPx?!7tyHr*#0q8eQe&j_u-TH@UFUZ>bP1+=V2@9)AGHsjxMgh3{zt%F__BgZ|>n zbDgjHC+Pq7i`f4OXh-ZD_*!P=pz=3*n={zl3M2j6r%^dXnQP^!wqB}zlk(Nn_|}Rp zz(I`*umre@=Av7RR{j6|;EGX3Ff^eM=cq8^jf^X@`Y->X!+IONs^35n#Q+Yl0c0C; zz)zxuqSyf9+8jD?1UeuDa=7&5pA_4;frcAvtnYs6KD?0cg4eT9{^9Y&>l_xFzDA0v z{kZC9?qx9z2mI|Ft!~{%ebZ21)sZCKE2ZYNcz|Z4suavxO01L-Kjkus(i0_LP=h06BwYOY5TBMJS!m4=7OM1OL?m6Ug-Gm5@k-OW6ho0`&Ohiyi6lXNkWpFo`3H<@y9Hq{&`RM<-#kvb-e6o? zG82qF<##w;k4$3q_~Q>)|F8z$f%-Ws@I15vzUjW>dBE`4eanzdjPmVRJF)iE*qLTB z(`Ut!sd%}aX$3R2I+-qJrnQ>sV@xl#riYm6c_-7!$b|M6X|~l)w(FU#!O3>uMbtG* zGp%2Zx=8ZYcw|!gnC9ecWzGO{Mr3|1GMCto6S}h2LRV*j^>Lqgxl0Vk$z5G=p#!KO z`UFB_<0Wq5Z}CsxhPih+*I&wfVg8|oB$l2W()9uK!}uX`g_|#onFyU=4Qn4W@DKbu zqDird{%8sAr2)lBN*N|8<#1(ig#+QNdtQI6Lucl3X|`UmvJ<)zy)NcGSN*U|^+Pen z6Z(NR4(Bh;LWAZBy|6>R>-Hw_)Mg${fcWV6Bk^{CaHwQemB5V!JjrQznclhQfxjT$ z`&9oA4x8)2!{#mtfa+C~dtSs~>$z#>c)MN=>bCK5y^l?EMP5}GymdI_&Fr&+jmFln zo^$L~Rnbax4UHULjg8e8^q~FdG$g`0>&+YfUnzZtd16mm<;7$<;U?PjNS%-WkXo&+OzDHq~|N4|Arj z{^aO6TK#EB)l*~*O0IsUTlJM)RDW7@yX-1QP){QCbPvC>JPALUZq;MnkaEngiq1y$ zI6!a*Jk>wD{VMxpzX^6o>a@fr-m;#%j|<6qfS^NN!q6AHx5Hxuqu+BtVV6PrW8(l` z#137_ui*jT{U5ubyY?_uZyfPK+Qe`#Y(g@+H0)XQqEW`auwMS+_|fjFeOlx2+m-twRH}MT$B=`>|{sbGJL1Z@)4}1e1TyJ z>BA$sC^MiLttUrQ!X=V-jN9leg^5|lm3mgd^9}pK7Xqz;jTCU{@5Ekr6=KjL&1_=M zddd#eZA%`JuGZtdI!V%K19pjvpj7{4fObvi_+$3ETr?`duY>~_T5c=mNob*niLgHc zm~4h7VY&ksw5CAsVNshY0De*pQ_4FwV-eI|0qVU3tOss%P_Kt!DycKS~||NZHJRTRt!Z(qiw-7u);COAwtoAzkCD^_>NHN zX78_?;vm4nQC6UJ zkd;V+GOM!s_2@*0GLwqdbP*!2^m#hzqjL-e2@L{)ga-O72Yo`&f<8fOIBGqS{zx0A z6*O1j2uHGINC7WphlB#Mk~>NSnh**tp`={eu^A=SJwQr z6zHdROEj9|-W318reTq=enIjBvKQyplByt+)i$tWe?@LERub7D4@7RyrZmKy#cKXv z8i(~Lh@t?!z7paGi%WC%Zy)j6gWkC-@ZC<=>tCvW0V)5`?;&$}-P1TqD`23E7{I8r z&QZTr`&`75AYJ4F5K4Rh7)iA;SEQI5XT@Vq-Oh9N??3O08>+EGV!+NPY5$Txi=%IY z{tR>t>qv{?0T=#(0Vo1cJ?Adb-%Fkg|GDMy>RXWhF^Ze?h6s`(aJBrRK%L!Xto10v z|DG%H)!Wb)okAY0fiMxV;|4#4o!IcM5#;p2U$MR5=SvxEoqdS2si zq$O%Q_V0IbEma+9_wR9ht^TRg3a+{+^fd4rL}`3~<~Nb$v^5zvg(N(7Hs?gW(1!Kp z63jjN%(N#v_dbgm#r`o|z_SSfbE6VFyR7f6Vv#L3*hK;?@&=1w{RF?U^JnP!xUzY< zsio9zbkkFIqj#`|1x^izvxbJ`Mi)ETCouc9PWJ6fk^PF~+Ru9&wS%d!KaAPWcCtUu z?58Eyp6O)Y^=oAB?PR~3+4r8^)trhfm~Sok4-ZkGVE|NRv6I=!ZY)|Cah$I|W&U&) zct4x-r!3B&@W=DoeZxWB#eo0Zhi%l}^6OzB9;WkLa_eNYi22DYovKXuK>t{i&VP21 zt>^4&0#-QxQQOWuVabV!1A#*uCoW!xw8v#f`enTJb>tG0iIaLQWNy=dl-j|{vA(tc zqcrR4FCY-ZnScEiz=k|-xRC8bXci&Er*rK7O`DJY0bNDDP(N&ofkZ9KsvG<7e_NR5 z<80QfwhUOU)*~mPE+87`k7H9~W&C|JV3wbNc+LI|k(zcesKhVK6Hgzzzy-}+N1l!O z`$K3moY^D*!OeNUv<9bwEaUnzWE&qw60g>QK@{urw5K6IhAG}tE+s;+Bd$dDNdUgp zy8gO{b?aprBbzFK5MU&8xgbt-nvE^7K&8b17Zm7%c&iq&1xvbR)-}VQ6tsX}a1~Ri z57(}Tu#W{W4ko}(0U%ppsZ!yYF`To$32m*@!9v^*M-F#ZXxxvCw#mVc`EZU1e6USK zDl{QJ1VV^b($Fez*0>BWu9l9V2K<&g8J9?HdTL4_)Wbdoj0QEcF@AQTWYOt^9j$@L zQ5=OmuA>D?eXzK5{n)Sz017m|x1?~5_rV)5+l&_DPcrN?A}-M5(vxsz?xp!)kRtH+ z^oKhl)_~I}q!JOqu7P+Gwe+sN?tB`3$BjEpeBia<&ph&H4*4?&*LZ-#CuamgIDF+& zgl9D0hM@jYwf<1Ac7Ld<9bY!xmJelCB8nIRU zTL`VQ&c>fe3|{NE-^D{2y&b4Y;Of|m+7Fqet`z6zCU5OsZN_PGhVT-67~m-7t8#+i zBg#tStUg#56?$_C6bkNWVOSfYvT$q!cU*)$?>{mI+{b7+>x?SS)Fcd&myDgU+i-Dj z+$!^D26}LdlLi#sgV>ilGZ0I?0;qeZZfp<9o2#@L?E4N@Iq<(fg8{mw-hSzPmV5h+ z%WCV7Hm{X7zag*qtn6`ZY7W#f1r2FLX%|&>ykb3sAY3;f;tMfS|X-JK3@mi z=5YM8IsV8$LB=1KjPoiNl7fHE-ZTiIyGQ$ilQIIqap?TWc646OmmWzO_O{jUc*;Z1 z#&16Yj}LnK@nN)ItZAQ7zOdH1^*QUT=f7Rp(e}&4@txIKKU_Q8mY)N|wtnb`8sqds z4|KG9`oZ|ezE=IvLN4y)A2ZWv<0p&L4^7Apwgm}LKg=`wVTV*=7qV|dTW#NlcK^Sj zAI7og2*y}w^n*;2L3{8NcpC1q`*-d<)epV|{qXLWiTa^Bo5Tf^Rj9d!`k@gZ@IUB> z+l_vxp~|Y|H?w?3`oTwy24F9!BK#Rp5$i*uB3`yt#B^y;R74p)(J>WKW^Fx|Lug+q z<*0}qXego+k}_YSj<^UyOCT+$j;KUNfSI|>=!kMwhW-IeY6g%fniO3|9dZ4gsw2vc zeQ>HO3N(?ZD2m(^MKfzPeheKo$n7S6v=v2s4mMp1MUf9FPV5#Cj8bn_dYp2|;_oG> z0g57rzn4jE3uLG%1JM8#1Qi7pgndMn?RTM~U=jL1sibh$4R&-vQbJ)26h-03og|p2 z7vZRR?}K#iMlVoR0h&YQO(^6Jy(o$U7w4y0d#<9AXwOk45!Xe`zumON>tDMIiRj;w zwS>qA-v0vJ%!DR|e8>+N`A`z-=MVWsKTHaQ`xg1veAMfbP_KRyLs#|7m>3H5L;M?6 z#qdDr0jJf2_NR0V}* z?j*HJWa#ZVhMu=#zr{Gk`Yl?C&34+JuzTD2DgD1XRr_eTf*vIaIXPMUpRjX}^Mw#{ zAnrH7s5X;MdSYL#3lkuXgYEDH*rIo(ww(wq=SSxLj=`$`#EOOf6RrryHY_Y*gWwkB z4j&LmxPeNT&$8_XZcF=95kHlaQu1-5laxe%$~1qT7+CNO9K{R;xN?cz%F`)11Z+Xf z4~)5Ffv<3@_knaWFmfZ;Bn%gwSeyA?g!epk#=-|oXewDdl*T*}%18!OxW&)D2>C)GYGFqGl_t2eQcd)N=JVVGTEA zuy3xQz~}IlXQf$rtPWkR0lWqHxG)_G`)Ga)XU-EqFsJ+TztD)D{~|g*US-!oHn#N)hEoIkZZJc%eZF4>dYrT-Fy`Cw{ETtUHe6SPAX>OJ$(2 z^1xBTich5NZug!fV+HpqC1R!SVLC}+e`BRas=|eebz^6LLO2e?*&7*cr})AXG1Pl$ zyN@Oe!8h8x$*t9$pJwi8iy<<{urwHz{EP9-0ZZctmv-f_D@?1#bUwgY zg|6}xbZoZ%H6LE6H9V7wofOD+ejJ1Bi8#m>Wh!L%8{EAet$@Vicq^H*`D|GrF!P^i zJk^?(?RcwbNiq?O{O0;T#?P7mVllv{PG>`$Xkae{3nTweC+LS6(D5BeJuMD&Y-X{M zYUrb{!0(G8G6xjN>2Zo4s7|i8y6A@L0JmTn}X{!;&$B1tkY%Fe{*7IM z9i7-&SE>BiM6OHd0}ps?#8)0>LQTcfU8%XSG*i)dRql0-f!yn3{S26S4}8+t++i+j zW`C4u=+**zVEKcqI2F7Q>^huHiyA*c^OECjD4AwVgq>txp@D zz>vT05*FWz!w4vC6h8nm8$cchAdiocrVOkEr*PX)5f6*-A%6ceUWkSQ+#hnBS%I|a zRR&rn2{J?Ap%K35hIm^{@%INpo`AnbowPJA&V3STjq`G!lFr#Xvdo+WXycs3K^tF) zHU@+(!Ef&hEzg*3slY5Icbe3IY$^yMkSQ_4+Jl(i3JgsG zh9(n3AX2QH6GIi&(0?gLN{Nw4#K>e76IjkJCq^owhdG2q`=&+xzdz?9)0|zLY;k_S zl+Um}Nlg$hX~0S|AB%H0@G&oUBQs%Y&>~O0rkljHgYR|vJ*^rmtC^>qgjJC6fZ24BD}t4&YUp5i-E$hx*lab3_0 z1fMaJ;%5YMMipJ4r+vlKEX05@%+Yw|4)2_apa&00GZ0WT$y{bQhmuX-w zW!(lA$fb!SBqb_6)Ym$PX97!53B?f76U!vOcVD)t{+qV*Q03ducprr5H|}4L({HwJ z04QDP0`>-?9=d`eL`6L#Vn9tYi2dP<u1Q)D2+me%M)CTr`+Nc0i!K?8KJVLqM*%+H=jsWi~-X` zV8Wi7)4`BOGvwBGhXu)#%iafD@F*|?31(VZi~uw5*5IDByg1o9_G+DM5s%;nq8Bp) z<66TB(?hYcAG=1Yg|50Z4lc^~|+w;ZB$P2*L$(~V6gld(y8IzwYKIwG~w;9?aHz(3d8 z5y0c1JueRJA(^g2XkNp4gO*{mka~mb0kVgn#R_BmoH4^!p%oycQgZooU>04&X|*}> z?HinE1KXF&JLv5~0Zg@l+z<6rEZz6z?vldH@39%As<-S~Yl9uCqMZb>LkcyU*t1jr zIbXw*Ol<&JG8i2bl6&^8wFHZ=BF`VowgDU6b8dV=dZ} zRybqCnN&g<&{1aeu>d@`ni~j#Mdh$tF#}Q#$UqaJHr`UW zngcrMDzTAaCI@{ujDpodSv0_~G`m`aH(#>&!lB>`h+wrL0!$)oBJdAgXOF)KyLn<3 znDO@yUPrS}$N!)9cn4dGgCCUyqa=-`sN6bA7MVEy;1qBDBSHh2y|5d^S2*BX*@N*n zeuEseke~7~BF`4goUKvs&+i~*JR!xBQ8Sc0hn_dFz);AYw|zt3h`*Wbb%#R3C!9&8 zJ{?yZ>Xa1%`Wl{*H-8Y62cp5|9fu}hV3L*6u)lJb03q&sNBQO3tQmorYq>Z=bxgd6^KZ+NKi4u>oH&tE;6OrSuQYXRp|Yyf z{-n3WXm5?T?nrDgi~gVB-cwjinK$Shc^D%jPASTuVJvhIIe0Vyi&)mlWh)_n5rJw3 z5XQNhg={j#$gzLq59*8~fp$5zFG`GB?Y@v*iLo@q6+}MxJM-rvAkx)jk0}9^KZ;AK2W!Kya;f zBYs*-`R8f;q5okKUmnGu$RXIPuWvb2dv%J-*<|+mg4sVm3|s=^b*Z4->>G#ix&-fJ z9Fi=I)vbIi&V8ScdAZy0ps~6`o=S8yRynYoIWae9PRvgIDET4bcHo@?gG5T1NG^JNGp((n8(qygRZQkAqH)22SGi=+DOjwo$9& zvdc9%#lQJWOm?uZ7k*i~2f^J-P$Rf|DIQ`NujG4ZG7Mk$F47-^M956~V`QxcHQ7_n zxY{Dv-K37wrGPe@Wm&gT5I{5tsRI zJTSzdAwi~nNo#1($D00$d-~9ge*6pm-MP{m2O?P|;o*G(!Oi1Hwb*>KojRYmph@Bb zBxL9!K7(J4<1Fj-0KM{yjTW#^?uI9lS5)F$LD?TcTV*>9bLYeWTSV9vl^xBojl<8k@1v@S50yBT#k$4|_Nm}y-hz7kxHXn^<0{X^$@SAoQTg09jf zsBEh2JZ0YupN6+ISKO-K)qi!$mh&>s44QC-# zT}dxC{y>_EW0aU`7mTUrjv}%a@9ex%)p9e_UoIGBdK#KwIx#ENMgN7`#chQzVxW=} z#Bar{Ad41x8dd-S?ZA5@MbAtK1b7a`Jl#t;z}Q*-;5)^^kFCkHk0F5TDaOFGS5cNO z#BXx-PdLfZ&MKn(!GD(oUxU^=Xb;T{4Q!-6wA}~wriVJ0r#ZnMvf-!)9i+^uAs?5r zGw6R4Kp}HVEf^b8oL$PeA|1uRzKLRpKr_tBArooi^VCp6&sZG#IVz_9(+`7a^hIkL{FBARhAzb4L@&g zE;D4DMHIx5afs8PhCNl&?e^R$S32d+lPPG7lqvWUq6bH}UEOsPa%0#3wZwA=BTMDESnqO!BFjUWqQ=>|Q^_zpkXY1Ml{+mE+(8PL z3WHH=+@|>*5%>ymWxZyyyF=VeqtKd4GL*WJBU|8ziOGCg>?E%S*xCH2co~H?3={@at2i-+vJ&QF{SKXN5PiDG>aa{bc7| zwBc)Ki?)0nkIsdmO@E{5zfG0ipy~I!rjOUnWAlV?F-6L!+#ua@QU+_O%pY9u$JOn) z%G?ns5F{KcDvR+r65>{KYJH*(Oeyvt^=?0wsZJ$!&DwY8I4DKWjDB_&y z*Kt1u&)!BSm*G1`1cn$V_-bm~=4pgwjG+ROl^DcU?E9JgJM5`}lEVI;nONiBIR?{0 zndFsKk4UrL>51S<3HG=07>Ou9dADO9`x|C zU%N#9g0FX=Cp2#Pr1>HI1a>7K(e@yv!r0B=V{vXDKIY{fjt4DOQV*4)FeL;46#>bc z;|Y%+t~vYOw2s_n>LJot?S34~RVSqs65QpP zarY6vH=5uU@4&fcSsYD*<_jIQGJ_ehUWZMXqeExO`G)iG0O#Pe1ao8C4(6G&p1oZs zhoixpdw#leHW?NIM(%;>3KurnF+Mjcy+|v)xT{KIpySA{2DSzWi9~?jD;{*5AgQ1O zawrD}^42p2^38aph8(B50q}d$5)NSN8u*~r`^&ECwSnjT4OJW|MXgG3TTbczlKzyB z+XdGrY0WuZ)eLB@j-4P5?uN8cjAKbUBl)9|(*K=!r0l;9C%~*s1*TPVbPUAVTIt4Hr(;C~E;dD^D;5`NZHv3A z%?44p?4CGMMf_`b`Ro*JC%3D10-?;lfLf16GYrPi`Oahi>5l{l|H30B4q{Mys_#l* zE`;zHxgh7Wx^mZT+Co)VEdbsr-xFS5KBV%%9o)0EvN2s%W`oPssJVh;cdoKFWC<f})H-j82RnE{2sD9)V z{cYW~a4{1npaXQxFeTrbaSxp0>VC7A#yn3Q06)Nm1DD+Ubnp0#aFKHicM#!5+Q;+| z1AC1U(%4?wf7Z}^aV9@?qsI2~8|M)bKEs|J+YtY8lKj>PGv_3a-5uWxQ1GE}gIL&; zmI?3hqB44i>A;iN-g8$$<2W}W#+}cE^U*(9XpW5Yg-1Vg0S^RfVoX72?s#dqjO$7~ zx*FFdn(fIhvPBSIVr$r*-iBw`FGo$AqZw=r(cV)vU^~!PixFV0>_>v_5EXEOwmGPa zHW9j*eA=A7yy5xHJ`SSUDv866R0X>X;plaz3l7%fkrD^7zQMi5TmDk2hylWL+J!5% z=BZuP%r1x#14BqAn0Pix1D>6GwF{cuRTt8L2!FZEorUJ&3cw{hM z5eYF5%K7#_SUkD)PgYvn2yzY1f$RE1o_;_|fG^v?Awnsfk6n_RoA0^oiAU z$Y^d$6i?RmvVVYUUN8!qrO%8#hGp2o7d*ErBHsUwh_HRz07pl&GdWvBWhkR~q#R0! zsaDOlxvOmUh{GPZIptti91&BtGqutiyQ&mYw*-Bm#nQE|{gGCd-&JLC5T>?RUOzkr z;l@0{&L%v%z|Mf%_5j-lHwWfvZQ-tJvq7Z(son3Xo}Hjv7F4KfXaps-8|#$K5bqlVR|3NBv8BPA~W$~lp5FlcqHuhqh)u=9Ou_Mh(?iJ8oR zYyRCWGPzcpnbB1Jt=R#f_X220BF{_T0O+oa z+!b2!OL(Nj3JB>z%@*k@8>ZqpjaTIk#u5N-mYPk;hFvCHS1RDTQV|^;SYd*OSNmku zUvxg6L*LtAx=Rp!%3@et%BOd&fQw5-bYWnb3B{rappWgL=K9h~1T5+ly#EkL&^f!B zds2`hl9o?Q!TIDAJO|T5PQCNw36~e1n1b&`GN$1B_?VZwpM@|5PeUT7;2Dw`4jsNj zw_8k)O~KponluIf^)bj1_KZ9AUhL1+Id}_l(e$fd4?>k`!Xlwqg~^r42wePRJO^&7 zA5IZBRtFv!Cujoc;hgpCu$Tq4QY%&l1jt$0W@bL7vK^oiuPsbt6tS`Aa0|;20Gk};|f3jfiH9XugC*}rRmk#E{Gcf3y_MOhr z?46LuGAWREjkb5KdwZ#n_ts%#c7r_nekh3*B7?jaas+wb4wmlh!J~6`Y~-o_0nrgo z3E~skGWRQCBO0n*d}MA%;c{i*j;_t!Ha#xQSTJF^rYF%3(TEso& z44I&1+Lx|qVa^n28LF)eb8jUTS|08dhn6CuC5R|{jLXK81TCBJI0#x^F!->QsVjfq zkRHRw&02M(Yt_WZQos=-VZp~KUr>SWjgv#-AZAV%e9(Rwl&#Gi=iW>zgxm*u=KkZ3 z*+MBRiINA77nHnoqM&3Y9;s2H@x8|7Ng zRy?COW((r((dzGYt=<+pg0fcuqp^Rz4fEsB=IXt55!gp-Q~h0=BEFiW(gb{c_IW(M zY;-YW3Us}4f}rbFJPrX}dBOq)T{&*(I-3?iXwXEhzSOn)1axsn3MKSY(y0`~)c!pj zBn{hVmy@-&qFvhO#=rGU)cCg+;YX485d>^v)dfRW5-Q3r@~-&7rX$QkN8-c>*s{7} zodPop1`1{#!NUzRgX%TCAw_zM9(+j`4>{+;P zRGM`bLqGwmd=pn&%kSuFldImfK$h9xfq)%UU|rpcWw`L5bAE&nOnc{56Kl5Z(a@kv zj}t1Ih=(f`{aDk_cTJCtIy`F{JYl27@vJFkI4~;M5HcZV^J+0h8Q(GO2O&A{yey#z zE|~%Ya@7mS!zY9&Ob5RUfj2t@ci=Y$30Z6S72{hePsAt!Y1VHp=l%h#$KfO4+$YcF zI(fiCcp9J}2g>9DSe3~`(2ns)+S*EBocT?K72L@1KpvZ6jwkPA=qFehhOB@BffS7i zqyU1DDxvL2Noa$9f2<7A^LV%p(IQP>?3x}MA~@H6+7)B|`+ymSV+~`%p9{!IfMCo@ z4g;u7xTX8U!0{b8<-a%*goh)6SVjbjQh!+on*Zyg!H&AK{h&d|$Y`91hwEr$YWk6` z=?SB8LRX_PWB>OIAu0yK86Vj~%!3=?uw1Rte8%T_&lB)@;=V;lOO907Q&N`T_WT*r zt;bJQw>7c*uR7tA& zmE@JQ+fyU6rN1Dv6%SWrHfj1A*YtQ~*8d5O#IHNKT2Yhski@s&odeB(xmJCJYt@t{ zH8MO2eH@BD#%52Lpo?M5j46mEO&dvfZv@iE70m1R3MZ;n+=$wv|8oQfVbGID3%Z`d zqcge^&~Yg9r*prJVdZ>np~$rbVx_4wR<`fJ$akJEFlP$1M30hwe2z!wex$U4FZ(VI zEiFXL&-(~keyP=kT&qh!%W6;w{Jq|WhsjT7n$TT)_Y`d=*R>gPpfG8ig90P=-iO4^ ze%rLOeLBpU0ylr_C%AbFk3+!C7@=%q@aCB@qK0(l2bVLrG&JaETK)gHR-b^YwSZCQ z2MA1gBoSZTn^1k7C0+Rj50|b0VN0aegbBhQKcE;<@j+k3dl8*cF>4BpEz)KdyEl`H z$vmKXTfWZDp;#6312hqjHt4VD(H_BEt~N8owV4FWy#-h)i+(HJOTpx??RMH%fwbN$ z*m?~QH*CRtHN&dfcXIYC>I84+HdH#n{{?^Y5AY|qW0?QvpRPQ~DpFwaa&7(!_vTYz zQS|SsZ{qlJ30jE0PgN8e^!1TC{&;lmk&Q9+AHHHx_Gniqo8KN2RF7)ikGa-OLFG%r z7TsR0U&XxcaDojQ_m6mDQ)$j}DNuB#wt1F&n<-F)^I^V@!%rFU^H=HRpv{?rpLg)+ zj30ovR@2wHr=yRh34Od3=4j_W{&agnAK_BQwip>7vvqE$?1#?br=eK>e9QOU`@S{% z&i4)8Nb@)!GQ=P5mBrXm!j4FPXwa(5xe6-P01PP$c4l7di!Wu6W+TcGrao&e+~mFg zQqXGK81(6bzS8Fp@o?#LaIY)sap2*WW=0fZKR{BK$E_q61O_848mlT64p=%5BM9Al+YTx-WHU_X|>V-xt??lD6so73{uL1CXRFy3f4UmtSc2aeVuK;F=w4R<|+(rM+Ip>gruDMLo&Dw_2WX(jJx~#H695!K(^t872Kt= zW}E~m&WMyCwD^cX;W}^Kc{UQ>KU|Qo4UcXkK~AcE-+JqH#Y3&ZLzX-derfQ)mHB|; zVcOQ6Y5wW^1QiAeQVK|5E`tQAzy%4cFclI+!3q-Cf8gO#-Z`6qgucb0wDCj&rkOlF z$e_TXgDrgo1@GZ;s3_RIKtk-A!NbBhJiHTA0R|6J3V2{HBl@HQ7d)`SRCvfpz{8=*|MNiz z!Y%Lj5+rQH<4}?CR+CDFWrPFW*$P;3>agg&&91_48PSEDQbNT-5kI+fywvG9TpZd_ zu1{^Rg7X6>2^hRfY0w>WL;hO_K8=%ql1SO`6T7p!daC@xquZSo`S+^!w4ifOpKVQE zu@nK=XnHCow5QoAdYTv4(<1FD`}s5WQ>p=0N(t?4UW(op#Pzl^)>|=Rr5f~B%A&W- zYvp|sH>8rnPF`hq@;L3}@rT;Ue$q*}e+ehrOp_-9SI{OU*-D@j_X%Xr7>8?xAu@w+ z$A>lq+s(3&sQ@(10*0BTE*F|+-8M6mS!m4dz?1qUTXA88TDOguLK_eL(q*uZ!lT=R zZG_ojFRL&sGpMix6h!*qov3KEQQ=oq-2avx9utQKDGW3)vq6K@|2^x;T;}FrH`hV4-?TL;>5XTkpd;2n;*q^{-H}A^R)a%^(8NC z>&c2<2>hcT3jcE?frK;g*lalgr~oKcx63O+-o_yG?QDd=;hqjAg(hOw+^)x-j!Eba zPsbb0khilf@nO! zC)42v#u!H)U`J#>1012vzz}5dB)AdxS@3_z4g=?FYzY4JQ2Y?I)j9Z&DE>h;Gl2uZ zAQ&oTKp_s@n37vrg41b!!XQH#lQQ&v40~P*6v%Mko`h`N{GcOoHoFaSsnT8hWo=78+tJb?b`|SGQM>(BJ^FH~JZ)?1E*&kVClg2vXaWn zveO_4{-*%{=oPXb&%sXe7n214~S3zjP`UEUv8WWDn z<>3oW$ic8pF|HAbxlG>8j&!(Gm*U+Yngj}Hfp?7;5f0+O)zxIBdFwOq(>^}8etT6` zAe4=RS#eWe9R+gz_PC>2E9JzbTGkHpqlr(V)QPuJ1*E!C&SW;Wn_o zVwv_QJ|FBj)L()Jt~iKqPEdM=|Wc3anH=-wz)Y|i&Wf6%}b3Y`Vg3MqrcK>tkP z)~Y4eqp&yH9>+mfZ7=X7%QgFZ_|o@F`xxANa6`-2vp>TxpZC%&NN?NHE#8yz)}ncb zAU__6Ke{z0zlXcXkC@c3%20}O?GWUG)$35e>f(Me%7=Ch-o8%dgUAKQ2eJy~1D})z z%46^x;2l!wN5J735bqOP~`b3qFX!IRkH+GQp4krVcvmt{% zFpO;JE6r{@$rrA{t0q}>e}JwH*JMk&^@zNAjy(S?K&o4^tTp@4AH1-y4-JZGgIML!f{(0 zWd4l(1r!!&a&>MkK;qpC>`sv{$UEddheaZng|L=j?>0yl{Iah3JvI{>;YJEXP!kCg zF_yLn=-~@ZMMb=-%@Au+7T#hg`Z+WqgWQ&n6TM(XL5@Vw%@b!N9lrbZ>zEZHe>t&% ziv&FB?~Y2t`p!wDK5TyQ$)UUF3b?q)VhS_H?SCw{S^+Y9igp5&Xk(Z3VPqDpU2a87 z0aFsva`#&HC>vjR+nE)lsKQe0QX{8gGSBp%6&{WuI=zk#e^DG`5 zhl>MOT#uUsSKJ9QpL}>p=!D#H!B#)IpHYI7Re{gGIF5BTjnb;ztYV&%`=Kwm1twi_ z(86(`#lZt5!5#kKX6w&{0p&`4L5y2)0>=K!T8=$#0qudqXoK+Ozh}*S7D(g)IHI2l z>&9-BJh-vrmW(!R1H2={diFVF!Mz&hUJl%`vA!JSYELBCpKOAZLy+>UbMEJ`*z*cj z44z{uOtid6bbI`50wS^#{^*=#NePMc(>AdDj3vGDG*o&#&Q7Iid0$+%+;|O zh{aVjPNIl*ClTGe1g?xnUx9Nj?0NgABk>62USeH4{9(lB6#&@*-}DW>H6Qh?`>eOG z55`p$0p*&oH7X`>R{uA_eack*9t<;t2|uZ*0-p*qM$t7wCLfM4ACCfig$gJnQ%=133d=N)(_ zHPV75HRj0^4s<*L*+TZO}{D%L~Q9Y3huTBhsuj9lXvDd1*aJQ^pE;y;nABG^d}2ZY^MI0x66; zXm13TAaSLDsz-Lo;tSrRZy8v`+K=raQ}}_bi3HRI0jRc8s}-l3(v^|B4JrM(W8F+2jD&e*1 zQeBKL~J8+ zCLp#3h_&UX;CC_W0)CgtQ;!uCU$?y5$2q!mFSw~2J!@et5T*<9Bs^@TQ~#zgSdIOg zfccJl|EP5;tTsqpx1NIf4t{5jm07Doq&v6ecxC>%3O73>Xtcx^)o*^)Z;-Sz!EVrR z6#(ZnN)-|er3yO@DRL@^5Z6?%c1T!|0$N&vbTICS(_pYy9HVx0dEMB)cUZQ$A7KtP z_gN^x+?TYl=c`jude~iR?z3gc80BNdIxT)q(Lu8?vJ^OEX_B1rS$xa_D$e}&CAIla zH8%g)!D{op&0a{C;5vJr0X)ML= zTd|Q!^XkUFbvv8Idg?Wh&3(vk(;7Fqu{SEn6iGVP%C z8!{F+rXXU4lXU9VSJJW74NAW7?(S1^^a@)YCK4~+s2|P!#>J{1TL?GwV>6%7kMeXh z$YK>dpx}1Nw_Nw5Ko~ERclBy<-cUnHy+l6R$9=%t!Mk4rp~(g036dr(ye9Wjn#?B`H_ps0354#<#*$B-nIqkbQB#9sYVpD~2Y%=&Zoq-$) zfACy?_%1N(LdlBbpKr^+{n#Gs4)oezcW#=uK}-=_c!kd4eYU*dn>8#&4S^ufa5dLN z08L1we-Xb#;Q>AXFF?{|Tuzr{Es9xNd4o_Vi2D%?!A}h22NoNU)rsm47SxT6-o~CC z<_}i#rcB_P!q8fe&iU&K(yB`wKI2Rmu4U_4q}yX6lW7^~r=%J)8mFQiaWPU8H8a1t z6IxfWy8e=KDn%;Jw?41oNT--j(dC^V{Y7jVs`}+K3R2hm>v3eEZ|H$Q_>zti@5`*ys5J1%$~&Rbu{S}b~% zgr_2axCrMjZo7M;KU^v7@*!y$(>l>Xm~y@ieX;6Px=YqrM}G^RAzOjgeQXD;t-ui{ zrOqJ=Wo?i9!=uiz?H7MxyZ1f@u9pPY`iEkz?Hk|Fw;1Ug82o`R{q;cj7wIL1JH7XD zPq2UJet*ZtlERh}??kv-Hu{F{3xp?i_`loc$N3l~gLnGV*ZK>;uKF=a)<%FRlXf|j zdyRF|QXM-Wg5MLNBvOeVf4J{JT()fDrwcdUdIY!?_F41^m~K`ZxJgcpRR69u@Yf`1 zG_c0X!q12s^;lQj?oKl^F#k>|+C|n=zBj6W@_wGIIA_;hk~8GH$ZyDZK53~GfW|15 zi$rO!miZ7=(Z!I>7r|;7AAk5dX7h13r2iUXW?0R_zO4k-^cI<_h1t6+SJ*FrtdKp{O{R3r9D^ zj7&lhfEV0iZTXtSa~TSm3MkePIe;R8V6Xh>BH0SzfH9F^9Oae$Lxmo{wErKR?;ml> zhp*_B8i0(>09>vBppXN=*L2Jhg0H<(o4)b(0~r0|z%cvwft1!i0-8+xXu%I}!;g8< zfax#0N%Nn^njiy6VU^a9)trJr?QDy_nxXj(il1g}$2cfPwU0}+FUTetMPtfp-&*BV zTaj4pa2v?erM5Gqwgoyl)g2r%97*sZ{_(C@l>_3cwD}kC?f!%5e>;A78-7LdvC-Hi zA=IASi4gwQ-Zde}B|C;5?eV|GZog96w`7nULhOPL(mJ`EEV=2!&!2gM`Ok|IOW~K(6#w)EQAXXFVk!{8>f}Bw@q4HJgqtodr=%Rys@v zkF3*-GLZF~mFS6BW#Lgrs}Trua9GSa5wi%lodk<;^p~^<+DK#h5koV?`InYqf}GYw8|+QBgdKGbmV$?X2ct^tRSqDYTTCL2s}rjF5Ms zx6vz<-r!tNdh>Dm;Yx4U4+6ct)~57^N@Mf}lg7-%!b)%2bUSPlYXQv=n#ace(u}Y# z%IVs$DX!2{ycELvSVz6UKj$gLCvU^WGPo+gu!M{fN`Z;|Y0Z4mA&0{fYyR`^Sj|R3 z;XxIPl^d&v=h(+VcpvJi8W5*n?vRSllZv||)`ygc+1>uRTFIazX_?bS=<9$OOyMK}Tg6+RO3 z(!y?sGiw^*dx7-gt9L~+ZdpET!9S7E7ZVe68fDnivaL966;3$Ecg^W&rNZaf!%kZ1 zf|o{d|Hk$n$$F{gTB}RF)aOB0y|j7PLG)6RfC`U&tTzsn2ic}svyOz4eh63Kse8Zo zv0(B0e)9-8wo{>>JB7xfP{f+%lxjT&r2_7yhC8K>U{j|$g%-2WvF?SwJIsb}OC}2K z-fF}53l`e>j4OPvW}y&d1@t!x!GGwK8p%@6yO-K`v|Z{3Hg&&K=syEc=yvx)jb6LZ z*(@~4Df9*lUEp5mL8qm3fp4Hw>LHfu>t5yq5olRZj6k5$fW84c>4@6TQ4%Hr< zm}>QN3e9Dq9`1#ToI-0*2>i3fM#UtSdh@AA{3{dc>&={f&3@q0&6 z0=viWk^PsTqqN^tDcYe^CSHxfdAyZYuJ3(Xe&8BdTsfZ6)|1CGkm?iq`dXNHQ;;1! z1;#EAjJ2>K7{juz3MV15$UB47kPnKMu3YhwiyOX*<`JynksIJku};J8aN1e%{ZY?c z{1<~?z4`bsj@*JZdf0q?E?0lczpkYS@9d+C{vp}hLi*aF{*}EXi#fXlsln%Exr_dD z9ZW?q>0}v^4!uO2(o${WlXur6?pW4m1pno<1|^Fb0%p@8$altvLy$u_%e7>su_Gl` zM^i939GFV1^Hrl__@Qt(I*d*0J0cMQ0<}cDmRr2K+hem!Nsj zj10Tqw257JKGcbDX(AEyj=))F$p_g;mQwhC5;OUjDNjfRHe@k+j;$m0JenH{eYQl7 ztu{;|HEyyNZ3az;GvDns8rYH}uSnyfoQ_=*jNq`2}C>b z>QxsKLZE#TxE4-irHDLdP>?bk-sgF22^ld4ynGeM({hAnV*Kl{$-q<*R568Gbo@{Y z2iX~IC%;}d>XZgt8Ei1i`pwVddmTLnXzR4}Bp5MlbQU5=1y+q- zJS~y)h@aRqCe8Y2uTb7LvUMHXYG)q=9vnb?htiBEGxDDwf zlt4SW22W0O5-@bmSME(+FFg}bCm{{XXF7mB9Y9b%zS^OClbzBLWp6CJjyg`lwPchL zlz1xuh9f=Fmal{YbQXbdOGvn28lUy_KRH7r4N-kbTq5X!BAh;YuC1}s!%av@u-&>< zHaCb1W40TNR7Mve!QOF6ng zwN0Mtb?Mk_?dHkDr~|ZbR#_lT&7w=C^^TSy~at=h9bq4woT}^@o zr706T;c(2VL>?w`4+hPJeY%2Xh)Kn$2>~oHt<7(ex)m^`P4ss*35vICu|EdXr!ldC z{EZ%&2yJshdEK9b5(h!u7M?qt5_KyjRZ-`(Ux&C3w*P=M=wM5 z2eEKiilvt6z)nqSD~55Eu@!Jj9wnJl?ydN3M+ZnOkt{mW5N zoo!bxe5OJc)s$jZRpjr|XoIoZ*QFGqB5j$*aaWW@;kG4fEn z7;-gla)6q=)U2eaX}|KIsQCh@PT(Ti|IKRue@pV7vrFyz=he;+n9ksGLFI(4FPNGKimnq5%OThz3~4yb2-bIb5&?O=x(2c}eKW zW+~q?BQmbzU165r@B`2Y+^E4*K~|0Fv|1^EpmFP$JRKNK)^H>%Sq2i^2m>fB@~t&P z^4Kg>L#C*-M$!?kP58?U#hX|{5GuaJ)D~Ogiar=}qs=kgg}i(lAOtT+8wm)JM` zMj+=N8yx9_O&2Zk2;oG)@xEWu{yrXSTWcg-dA5N|JHI4>vjQ*nW!H9%WJ$U_at}~PNWcl zB!Ls4F_1e5-MM5hVjM4Gj2&8mEb>fkgRMTAAHtbDTMpu-ZtS}g9WjwZITH&w%(47; z(61E8J+aY;xTFBu@%7_#P^0fCL%+sur}%(HD_p}{QAM0sL(c+(;A4(29nmWIN0{r@ z=cm|_YCV3r`mwOz$z|X2fnQL;y|bEv9+Idmh5*F393F z+pGtTM^`g*dl}$`4C#9aTNmK+xW15;sVC*vbT?JP___8i| zE&8Xf;M~M&iA#FZL(p z;fHmgnk}MO-TI7m)*sM*+wbFsQ0l)rk+unb0r{iI3D|$JCpO@ft_Kn0Gyx#ep6NTZ zMT~;Q=#GO8+0klU$T5l~I~cKsC7>XBmtnLxnBspbech+@t%~iT z{w1oBkPp2vULcSjWC85I9}{8_0?a}{EHgtbmTkiOL9QQSn;T-sl*epa5oL@80a_{r zincPH;;nG&z0ZN+{l6HUW)(+;;lEdgXItfJPi%vHGm~?)5I;Guux^&Ix}}n~0k&;y z(PE)st@H}20O#vLu3*_nU~=S{)NXuQ70EN%B5Uuf0?Wv+M}b^KG(u1S&?{#+fe`rW z%w&UaVkWzuWn?CM&i4>#FNP9kvDUSd;^{bgMQ6e_gDCX%W6)O)WoI^JClE|N#5e$z z^aH>w2+hJ**&M=tJM5GVs?ABwPU0UcjfaF70|}Df7!8g2MK|bc)-`|+0L5&_*`)uf z+#=5JI;sjGnNDhiNPw(@T#7q$;-r|+7^FgDrVJHpqCrQeul*Z^Gf+wLsSyJKKZTB~ z^acFWy2BrP*=pS`5Y9}9S>PC?wK}(!Urj(VS{?%k&PG>8`$9iKdOJN-STF$B(7(yG z0{Ez^uO^4zEt~wSW{E4LK>qsVZy6Dc&4W6t5kt@M6o|kG=@xQG?ZZi`Kj4aD1~_wS zO{f?@?&1W~lXdM3M90}g=NJlRfNQ#93^dCp;M%!U;C0=lUEnqPnoY1OUnF*|ZdVcU z2e%UcKxUVc2Fif39|3!3pq&w5nj6}|4l_O_cZfSBfNaLgT?Rp5?{K>2`+W8P3?w4~ zrTrYC2|3l!$S#CEKYRq+;5b$m&iq^!#J zdYnNHxP@Gxu!#78Od~k@No|8NN(Poq$M$S73-q83qI(3^-0`4iFKu#C{nQvfW1%|;?Zd3hvAN;u< zUQ(S)*7MFX=*HIzd>%-Y_Q zyic&})|ZOU8STpK1~!va-zpiMx`Md+1Q0s`&-tXEq1HQaIsxe6W{aBIW2p?M=J*z+ z`wrZpe|HaV9bX%6cVgrqVD1T9Q_yYwX+jsY$zJ8KS9y9?%*jHkI=)wm|21B|G9p?1 zPRnySNC7if1t6zmz-MEuhheNS&gRg*(4)*AiQojSj?HLgwr_eXu0EvUy4j~;@jisb zJBBOPbUY)QB5flTG}nwTp(?FM&4cK><}Owi$`f?%^$Op_O-%ISZGXBQTuYiS?{ zhS12(QAVt!&XX^Bf&kta53{(xNp6a)0_>QK}i|70B z01q1sW~H1uiEHicB1fU+Br3EVtN42McS`OtjiuNNIR!A59>?c^#?s@7Lzs)DIdx;_ z*;UAzP-&j%L{J@Gt-+{*vJlG5akm*An3Hl|oN@qeyQupEFgK><=zlZkul$ranX^l! zhB?wAY@U!FB*B<#ZM9j4UoMO6#>IxfPim7&GNLHR3aYYl_}oOw!BATB}rAC!MG{)ESR&1skgZ&aK0YV^XX>0_JSmVk8 zi3=?RxP}C*l3!t#@m#fZx}ed15s?fH7HnbVb9xt9sFQf`j`21-6K;b&`(O|NlR>*7iwFXR*wb#JFW>4{+=X&yH}j*H#s)5K z{^GsA)PtTSoDn7?LM|!ud0*M$>)42UDEfKl{tEH|+@uC056=mY-oNagw2s^@a-KGs zJ|BvP@=sygp1&Pun?(YSA`;%+GR_m zY*Dw%Mo@V7Y}0T%es~*N(FOnXjV=n@rR}bJh4}^hBh>~_Z3*`ctnsec(7no`Dg(hy z0Yv}K;^D{Mm*4Td@j65-Jv=~pyoV>;3r-0eAsF}KSlOvW*hsoU@Dmk2@d1t~f)E$i3LfeHU{->g4Xr+;fw1-|#QgO>9{u%w6H+{-6!H zuT0AQhp5Rd@dE={;%ukH^DJ>%Qi=0Fwd?<4Cvs;vx$j}_eRm|nzGJ)TsnoxUCAR#* z?rnf2-bgAj(1yqgGxt&__leB?cv9}#g!-qk#4M-8uFp~87bp>lH`&3leTy19n?2y4 z13z}vyR;%Z89o#DcUq=U`zJ!PE%AKOu;($a3B2M-s0_Jknaza?Dm3v;g*_hzvGM25 zzXLar5HOxf;kiG)fJO@@pj@H}W?>x}Vudf(3s*zGga`ccRmM>dSobWwvb)AGH@&i} z@Gf52KjVjWEn`2zo@L(xgdrdd8-$W%5UwH!-@Tgv!edgY8wh782)z}Ad;#G)2ZTHu zgp&xu&i@e*4h$HXw(2MW!Mb?|$pF)W*C8XJNkRT}2!uUbkjdKp`TUO8v0DXcN8;OB zd{b8_Gg&X3mPQ~DSKIoZV1$xI=kDZDi^3kgNDGjih#?@dAJ{Q}G zqtjx0$!(ud{FD4U3kUYc`;SXPGjd8AKBqHRd{?EO7})7)1ESbdyimD6;rAi!rSz-0uu902=+yRl0gF#Cghi-R8l z{^HX5dhcCPmd?TQ zW??-HLTq?}s{% zZW4~T+E~E#gGB`g!xcscd81!rZa|DxD#rTS80(pYv3Tq${{9>EJLR(k`W+JK+(WBn zOsB4NpMG;Vw#n-=e}UdivlgDh5aX)zsOB)Yz5x7D1$7v@6g)CD%U5_&Ms<#L*4dH? zXJf*HrVD}8nS~Rw5!T+;W8?B?JA!NZf%5Ku2dLVN><@?@2QW>l+F5x0%U^ zN~x8nImrnmw}kH?wd=e%u^2Su^JW!g@kbeF0hr59$@OD&ugRSd0B9g7L}%diL-w=W z7aWyKPR$4efAEtxH~NDIz?FgES90v(CO;3*#QBZ59E%;(wGC_D1DyvZiS(?zvpbDb zGJAS}1`=D165C05753~Ds2t~CkbBA8{R>87Vpgdb@z&494}+Bo8!I)OU<4LV_>Zd}%T-d3M~XbRuk&adtK+HT$U zGuD4&nhEghxgd7|V8esm#)Bt~VG#^2Q%W;9GHdaH3s54>!axgmbEa7h`0K0F(A%`? z6R{@$@r_V(;mlooX#E)}2NGP$^2kW!XvRNl#v=yu@KAdjk8WY1@_~%)g?0Yf;Eyn3 zF5_T7oyHwtx2(~qGdyVAA6Ua;?IxOPW>XW3tdvszJTAIZWh2gTcgK5RTAJ7#$2uJT$^AA(8CL#{m^N6SpSiFj z>aiU)I{puThqDECe6gQP^{jug*9K=a?tvE9VC*aEbUp7pg!Qz;M_*kmU zxVg9bf}417%o8=-%tPH%xX(Lx5VH;il#F7bGU9PA(CRRGzV?0hf!yIZcsG?(Ss)!Z zV8Z=adjOX=-+_Ju3LMDP>?j^+#QW4$6H-}BDp<}K>A0{_sx6g#MQKYiInxVpms z-B$may*M%E4bgo5bjg7O&2TX`$7VdPtE}hf6oYDqkE=W2xpyl5_Np3y_&U5*-%3a; zJ1)wL?gQR{WSq0F3zcZG(pt%nfTXhH0<1J}Uc>Bc3$8+V8l8rse??Bzco8S3#2}zLq1073$@|uSv8t)ReNoCu)h6^#5zm|tRdWfp}}~QZ|E9aqhj#vAKb+8E(M;Qp2IYgP(T0` z#m;V2K|&K_WB*UUmb}8C)%r?)Vu1HqpWr8&wbfkAA<1cOo;4(2AqEKXf8=RUdo~*5QZbKV!)_h)wnwC+g&<`Bq%16sdcJ>*lbJz3$iw;0 zVYVipVTQCV6gNVsvPm$uP{eaE8UBOyPv9TlHT+uzW`Tbp;jhOTt?STL&u2$NL&U%r zFn>S72J;z$S&va%xI+fhD9}0-^f;V4JhtMtd(x~M5Uoy}eK2>=t6YOV({$5I5}3&m?knzS}(%QW* zJoG$%co(eoh3D`WGi1$()Nii#T8|y`IQoQlHO}k)LMlnCKFWu^s;h2R;@32(Z0%F_+TqZ8u{Gt)s|2qLa511-7tRK{mU zB7MV%$qKzd7-mEo_7F^tJz)Jx#J&&$Hg<;kiG0~y1$ELRiBAVC5I#Ld9*KPV+%TI! z>Hwp(e|=*6wKe%^)#nNnf(aOeF&J)$!BAG@aN3LKBv4`~F6oKHBw@l+Z5X;2pLR(i zd@;y?pLp2b7R@C1F#r^SOV*4?fK34S%}^T&zp^RO{VDkAZu=8EwO@($|8jcg_JHB|!e+571VSGU1!%ciH4stc>1N&>BKk&T{!M9K!4?HAf z`Jg=P&oUtWZJ^rzkT4LTq5^luF}bAuZsMonM&Kue5Uj4{Tky31Hh#Lx-`)eXtb~4z z))z(W!ru)MLFE1NNaXL0r`n`V{)T`dYpIB+aV7}3O+Lu&sk+4Lp&iM3w}7CUBG=l0hQvGMR*_d(yz=4y&`sUNA(HRz&V^8!{lhUDhwDo6rk|+ zEmI5qfeJzrT2anN;ilX2eWCszP!h)YS512e!bj!_|2`@Y+vJBSX6^DP%$uFmAX+V@+-IS=PQE83WUu?ZZNhB(2Fi=^S zm8dAR(w3*%N?Tf~rAo!NK~PYvf)_w(74P3|utnPnN^Ab_&zbpdc9Z4S_IdukB;U)< zcjnBT%bYpq%$e=|Zv8s}`2l%`_G{ssjTxy!k9!NAWCs}@f|&zFn+i^^LzQGw&edV> zDGj^#^K9z!`r)?fUrP#EU;hYKKP*uPkMyel*lpF{+H&IVO($u_i9C|fO1$;sKFtJu zw@a*GHh-b@*Q zXsob#pYXe8Ur`@CFpb;N&jnvImhxy-+mg+#AMbu0XHsQgMgIoerqA%cd0=bHwFOOm zDLJ9D$RMOjuseZ2t$(F`LD(C}-fwcppBk>&A^vs#TGsmB##E_A_muyarb!(tg!@&z z>01wcCPeseavSXNWb{={{n=I!tKn9x2Dbm-vX~NnBqP9;W=e?GBFfyxUN7Zbj0ue(PxZf-T(wOAnRV%9M;kX6qJ<5?n*hu^A>jaZhf2_Ul8# zuHKbtHgmJ>_IK;i{#_F5J=>?dJ8Zvld+meYmL1|3*Jm&OZh^ngc|F5_FC8rCa+uo3 zcO4S;eqpB5SvS~UX48jga`s$Zda(h&cevm4+iz_Az6^YzLpy!2FG&VqN{S+p;_|2! z)wTb3L2%}D#c+(5kx50gJIJBupbUV&%z`VtrF}QM`c05Mm(glJV;{(Zp|$0jf~Jvb zfoXW!2J1q5U>9~TvdIcB*MQHTg}9f;c|~SZZSd0)<|oYW^dkG)+4imT;f2tvGZrE> zaRwc{Ho1)sRvzpzkk39~eU~NeB8zqDY93eD(Bu0}{*;&r{ z2D`a{wQSiH92k=H|2X@_PS5XGwb}fBwOw-N_nDbGbLV%{pDG~YyW@HFr(MC{P~mT{ zTXuxMJwj0a6ZkXuc6R+aV`E0YmK$w5_N8|w+d#f+m)x1<)WIQk+F;^jb@?_Z!*Mv2 z6y06{evfVMckAD%-t?6;%T*8i&_kVB{fj&zD$9lajsrs2AM^sq>ev2Yq*wy~p3{T!&x{~PL3T9oap@?sc{Shqb@6{)gvvR)Dh~*Oh0Cvx$N5R}b>}VM$0nJLCV@N&L+d z{=RVCj_@}uZ2SKVe><%o{`d8Umao_)M?Y+egaekVAMS|%`8~>P%Yrz+d_cdc+a3+_ z`?=fu-RNT{@e@58{3M%pgrCIT|A+jAWX!fKB%{UAB(W9*RumCfA^SphXvN0Pe&If% ze>tw=R6^|9GaSAn|17v8!t>DIKeT~;H{3kSjW#AT>#`{L?YHtS3Np1nOZ*0@Vv==e zkNNRWVAs&?;g|2Rj7^pSD{rwK=?{57%7QOLKgH1m1h4!$n7Ic(RZz%|RPwofp)U*H zX7*FpmFRftmXhF4Ule&{Gl#xldBaRdxQ?v}T06mVOH z*3(<;fMOi(q?c{w-0!I;nW@Q&-|4I$6jX8z3y)-Qv?ZNf6S}PKq{otEaLAC(dOY{=A#Uf!$9dOVgiP+=Sb799%~A>5aS@+4}JXBMA`K zcKXDc(d-E%-}W6-sg^P6&-soj(A3E3t^-DT22Nlrbn%;&YbU@f zY^yMaQCR;N1XIzYM-grcc@ws`COBuR9Z!N0Sd2wvVLi1|kSqjrR()$wk7`ez*1tS` zxsBk5=?l4PU{y(Q&$1jU*gx#pn3D9p>R2j62uX!@B-W-eb6EcF`})z&iK_) z1?0CPI*{PpcZ2)eG~)aePf}jUEq4+v@nSsjMlj_#F_i7W^GAvDK(U!V4BGbV&9umK zMYXrnv>IXuK-QKLJ*e-BTCdlGx}k?gJ=hrR;{x7ozktZ6)|0++xw=Yj80Q?u=_e)CokK;rKhOv-V_iF?yJ7wKIm2mEf`b{3{Ah<9SoWydEG-i^*~t( zlX#&jwvp(24DeS}XpeTGobrrGR~<`;AUC8|+TDHnGvzPBs*apPTG zCa6+X@7Bt6^OTsE{IWy`ftXT06QvKe>vVr6>ErIeLPTXX?}eDCU8k4T+I41Gon7aY z)pHeKt{#_4M~F~;*@&s|&mm$|Up8V?pPv6W5hG3G1|rwmd+3qX(+G$abCPfbFOu?P zR0P8ddx^QoBPu5`CppS?K5euc27zZJo%G|#w^qunnv?%qGNo0d0%?nMHR98_wpO4& zx(xGYqG=*IPTV~*Wj}MvItfBnEzzKORv#i-vJZ#7oKa&ky7V$7?N~vi%F4<&-L#a< zB(P2v{XE~x)%jjt(d#9GR_O(kMR)R($ciLPGEX$3khd(Af?o$%lE*g36n)7TtIH{t zEIO}O&7vBO0lV+2Gu@M7h6t5A8dNYtTH3`ZlPRyHe|FrA8QAUF8!AFBAHH7BLCcxx z&PN&WXa$g7yo%u*zMg#!SC9JpS&()?xz$P-Cy(#AjCnJJ_AFO~vFT092JSX+u# zQ)M{V62eP!hcz>T(e4p6R78VcT!Di#HQ-O*8v(VMG}rW!D!R3COu^#+(zvI1n@OWN z>iQqxzYlKISLP-C;K!ssxS}E_k)|pd931fJtey%$dUrSNJNo~JqyKuX5$m)@*`q?=RZB=i7B+yt!kEzq9@N?==kxf1a=O2btNEI#otLiWr97MA!Y6&Z< zh$d#W^1%7;R#!1~HR2y-Q~NpeaBZ-!tLUeH2`ehM_`j_aGf>?o8qt19R6 z+_^th>V}O$g0w+ZYTc2u$Iu^9p`Ao)gCit{U`D9Ww%-W})o9E6YJ^IC^08`HqH^_3 zH?!kTFmtGf`WUZ#I?^VcTjW(L5e%IUjFI1l^W#yeW6AL)6*b9tNtpEYIjtX8pXR!O z#?1$@#ORWWSn5Q`=$7iXs?S=F_KYRQmsF=GqHqRp(hK%)eUp0>rf7Y%GTPA0DO>JX zk;-UG^N~Dgh@+JTRWpgZrfGb5*05#o@MDBu_|Z{t(4p&3V9|Zbu{z~wg`iqb;8}a{ z_fKYZr8nhSMM?kVgjBEpE*ebjlQ%YqUC@8)bxpZzZ26P4$;>;ytj>N$Ewn3pJMD@p zVAm;Sjaa9Tk-VBN=pEI50kh+x3gjhqETqPMAEP&>>xb3v0S&c*sPb?jC4o;8`( zG^eb@UWd;Mt!35BN)*YbA0@KwI@7@MMvaq)KYjA>7fv3&{^a3rpFI5ilR0{_Lrh-p zE)DKd7uM2wg3gr(*Y%7TTO83?Y7%eOBsSJ0{;5sPD6S4x6Oyaq97V5$tnOXh&!n29 znJCcI=u{lmZq!&ARV5xUbx>-fkr(RXT*gxT#rzSO@>jW4H4%$yscxEGXO?Z?iol4w zW`o+VNPaWkybkjt*rv+WgKTr;INMnHxM@gI6|FjLuUzO?Fx@*WpOfmS>SKi;NV{Fd z?G%nFn$IcKw%>A39apU%4CgESp3CP*ji(u;n&RR4UTnTRh4$HRDYdjgbq?Foz3VbI zWQ$gIYM`cY)o9p!T+PL=#=2Iz?_+IS_ln$hR?h#`{) zN8Vg8s;lg^b}77bc~_IXxTGfe&ElHGdo{y0#w*{t`Q}qo{ZCMWB>G^(nJO9%gCJ&) zoFIYrxLcqsA4AL3350IY≠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

      6VG{!=H`OWn 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�FEpMcYx;a46ESjE59K%9axX*ER~rj@&De!v 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%0DmjA;)h> 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

}i4-HHWSa{8a(A=J)fPIvG0;Zyj6UW)--B3PdoR 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�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%0AD`Gc#w-oH^&rnKNg0|4*BF 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�@CH}eN3pDI2?FCV{R%e$av1xi^*3Ix)F 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�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%0Dypo-H8VNj4iM| znMGZC*A80t!3A+}#aYmmXSpjV4!!t@2BcJ5$&Bh7kQ8Z2AzoD~uMla*pAapd}_r34p2SVLS!M^LqlupNwYAd3w)2(49+?6_i= zjnhdcfq*VdfyAvs>?1~r?)qa5b^)&5}qr)3QZY;qo z_ok3Hep}PX3mg_z6oMz)lbZHHBwY z&J^N%^S$MJv+nNadi5K;ZP>%`aQYtNCcgf`8=z6R9ox04&DXkCn)iscb85y&v9<+M z-BY#_Mn+w#3Z%NK4yWdFW3s`0;eKGNoCqWCxR=*wQ{=9tpVt~QumMf!DkuuD4=Du?Tx;QCraA79_5c~0)dwbi^Q9NZX1 zo?PEij3&(wN_w#YXG}bHs)5UMnpxrD{`DXr(oy_Xp964osSV;W^SxIc9;CI|rPY3o zGKd&At95ZIy-~X$yQV8+uS>tb!JWOy?Hs%viifPsaM}>@<#raY(X#gzFBfPK>t=m` zZrjE;-<)bNj^K}dpONEl=I!7zsFB=gg6@_CcblT?u;i+o$iqa{#pxCPME6Fw1G_}s zI18pid=9`p4hDWU^z9g9#VTw_Vqm0FPK5TVF1ikqJp6#XZ``xhWcJ`9Qv^u+m!W+y zHjcKl{dj}=rG|sQeppGdk%~%SlnWhm&j?kr-df*Gr+q8Rz72z}*bk&GoMiXo>@*`x z?E=HO{Thxj)fDy7{IlVaFgk6T3ocdZntxh>EBn~I?k>N>SrzId$Kz&=;Zco1@hOSIsRJ^_zNWsdYx~a6#2@vkAD>47@Gp>%$Sc8 zgmG?v0v_C&6pw0?lHC5WP{i-gj46uq_`3w#x`bm{8G`HOC8dZbYAxna^{>S3`zQ<; zXyUvBKHgMD5Unj#NLwrLpb|KQ+lnJ~o}5owee_$na&Gtd0`zOj_=b_+=4X3+|HQZ% z}(g^XGvFAl|y^e42F?>*QLuXOvq_V_+Sn(E-+pd>iG%;v?6&{dzu z0(}#&ig#xpb}n4Tr&XWEx%{0HJpQQ(I4(9fA<5(KdKC)gC8W5Kq6ncykd??^097O> zhw=gbhec!EkmNaT@JAN+wKUo<=}(*nX@-3(n1c|Z#F!4~;B#Jlp)%8RM~i4nyNqrr zAQ!%N<6%xvPUKnZOL%$(-HfsOy&Lmgn9N9^r2Jc#(Ep8tcb`##OVEIq<+!XMb-|#} zb&Myg?NU52DP%8?8d?7QO!O|D!l5%MT$Q+$C7F) zqFMTHm)Fd#WQnRnsMURb3Q+k45n@6H->ZtR(dqEiEmv;+kD_v@_=J~GlPo=wPlors zCgJup-TZ|EQh_`-lXbvAC5mJ}e8V7PWviik6PpDZie^bs;QF*NHl77Ap*$-EaKH#> zDQb#Zm-O#BsiL?)^*nr1CDGWyVi63l&LmK2l?wePETtO>B8+-wsALXP5%OD&SJ8-o z(^gt53&l4qVcpo~k1NUUiPHuMh(q5dt#tiSq+!8gkC8kD-j`vP1dK4+N`^|VbZr5U zSdG;G3Z^j5FAc>B>$t4}fqPj7lG9-7T)2}9W)nCtaR)>p>{*nKzx|6YQc)`R^#NCY z&xn8Qd1SY+yS+vt!^y=`)GZfpS{IepMYVOY7Z;lTD^zKZxJh4KXnkD;~F#6(>p3UBsBRX^ZnDP)R|N!vFaE%aH)CE&``W5Jcv&SkvtDVi-G*gig1CT zlL#MrC$3x)161@C?4%-;AC~u+rnVZJk*b*x8K{A=)Q-yULun`Fca0=pqT`!{EMsN? z^L-_L2@%T^0`{Nx6l}aF8U&y%m`{}cL$J!}QN%UMH1^DPNHw-C4&e3M5AuV7azx*( zV2Td*oaL9wuL>e)#X@Ar=M{L)H3E2UkMS(s-0=NuepxABJS32jp?AprJ1R&tzWf;X z%qO&1p3`VHUcBUJ%*(FMbv{?g%_658jJOFu;5-fvR8)cw5Zn{b4sr^^q^D9BdVKFA zJJl}6#pVd1cU}&D@$BDF3n3ThrcK7pzbJDH*)mJv!70M8Va3b^r^~m|=C+0^1X0$C zKZ(Xn^Eje;bP}rkwwvpIZAydqvcXbeLW*y) za6H`k$U-78``ZPu)O78H(0}IY_y$-Z;5mF}>n{LZiA(R>5vzS1jj#ky zO0otNwMKy2IDCK*-508k(_XK(#FZfwamg(ECF2u6{0wLhF&yj2Ej`JBG_Mu*mL1H< z0}ze-e@(D)mFuhI5Q8S1MH-6!lIuNrUGWZ9L{(CFX zTkZuvf@_F)qcwivlrH)e`}Z5XX3X)@`Vw5Rce#!r^aq%Xj3tv)?@}3!Z*RDBdHV1V zfZtpOB}cIG9p3sjvtC8_TF#Sz!JLpIk;;BS#e!i0!knS{^-i#>(&I3yLyTbFTqOv< z-4I4CPDKz2b8;{ZG2oHby#c+8OoWc-wA_7^>wKb;8fcs(Z}w{^`34s3s#3tk9lxLMej5U z_V*p|&RK@{^L-(JD}ukIE`}2tJLh!@Jq@}rd6uChIs@nyeTvB(uDe_k)O{q!xi9<% z_5_vUD%h1Dw+nxqAeX|klPVa#*vERNtfx(r%dHV5*YzuQHBt@$>jhlA6n7YcP|Z7u zQt)SBJTPjy#EB4a)ARj_v=Y<_r`!|48>pYv?ZpzL5~h32Ib?_B>Ruzh@zEGR11S!0 znCqOffz?hOh5vHHV`{u3sF6<#Nnl)|A#6x+02tRyP=uLAwUVHbHkzUhC)&(hiG>*& zeT75x+i^TL589IVTcK0mcRdq!Vj`Fh1OE=#68bwIz6%S#5GsPVkat0+6Z3#y6FdsjVoiHtD%PW5-UD6l4F-tgT$iyE15Pr36@v%}24_Q#7=s zU%%p9mp%@%#-_ZXHkTJ3Kw?4=Q))W76V$+*NKyp;h4VnIjT%3;P|tn z3r-kciL@X*yBVs^?Hp1qD>-DNJ}bQUu5gewm!ZIc~xk~`6=Bd{7ZNFmtve8)kjS6HQQ zukfGI{}4Kc(0fl(@KS(z*V>@srM9L-&7^EkDhi=z$1<=82d!v zGTX|IGX5xllS(h3j5Pbms)NJN&{Jy{M!7+9nYj(qj?0H=@H;861YxBciAPKkhsdxG z)A9|L>k1|2bP29GMcn2H_U0gjNW$KU@y0I|lNNG*fXvz8^8JfV$%@Xe5I01>3zNfl zZDw7fCWix<9Bwiv2kOrAA7K>w1ATTP6n$_E*0<*DfE*Q}$2kP(L2*h&^jNhYEK0#X z>;c+m1^Y+sWJW+8s2C^V&eb-ng%sKZ;*eqyzrkTY6Ve!pzg=$0fVAGuvJzCx#yH|r zyW$!$nq0<4$%tG*R`M4s$fwPF@*MBUmKL!ZuMF3i?^Tq1kMCoTZ(r^z=};6AUHbS) zY08~$Odjx$MO0m}j)-~*1|pb09Yo~S#P?hsE|q#BL4*bfCNn`~a3*NGk=*t(;a^NC zuu#Sr2mVD}^$=~H2-T?5v?yF`<}Zk3=IhAJv(5Q+7xi1?z<9;evqKgePOV|y<^UvR zC=^1xo#EDdLf{@4sdv50qmSQ#UEl=g!#so#8p**zkssvmRb4}iYRFz}2CM)!Z3! ztXG8T68#y-@@beXW0BdrXf&t-`=iIDyVF46txPz8_&>-a0h+XRdB1fOUFP;pq$&?5 z9cI?B=;L@e9$J7<%y; zUtp(mRMUd9s}h`0G7%47NwH7ZQp)p3>$r|`u($63}FSCmgJoaGnsp@jAM z9{!(*<2wQ&5N~ON5CdTkDVZY>(ykMHv~Fwz!%$1c(Wg_K@|J4hf?&COsN%*CUtsv zQiP8c_s$W{%)xmTKJl=XspD4SW3{Kam$oY7)<@R=H~rQ};5SgOt$Oo<^5Ccy7r@C4 zerW3lXsdU>IBj6tJukvWv1@vJn63uQ#e(G+_6Je1{@aq*zX#LQ4%cIGrnj2*wj^vq zBT|Nr(|VZCxjmSJZ#O$1UJs}-3AZSoq17>wQ%v#g;@@a_gGE3}LrWM^xF6UdMQWp+ z+UhW*C>jlE^6GAA0SV|BT3~+=J?F3TQ~NK`rzgMk@*u}xf7fSS$R33NLU3TCm&M>7 zw?6x=HUSyTN3{-3py<2vkqk&m`bzE(e;^0E^yFWlCO9@c3zo#E=g@7;RkvQcI5o_P z=pQ)CWJXvhO=eWyZhMMa5jQ~`13fc6)`jV@XL@^nGavo{UHfSIc(_??B_9Ot!AMqa zTrGEgYhInIrG{vFcOAiveUDPvhiRP0NQP{iYWk;g{7&P{Tqx6#@t=<(Vu#;G22(qw8=}$Vow@s2L9+U;}rHVW7%JmvOQ+drR>LY#m$j z^ai1bgnyyg$iDh;nAKqEO{Qm>?VZ}e(mjqTy$Un0+oqx;}POi=W09Qc0 zo{GIC=-O|}jY`MM7#vG+&#lO1_(j0I%lPL~Ou~o@Sh()|m=-ZceLdt1%oF7`(9{Th zro4qwBJo#Z6QB>7%rQ_jaRrkZD}rxL;-JsqVuSP4dp5!W2TnWKjuf@zL~tBQijxf8 zM$AFvZl04d9%}(YbG3pg@kB6_3<=ic#NP0RPI)%Wncs>HWf*~ly8<{+J>`CBxoVL*qJOWEnk zWainBNhOTKc&S5i#MyjeGSOLm!Xa5mBu@U3pH&ESV9T@o&iV|(jvR~L;>zs2)o-DX zF@D!6oKF?3uy7=5ni|XmUj$61_~aU$|J3x@=29Y^vIPPLk~DB7BJYIEj-dKiTJav2FD)%t z8>-ZH!TqI5W!#igs-;IN$)CR06rbwqHzY+~GkLR2c>q8!-z&wRGt)4xN&6W0Al@L7 zUx^pFpdpIK=1MT;ooio z=4QEY!j{>_j(>cs7Hvz}f}Xh4!J|=TuQ50L5MC@iMB^v2L&Vo&HsGxU&x&JzA+0>} z%%8%Esf4c)k6ms20nZU##`k+sfX*BrOF>FSEK55u;4#AX$3k5=j~y;VARBrtXi!oY zEDpTQRTMrh;YVn2DSu^tz|At;gcwoy^M4|~k+&WGu_4Z|Fk*3##W_)!0qM|Zo;^@1 z5U2jrOPdxCf!jqM{D|>?JaYV_zMnS!@8N9T^!O(_Nh2N=&yQW5O3YG$Lw=3}$1%6# zwQxTAhS@lIjLiGoUfS~FdH9eHlEzL@v;NtB3ms=HR;oU zl>m3fpvgv)uc@c-#c*Ri#vP390%8%Pxx5=2uk3q~9vS^ji=$E^q<;s7kp8BrvCz^l zELRO1ctiC3b-CX9^Jh(P<75@$vCJ5i2ZqXXV+1c|%X(bzT$~y4on}-Fq{Q>>rhU49 z7n~jB`5eq}pbeqJn8*t`Y4IH377Gt~zS!k~%b{_*e8&Pjpb6<@)n~l*OG+PgyoQv} z2=;8tZw%Oj@fmw4HNkeUEn&03)Ni&pAN~~JQRRkUf439jQHI<&#yWz-Id@NHCzcBO zj*?e4A-!ot?ObzA=41(DtSV{kIGgaGcN#XGfuV2DpLMTCF9e3Zm~m?!EWA0iZI-Zd zoFC446p(C%at?EX;J-^};%5TzBb||Msr?RVE)S1$xZS`CxJL^i4yNH$GR)Vhv?7oM zEFlAOfZ?K$DMIQt7XE^$viMZy9Rk>xqaYBBQ_qROoXf9IkS$S=gZMnL3F8BWa}?bmee#VK&r@82 z@lbkPtSe)KN1xCd=6rh7;nD4_JkTK;T;A_u=cU}BCrotd32yw~4hOmF!7_ohK!J1l z;1*cGwRN}<4;8bWDGSS5`|2~BT131ZXcp2hH}#ThM?J4JbFt3`kN^&lnUIwt}e!-1O$ zVqM96qr(!D&K!zKfr~I*y@&ki6Vr|={Y!$hmmX1C%4_DBHh(wA?YU~00}enj-hs29 z-~^AO5XtXpNJ`>MUV&G^j)*q%1}^aUZ+L99TuV@t{FvmOJv2u6VHFgr7|l5h$49t& z$F6`LcmBcO#Tf4-gJVHMJWDQNHNNCh{2>3EwAM!R#ofkcaE@wlAc^oSnO7%Sd z(9wAd=RIXpen&>S6mpqSAW}Jyz-_Rs~Fuf+bPpGV`oqWmN2C_ zVfV3CWpuYEm0QocXY+&|H=730c3%R3_)mQarkf2PyWlgb`c#JP>FQiw1W2=wIUifU zcywBq9OvVk7@w%Krq6y3!g>>>b`CDKa4n-z*(!u)eT9uw+JtLh%>_!QCn2n#`d6a) zuAb2cys#Fa@ZSPFxDyY&16M!FuD1hw-Hv<2A0b1H!KHB{IuG1$bp!XPpSb7z)up4L zKL$nQ>E^iaGS#Jb;5||q@%SO0NmcLT!uUcQI+Ck#t@*nJ_~XN3DS0`syaV|YGqcmC z!SO(iIlxLca@-+c0wjtt3}c6ze);ghja3Il;Ue}YHR{4yB*(26Oms8L^jvt+>%ZaRiN}Q)&5k~{x8h-aWt_EFoR0; zpW6XZ#>iZexP(6x>e~W?#7Km{d>4lLen_(Bqa>Q zXJC)rBgeLQ#iecix}4xNt-s2G5}Y;{hDUwD$06~7`3E!VQ4KTQQR5Qv&b%AbNM2fk z@yXclY5&B61F5$*#})J%=75la_&xQoDSqPyWm5dcW#g5I-%MP9gVXWYn7Ew4M=6j} zaa(jI`i=45ClJLl6C)+Ech>o_RurX?^S>T<;W);xS=~cLzv#r?>xqNr;)n*~*XW7s zj~~KS;^}rAc6kCcN6K;BGaKr_FL43-tbSL9-TPy)lDyZf3n`meS5kph*GyH{cB$*6 zZb`4rtcwG9EiR1vR87BOO_!K8C8?Uace85hscL#sYI;3XlWx^i#+oieO~&AB&@o|1 z#^Oo*u*b5PbuxSDahw18B;reY*>QRj0oJ&8@JOk+dgA9+QPF=@F$Uv9G2K>dFX*(6 zG&RnPC^N-YW_hU0@du?jvz{TgGTByh#&%VPf%nkXg|;$1Gtd@6HC|O^cqkKPzI!_i zc8gG%MJy8z%};X1?Xs2Jm2TEX`-duP#n|^@x*hWn3DllrCm$5A-80k?>;NiN<3b)9 zo8AF}b5}yLBA$dV?$?WWSTb(M7*Ou64E8f8o^fG-_S``#9+I9o{Ttz@U>ow&fBY5? ze1d!7f&I8J?ncF^Y13Oz#;o?E2242heNiFk2$Kw;5GmPEMKB;kaxh>|v7A$Xi|r}F zw}n=FO~1M@<}(P(*!D6B!ARCVNi1s27U|Zz9jo{>#^X=xh?8^e<7wYcclqabgghSI zK84aO6`OGoG=L@x&=^;h0u0PwkghO1-~#XSQ@jH&m!5EYg4!{JnCL+HNr6!qjf|4Q z7slVDU$fO~<0ae$`ry5HVDL8;TOk-;W+Ws8tT_q{h`XCmp1^Iw3!R$wAmVzZV zdWo|dnOgP@@y_zyY}-EvM?10XE|-#GJ!7?R8&IEAfo6gY^`H)u_N5pxX8BPvk6=D->tU5wT3`FRfBUfi z7Xj%~|AF~f^V-wbgs3X|b$>P#?vz!p)f0i=gI1c9?Udg)#Pdiwrl#yUNyX3XJ=fdmN{8d02<&#GFq>;$a@=u-R1Na(=?8}mQfpMWSkhNJP ze0S4~Ay9r2NAm|cr@N_~(+QmTk#iaX99Aj}k9-Jm$vkZge)HP~;FqbVbG7DEPj|jI zBK34i_fVqbTtsk`t>dcT^D0a78>sSU$&x$?lMm>tYJKJnD0Bb$IK;0nFE%Mk`~{X^ z;v;(%l5L&kf5RIrfR2<&R-F5E&R>MX(_OU}!f$X#r4LNR-0H!6=6&Vh;&o52*d`(@q6@4zR0j zFdq7-8SI9)y^Zu{dLina?05%;nElCDT=^^93Rm8O3x#;|uk`PK#sBgJ5%{nEu$ev> z_mux6{0|2HZSvXT-vK87c9ZeLh}zipf~&3OQ{X6_)yNKkV|-m^wjX?n)P{a89C?QM zSMW0o?WdFesic3Z)qbwoKBgjQOU ze)aPa?Vs8gYX9}ppE7=&3+GWlHX6gG{!u)WBpMUR#KtF-Dct6YPKRWLkZ2;Wv~Bfb zVy|L@(Ju`Cze`N;19w0UiUd&daSm=pKJrXu1Q~w{{i+ct%tpVJdqeoU#{%H2=;vIx zUg0m3GANxgC|%7#SpRbVsp4zuZ%^>T@&SO#3NsD<6oHd4lcv(vdOPesi;q!9J1)Bk znltYs?0rbw*vsgrY=#WCrANSSB*JT|WL>NbHQtKKu=a=4lUycPpo?;+h7c@5LwiVY z#gQKziZNELMA)&v?XhqmL*BS!fqg*9>DAD1a+cFjOL9QI1=6A^5^KES$!(Z>zo?EP2;TK<=So#TiItY%S zPar-?pBlT#W7ck9kN8OvakEs!&9j1t#-mC&;vq1C@(%zgb0b)yQyPf~py!f)iAyd7 zGw4?r9VJhEWAVf`#S+L5aOoMCBHm((zNpj9>SEz!c`I!~;qkZX0~7dkHP$%vWUSpv z$~J|+4B`(~DJ==>12Z+zx2b^7j*|&iwF)Ol$%yshrby<%-A@|7=2G62zo*`}c-MG+ z?%DFkPia5>4-x!%f4Kc#|0nHNzZlW}sa@gz&-p3+cP^A;9nHyqXSp~RfaVh;=Kxv1 zAGjaDKzIJx(%c&vq5eR=7zZ9OyCeo_+nm7g3BsqhlTVxbC-nU(`kD6;_G>Rkim4(# zx-*35p%zd-sGl`8ejw;8kyYIvUwR0j57H)JJHWD@_GBX>N|gVG2$bzIcxsyJqxA15 ztzR#CMRAeYyT8_2y;C#5g!@gr|A_VLZB0tK;_;^bJ0Oy6jAdAFit1nm(MC2zMuS$N zt+A{Xtyo4k^n=bJz>Mv)E%sh4jDY$DKR>g6H~GKHqtKKu&+M=;V~hv^a8~P+|8@O# z?P5hLbNw720!T<@Tj9Sx%TBZ(t)KrS{yF^T2>zL|-NKUMpNk_vY1aPHH0RvM5i+US zY0*-Me(c<5C3*|ZfA9*kX21=`%5CP5lL@f6OoR$GPL8*x#_v!`li`f*$~Ud5 z9$Od6D@|OyY{}5VKtK9V6HfxPvz$pM1y_t-+mvi-4u3xden}=5hCj3~V!@BC5gYur zWO8BnYv22s;4dWpZ$3NxbH7_@ki@?r*_I403}nv`kT&^$hW#nZf279Zx}y2{`$@hA z%rheevCQ9Hu%y!T3OU7D`=yBGi8s%F>6tab4^=YTbLjlnuMI*a;8f_NQZBsaQ|Q;h z+j@z-sydmZC?PYaDM80b+G;ij7+xJl->JoK#z`_6Ud{L($L zTS$|#X;Fl1+Os9p{zKEPDdbOVJX7Y6AF?ksBOeEw?JN6m$i9U3hq8U09!nwZ;ifPQ z@gW#q2*dDKndAQwJ&vURXSsed{HpgR_V?9e{8t@_CKk8 z=R(;4@g8Yzf25DKKhoaZAMu`S)$HEL3m6Qxy^*Wo40hf)EMEMHDg1#m81_a!j@A4L zaAh0a0t>O~h`kXb<0&BVhqgsNnvHD{L`#C*c{dKRI9i3aMJ~?>ZHxR-ZD2f&3V;4> zkq3Xv{Tt)J<`DHO;9o5+0f9eTn<5oz&9~0l6?s?fiiEjP`0wsW*%J1xF!$ebd6)tF zZz;vsa!VCMHS8tPe>{)>ak&_Bl2A?zSd9)(!TDFbKhyr)fqP7#MGp;3jgSuJ`tjx; zfDh(HbAPalwLe%Ci!gv4%{{`W#sP*_c+i|P#Vrv)1b-8SpNk^fSNns5QE6Dqux&NB ziLC6*`-3pn9Qoj7mEveaxY^K^xDYn=!YuJa?|E*QM;Dr_qEBUWZ&U;P{!Ar)=)IO5 z_m+RCqv&E>tiT2KZS}a*FCb7lq8cLtv>w-LI=Y{1-poE9H^_1rW3{Q~zpfnj5jJMx z8(V71zU(afTt;H(kskNy>K9;u$-(|_OXZ%G>K)j95`CF2g|lQ9{-2%1KdJnaN#;du zU|ETkQxG2nqZ7E_p&DcFopi0D0S`8}EMv;U;8=Ym1P6{vpuF)kU2(8P##?MqBsx-f z>cd16vhGbjPpo@={D1~ zI_i9DRFd-vMES^txfCL+Y-h347>yp~W0 zuebkBFbN}Wbc54_=PCN@V}Pbp^zWZYe-a!l;(jrCpV3S^0wwWMu<`_IXC?q#Ls7WO;Mgps9x^htHTgwb{2AFW2$ zYiT9C)y-f3a5M!%z>6=1ZGu9Bg)ubEe9j9jKKM8 z`8$p8glDI*Xd#`c@dsjnQg$sJcymQ28;9Slr+)?1a%2gYrWLX@g)Gz`i7b%JLY4`1 z=|=WtgOT!UxI}i0ni$Pdr^eS2_BF!CfWYOjr|6)D4(>&(*>SxVLKGtiX=QXGMHWYI z=_BgD5m-Gpxn3z7+?ZBYalegde930|z6i+W}DaZhO+<>GWHAOg7lDu&Y zoNTjei@;ttp+OEXpfx?%$|~yS)=BcKqbpDc##IrF>}(N=#g-xlbdvZI$^-&x(zNR)!3@KdAk1B779kn$&s9oC2+pj`+G0vm7OV+s@*dV-N=1xhLe z$~hw6^Oa1Ip#qH@Vx;IQ_6tlRicnZOh)j4jRmp^Oqbh~d3g-;6xe@}Q@m~~Yyl@k1 zCam6#IU8(OfUMELdE$;{2F~dyghWYek^dRs9gGIce+# zMo+X8+!C%tzMm2`f5-p>T5~|}IbFa**}IBUaeeR>VG(3+kjb^=Ca@Dan2M^?(Lrzy z&d$;S1_#Npr*)k8?GM$!Rw%OX(0`XqY}E0_`4JB){b4ryIF0n57CP}iRbnyVAOws^ zsbCYF0TzbExS5v1@p}RhbM=9rk0$8f7o{Nj3K$z94C%FdX{c9%;3VQ|S4FCS3O)#(`!HZnz&ee-0N?jZUoaZx zA~A~^sVKuUYtVOcWc_=h7-Wq5Pku!Vk}Z5ir#RFO5n;mMt%5^#w-4}|LZ54?TBG$5 z&_utwk`H-o2L;~Yb@oTa7t2m4)@Q&t2FYYIG>41=6DL5)QAnNj%O6L64r4V8ChEak zcwoFn`-$=A3Z71n`Us=K&~G=nA<$Csz3}H5<4f!xsfL-!;IH0xR_Du=d|5;SM#Sl>pM(F-CdJ}|!NdBYmP3VtylHLIUdVd8kCLi|wWZ)1$s*u>x@GD5-3 zpf;L6H=edg&|kR2oFu_Vocd4#hZW;mzi~Jwh=myie?GXhdQt`E6@YH(1`PegnJWAU zwZ*gRNygiS_JJO_UiC}pOZ!D8$F|y=7t0;YHLTz0f^vi&$3q@i7PFSFol2`boPu>a z8Zy;tHe`&j+6ca6B8d9M$4b9=fJ$uXk)=|@Yv##F^B2dv<%|KMa8&X=lc`*T@{6rt zH)beW>wT#F`aYG`pr39IdZn18a^&}bd>gL#Bh`wK!?+I1(1!C}vu?zfkT$&!WX3ql z8EFisLo>YtGcj#TisJ{en5}$z7EjOl>WmCH`M7gOL+A&0~zV z4KhD6=Ya__v@cMIf&0`UwLF3vI-mBOcvSLyTHM0()g+mP{wE`K-N?}FI8L-<%#L0e zHzxW^H!elDF@;>I)-JcCQkyVoV&aDy43}?Ppo&xUWSRT(JBzEm17iz_D`XW?kqeNm zJ{=W8{vbNO^-Pq1U~o^L6UIO2h=YvpqPb(3{z`!bPjm<+Xe3=^iKW`6tVw}N5eEYeGv5@xQ_GS*nk;@`(C|DLZ+cGVwmreDf` zqpg~*7yP1xeDgecn2$ZYC#5ByHu-N5+vi&CI9=*;0$<4Q>@0XfyU)l%U}qqx9Kq*G zwb@!_3YffZ3~rJoV=qd*h@p(Kyv6@-0wYNxRWpE!U`(6K##}r`8|LEKelfj0rBynbKyw7!Bmiz)y0o#F@(MJ^Wg#pRTErhBykAGHZ?`^&#(VGp$ z$d$?pM&+|-;=?#?H~94WJt1MJ&3LP^K#UK=&Ln$D)X0ayt>Mq}719F&>C{O7(+S#B z_E3jULM3)~Jq4c%m?YZiO~1!neZ+c1_9(Ua=Ut}FHKzZxd1Z$R+?3yhHvL!isW-U$ zl|rn^Az|_a!L5dSC5qOlt2QN)wwwd%1fhGjhM^f1)ypZ(Ux_G#Hhu>5`Y76cIfu}2?3xcJ{( zXbmc`VLmgpbZT7!$f)9W31pOnpLca2g7k5Y@M%SmhQyGT+xH)O^)T@7cI|)K@(bgC z+RBeb`x;>rjcw-(e&(dF=zp5ob^T3QhPG?@vGq^ySpVZ!ebxF8YhT`8rg5mbm6eD9!Vi}DA2m4Ik@NnQG{gCv7+Q#tN${3C36?Uk(MjK` zOdRQl^;SQ)s-gPhr!+dy50B{={a}6(5R#4UmX*JhM7@D9GI;}S)-vo@nz{{{^CQGR z%91>-yZk-P1YE#AMPi?P$!=R&vTT^LD}%C$X&jY$%D1W9lZwDlNHY8h~Yf@@R@a$=B5_6ukfACrv@4#%4oy?vm56AWyj0 zZ^tJp6v%zjO=y#-in1Y7{+{Q1n9tty_Z=ZaGC)-IGU1OY41>jtul?T)28YR1oiw{s zzt;Y4Q&k;pSkoo6=md0ri9z%NO~8~NS$P*qtUV!HDrHnWOTIJzh#e-Ykr33SCsd9L z$1f{MS(QdPTvmb?v|@Zc!ahHv;yN@*FaL3p6vakwzeJMDu^3+wDgn}r!~p4UtT+j5 zi2UZTwSKumXAoP+`TUewWPO=fYj0zXh&uyg+sl3;!-yfT0{bTKzQfozizf#7>uldF zF%vv9J}&7z_mb{}0ze0M_#;_V62L?JAKW0OeNUb?L=|NWyd^&Iod&$LDO9_p^G7B@ zXqRst&d+u3`k{tSr}bWDha^DwKN`Gr$;4r|=Q}1!fA`-fW*!B2O&?n&LU_ zS3yVebvs0gJYU4>9r5}tdYlPWHc60%t>vs-3an{sQZCNNAQGzRgcl#n@NeIa@`N2g z2C8#lG^MU-BVBd6e*H|L+O+GUvvx*OMFHK-GiD5uUC!g1f}#NHva<3@d(m5XGQ<=G zRGBa5si>JdK6Qy*$Oy3PW&h#;P62Q5Q!`+KV>~nv^Go}vhDX-_wErISyuv;ot)f1U z>dgpiCz5bO|C4hTf5GJe+qBcnn8ijX**!WTF_7fnQ&#?cA|h6QY%BoepRp2Q;SuTan3({7u2W(z;mbAk zn(U@N&BrHf&ZeEA?~z+_RMQ6RgMh1>kwb;2gQT8+_(=xh((3=Eke9i56uvmUy7jr& zXZNgRJyf52BQE$-UYFe*g~kKdOph+72Z60IGJ&HqdHsSBm)?k#9Uovzaztyy7XCJdm=8QyH8&!YR+{ z&96PUlcKjDVT(Sd#}t)FwbIsRE^|5g9Zs2>ufzsUG2TdRg5%_48Gg7aleg#&DbMO3Kz`t$jNd@laCb^gZIIlsM5;Q4WQYes#`+4z5|Tdys;?nS5O z86nr}pKq$S`v*<^I=#=WD~E&^=ZJ=!abXM+GI{Ot&x;u1O%~noUi9BewIUy53QPrE z;Q5Jq?v1GHexJJc_c0bedp<&438OCQp<9r}5MD6K`o05MNZr&IO3~Rq#(z@Xdg`?U z*OLm@>%Y%6_&sRpMrT?p0XHYv?X&K*F4dTkkp8XFgILA%qouhE=Eq90{QrRv)L{=k zU8p`<`FRGiXVLCtafaJjZY^^+4jaamvp# zP(dqR_QcWk8UCB>6(|2&s_d-q1t~{>m?8P)A?y(o#8#X?M;iPU@DM9Hm4 zna6hj$SnugpOimlx6QA`p2$Q-En-zRAJ)L>QorP=Miwir4tfX`s3c@eP|RpE%LiRR zW&|r=t?G z$MxqQ%pXhKe_{PY4zBq$?;&C~ZMgH4mCW?-vGqxy-z!v2@eCEaD@=ZWn zZ~tiu9x{yWzVQLd3`-jM)N+2iEbG8n!HuE+r3a5M##QCK_AzB9Qqmx(8de82AWFW< zFw%F7N))BOV+`R0@cnV=U6b zcJR+F*x(ir8_!Cj-gGxn@=owiAK~zA+}=x%O@W-$RlZ9EdTjIjr3Z7cq5mlO7cP?$ zmx|r(9M!$hU($~Q1)ZzfZi>_mKY0iPI9j)ezhsNbFP5D^sry!x3_S<$C-_@j@8`}*O|MOvqZf|Y8}1ES z>UX>CdSm5rxA!LeL(c-D>>MbVP^KFC!r6p{cx)G#ItFl%UoLicu@;h9sJ9-_NICX zhEL!-P&D|ltIZ%;uV-6$2C_HkT1TpJ&GPIoxN`1(#NMyc{M)IiGtX-HYrq*PLfMRp z=KbB;d(5+@StIzn+PO<}d?%;T?*<}tzI+9|heRGJq6}dIRkRcqO}nA!I?zGE;S|Il z03xf{@M^sL zz`AT!5B~ZyC+hF4)A`#pYXE;&&zx>5t?p21z=5_0yPa>Zr_TOUO)EQAJ4DXSpc5To z*nE{~af@)g&I-3PN-bP1mBIO`PTf=H%~8x?>J7K9L@w_%a=AhA6=ao8u}Zf)PN7wt zhCtaoGr!(7k*FCNd*>U$(V=xp2@elWGB7N2VmjSHy%RKXuJ!f;3*l=sMWZvSxP!@G zXUM-|Xw6gL%H!{#LjQgQ{vl)sGczkWD2ZlX39lToq@*LTF_5@G&KPmoFWWRtWBIn> zdN6AJ!vpu3@f|^gF-oMWC^T$sOOZurzbxCqSJ7;jigVVd(5D6lKYgX?{|4uw2J>l& zP~be&II^)4A!CG!C8;6#y@1gHi`lpGefpEjsP)?$fUd*CG=8L&Gk!=lwBuK1)!#8z zKsBU*@_GI@fZ^vgz^LyUjvgK0=+N4siJlHo&fq_O6Aybjm~InCi><1d?0OH&FPrqg zRqxNp&&Zf{HoIUm%6me_m7LPcPlJ5=O`GXX|2(P!-Ze8{gfkjY`U73Bq%HA#3L<7G z!St8+&53>;Zf72)k5A)cP}YPrO=LMaO+q?3q`L3zI9en|4Y%d^zd0`{O!*$Vw-Csc zE>b&)z^c*bkH+;>(c4*+eJ)qBRBE&LoEpirTC`nsXyVZ;Qq19Mnz`phidR-#;=X{8 z(!cp><>)tNZ1MUzCv!H6teN7KbB=d=zgltf)G+EZ5&=60=SG%1vHtcpzeYI-zRYN10oS1NdEzp1c<)#3J z++;W}r+V4{%zaM3=@YgF6;0|lIqlj_yB?l)ou78yH|^TLw7s79?KQ~C>9^Tj zPXf@Z&Hb8A_YIxypY3ozDf?mWtCt$%u?!;;c{%qC&a50R+`MWlh0Ph0N%V0P?|OpL zlH1#tx{FhI#RZkKG`9b>Ia{ii9zdRUsK;Hg6x3xTekpAI^s+4(%eL2Axpsd={jcE&gmNaIn z>pfwNsm?@tKFM-BxRtS+HqbiPZwGf^Toh6LtL39i_4>2cv@zBB<{B2>;Yv^tE$(O3PSFUjz6T{i|4l7qD#DySXWUOl zf=L8j-OtuL85Y1M5m#wAc9irT#_^%ZbI|$La!PCW*Hj4LEW)2LVq;!Orn6}Hu_aXp zb~-T;CcY>3Vb79=9ocPsVAS52)CRqY)!tCBZa z^DcH4m1KF-s{mw7*A>LJ_H5jGbZpC*#w~q&ua12*rtza5y<20O$Mjyam>GyMlx$P6 ztxn_CzNTakQ?hq!e9dAQD6LFaAjY7*BjUS%Sc;JNi&OK`i z)>MC}KKI_)sn_N+yZOk%X7n|Ft-!t{xGnuaexhMLB*%=wUx)Vj)|?Vs-4j7 zxsLMLzz1AeGso!LqhoLG48E0Mx8KH_8e4m$Do8%gdak23uoc6bzrTV*lT2T@d0aPU zP;v7hHw0dCmeSo^wGZen@T+LJL{H96Wuy>)!oigq-p*ZxMhOn@h5o84&vm`q@XU^$ zb5uztfpjCX$7Cj6Fw`B@tx@1h}ZYXNb#$4lkfI-=iU9G z2ETimv#5c>+j(%Q*FD5-4*ymC)r7u4=7#|T#+{s*SvInHMjwN}vXM(?_IydbOc2F* zpj(9-@j~4q#Y<;iPtnrMZlPF1m6UL@6yAsfSrsQzD$B;dES-6VDVdcjnQiKGGv8qR zwftRfC&iK{wY;_;g3t>IkP9wHnoGvU2LB9&%_$algMT8I^ zFZT!G_s@EJ2>d>(cj@@On+N|d!0$G~$^!hZHn>+OlZO8~thWefKEiv>J%8j$yM@{BSbgb@ z`VoxA2@LZMOI!J27<)wr#{NNQ~$x}Y9j7Xf2A4d zKgG^jkzT}QM3Gb*{FBX7GY*dDvR&S!nGWW%3;FY}r{B81hJN)K?ets5qpwcCEA{37 zH|ckW0@^J7rgIt4?9|0(*J`PT!mGy=T7sx>?-Qq_7|MRrx|8I{BMW1{Na z6`VK=w>qWoxNQX9y&G5=v2B@*)#r^oA1e9G_mz`*Z@yx*=2o>{QZb~eb((f{C!ZqH zd%fI?7G(qu+ti}v(W=%Tuvr@I`n=J)PUKaz+9@oJBr_qH$x6KzOFBGRD#cg48qX4= zXey$%n>X)eM%jQ_S+V69f~{HQW6*Q!8lR+pqmC;Xxu@cFtzoU!tI9vry9W5=nn9yc z%_-B?PLLQr1}I}cn)o(Fux{{oDpag(DT91&C}rO;7mX<`Hlm|@UYX~<9IDzkU{)`b zRldHLOe_B`YV*|oPq8SlsPBNXk&PA43!?q5SN;X4>Hd<%z}R<%4tAUJiBr>E=&xCu zTuR>AmOP!4MIa}NRo?vwIWU$S1pE5ug=zmn0jt5j%OA<*p*W=T_-3!m)D=}lf{5ug z@Yk%GcdE1K7+9pTry+8pzc}T{<)%=kebjB(+F_q_^7c{bf(t?sUt8Sd-1`?*cGs~O zKEl#5sQc?GwpjVf^_i7lW6vZDZIp`CRprxmBwjUyAG4b$@n^~u&6vaA;#o6wO|)q2 zITd67Bd2+_)vBzuG3wm9XZ4241N*c3fbQoW@7fC|HXr6Kt?gdqwwb09{ZwT|&*fFa zD3@ufX$f_b$Lv*h7RYG^pyU@RZqiA3rXe@}tXenSe8P0osHsK6kBPkj17u)l-Q?8V z%^P+o6`wtv-)UTuBOfuvCcNgKgl5fIJdej z=j$NzU5vz+FZM>cgvqZ-tl{N#6{|V=d7YbCZ?F;Ho%ku6rs==GSYc@FpZ=ryUE}}O z-ajv@=>4O?^9T6tf=TWC>ucHIFZOYXVqn;oqd&~QT)vkuyLUAh0oa_7xU`=c;0TlB z#lJi{qtc$GZL!;3=3T_Q3>&n0-Zzc?eAgc_*ZF=>W~gd^Q6;CnUY(ibAEW z`=m?I62}yfi>K=ny)BhAh%6St#7#n{tOrInVT1Jp4owbYmR2V z9d2XyJ%Aj?{_>+#QONnXCFbMf%6e}Mw=J_33BcoQMJ)wXZThhj^9LnCX`8%gxAb#zs4ealMb2L_nj#4+~QHXhh-Wee6i3(frmIn>Y-=>WHQe}qH^CHjO5cjc_lFxlO5VQLE?-2CH^8U}b641kxI*~kHAa6a z)sEck)I7y|CN#{FmOA&&=f=4!*Ot5yma6&!2@vtV(=8g`Y&j^8XGj3elnCLm62QEn zf_bMncfDreEkyoNvSlNE*IE2&Fq!IE704_-%yZj9D^5;99WAa*0Nv|?@t{N1S# z3Pn;DmDWZIkA*AxD+HNnO6`Ru9mqO_4)GBLA5%t*)t|0XQh~<=R8lH&nie|pwHh!) zulgHs1wV!Gban22B)%!FLw4Y%_lenwA0lEd+}03|e<`$&he1XmP7t@F_**>dWJ6!n ziV=xNMdCXm-sy`j_J;q^^=7U~yuyP-1N3RTuJQ=3LoY&<3>J-@XWj^Bt}cy#$h?N} z^Edc2m`BwU;uc)ia2d>_Zg0Q*p($Vt_#4}wUd?5?r)Jt9zBS8A3V&>Qf%A$xTlMYt zR=$1$HzHq=s@lYXd}YRBHEacOD^{jgx1K`}ocpvp#;tBurp-A=$ryq5~Qt1Qdq}Gl~va8y&DI9Dj`s9ihJnE#c-5q6M!+y}51C zf{)zOuHc~9RTg34=J%roZ$-U{g>8|7wMtIcyfsp=B;0$Qv#4HX3MI|ge~b415_<^_ z`!W*W8~;rFNiR52%)~L<=q6)OxXmBA1+8w@6*+F(>S3#_#@E4B+LV^3dFY-^{`;q? zFDwnqgO;yIO)y#_{&JHDsaZR3yto#w8_~ZTd##K6AIs1Do-Yg(rT^g8<-Sv&_z%^Z zBfs2_gDNSnCquiea!$|6kyRr{l%H*DCIqW)L_?<8$o&WX6u&dSudV+{!+*|QCxbwm zT9^0bc-?&bQH!m(PW>SO*>8Y*k@sV zk6XOAGE76XnPdsFu>eOj-W(meI_h1-DIEI(dEUG=3Z=c<+akqp&hKLyX*mlp2*?e4 zcVs5A71cY0uv%*!HE(qbcDpr8D#?9&2N(y&RuZ@fww77!{xP%SUH+*h9f!+#13C;{m*54@ zbepzEdJ`;SLJC<fo<>$||FQGV zAZJ6JlapSgP0k-Gc9-Zjm1 z2vJKn0jc*#w%+gR2W1wkw>5NUvGVH1&L*OF#j#fY#afRoAI8_`+pka84<6~_4KpvM z!Cb9$5+2t1`%bNQQ9#o^jp5{!Y`uTm1(J#D{b~IAH}Xg3VyF2_UH@y}JtTcDNTbhZ zUDM|?*1cDMmZZ;TU~EiL8hy5l4xQPthPZu;>q{M^uID+Q=+ z;!oFqCgR98RORoSMUWD->8G15=B7*1y!3^s@)`YzG@2^$N%x;pTW8b)A5+NIK87ka z_QRR_38=z%xqSDpqROUGmMYEs`fu>3qY-cQON-Sno$YtBDIf@1r4Yi}-q(~a^TX(m zsF#}?^)5dUM&=-Chv4%~92suJK-660K>e zT$|`0ra;q<5OJ!J-f!|j!2fNTGuf(s5kl&XIe#s!Wm_->V;^OO*&Gm!zpnD(-c&sg z2=`@GmWI7c5g=&6_?GB^_rqfW>T&MIv zH2zvN{tAYVT0nXtUI95ucbh+n)O<>j)^Ks_oZd_yR<$TssB9=UbloT$%H)AG+O0y$ zh`CceTMgff{5-=y@3(e?qj-{SjlU_d8yrFJ1h%@P|G;xfz;ctLtqlC~W-?WKeUEUx zFdGmb?}yo`WWOXmB2Q2%7b~~^%yT7UN8EfjX|w9GC+R0%!oK?Nn{Rqhd`N->YO{y< z5lY%V%D5{EW0Z*!jX>M<%Pko&h2a=FAFVqkYX@)f@USV@; z_l*~1hS>pq%+wH(>z_H-n4oYwEi++p?e=h|#m4sCHDV59;tum)IXYeG1n5j|Q8E25 zGA8b@7RA4&>7&k<5$}mYpCWdP|2a%l+2a2&c9Bw?)a%y^e%Xfpn0fxQ!l(H4wz2+&+E5p{RNr+-&xV!?OfAx42G6B4_YV`M3AflZGtHg;kjX6qW zB~ya4OKRs7eglI4Ebg8D?Zx5=C4V6SoBtA**HpzuLq7u@u6EHOKQk}>@wuXKiOf(FB%*S`Fl*e8uhW!YkM=C zjeiYrEaObbA;GgpCi>us=I8#kXAA27_mFv)5k6Nx@#zfh`-ATp+!K<6`z)39`t|w+ zF~v56vOAT?HiJ8BDjtM(FZ(<}{BQrK1H|3Cf;e9-R;Hk%UCwvIQI`g>|GRG(Xg{qn z(7vZ11MU00^ldt-y3}OzYAQ;8ePEm)A7Lf-@onv-;IO1z-X0e=@g(C$_FkW(6etMYb zW93(RqHuFc{tUPB$Fd7K|0EZXKUN-*=R)_S(R-F(|9ZCdvOgkC{+QQrxOtrgdrSUI z>L7nO#glY{eBMF+{HLk+Ao*kJ^ZHGDiy={=G=wSH!$1n4BC{eNBYSo%F|ucMy6kb0 zJ?BdHoMUCrj?b*@xhGxra1=9>LccuU$e!;@_MC(4!TLq^ln9X{1KHzB_MGd7ZOIEU zkJOal8s7);Ezlh==qexYfYJAl>jJtA(}s~hNqnZuM+2XChLMkNR2leQ z){l{o%d$Gl#~UbV;VV82d|h#~nCF8cBYVgnv5Bj6>GRv(>C&gZ<)RdH8 z%4T)989&*Vg&^e9zvw{7fyV}fR8AeEm(S}aN?>N2j92ML9+ddcoF?4$%K>0ia;ARb z6VSyy%r|fsnX9asT|-Gx4^xcz+J`_xUCLc%bFFl^_XaW_Dd8W_*Mp-S+J@w`{}brWz9lJbJQ z2=u$6a5^$=)a6P%+_+;**y}q|yNtj`36YWHC;Kl_xg39IYn$REMKAnS(@i{M=(!WA z4zF}se6|1Z^=i@B#Yj=tU%7;nD8RujLT{0ziEVpEzFT+u5Kh+shP@o+fLNa`v7RQw z&t^0k8SeGJdcQJ9O{55EqpE1F7ysKUBa<+xvf_WTiBZWgC3g=KotB^JvmnbXUp~fT z#6Pb_JhNA?{$$cssnTb8Y%4VxasOmOlxomNRJ2mRlwQNHsR&%IH}8H{xS3zv zJRUhYpC=5E@^AWgFV;C60p6>Zi5$!+Fh~6Q?105u#-*5wL|$NJ5`%GN+OCIo8e9Lv z5RtZ1{%>4tsNx`&9@4C}?X8b3w;w%!jrvnei+`KCY2XDCKsSN+#zgWr?Spnc> ze{1za+t@+LjZy@WX{QLI934YVp)qN#+G=gB5O4eIRFoj2{3AeJu{#s?de)DdS>QDx| ztoC}DR;6dK8|lwB72gVf#+JDj*X;wlefsL>bPw=v3`2pE*Pd6Q<^B{++OeO^uk=si z|La$R|D!tMf8o!;|B)|t!vEh^g8$h+JsAJTe0eDR-+hX~|F-ij{?FIP?fBpHg}&<& z|Ci~*cKrWAB@c!FlT9Q24tytx|5$sy2jPG3$*TAt*q%(9)Fa zU3LIR%89d%CLlX3X|%-1@5e+2k~r4fOrffgMNUmjPl!~RGsRgnA(PeGs@Cf(3B{Yx zE#h5xz#I`1jW;H~>zMpeDtK;H>kliLItC>qGgQK?-|PKxRjsot$*UZ^&k5cSp}sZ> zhWD%wH|`xHNBTuxZpKUcK5@iLa#&eF@c~x$e7QuA9r^E^g;J?O`v>||;_71=k64c|l-9qT#0lhkcNYANX^i~(D;l)+%9q2|x_dqcKJ=+PX=d$WlUbkJ zm*%qkYZ!@)B$!iJq!oWH_t&>*wcV^m9AMB-{z4M;y~VwG=x<@#gkWjCPdpMhKXl?8V%5kCwV-`h>bq5FJNvN zC^AlU9v227xBdesiMjf}HPcvrujt2Eeyhzl>6YmQ33vEPJ7?r~ycxCs}(<-~qTM~F1|kh*t7Ge6+`zmI2SM~Zip$3U+$5+r>0CmoQ` z(khfQmks=xvC(_?9vTbYi3STVRT?ZjqaSPkns3svaDz&EgGb$KsHb6xrcN%2154~& zD_=JKTL*BiIS8C-oxuq_77#`HVSj;v=yVIw;1opP&}aB((qVd2Wyv?{9Rj8u=YXG! zIs&w6UuXQR-*agEeBVOz`wD}fU+Bl+=Lz#oIxH7jSO!^G>{?F1-Cp)o0n+$j2h5Zl z1jwa_0p$IBgO-ymAjhTv8F&yNFQ}w9_?^!~>p%AiiorPrXL+ zA@Fk)Vs(Pnz=&5oy)36Z?=d z%XyLLK~$3)UmkKEY?P>+u9%On6CsA{*uO-UJ(II?4AHH3v+zcIR71=KDxW@LQ1 z&}HUD{eQ^AVV}#-{iF8!Y5#tNnY$v?ONu8p`nkW0x_zmn#|IiaN1=3BqwxCgc^@f# z@z=zdCOhtBxKZm&VeAQWVAf?hoZ0F9$cS99i~REkQr?aZ7xQZZuJH(Sgql?^m8f@4 z=^Jj_s$hZsWrSdciC)-al#Ie#z7Dj+Ll*CKVv0iI&ROs)F52PW>)ds}zVotoego#c z_{VnCsW0e=3xPQhk5jB&x#6=E^G@ohBqsSk7;Hw}FQyyjt=ErX-d~$<(wVo^l+@-U zc*GmrKW;^m-KY`t6c_NG^*H2p$cpQft#RXPk^?R%!TAV+`Jws_FyFVWGt4I+2Idz` zI86V<4-L$J)sKOB*KYdRQGVWMiVEm9QhW`bQriX4UiNQ>0aEvlAbqjbf|OFV52$w8 zk%sQ+s&eTx{-#rfU*6@IG&QM z1Ord|3nebjsOXK%aB7}33|9_-dpgJjOvy~A=03}!(IRmB)V-G6SYcw(>PJ%Kmg&r( zI%ii3xkVjWw8($;c*CN7e_+V{<@b~1?qX77ppi6fu~C#2*TLtCwB@Q350hZ7N{wKu!39vJOdChYPRaO#!J22 zDlJ4`>UF;i`SzxB@4r(G%YA*148cuW5;ZZ-J$L_dc8ckck`PWHonD(eltrRE@vpd7KnA!gVq4Hgtq zJ<{CVaF)O0ztefi$hVfoUFY3Rs-jNu8`K4!_GivH1>O;VihtOea2nGG?L%naGo*b8 zilX1hq@~-OvzVDw5~n^XlK|bS{nuCYt=j*?ik?&J6{~wRe>gtod6+okr6T?$j$~nM z(@WphWtIu5ZJK*)`RxSwv3V{TPd(Gb4`Ut-2*vlt-puFCcR0eTs%`45KDL%uc%j(m z%D%A!MU}_Abe-yZHg@2;iep|X(Df5muv@oP`ZZ;oe``qhVXb8O*}spm-Z6Ya@hwpG zR{0Y7WBmC#*O%S1C|agWcNDQc(U(Xzl<7{Q%+Q`Q`G6E9uLmeLdU_j~2T993>VCKB zBW)Xv?aP~C=XXm1)Ll`PkBZelrh#pVBTH(B=LPZc5`{Hu=bQ+d^PE_%iqt)<(rBOD zoO&|B>1M|3i5uLydR@A46E9fL7R9(Jn0!vW9Eo$TQKmVSD?gbUy0sA?UsUlnO&}~+ zR7un8pHMS|0aL_STyJ8<{TUiZ$(x(Z&6?*mvGFIFo0azFVs6rK*pa`q9-1K6^bGbE zjq1h#th&e>HC|Ed1bevg-LRewTO;IPgS>jp#FreXWc#t{+PtF(d^FvCv85Je%=jYS z%c)T^gLE7Md=R!&_nfg^hOTql@Fba=bS>WYrtGDGQEy7oxLQV0+mf*4!=Oh2?V6}p zvIhBJTRt~v*@?YJmk}1Z1eYugv)i{|XSiU0xO$&~>%UsGvn}FvzdzixS>p%zW`2Vx zG+UCm$Drg~r+j`m)bSuWNbL`}LodDVFVi2;!?|wsBvP}yA^~~8f6F5Z2n@>mmryv3 z_>6##^k>cG;`Iup>KEZh_%Y#BABuk7sB0s2-4D2Rrspa9$s*QSD6c)*`~af2;y?~t zEwUl0?9)AS2Oz}f9whStuwR2Z7aiGZZG!Own5~+idj-L3w>CL!82#3 zWi~~-^eqY__`~c`g6kBYvX9LbeZs6cr$({d7kfU^D2{l8Anvxv(D%aL*fw{x=rs2z zC)QU0##R(vSUaarTjIxxi@GPYyxQz)N!)3hmT^$CYUX9~`=_cl0%A)C0YSLZI4F#L z+FrkA-q@~^H(zT@JVQMd|FJw~tA9KgKkC~7v%pEQT` z#kb<~j4jJYEV1&jcog6HkH{~hrE<2ljxv)8D7$RV-w3$V`E0yRF!oc$zpGHxp!l+6 z@lo^t=3mB(#LwFeH9J3e^wV^m+7iJbmDHX3?Zn?Tn@Hdp$l>DVxi=)`vlFv>j)rF; zZ%0&~jpBg)Mc?Aq%7UurM8*vECy99V7MT^z*nCJ}8G}u3# zVMH8fYvl<^#1~L_UO&PEGTRUYL=1xVRY|lrE?8B8l_E`e@Dhg{YsXQb4~vZ1>w1!Y zHH&pUv&2XT9+)hlP~G}xOdn_APjut_Wv9Dhh5VYXQ%ZO@d2sirH zzEi!mjfPVCp;dR45m%zHxM}8v7uDrr889MLg`3%`Mu}DrJL9om_EdkU;_Rw0Uk$3q z>}ZqgcsL*Ln%S4Wkw{ll2uvJQc4NyJE00Xpwois6GVcMCp*H>o1aLEVDKSZ7%Qa@+-HN_3oTP1?=G6F3(w9iJ>_285mc9@C&*}Tk?|)VLz9iNeqmfqdPS~Um)J>Q}crHm& zsqCV<;g-Zu6em$9Du;>Ee>qu8q~7_gGMf?}~j0sSl))dY4GO3;)%8$eT{*0d6c&^^b^5 zPt%Be9L(A_Kf~<}c)OtPrzb$&CfE(?zCmD{jm)+?m=7MgmfBYT)CixkkEh7epCn5k z&kO!);zh?ubIdkT2RP=gU}IKm-b=E2UFXu>T7fQMrugTd=pYb)@PBthYO&cw9T0Lf zhdNl3ooxaY{af{^S!*8FAo=BA`-GNT)naVf6!L!&wA71sbJT90pvd?0{QXKX%nJn{ zWzu0<)QuaE_g8YW-PZ3BS?0@AQh+4ZYMG zb-H4uWjzsN9{Yl;X0G(vV_-rtZgi3L+g6~A4F?5hKtuZHLvTo=97ve?XGvP|F^53 z%t)NTYaYp)fD_@@3whKxdAE=|1{U$}e=^OxbuZeU7VjxPSM<3>o!P8UgAju3ryeBi zAPY{=YQK3?XR#tTrCq?Z2hh6UTDaVgk?p=eFye1$WRju4Y&C;P0eLR!S_nLh&`x zcxyENDq-w88Ff$m9lsB|r?mcWm?LPZYV?FhO?X~6N#cN0*e7_iurdW$N@`y$oWw6v z;}=b|gt_RIe3Hk7R`%{W7e%Nkyt80Ck1TxSXC2R@vI_kjUztt0#L42qMA*K+Njov8 zX6g|`EHR2=H**A84dM4K!S=QI-wD?LKqbQQ*CX){)jxrSebO)Z&N4~_KJ`Im1kd+u z?Qfi(q^kk=DPEb2XSp!;nNy>*_Hb@*=RQLN&z_DgqVMI6A}caz$%q85)n#3W>)4S< zdaWkcv!N@Icp?)2$iKBf*tJ6~38g|7Z&qlZMvhx&`OH~lF&d#O24Z9c2c7}8?MaIc zo0?h=WJf#qJ;Ze+{zPFFzwZAM!tb6WARe@J#acOX`hN$l^Y64YFq{!K$)fB)Cbbp9U0 zzWDye&l<+xvWj8EXqIX%bl-S#0e}zj6S^faFYSi?qt!G(p_?i>K<~lA92GJin;?H1 zN+RvsYbZIj^0ZXR(;h6eLnE2)tz+@iw7+=Y&DdYU{yfy5UE}^*OYST^S;gL zGc>d0X0&C#bng)9-XiJVku5vP`P^AmN(XWV#^>f zX8{4o>4MG>0W63v{+0as*TaA!5G<%z!H~j}$TVvxf6FR{iayAv2=EG>QRLIN1-!-W zTJ+y_l(?yqHHq6ndg?{uVjfSeEO3XiV|VS#P+A6UYkCRN3zZttc5@|Lgj4mq@pV@8 z1Wj-c;U!sw;G~ohVpCE^(A$yg{EQ$xj2j*ZhZ-7MM7>!{(lDyVlW(GN5jdMwsCt>k zA`?!GU*p3ua=^sImDF;YlSbXp&L^k&e?3Sbm^e8#g$o}WdT8gv(^xn;NHiExVdn?g z(nqn6G4*aOoZ@0$PLUXR46F(Nv&gXlG4ywQ#q}*^@CuhVRbD8YeR>ilRg_MlM5cs6 zNqkQvzPv2H(m#d?tmXkzml1w^G&i}y?>6H<|Kt{J+ z<>zV7iZRV<@3G;m+LCDFb+gZpV{HHADvWKFri-SaWYS9dy1aYd$pkp$F;OuY2`qNM z0+fa>$Y*~OVQ%gH6C;ikBbJB}U8$l8V#LeLRvCp-O!22}wCqPXs>)&Tn_1ulvEOB8 z#|WgMpc!8+j~;$~PWs6wD#Om-7BgVbPY(;{=%;%9qMyvK_OCxKF@=fytSRtf;dAB} zPStPSRV-66ji1OAvbbp;+wyGcq|=_w*HD}GIf3mNk-DCdp^fhMR^15Z=QGy~YG;oi zbubV?Fc(JHP10wmvnl4cLmc#(CR9?otS=trFv?>=p(&33_zkB7YV;f6tVT2NqS07l z3<~<&S~`}pTmFrQsVTK%m&F&=B#7j>Alw%@&kZYc!IjiM-Q8V@kv|nyQCL2@p>*#L@{dNm?iev~5h_Z)fqS1bq z)dO!(HwOBgp^;*y5ImT7LP~tphwb{16Ptku8%O@2LHP*+0gH_IK)x$qLTB#o*x=M~S2qeOX1zMsBM>QCR-486*-!3kCPi z3)?bg9Ls+4ZtN!~5zm7LQi6~;;E1eC92(DQ7fZ`PDalJ$%0!9JkJk`jDrKFwYSxR&zXq%HVt*hBx!A>z6ZB&gXY5qb0ti7I4Hw@Gd8H$eugVA(vm)iUS@y7nU_;7>A}VXOXQ8 zU2;YuOA*hp7mb$5s2D86NIF%I9_E+KQkNp5S*bW$X|XgeqMp+8ZYUqCbX()hOhC(j zg5X_zhj-An;^UepsChW4bF(s4m^F-8xU12Cz+RrDU7Q zKE+f@2GR`w4pXnX)u}t$-+#+kI(4Qx@f46oyl*p5Hb$Mu#xOA;^X-^x835HKP9IZ| zpuZ^r6Di*4+&O^~g2BDiD?B0!#bAOPF_V$8sR+f3yg^4tino*x69%S8g<_Rkh(844 zifW67*DjUYjF;;66v5~QPBx|vM4$Hx6V|A;i})@xKKw_sB$Ye$O<`ZIakUxjxlI3N zw_Juu;cFHJ09yaNO0943FH!3h0o|770$@68^lY?1vw#5gDM|j&b3Dih zJEdzF-gEoV*TrY>Ad$WJG?hfXOwi&AnyGxa*{oDMxo}*n%{yt6USR(D>n;)P8PI@@ znV?drt?9BUrq>QC!spy)?ge3Qy0L~%O4U$eplW!2LLE2Gon`8v(`jqZ>)butSp_1Fl$GtitZZ+I3?-5LuJUiF18~(GS-jbA%@?%r zY@fw&FW39lDnAtw+O6TO&i)+4a9&<>!l~ETjxE z!b!4EX@~ZXs6kGa2GIC+XvG&AGGQ{26ZJ(LMqjc4Tet)Gy8*v38v_|ry-cEKDY)%L zfZ~!U$=#U07r!$n5+x0Cq`0a4eWA=1G?OfmBKT#z?1$%B-rgAznXfQphC4g)tRR|{ zcpPVJ%az!Ku%lTYxMR=$ATjx_&jS(K*#H%9P0~zgivP)*UE7}Gr%7OyGA+MJPe>;D z>Rb8RN8=ph((o?ILccOD&Ar_}Ci%LPdr8$&aV+x3F!#@bEoCss@|0M8Y%XGT|HVn( z4$9DPRgsjY>m$hSDjvwu*}yOPVdj&hWkPa&ys4a%w#_&-$h??J#f873UKV7GTvL4! z=9N|a8rE<58k{3pr4bq}UX4g2XG$=Fk?)W3*!n*r#jBk=dm{1O z?(**6fU#KLU7ixJ#J51$>>;PJhS|>~7^etixIV(DHtb=?+UdY8_E->ZA8V76U`tL-VHEI9%S0B%h|6jz zHoq)nHu?3R$$DAk_aa$JeOEI*Gtm6_Ylj(QEx*N?nC4`({sYb5JFhRYzf`O*+-X%p z$kVWzV3?X-mPkiJ#0qVZWWLKHXE5b;Z)aTn%1!dWaY#{0Y-nm@AgMNuuzDM!37O)1 z%!V!OUz>-=zw<<33e@4()fTMVKCOQLNAY(S6i&i*$B;^RnXDd@8fg=(9(s`%IABWOG8q?1a#63enXto#y5Ov4lL z4J>vUo+Sz<`=MDd?C!E8&21THk*!qxq(+p6aJm+_ZV{fK&1|b82r))XWs#Gs99}XT zJ7B0L>bH{WJXQX0RE|E%k_9#8AJ=RI$nx$v1k+XIWP-ME2A%6nzp%Dib|JAC#jd`!_kPCpo3oa^D_Y;H|SlmZ6j)okzx9k?2@$8nJv@g#;IwW zHz`@=g`KLLswx{xEy9vjwj&BDc8ID;?*3iWczn0Xe$D*8WaRG3p3hGQzlrSUC-8$U zMlb$eJ{-we76{U0cf9ORDrwj?4VNq6NDV<2z?al48;fwqYd80Z@Scs&%hs)@RvEj7 zGb90oAeO}|3a6-kGxpI;h84W*`&9e(3zK|6p$@eh>eeb4v-L*DTS&EpfMJEDg<&EV z!h5zyGS|vpMaP8M{uCKXK51jQMu)Cc*C3GLQ+80ne8>{})vZ2Qbv&EtX$C?HnA(lmBupt|7W>wMi8EG^ zwj12W%%uaIP~S?5y1hV8)LJfa;aj8emEoaHm>^Z$gomy*`cwUZOiTfVV$4b$j&!Q5 zqEn|H94oArGXUt1%v{ugKBA97&s>i6!Ll{IyUg@1g;&$n;fWeZ0D^4o@ua)Zt%+Ooz!eN{1!c z$BT+|nDXhpe(v9QJh}YhbK{}#9v__dvIG_)pl`@CnCKQ@0=llm;wN-OR!x-{FfjT{ zYZc?qY++mXsASuclz*uBJ?GvSC1pxsyOVVgL9)fc)z-H+^8<-3%rJDPOciE-(4&32 z-Y&%|W-v6~EJ>PgBDEB5=do{$mvLs)nE88Bu9#!cVYU|hu5ALg9a71z@~)vnJ_tUv zeiEtx$PNN_!)<^zJRP(oRELD-b~F>v(Epa(@ZxmR*T(O2=;fQCOApfAVrZ6g54n7E zWfv>E)(Erq*9{o>*k2{`=8kkd{-o$v)8^b$WL~!s;&BXDHJd6O+`_Y&^Q&}>#P95K z@p9Siad{^3n`_bS1LhVmU_R1Ds@Q@2vH?V7uEMry-d0+$^dhfsAAH`(Jf_C#y6aAB z3JuSMnU>^zIEZjff+~nd;B}GfT}9gU)`9bT<3b2IKerxA(Zeilodn|)Y8I;GoPIqi z8So4`-ZdJpjO-%F+MD>6KIQqPFn?iLyg~aR7VH*3G7yG@_iP{?`Ip=Zc_(R^jVz?G z{Xk5DdkjkJrwui4Eh|_ZYFizOFKzZq3s#mDm^9(xu;-GuRA1(Q1kY(0&?@VX0i{J zBrIh$Yb&}9Ym4p4#9YKgLxzF4`0Dt+_&R@DwA2@v-^sM0yFV zWSEv)j)DKk5E|bL6Gq}|New!83-0uktRfyQyk|2Z_oPf1bbqvXeMM7zF9loP)@}y& zN8gI6>J9#3E`bOeTlebG74}g?k5<@6CHB!!J^B-m%$%VYB+HR`lxNu7zqTRZW`;Aa zUp*Hyx7=XYeJp=Yw)}~GqbwBgXGw}bV{OFuoTT?1__74PBv**@m*(`NViYkQJ86+rsMcJWr?qsAG?mYJp+-YVFMaD~F_;ZaD z@aJ~|{u~K^_J==@Eyq!c#ch~#Uq|MY?h$i-J;j_roX(tKrJ-JpsT_tg*n3j2GHSUK zgDlCN>SQXtXtba)3U>~wEI|HY zwk#TrW2z@vRAvo4%5)g?1w7hJx5T3;AIqa7JMyR{SQ?M^wLFUNyq!rmYtiR0T*{C& zZ2GEY)0d|iHuaB!0ngrR*z{@p=oKCr`@tW`bIX|0Lg}2@_?NEbY|AZaOOi-U7+L$N z;7WD~9LRNIe-Jl%{R_S|hFM|mZtc<>1b6C?2?k}Uf~}h)afAtqZ!d8~Y}cG|X{Vmy z>@$1fBG^90o2S#qvS$WqzWz|&lS+RJ{RpiOp8cFb%a#Z;pc6*!WSPT&nr95?Xd>E* zfka_v&=$Mzw!B2Iv9*(rJ;1h7c|x5#*NR+BiyOD+BY7(aQmSeD%NNKusdH2sx1U`4 zz126C4t+Ioigu$mCDQCY(?E8F_i~lS_uJ3xvGkel=#^CM#O{QzBX!|k5mq?a%oFhj z4|?TkTo{Gd%0aG7$c2UUFRbk0mr!T6_G7;~Ns^a)Av%e$&#~hIX9B$p!z1+HD!gsx80;lg~QI=j z`nZlvIcA1$RWMR6T!5l#CTv~{^+Q+VL^J%+R5@5Y%#Jfm5Ef5ir9u2&n;C9fMSRZ* z;rPaI^jS=f@Lg=Z$Fv^P*q12Ug9lRT(} z8-tg(bk)Roy`+sPR!Vnh!5C0Jq?8@u5q2R3BKiG&b}gJXlW!_YLFLU=nc#Qs9P z_8gACh1*^aBQ*(wFW6|dR=g{~ZiyCb7jJ26&3lo8go0`N8nOG(Qm%25n)E&u{beZR zD1*vuR>R-V2ssZdO=O#U#l(9zw=vprOl^udWgpe!z8TB@Q@UzT24NQiS-jbQ^ie9Z zK3eeCD6{%L5Z!b+5vuIPH5o-n;}qY;StCVV)}TOsRJ9bSO*W#PK^%oc-SQgc8u=8h z`LeQ)2@dGKph0^&m+-1Ls#c$9xt@_?*%KMW38{SV*NOyqAH}qhx{LBH*@iYTAR_UL z@;lQ(=Mu$zQ-~F$2=VU4ugyIp6n`aM(=uO|KEfW%#U5;~;D8vPqUI}5t9T3AV%&hZ zig7SP;;1g`J?&8SGH!yZS5R*_zJyv0%~flOYVD57`Iv0Wefjk#(9`t${(G~c!^ zt^NA6*#F@C6!kQO zLnd>KkW=tScp}PJDgH z9_y#j7a8y@%8t+P4StWK5E1|%tj3Hj^pRmu3h^GN%5|9hRn2{fl|ydN|6P05AES_QDh*IWDX4sJ@lX)KW5n#Y_TQlZ}PTkK^Y^EWW^{-QhwVdt5*p~Ok0 zWH<;leN;MhU&NcuT1s=26DAOq(YgWA;?`MzPTU^GBqAO^S~o2x=>N)DQ{18KBIEhc zSEBK0IpIBj3pai_CS34JBy)Rg^s1)~@L|$=P}Q6Mci#azZvsh7faNlF125t6$`lE3 zu=zLBBSR$ocNLh*{!i!xAZwB5)eVOTL}_ZG}~ ziLZqf^+xJPAv&;aw0(X@D2`~^Qqwl`#@N!{p~V6AI6^#e5}F|DJhLs_`0+{Oz0;ov zHGL3@zgar8B^3XX=ZSFRCntr9|2E^y5YcLx#rrG4U`AQ-2QzyOTNR3bf&LO_OLmqx z4=zvCBbe`@0juy9U=Z+BC9ms z7%FZnKSD-$h+{LT4dsuM5)F~)i=mfEAZgFr?psDNg=g z>y4qIZ5Mi@#(48Hi6N6E=fr-?-$-2v_AvokgEL-u8b!5e)cJ~Ti!I>Yg|(ylz)E3T zzMTCrvnh+kdRZHbf`iUatsky)7S6!_O`KPm3lt2CA^<5b2$@y<+#}6qWscEMWKRcj zn8DrTKgw{x=3v#uujjIqP$pw)#>{j0s?nd#W%BW@T(?_~N%{Ab7_Q??39sAtT<^ze z8-QosW;gSWxaI7zOq?bj%W!4Bu6?bMcgS|QXRBr>jhlNSDWKqr$h5{0zsbzNN$g-= z(}Qb?(%9P5ZTz&@?Y$fGm?hm5b2V=6!S?r78*iU_itK;%S|j`4V(Y5!Y)AHEQK7z* zQ$c_6GyB^x+`wDXKheUO?x`hAE8i2ge?v4A%-2ki&_)r7Udz0ETo)bs>MVRh&&=lK z5wpKRe>2&W(app^^T}Kkz1hjASX4y}uosz4TVz#H+DDzXOMJ+OZsuN{VKr@^(182e zA=>T)(6Cog>jqW5>lK;?%Nv9xa3IlSZ!mOjI)<#A1GBw!@O27B!DBCb_B94Yjom=e z$Ns_U(SPXo2g!q$ZOE0B{?ig4^dBkw;M3Ee*xnn#=XW`rncVjcN7;qML`4T3B9A7lUCHe2Wi=O6n-z$UT>+#U8 z6!mF{Bi68zw4?i7WI&loWl5OrFS`SiP-z06Z8`t@1lzq}_ zf0y3Z`j&xd%pir|>7V6~#(%E=CV#)zZ%^sr`hQ(}|B1>R@$P>ervGq(7LD7{fIW{P ztNuMI-(hDoOr`S%4dg#>-rwe5$$dH!{?F6tNN73k&^WODA0vg|Y5y?m`?SxR?u|BQ z48D^-PR-i}Q*C|bGK{WbeTkj-&ceUzq1XST3x$tXYh(|Pc-_a4f~H%zdanrPEHp@# zc>O3$y16@_nKbwTnPZCZ>F?ne^fJp^b2{i#e~0Ie$ihoRwk%uiDq*n#e#O{GV7TlL9kwbvN4lV z@1%Mg{heziY8x&8-N22hx5;16Wg7O|ou`6*h(F-B>BMMvp$gU^EqB;)*oiGux0XJm z{&)1*Y3Vb5>|yEi7nN$K&#x?fPWj_u=+jObL#YnYQ`b*2^jUn$SEf&Wu<@Wv`XCwt z+QbECJKZd8CN`zfX2qH$ZHWKj#i5BqewE)GhC0|^|A0R7zwET}XD>-$Re!8mo#K0I z_3H({xF}3qfp?`zlI$#;OJOG1Y_2zdOU&O1<}VRGJfE&PW|qmVK?dSJFNCPBhdN6ET~Om^J~2c2N-Uu?0E z6T6nzgdOBwAfPcFFGn;l0AQds?@#0X*yW|U7Z8BVGKD#kMO$a2U-*9E0hJ`2cqmC2 zmWRxc$MycQayM&??L0y=U-rG zJZcOn3_>%OB+d?#k~QM>KgmANJx(1g&ly)cagd10q_^cHIqj2R78Xd>lxXT7@|wq0Z;TGzdU4?X4d$1D|Mx;TC}7VA zfB$sGrQYciqu%%B_+^t$Y%e^hbJLmR4dS@rHP{`={4v4z+toVh#fiS1$VW%F^C#cl zsjNsXl7IL(P+FH~rd-&BP8jVKQx4Q%1RMhZIKuB}cZ6#clus?Ky)pL!I@@Q)nWm#3 zY5WBC|EP#}y&Atljk9|#RGvpXeeP&*o9MxxXq+RWx3;{@@;BZRgH|)X{Kc&u_2RbV3x6S3nARl|jNSOi-p#E4y?e0TXchpC z4of?E?&2r-wxhvq76gqpGfvPVv#dU>WsBS{Y4N#xWXT*lKKC&YtbGpxU2(b%=9ld^ z<~bpcX8(agx}Gy{R=Y!u|N4!2b2XkH(?hQ>Mk*#KgB;zT{oZAWf{kC3CPE2Vg& zg9umR3{|>^O`7?Ok?;_qsC z&C9-?#<5QppP-ls?Th$lDrS;R(0<}rcj&v}_}{e>N)BYV;4?S#J<>y%;QwHJDBt{r zQVSraN&w423wU3*??csJ=;_>^iy0mniLh*{DYA`b8{_3O|Jvz{>ULjq5YgLZca8rr zg!c~e^Eu%iW`02S)p9DQr7zpC^Gr6wuy=7c!@sOAlur~rCJ8H&2-@E<4$doi4GG;)SHziD+@?X6kt2%B7}Ef;5nVjnoP zeCueM-B^CD*+i0TTR}ONJG|`iYW|mllZ^2do4?U)qcJ^MJ+Aij{6s0IkR$F(;~$lp zJ-CD=_z|&!UE8(%&?O~7Vwi7D$2q^~u7ATBl!)5RCA-T{g;Y>S)MEa939x=Xh%uDh zSF#dDGOR!?W@`yEG!|@7kjC^0;;6M07~ci|uQ;6j)h<{xy1(In@{6x1UFa6&vCqEJ z`A&ZYWac;U;H?r2`oj>IBA3}5*CPlYk4u<<0>jm}D2NDYQ>t($^l5wG@_kWov3;O$ zp}_sg%#c|5pYwka_b%{J7FYjx0to~JH(RL)QitOQ1dZKL7-zg@27VHRt%5Vl>^6g)5m z+#5es$u1SJQAojRE)B)EFdICazo}^TnhYjVM%|yD4Lzpr??UTVyn&~#_4V>A&R&kO zn<4Zqh2?->AN P}~2PHOvk=XeB>9V1SBK|%j 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