From 1b2eaaec28956ab0ad3290a8c39b15cd4fd87053 Mon Sep 17 00:00:00 2001 From: Phong Nguyen Date: Sat, 28 Dec 2024 22:09:21 +0700 Subject: [PATCH] Migrate IdentityServer4 -> Duende IdentityServer --- .../Controllers/AccountController.cs | 114 ++ .../ForgotPasswordModel.cs | 2 +- .../{ => AccountModels}/RegisterModel.cs | 2 +- .../{ => AccountModels}/ResetPasswordModel.cs | 2 +- .../Views/Account/Error.cshtml | 4 + .../Views/Account/ForgotPassword.cshtml | 22 + .../Views/Account/ResetPassword.cshtml | 33 + .../Views/Account/Success.cshtml | 3 + .../AuditLogEntries/DTOs/AuditLogEntryDTO.cs | 21 +- .../Queries/GetAuditEntriesQuery.cs | 57 +- .../Queries/GetPagedAuditEntriesQuery.cs | 77 +- .../Common/Commands/AddEntityCommand.cs | 41 +- .../Commands/AddOrUpdateEntityCommand.cs | 41 +- .../Common/Commands/DeleteEntityCommand.cs | 33 +- .../Common/Commands/ICommand.cs | 7 +- .../Common/Commands/ICommandHandler.cs | 11 +- .../Common/Commands/UpdateEntityCommand.cs | 41 +- .../Common/DTOs/Paged.cs | 11 +- .../Common/HandlerFactory.cs | 127 +- .../Common/Queries/GetEntititesQuery.cs | 31 +- .../Common/Queries/GetEntityByIdQuery.cs | 41 +- .../Common/Queries/IQuery.cs | 7 +- .../Common/Queries/IQueryHandler.cs | 11 +- .../Common/Services/ICrudService.cs | 21 +- .../ClassifiedAds.Application/Common/Utils.cs | 21 +- .../Decorators/AuditLog/AuditLogAttribute.cs | 9 +- .../AuditLog/AuditLogCommandDecorator.cs | 31 +- .../AuditLog/AuditLogQueryDecorator.cs | 31 +- .../DatabaseRetry/DatabaseRetryAttribute.cs | 17 +- .../DatabaseRetryCommandDecorator.cs | 29 +- .../DatabaseRetryDecoratorBase.cs | 85 +- .../DatabaseRetryQueryDecorator.cs | 33 +- .../Decorators/Mappings.cs | 53 +- .../Roles/Commands/AddClaimCommand.cs | 33 +- .../Roles/Commands/AddUpdateRoleCommand .cs | 31 +- .../Roles/Commands/DeleteClaimCommand.cs | 33 +- .../Roles/Commands/DeleteRoleCommand.cs | 31 +- .../Roles/Queries/GetRoleQuery.cs | 49 +- .../Roles/Queries/GetRolesQuery.cs | 43 +- .../Users/Commands/AddClaimCommand.cs | 35 +- .../Users/Commands/AddRoleCommand .cs | 35 +- .../Users/Commands/DeleteClaimCommand.cs | 35 +- .../Users/Commands/DeleteRoleCommand.cs | 35 +- .../Users/Commands/DeleteUserCommand.cs | 31 +- .../Users/DTOs/UserDTO.cs | 39 +- .../Users/Queries/GetUserQuery.cs | 49 +- .../Users/Queries/GetUsersQuery.cs | 47 +- .../Users/Services/IUserService.cs | 7 +- .../CircuitBreakerOpenException.cs | 7 +- .../CircuitBreakers/ICircuitBreaker.cs | 27 +- .../CircuitBreakers/ICircuitBreakerManager.cs | 13 +- .../DateTimes/IDateTimeProvider.cs | 15 +- .../Exceptions/NotFoundException.cs | 19 +- .../Exceptions/ValidationException.cs | 29 +- .../ExtensionMethods/CloningExtensions.cs | 43 +- .../ExtensionMethods/DateTimeExtensions.cs | 19 +- .../ExtensionMethods/DecimalExtensions.cs | 19 +- .../ExtensionMethods/GuidExtensions.cs | 11 +- .../ExtensionMethods/HttpClientExtensions.cs | 21 +- .../ExtensionMethods/HttpContentExtensions.cs | 45 +- .../ExtensionMethods/IQueryableExtensions.cs | 11 +- .../ExtensionMethods/ListExtensions.cs | 27 +- .../ExtensionMethods/ObjectExtensions.cs | 21 +- .../ExtensionMethods/StringExtensions.cs | 105 +- .../ExtensionMethods/TypeExtensions.cs | 89 +- .../Locks/CouldNotAcquireLockException.cs | 25 +- .../Locks/IDistributedLock.cs | 11 +- .../Locks/IDistributedLockScope.cs | 9 +- .../Locks/ILockManager.cs | 19 +- .../Tenants/IConnectionStringResolver.cs | 11 +- .../Tenants/ITenantResolver.cs | 21 +- .../DomainServicesCollectionExtensions.cs | 13 +- .../Entities/AuditLogEntry.cs | 15 +- .../Entities/ConfigurationEntry.cs | 15 +- .../Entities/CustomMigrationHistory.cs | 9 +- .../ClassifiedAds.Domain/Entities/Entity.cs | 17 +- .../Entities/IAggregateRoot.cs | 7 +- .../ClassifiedAds.Domain/Entities/IHasKey.cs | 9 +- .../Entities/ITrackable.cs | 13 +- .../Entities/LocalizationEntry.cs | 15 +- .../ClassifiedAds.Domain/Entities/Lock.cs | 17 +- .../Entities/OutboxEvent.cs | 17 +- .../Entities/PasswordHistory.cs | 13 +- .../ClassifiedAds.Domain/Entities/Role.cs | 17 +- .../Entities/RoleClaim.cs | 13 +- .../ClassifiedAds.Domain/Entities/User.cs | 43 +- .../Entities/UserClaim.cs | 13 +- .../ClassifiedAds.Domain/Entities/UserRole.cs | 15 +- .../Entities/UserToken.cs | 15 +- .../Events/EntityCreatedEvent.cs | 21 +- .../Events/EntityDeletedEvent.cs | 21 +- .../Events/EntityUpdatedEvent.cs | 21 +- .../Events/IDomainEvent.cs | 7 +- .../Events/IDomainEventHandler.cs | 11 +- .../Identity/ICurrentUser.cs | 11 +- .../Identity/IPasswordHasher.cs | 9 +- .../MessageBrokers/IMessageReceiver.cs | 9 +- .../MessageBrokers/IMessageSender.cs | 9 +- .../Infrastructure/MessageBrokers/Message.cs | 25 +- .../Infrastructure/MessageBrokers/MetaData.cs | 17 +- .../Storages/IFileStorageManager.cs | 29 +- .../Notification/IEmailNotification.cs | 27 +- .../Notification/ISmsNotification.cs | 19 +- .../Notification/IWebNotification.cs | 9 +- .../Repositories/IAuditLogEntryRepository.cs | 21 +- .../Repositories/IConcurrencyHandler.cs | 11 +- .../Repositories/IRepository.cs | 37 +- .../Repositories/IRoleRepository.cs | 23 +- .../Repositories/IUnitOfWork.cs | 15 +- .../Repositories/IUserRepository.cs | 27 +- .../Services/ProductService.cs | 7 +- .../ValueObjects/Address.cs | 41 +- .../ValueObjects/Money.cs | 35 +- .../ValueObjects/ValueObject.cs | 77 +- .../Areas/Identity/IdentityHostingStartup.cs | 9 +- .../Pages/Account/AccessDenied.cshtml.cs | 9 +- .../Pages/Account/ConfirmEmail.cshtml.cs | 49 +- .../Account/ConfirmEmailChange.cshtml.cs | 79 +- .../Pages/Account/ExternalLogin.cshtml.cs | 237 ++-- .../Pages/Account/ForgotPassword.cshtml.cs | 87 +- .../ForgotPasswordConfirmation.cshtml.cs | 11 +- .../Identity/Pages/Account/Lockout.cshtml.cs | 11 +- .../Identity/Pages/Account/Login.cshtml.cs | 145 ++- .../Pages/Account/LoginWith2fa.cshtml.cs | 133 ++- .../Account/LoginWithRecoveryCode.cshtml.cs | 113 +- .../Identity/Pages/Account/Logout.cshtml.cs | 45 +- .../Account/Manage/ChangePassword.cshtml.cs | 133 ++- .../Manage/DeletePersonalData.cshtml.cs | 107 +- .../Pages/Account/Manage/Disable2fa.cshtml.cs | 77 +- .../Manage/DownloadPersonalData.cshtml.cs | 69 +- .../Pages/Account/Manage/Email.cshtml.cs | 199 ++-- .../Manage/EnableAuthenticator.cshtml.cs | 223 ++-- .../Account/Manage/ExternalLogins.cshtml.cs | 151 ++- .../Manage/GenerateRecoveryCodes.cshtml.cs | 93 +- .../Pages/Account/Manage/Index.cshtml.cs | 121 +- .../Pages/Account/Manage/ManageNavPages.cs | 49 +- .../Account/Manage/PersonalData.cshtml.cs | 37 +- .../Manage/ResetAuthenticator.cshtml.cs | 75 +- .../Account/Manage/SetPassword.cshtml.cs | 119 +- .../Manage/ShowRecoveryCodes.cshtml.cs | 27 +- .../Manage/TwoFactorAuthentication.cshtml.cs | 89 +- .../Identity/Pages/Account/Register.cshtml.cs | 151 ++- .../Account/RegisterConfirmation.cshtml.cs | 81 +- .../Account/ResendEmailConfirmation.cshtml.cs | 89 +- .../Pages/Account/ResetPassword.cshtml.cs | 115 +- .../ResetPasswordConfirmation.cshtml.cs | 11 +- .../Areas/Identity/Pages/Error.cshtml.cs | 21 +- .../ConfigurationOptions/AppSettings.cs | 25 +- .../ConfigurationOptions/ConnectionStrings.cs | 11 +- .../CookiePolicyOptions.cs | 9 +- .../AzureActiveDirectoryOptions.cs | 15 +- .../ExternalLogin/ExternalLoginOptions.cs | 15 +- .../ExternalLogin/FacebookOptions.cs | 13 +- .../ExternalLogin/GoogleOptions.cs | 13 +- .../ExternalLogin/MicrosoftOptions.cs | 13 +- .../IdentityServerOptions.cs | 9 +- .../Controllers/ApiResourceController.cs | 373 +++--- .../Controllers/ApiScopeController.cs | 149 ++- .../Controllers/ClientController.cs | 537 +++++---- .../Controllers/GrantController.cs | 11 +- .../Controllers/IdentityResourceController.cs | 257 ++-- .../Controllers/RoleController.cs | 191 ++- .../Controllers/UserController.cs | 337 +++--- .../ApiResourceModels/ApiResourceModel.cs | 85 +- .../ApiResourcePropertyModel.cs | 37 +- .../ApiResourceModels/PropertiesModel.cs | 39 +- .../Models/ApiResourceModels/ScopeModel.cs | 43 +- .../Models/ApiResourceModels/ScopesModel.cs | 31 +- .../Models/ApiResourceModels/SecretModel.cs | 51 +- .../Models/ApiResourceModels/SecretsModel.cs | 83 +- .../Models/ApiScopeModels/ApiScopeModel.cs | 75 +- .../Models/ClientModels/ClaimModel.cs | 31 +- .../Models/ClientModels/ClaimsModel.cs | 23 +- .../Models/ClientModels/ClientModel.cs | 261 ++-- .../Models/ClientModels/PropertiesModel.cs | 31 +- .../Models/ClientModels/PropertyModel.cs | 31 +- .../Models/ClientModels/SecretModel.cs | 45 +- .../Models/ClientModels/SecretsModel.cs | 81 +- .../Models/ForgotPasswordModel.cs | 13 +- .../IdentityResourceModel.cs | 103 +- .../IdentityResourcePropertyModel.cs | 37 +- .../IdentityResourceModels/PropertiesModel.cs | 39 +- .../Models/RegisterModel.cs | 19 +- .../Models/ResetPasswordModel.cs | 21 +- .../Models/RoleModels/ClaimModel.cs | 31 +- .../Models/RoleModels/ClaimsModel.cs | 21 +- .../Models/RoleModels/RoleModel.cs | 17 +- .../Models/RoleModels/UsersModel.cs | 11 +- .../Models/UserModels/ChangePasswordModel.cs | 29 +- .../Models/UserModels/ClaimModel.cs | 31 +- .../Models/UserModels/ClaimsModel.cs | 21 +- .../Models/UserModels/RoleModel.cs | 15 +- .../Models/UserModels/RolesModel.cs | 15 +- .../Models/UserModels/UserModel.cs | 7 +- .../ClassifiedAds.IdentityServer/Program.cs | 31 +- .../Quickstart/Account/AccountController.cs | 1055 ++++++++--------- .../Quickstart/Account/AccountOptions.cs | 19 +- .../Quickstart/Account/ExternalController.cs | 329 +++-- .../Quickstart/Account/ExternalProvider.cs | 11 +- .../Quickstart/Account/LoggedOutViewModel.cs | 21 +- .../Quickstart/Account/LoginInputModel.cs | 19 +- .../Quickstart/Account/LoginViewModel.cs | 19 +- .../Quickstart/Account/LogoutInputModel.cs | 9 +- .../Quickstart/Account/LogoutViewModel.cs | 9 +- .../Quickstart/Account/RedirectViewModel.cs | 11 +- .../Quickstart/Account/SendCodeViewModel.cs | 15 +- .../Quickstart/Account/VerifyCodeViewModel.cs | 25 +- .../Quickstart/Consent/ConsentController.cs | 379 +++--- .../Quickstart/Consent/ConsentInputModel.cs | 17 +- .../Quickstart/Consent/ConsentOptions.cs | 17 +- .../Quickstart/Consent/ConsentViewModel.cs | 19 +- .../Consent/ProcessConsentResult.cs | 21 +- .../Quickstart/Consent/ScopeViewModel.cs | 19 +- .../Device/DeviceAuthorizationInputModel.cs | 9 +- .../Device/DeviceAuthorizationViewModel.cs | 11 +- .../Quickstart/Device/DeviceController.cs | 335 +++--- .../Diagnostics/DiagnosticsController.cs | 25 +- .../Diagnostics/DiagnosticsViewModel.cs | 29 +- .../Quickstart/Extensions.cs | 35 +- .../Quickstart/Grants/GrantsController.cs | 133 ++- .../Quickstart/Grants/GrantsViewModel.cs | 33 +- .../Quickstart/Home/ErrorViewModel.cs | 9 +- .../Quickstart/Home/HomeController.cs | 69 +- .../Manage/AddPhoneNumberViewModel.cs | 15 +- .../Manage/ChangePasswordViewModel.cs | 33 +- .../Manage/ConfigureTwoFactorViewModel.cs | 11 +- .../Manage/DisplayRecoveryCodesViewModel.cs | 11 +- .../Quickstart/Manage/FactorViewModel.cs | 9 +- .../Quickstart/Manage/IndexViewModel.cs | 19 +- .../Quickstart/Manage/ManageController.cs | 599 +++++----- .../Manage/ManageLoginsViewModel.cs | 11 +- .../Quickstart/Manage/RemoveLoginViewModel.cs | 11 +- .../Quickstart/Manage/SetPasswordViewModel.cs | 25 +- .../Manage/VerifyPhoneNumberViewModel.cs | 19 +- .../Quickstart/SecurityHeadersAttribute.cs | 81 +- .../Quickstart/TestUsers.cs | 43 - .../ClassifiedAds.IdentityServer/Startup.cs | 289 +++-- .../TagHelpers/PickerTagHelper.cs | 217 ++-- .../TagHelpers/SwitchTagHelper.cs | 27 +- .../Caching/CachingOptions.cs | 55 +- .../CachingServiceCollectionExtensions.cs | 61 +- .../DateTimes/DateTimeProvider.cs | 15 +- .../DateTimes/DateTimeProviderExtensions.cs | 13 +- .../HealthChecks/HttpHealthCheck.cs | 43 +- .../HealthChecks/NetworkPortCheck.cs | 57 +- .../HealthChecks/SqlServerHealthCheck.cs | 49 +- .../CronJobBackgroundService.cs | 33 +- .../HttpMessageHandlers/DebuggingHandler.cs | 19 +- .../Identity/AnonymousUser.cs | 11 +- .../Identity/CurrentWebUser.cs | 39 +- .../EmailConfirmationTokenProvider.cs | 21 +- .../Identity/HistoricalPasswordValidator.cs | 25 +- .../IdentityServiceCollectionExtensions.cs | 131 +- .../Identity/PasswordHasher.cs | 11 +- .../Identity/RoleStore.cs | 101 +- .../Identity/UserStore.cs | 507 ++++---- .../Identity/WeakPasswordValidator.cs | 25 +- .../Interceptors/ErrorCatchingInterceptor.cs | 125 +- .../Interceptors/InterceptorsOptions.cs | 33 +- .../Interceptors/LoggingInterceptor.cs | 113 +- .../ServiceCollectionServiceExtensions.cs | 55 +- .../Localization/DefaultStringLocalizer.cs | 33 +- .../Localization/LocalizationProviders.cs | 9 +- ...LocalizationServiceCollectionExtensions.cs | 75 +- .../Localization/SqlServerOptions.cs | 15 +- .../Localization/SqlServerStringLocalizer.cs | 65 +- .../SqlServerStringLocalizerFactory.cs | 73 +- .../Logging/ActivityEnricher.cs | 75 +- .../Logging/ApplicationInsightsOptions.cs | 11 +- .../Logging/EventLogOptions.cs | 13 +- .../Logging/FileOptions.cs | 9 +- .../Logging/LoggingExtensions.cs | 329 +++-- .../Logging/LoggingOptions.cs | 15 +- .../AzureApplicationInsightsOptions.cs | 13 +- ...tionInsightsServiceCollectionExtensions.cs | 33 +- .../CustomTelemetryInitializer.cs | 29 +- .../CustomTelemetryProcessor.cs | 43 +- .../MiniProfiler/MiniProfilerOptions.cs | 23 +- ...MiniProfilerServiceCollectionExtensions.cs | 65 +- .../Monitoring/MonitoringExtensions.cs | 39 +- .../Monitoring/MonitoringOptions.cs | 11 +- ...NotificationServiceCollectionExtensions.cs | 59 +- .../Notification/Email/EmailOptions.cs | 35 +- .../Email/Fake/FakeEmailNotification.cs | 11 +- .../SendGrid/SendGridEmailNotification.cs | 37 +- .../Email/SendGrid/SendGridOptions.cs | 13 +- .../SmtpClient/SmtpClientEmailNotification.cs | 83 +- .../Email/SmtpClient/SmtpClientOptions.cs | 17 +- .../Notification/NotificationOptions.cs | 13 +- ...NotificationServiceCollectionExtensions.cs | 15 +- .../Notification/Sms/Azure/AzureOptions.cs | 11 +- .../Sms/Azure/AzureSmsNotification.cs | 35 +- .../Sms/Fake/FakeSmsNotification.cs | 11 +- ...NotificationServiceCollectionExtensions.cs | 59 +- .../Notification/Sms/SmsOptions.cs | 35 +- .../Notification/Sms/Twilio/TwilioOptions.cs | 13 +- .../Sms/Twilio/TwilioSmsNotification.cs | 35 +- .../Web/Fake/FakeWebNotification.cs | 11 +- .../Web/SignalR/SignalRNotification.cs | 43 +- .../Web/SignalR/SignalROptions.cs | 13 +- ...NotificationServiceCollectionExtensions.cs | 43 +- .../Notification/Web/WebOptions.cs | 25 +- .../Web/Authentication/TokenManager.cs | 71 +- .../Web/Authentication/TokenModel.cs | 21 +- .../Policies/AuthorizePolicyAttribute.cs | 11 +- .../Web/Authorization/Policies/IPolicy.cs | 9 +- .../PolicyServiceCollectionExtensions.cs | 49 +- .../Web/Filters/GlobalExceptionFilter.cs | 97 +- .../AccessTokenFromFormMiddleware.cs | 41 +- .../Web/Middleware/DebuggingMiddleware.cs | 39 +- .../GlobalExceptionHandlerMiddleware.cs | 123 +- .../IApplicationBuilderExtensions.cs | 91 +- .../Web/Middleware/IPFilteringMiddleware.cs | 31 +- .../Middleware/LoggingStatusCodeMiddleware.cs | 45 +- .../Middleware/SecurityHeadersMiddleware.cs | 31 +- .../ClassifiedAds.Migrator/Program.cs | 91 +- .../ClassifiedAds.Persistence/AdsDbContext.cs | 65 +- .../AdsDbContextMultiTenant.cs | 27 +- .../CircuitBreakers/CircuitBreaker.cs | 27 +- .../CircuitBreakers/CircuitBreakerLog.cs | 17 +- .../CircuitBreakers/CircuitBreakerManager.cs | 159 ++- .../IdServerPersistenceExtensions.cs | 617 +++++----- .../Locks/LockManager.cs | 151 ++- .../Locks/SqlDistributedLock.cs | 203 ++-- .../Locks/SqlDistributedLockScope.cs | 157 ++- .../AuditLogEntryConfiguration.cs | 13 +- .../CircuitBreakerConfiguration.cs | 13 +- .../CircuitBreakerLogConfiguration.cs | 11 +- .../ConfigurationEntryConfiguration.cs | 31 +- .../CustomMigrationHistoryConfiguration.cs | 13 +- .../LocalizationEntryConfiguration.cs | 47 +- .../LockConfiguration.cs | 15 +- .../OutboxEventConfiguration.cs | 13 +- .../PasswordHistoryConfiguration.cs | 13 +- .../RoleClaimConfiguration.cs | 13 +- .../RoleConfiguration.cs | 25 +- .../UserClaimConfiguration.cs | 13 +- .../UserConfiguration.cs | 53 +- .../UserRoleConfiguration.cs | 13 +- .../UserTokenConfiguration.cs | 13 +- .../PersistenceExtensions.cs | 99 +- .../Repositories/AuditLogEntryRepository.cs | 43 +- .../Repositories/Repository.cs | 165 ++- .../Repositories/RoleRepository.cs | 51 +- .../Repositories/UserRepository.cs | 75 +- 345 files changed, 9673 insertions(+), 9876 deletions(-) create mode 100644 src/IdentityServer/Duende/ClassifiedAds.IdentityServer/Controllers/AccountController.cs rename src/IdentityServer/Duende/ClassifiedAds.IdentityServer/Models/{ => AccountModels}/ForgotPasswordModel.cs (72%) rename src/IdentityServer/Duende/ClassifiedAds.IdentityServer/Models/{ => AccountModels}/RegisterModel.cs (83%) rename src/IdentityServer/Duende/ClassifiedAds.IdentityServer/Models/{ => AccountModels}/ResetPasswordModel.cs (85%) create mode 100644 src/IdentityServer/Duende/ClassifiedAds.IdentityServer/Views/Account/Error.cshtml create mode 100644 src/IdentityServer/Duende/ClassifiedAds.IdentityServer/Views/Account/ForgotPassword.cshtml create mode 100644 src/IdentityServer/Duende/ClassifiedAds.IdentityServer/Views/Account/ResetPassword.cshtml create mode 100644 src/IdentityServer/Duende/ClassifiedAds.IdentityServer/Views/Account/Success.cshtml delete mode 100644 src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/TestUsers.cs diff --git a/src/IdentityServer/Duende/ClassifiedAds.IdentityServer/Controllers/AccountController.cs b/src/IdentityServer/Duende/ClassifiedAds.IdentityServer/Controllers/AccountController.cs new file mode 100644 index 000000000..e06423bd6 --- /dev/null +++ b/src/IdentityServer/Duende/ClassifiedAds.IdentityServer/Controllers/AccountController.cs @@ -0,0 +1,114 @@ +using ClassifiedAds.Domain.Entities; +using ClassifiedAds.IdentityServer.Models.AccountModels; +using Microsoft.AspNetCore.Identity; +using Microsoft.AspNetCore.Mvc; + +namespace ClassifiedAds.IdentityServer.Controllers; + +public class AccountController : Controller +{ + private readonly UserManager _userManager; + private readonly SignInManager _signInManager; + + public AccountController(UserManager userManager, + SignInManager signInManager) + { + _userManager = userManager; + _signInManager = signInManager; + } + + [HttpGet] + public async Task ConfirmEmailAddress(string token, string email) + { + var user = await _userManager.FindByEmailAsync(email); + + if (user == null) + { + return View("Error"); + } + + var result = await _userManager.ConfirmEmailAsync(user, token); + + if (result.Succeeded) + { + return View("Success"); + } + + return View("Error"); + } + + [HttpGet] + public IActionResult ForgotPassword() + { + return View(); + } + + [HttpPost] + public async Task ForgotPassword(ForgotPasswordModel model) + { + if (!ModelState.IsValid) + { + return View(); + } + + var user = await _userManager.FindByEmailAsync(model.Email); + + if (user != null) + { + var token = await _userManager.GeneratePasswordResetTokenAsync(user); + var resetUrl = Url.Action("ResetPassword", "Account", + new { token = token, email = user.Email }, Request.Scheme); + + //await _dispatcher.DispatchAsync(new AddOrUpdateEntityCommand(new EmailMessage + //{ + // From = "phong@gmail.com", + // Tos = user.Email, + // Subject = "Forgot Password", + // Body = string.Format("Reset Url: {0}", resetUrl), + //})); + } + else + { + // email user and inform them that they do not have an account + } + + return View("Success"); + } + + [HttpGet] + public IActionResult ResetPassword(string token, string email) + { + return View(new ResetPasswordModel { Token = token, Email = email }); + } + + [HttpPost] + public async Task ResetPassword(ResetPasswordModel model) + { + if (!ModelState.IsValid) + { + return View(); + } + + var user = await _userManager.FindByEmailAsync(model.Email); + + if (user == null) + { + ModelState.AddModelError(string.Empty, "Invalid Request"); + return View(); + } + + var result = await _userManager.ResetPasswordAsync(user, model.Token, model.Password); + + if (result.Succeeded) + { + return View("Success"); + } + + foreach (var error in result.Errors) + { + ModelState.AddModelError(string.Empty, error.Description); + } + + return View(); + } +} diff --git a/src/IdentityServer/Duende/ClassifiedAds.IdentityServer/Models/ForgotPasswordModel.cs b/src/IdentityServer/Duende/ClassifiedAds.IdentityServer/Models/AccountModels/ForgotPasswordModel.cs similarity index 72% rename from src/IdentityServer/Duende/ClassifiedAds.IdentityServer/Models/ForgotPasswordModel.cs rename to src/IdentityServer/Duende/ClassifiedAds.IdentityServer/Models/AccountModels/ForgotPasswordModel.cs index 8082b1012..061eca718 100644 --- a/src/IdentityServer/Duende/ClassifiedAds.IdentityServer/Models/ForgotPasswordModel.cs +++ b/src/IdentityServer/Duende/ClassifiedAds.IdentityServer/Models/AccountModels/ForgotPasswordModel.cs @@ -1,6 +1,6 @@ using System.ComponentModel.DataAnnotations; -namespace ClassifiedAds.IdentityServer.Models; +namespace ClassifiedAds.IdentityServer.Models.AccountModels; public class ForgotPasswordModel { diff --git a/src/IdentityServer/Duende/ClassifiedAds.IdentityServer/Models/RegisterModel.cs b/src/IdentityServer/Duende/ClassifiedAds.IdentityServer/Models/AccountModels/RegisterModel.cs similarity index 83% rename from src/IdentityServer/Duende/ClassifiedAds.IdentityServer/Models/RegisterModel.cs rename to src/IdentityServer/Duende/ClassifiedAds.IdentityServer/Models/AccountModels/RegisterModel.cs index 50e0b231e..6446c1fb8 100644 --- a/src/IdentityServer/Duende/ClassifiedAds.IdentityServer/Models/RegisterModel.cs +++ b/src/IdentityServer/Duende/ClassifiedAds.IdentityServer/Models/AccountModels/RegisterModel.cs @@ -1,6 +1,6 @@ using System.ComponentModel.DataAnnotations; -namespace ClassifiedAds.IdentityServer.Models; +namespace ClassifiedAds.IdentityServer.Models.AccountModels; public class RegisterModel { diff --git a/src/IdentityServer/Duende/ClassifiedAds.IdentityServer/Models/ResetPasswordModel.cs b/src/IdentityServer/Duende/ClassifiedAds.IdentityServer/Models/AccountModels/ResetPasswordModel.cs similarity index 85% rename from src/IdentityServer/Duende/ClassifiedAds.IdentityServer/Models/ResetPasswordModel.cs rename to src/IdentityServer/Duende/ClassifiedAds.IdentityServer/Models/AccountModels/ResetPasswordModel.cs index 654a730e8..06d4ddfaa 100644 --- a/src/IdentityServer/Duende/ClassifiedAds.IdentityServer/Models/ResetPasswordModel.cs +++ b/src/IdentityServer/Duende/ClassifiedAds.IdentityServer/Models/AccountModels/ResetPasswordModel.cs @@ -1,6 +1,6 @@ using System.ComponentModel.DataAnnotations; -namespace ClassifiedAds.IdentityServer.Models; +namespace ClassifiedAds.IdentityServer.Models.AccountModels; public class ResetPasswordModel { diff --git a/src/IdentityServer/Duende/ClassifiedAds.IdentityServer/Views/Account/Error.cshtml b/src/IdentityServer/Duende/ClassifiedAds.IdentityServer/Views/Account/Error.cshtml new file mode 100644 index 000000000..269c3dcf5 --- /dev/null +++ b/src/IdentityServer/Duende/ClassifiedAds.IdentityServer/Views/Account/Error.cshtml @@ -0,0 +1,4 @@ + +
+

Error!

+
\ No newline at end of file diff --git a/src/IdentityServer/Duende/ClassifiedAds.IdentityServer/Views/Account/ForgotPassword.cshtml b/src/IdentityServer/Duende/ClassifiedAds.IdentityServer/Views/Account/ForgotPassword.cshtml new file mode 100644 index 000000000..c22c5bb41 --- /dev/null +++ b/src/IdentityServer/Duende/ClassifiedAds.IdentityServer/Views/Account/ForgotPassword.cshtml @@ -0,0 +1,22 @@ +@using ClassifiedAds.IdentityServer.Models.AccountModels + +@model ForgotPasswordModel + +@await Html.PartialAsync("_ValidationSummary") + +

Forgot Password

+

Enter your email

+ +
+
+
+
+
+ + + +
+ +
+
+
\ No newline at end of file diff --git a/src/IdentityServer/Duende/ClassifiedAds.IdentityServer/Views/Account/ResetPassword.cshtml b/src/IdentityServer/Duende/ClassifiedAds.IdentityServer/Views/Account/ResetPassword.cshtml new file mode 100644 index 000000000..7ecc845fe --- /dev/null +++ b/src/IdentityServer/Duende/ClassifiedAds.IdentityServer/Views/Account/ResetPassword.cshtml @@ -0,0 +1,33 @@ +@using ClassifiedAds.IdentityServer.Models.AccountModels + +@model ResetPasswordModel + +

Reset Password

+ +@await Html.PartialAsync("_ValidationSummary") + +
+

Enter new password

+
+ + +
+ +
+ + +
+
+
+ +
+ + +
+
+
+
+ +
+
+
diff --git a/src/IdentityServer/Duende/ClassifiedAds.IdentityServer/Views/Account/Success.cshtml b/src/IdentityServer/Duende/ClassifiedAds.IdentityServer/Views/Account/Success.cshtml new file mode 100644 index 000000000..fbbc5f754 --- /dev/null +++ b/src/IdentityServer/Duende/ClassifiedAds.IdentityServer/Views/Account/Success.cshtml @@ -0,0 +1,3 @@ +
+

Success!

+
\ No newline at end of file diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/AuditLogEntries/DTOs/AuditLogEntryDTO.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/AuditLogEntries/DTOs/AuditLogEntryDTO.cs index 45cd53d53..872ef1184 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/AuditLogEntries/DTOs/AuditLogEntryDTO.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/AuditLogEntries/DTOs/AuditLogEntryDTO.cs @@ -1,21 +1,20 @@ using System; -namespace ClassifiedAds.Application.AuditLogEntries.DTOs +namespace ClassifiedAds.Application.AuditLogEntries.DTOs; + +public class AuditLogEntryDTO { - public class AuditLogEntryDTO - { - public Guid Id { get; set; } + public Guid Id { get; set; } - public Guid UserId { get; set; } + public Guid UserId { get; set; } - public string UserName { get; set; } + public string UserName { get; set; } - public string Action { get; set; } + public string Action { get; set; } - public string ObjectId { get; set; } + public string ObjectId { get; set; } - public string Log { get; set; } + public string Log { get; set; } - public DateTimeOffset CreatedDateTime { get; set; } - } + public DateTimeOffset CreatedDateTime { get; set; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/AuditLogEntries/Queries/GetAuditEntriesQuery.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/AuditLogEntries/Queries/GetAuditEntriesQuery.cs index 9e705755a..d2b800cc7 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/AuditLogEntries/Queries/GetAuditEntriesQuery.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/AuditLogEntries/Queries/GetAuditEntriesQuery.cs @@ -5,41 +5,40 @@ using System.Threading; using System.Threading.Tasks; -namespace ClassifiedAds.Application.AuditLogEntries.Queries +namespace ClassifiedAds.Application.AuditLogEntries.Queries; + +public class GetAuditEntriesQuery : AuditLogEntryQueryOptions, IQuery> +{ +} + +internal class GetAuditEntriesQueryHandler : IQueryHandler> { - public class GetAuditEntriesQuery : AuditLogEntryQueryOptions, IQuery> + private readonly IAuditLogEntryRepository _auditLogEntryRepository; + private readonly IUserRepository _userRepository; + + public GetAuditEntriesQueryHandler(IAuditLogEntryRepository auditLogEntryRepository, IUserRepository userRepository) { + _auditLogEntryRepository = auditLogEntryRepository; + _userRepository = userRepository; } - internal class GetAuditEntriesQueryHandler : IQueryHandler> + public async Task> HandleAsync(GetAuditEntriesQuery query, CancellationToken cancellationToken = default) { - private readonly IAuditLogEntryRepository _auditLogEntryRepository; - private readonly IUserRepository _userRepository; - - public GetAuditEntriesQueryHandler(IAuditLogEntryRepository auditLogEntryRepository, IUserRepository userRepository) - { - _auditLogEntryRepository = auditLogEntryRepository; - _userRepository = userRepository; - } - - public async Task> HandleAsync(GetAuditEntriesQuery query, CancellationToken cancellationToken = default) - { - var auditLogs = _auditLogEntryRepository.Get(query); - var users = _userRepository.GetQueryableSet(); + var auditLogs = _auditLogEntryRepository.Get(query); + var users = _userRepository.GetQueryableSet(); - var rs = auditLogs.Join(users, x => x.UserId, y => y.Id, - (x, y) => new AuditLogEntryDTO - { - Id = x.Id, - UserId = x.UserId, - Action = x.Action, - ObjectId = x.ObjectId, - Log = x.Log, - CreatedDateTime = x.CreatedDateTime, - UserName = y.UserName, - }); + var rs = auditLogs.Join(users, x => x.UserId, y => y.Id, + (x, y) => new AuditLogEntryDTO + { + Id = x.Id, + UserId = x.UserId, + Action = x.Action, + ObjectId = x.ObjectId, + Log = x.Log, + CreatedDateTime = x.CreatedDateTime, + UserName = y.UserName, + }); - return await _userRepository.ToListAsync(rs.OrderByDescending(x => x.CreatedDateTime)); - } + return await _userRepository.ToListAsync(rs.OrderByDescending(x => x.CreatedDateTime)); } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/AuditLogEntries/Queries/GetPagedAuditEntriesQuery.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/AuditLogEntries/Queries/GetPagedAuditEntriesQuery.cs index 2fd47a8ce..6d6c117bc 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/AuditLogEntries/Queries/GetPagedAuditEntriesQuery.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/AuditLogEntries/Queries/GetPagedAuditEntriesQuery.cs @@ -6,54 +6,53 @@ using System.Threading; using System.Threading.Tasks; -namespace ClassifiedAds.Application.AuditLogEntries.Queries +namespace ClassifiedAds.Application.AuditLogEntries.Queries; + +public class GetPagedAuditEntriesQuery : AuditLogEntryQueryOptions, IQuery> { - public class GetPagedAuditEntriesQuery : AuditLogEntryQueryOptions, IQuery> - { - public int Page { get; set; } + public int Page { get; set; } + + public int PageSize { get; set; } +} - public int PageSize { get; set; } +internal class GetPagedAuditEntriesQueryHandler : IQueryHandler> +{ + private readonly IAuditLogEntryRepository _auditLogEntryRepository; + private readonly IUserRepository _userRepository; + + public GetPagedAuditEntriesQueryHandler(IAuditLogEntryRepository auditLogEntryRepository, IUserRepository userRepository) + { + _auditLogEntryRepository = auditLogEntryRepository; + _userRepository = userRepository; } - internal class GetPagedAuditEntriesQueryHandler : IQueryHandler> + public async Task> HandleAsync(GetPagedAuditEntriesQuery queryOptions, CancellationToken cancellationToken = default) { - private readonly IAuditLogEntryRepository _auditLogEntryRepository; - private readonly IUserRepository _userRepository; + var query = _auditLogEntryRepository.Get(queryOptions); + var users = _userRepository.GetQueryableSet(); - public GetPagedAuditEntriesQueryHandler(IAuditLogEntryRepository auditLogEntryRepository, IUserRepository userRepository) + var result = new Paged { - _auditLogEntryRepository = auditLogEntryRepository; - _userRepository = userRepository; - } + TotalItems = query.Count(), + }; - public async Task> HandleAsync(GetPagedAuditEntriesQuery queryOptions, CancellationToken cancellationToken = default) - { - var query = _auditLogEntryRepository.Get(queryOptions); - var users = _userRepository.GetQueryableSet(); + var auditLogs = query.OrderByDescending(x => x.CreatedDateTime) + .Paged(queryOptions.Page, queryOptions.PageSize); - var result = new Paged + var rs = auditLogs.Join(users, x => x.UserId, y => y.Id, + (x, y) => new AuditLogEntryDTO { - TotalItems = query.Count(), - }; - - var auditLogs = query.OrderByDescending(x => x.CreatedDateTime) - .Paged(queryOptions.Page, queryOptions.PageSize); - - var rs = auditLogs.Join(users, x => x.UserId, y => y.Id, - (x, y) => new AuditLogEntryDTO - { - Id = x.Id, - UserId = x.UserId, - Action = x.Action, - ObjectId = x.ObjectId, - Log = x.Log, - CreatedDateTime = x.CreatedDateTime, - UserName = y.UserName, - }); - - result.Items = await _userRepository.ToListAsync(rs); - - return result; - } + Id = x.Id, + UserId = x.UserId, + Action = x.Action, + ObjectId = x.ObjectId, + Log = x.Log, + CreatedDateTime = x.CreatedDateTime, + UserName = y.UserName, + }); + + result.Items = await _userRepository.ToListAsync(rs); + + return result; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Common/Commands/AddEntityCommand.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Common/Commands/AddEntityCommand.cs index c5ead5e59..5165a741e 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Common/Commands/AddEntityCommand.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Common/Commands/AddEntityCommand.cs @@ -3,32 +3,31 @@ using System.Threading; using System.Threading.Tasks; -namespace ClassifiedAds.Application +namespace ClassifiedAds.Application; + +public class AddEntityCommand : ICommand + where TEntity : Entity, IAggregateRoot { - public class AddEntityCommand : ICommand - where TEntity : Entity, IAggregateRoot + public AddEntityCommand(TEntity entity) { - public AddEntityCommand(TEntity entity) - { - Entity = entity; - } - - public TEntity Entity { get; set; } + Entity = entity; } - internal class AddEntityCommandHandler : ICommandHandler> - where TEntity : Entity, IAggregateRoot - { - private readonly ICrudService _crudService; + public TEntity Entity { get; set; } +} - public AddEntityCommandHandler(ICrudService crudService) - { - _crudService = crudService; - } +internal class AddEntityCommandHandler : ICommandHandler> +where TEntity : Entity, IAggregateRoot +{ + private readonly ICrudService _crudService; - public async Task HandleAsync(AddEntityCommand command, CancellationToken cancellationToken = default) - { - await _crudService.AddAsync(command.Entity); - } + public AddEntityCommandHandler(ICrudService crudService) + { + _crudService = crudService; + } + + public async Task HandleAsync(AddEntityCommand command, CancellationToken cancellationToken = default) + { + await _crudService.AddAsync(command.Entity); } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Common/Commands/AddOrUpdateEntityCommand.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Common/Commands/AddOrUpdateEntityCommand.cs index f7094193d..bd36c5daa 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Common/Commands/AddOrUpdateEntityCommand.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Common/Commands/AddOrUpdateEntityCommand.cs @@ -3,32 +3,31 @@ using System.Threading; using System.Threading.Tasks; -namespace ClassifiedAds.Application +namespace ClassifiedAds.Application; + +public class AddOrUpdateEntityCommand : ICommand + where TEntity : Entity, IAggregateRoot { - public class AddOrUpdateEntityCommand : ICommand - where TEntity : Entity, IAggregateRoot + public AddOrUpdateEntityCommand(TEntity entity) { - public AddOrUpdateEntityCommand(TEntity entity) - { - Entity = entity; - } - - public TEntity Entity { get; set; } + Entity = entity; } - internal class AddOrUpdateEntityCommandHandler : ICommandHandler> - where TEntity : Entity, IAggregateRoot - { - private readonly ICrudService _crudService; + public TEntity Entity { get; set; } +} - public AddOrUpdateEntityCommandHandler(ICrudService crudService) - { - _crudService = crudService; - } +internal class AddOrUpdateEntityCommandHandler : ICommandHandler> +where TEntity : Entity, IAggregateRoot +{ + private readonly ICrudService _crudService; - public async Task HandleAsync(AddOrUpdateEntityCommand command, CancellationToken cancellationToken = default) - { - await _crudService.AddOrUpdateAsync(command.Entity); - } + public AddOrUpdateEntityCommandHandler(ICrudService crudService) + { + _crudService = crudService; + } + + public async Task HandleAsync(AddOrUpdateEntityCommand command, CancellationToken cancellationToken = default) + { + await _crudService.AddOrUpdateAsync(command.Entity); } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Common/Commands/DeleteEntityCommand.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Common/Commands/DeleteEntityCommand.cs index 7c3d69123..bb21d6c93 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Common/Commands/DeleteEntityCommand.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Common/Commands/DeleteEntityCommand.cs @@ -3,27 +3,26 @@ using System.Threading; using System.Threading.Tasks; -namespace ClassifiedAds.Application +namespace ClassifiedAds.Application; + +public class DeleteEntityCommand : ICommand + where TEntity : Entity, IAggregateRoot +{ + public TEntity Entity { get; set; } +} + +internal class DeleteEntityCommandHandler : ICommandHandler> +where TEntity : Entity, IAggregateRoot { - public class DeleteEntityCommand : ICommand - where TEntity : Entity, IAggregateRoot + private readonly ICrudService _crudService; + + public DeleteEntityCommandHandler(ICrudService crudService) { - public TEntity Entity { get; set; } + _crudService = crudService; } - internal class DeleteEntityCommandHandler : ICommandHandler> - where TEntity : Entity, IAggregateRoot + public async Task HandleAsync(DeleteEntityCommand command, CancellationToken cancellationToken = default) { - private readonly ICrudService _crudService; - - public DeleteEntityCommandHandler(ICrudService crudService) - { - _crudService = crudService; - } - - public async Task HandleAsync(DeleteEntityCommand command, CancellationToken cancellationToken = default) - { - await _crudService.DeleteAsync(command.Entity); - } + await _crudService.DeleteAsync(command.Entity); } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Common/Commands/ICommand.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Common/Commands/ICommand.cs index b07b1f0ac..74bbb3e84 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Common/Commands/ICommand.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Common/Commands/ICommand.cs @@ -1,6 +1,5 @@ -namespace ClassifiedAds.Application +namespace ClassifiedAds.Application; + +public interface ICommand { - public interface ICommand - { - } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Common/Commands/ICommandHandler.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Common/Commands/ICommandHandler.cs index bc28c0f60..d8dee436d 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Common/Commands/ICommandHandler.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Common/Commands/ICommandHandler.cs @@ -1,11 +1,10 @@ using System.Threading; using System.Threading.Tasks; -namespace ClassifiedAds.Application +namespace ClassifiedAds.Application; + +public interface ICommandHandler + where TCommand : ICommand { - public interface ICommandHandler - where TCommand : ICommand - { - Task HandleAsync(TCommand command, CancellationToken cancellationToken = default); - } + Task HandleAsync(TCommand command, CancellationToken cancellationToken = default); } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Common/Commands/UpdateEntityCommand.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Common/Commands/UpdateEntityCommand.cs index 41ad3dd7e..24568f951 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Common/Commands/UpdateEntityCommand.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Common/Commands/UpdateEntityCommand.cs @@ -3,32 +3,31 @@ using System.Threading; using System.Threading.Tasks; -namespace ClassifiedAds.Application +namespace ClassifiedAds.Application; + +public class UpdateEntityCommand : ICommand + where TEntity : Entity, IAggregateRoot { - public class UpdateEntityCommand : ICommand - where TEntity : Entity, IAggregateRoot + public UpdateEntityCommand(TEntity entity) { - public UpdateEntityCommand(TEntity entity) - { - Entity = entity; - } - - public TEntity Entity { get; set; } + Entity = entity; } - internal class UpdateEntityCommandHandler : ICommandHandler> - where TEntity : Entity, IAggregateRoot - { - private readonly ICrudService _crudService; + public TEntity Entity { get; set; } +} - public UpdateEntityCommandHandler(ICrudService crudService) - { - _crudService = crudService; - } +internal class UpdateEntityCommandHandler : ICommandHandler> +where TEntity : Entity, IAggregateRoot +{ + private readonly ICrudService _crudService; - public async Task HandleAsync(UpdateEntityCommand command, CancellationToken cancellationToken = default) - { - await _crudService.UpdateAsync(command.Entity); - } + public UpdateEntityCommandHandler(ICrudService crudService) + { + _crudService = crudService; + } + + public async Task HandleAsync(UpdateEntityCommand command, CancellationToken cancellationToken = default) + { + await _crudService.UpdateAsync(command.Entity); } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Common/DTOs/Paged.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Common/DTOs/Paged.cs index 6d9274d76..c8561c2b0 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Common/DTOs/Paged.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Common/DTOs/Paged.cs @@ -1,11 +1,10 @@ using System.Collections.Generic; -namespace ClassifiedAds.Application.Common.DTOs +namespace ClassifiedAds.Application.Common.DTOs; + +public class Paged { - public class Paged - { - public long TotalItems { get; set; } + public long TotalItems { get; set; } - public List Items { get; set; } - } + public List Items { get; set; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Common/HandlerFactory.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Common/HandlerFactory.cs index 27aac16fa..630ed1bf2 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Common/HandlerFactory.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Common/HandlerFactory.cs @@ -5,96 +5,95 @@ using System.Linq; using System.Reflection; -namespace ClassifiedAds.Application +namespace ClassifiedAds.Application; + +internal class HandlerFactory { - internal class HandlerFactory + private readonly List> _handlerFactoriesPipeline = new List>(); + + public HandlerFactory(Type type) { - private readonly List> _handlerFactoriesPipeline = new List>(); + AddHandlerFactory(type); + AddDecoratedFactories(type); + } - public HandlerFactory(Type type) + public object Create(IServiceProvider provider, Type handlerInterfaceType) + { + object currentHandler = null; + foreach (var handlerFactory in _handlerFactoriesPipeline) { - AddHandlerFactory(type); - AddDecoratedFactories(type); + currentHandler = handlerFactory(currentHandler, handlerInterfaceType, provider); } - public object Create(IServiceProvider provider, Type handlerInterfaceType) - { - object currentHandler = null; - foreach (var handlerFactory in _handlerFactoriesPipeline) - { - currentHandler = handlerFactory(currentHandler, handlerInterfaceType, provider); - } + return currentHandler; + } - return currentHandler; - } + private void AddDecoratedFactories(Type type) + { + var attributes = type.GetCustomAttributes(inherit: false); - private void AddDecoratedFactories(Type type) + for (var i = attributes.Length - 1; i >= 0; i--) { - var attributes = type.GetCustomAttributes(inherit: false); + var attribute = attributes[i]; + var attributeType = attribute.GetType(); + Type decoratorHandlerType = null; + var hasDecoratorHandler = (type.HasInterface(typeof(ICommandHandler<>)) && Mappings.AttributeToCommandHandler.TryGetValue(attributeType, out decoratorHandlerType)) + || (type.HasInterface(typeof(IQueryHandler<,>)) && Mappings.AttributeToQueryHandler.TryGetValue(attributeType, out decoratorHandlerType)); - for (var i = attributes.Length - 1; i >= 0; i--) + if (!hasDecoratorHandler) { - var attribute = attributes[i]; - var attributeType = attribute.GetType(); - Type decoratorHandlerType = null; - var hasDecoratorHandler = (type.HasInterface(typeof(ICommandHandler<>)) && Mappings.AttributeToCommandHandler.TryGetValue(attributeType, out decoratorHandlerType)) - || (type.HasInterface(typeof(IQueryHandler<,>)) && Mappings.AttributeToQueryHandler.TryGetValue(attributeType, out decoratorHandlerType)); - - if (!hasDecoratorHandler) - { - continue; - } - - AddHandlerFactory(decoratorHandlerType, attribute); + continue; } + + AddHandlerFactory(decoratorHandlerType, attribute); } + } - private void AddHandlerFactory(Type handlerType, object attribute = null) - { - _handlerFactoriesPipeline.Add(CreateHandler); + private void AddHandlerFactory(Type handlerType, object attribute = null) + { + _handlerFactoriesPipeline.Add(CreateHandler); - object CreateHandler(object decoratingHandler, Type interfaceType, IServiceProvider provider) - { - var ctor = handlerType - .MakeGenericTypeSafe(interfaceType.GenericTypeArguments) - .GetConstructors() - .Single(); + object CreateHandler(object decoratingHandler, Type interfaceType, IServiceProvider provider) + { + var ctor = handlerType + .MakeGenericTypeSafe(interfaceType.GenericTypeArguments) + .GetConstructors() + .Single(); - var parameterInfos = ctor.GetParameters(); - var parameters = GetParameters(parameterInfos, decoratingHandler, attribute, provider); + var parameterInfos = ctor.GetParameters(); + var parameters = GetParameters(parameterInfos, decoratingHandler, attribute, provider); - var handler = ctor.Invoke(parameters); + var handler = ctor.Invoke(parameters); - return handler; - } + return handler; } + } - private static object[] GetParameters(IEnumerable parameterInfos, object current, object attribute, IServiceProvider provider) + private static object[] GetParameters(IEnumerable parameterInfos, object current, object attribute, IServiceProvider provider) + { + return parameterInfos.Select(GetParameter).ToArray(); + + object GetParameter(ParameterInfo parameterInfo) { - return parameterInfos.Select(GetParameter).ToArray(); + var parameterType = parameterInfo.ParameterType; - object GetParameter(ParameterInfo parameterInfo) + if (Utils.IsHandlerInterface(parameterType)) { - var parameterType = parameterInfo.ParameterType; - - if (Utils.IsHandlerInterface(parameterType)) - { - return current; - } - - if (parameterType == attribute?.GetType()) - { - return attribute; - } + return current; + } - var service = provider.GetService(parameterType); - if (service != null) - { - return service; - } + if (parameterType == attribute?.GetType()) + { + return attribute; + } - throw new ArgumentException($"Type {parameterType} not found"); + var service = provider.GetService(parameterType); + if (service != null) + { + return service; } + + throw new ArgumentException($"Type {parameterType} not found"); } } } \ No newline at end of file diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Common/Queries/GetEntititesQuery.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Common/Queries/GetEntititesQuery.cs index 18072f4be..840aa88b4 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Common/Queries/GetEntititesQuery.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Common/Queries/GetEntititesQuery.cs @@ -6,26 +6,25 @@ using System.Threading; using System.Threading.Tasks; -namespace ClassifiedAds.Application +namespace ClassifiedAds.Application; + +public class GetEntititesQuery : IQuery> + where TEntity : Entity, IAggregateRoot +{ +} + +internal class GetEntititesQueryHandler : IQueryHandler, List> +where TEntity : Entity, IAggregateRoot { - public class GetEntititesQuery : IQuery> - where TEntity : Entity, IAggregateRoot + private readonly IRepository _repository; + + public GetEntititesQueryHandler(IRepository repository) { + _repository = repository; } - internal class GetEntititesQueryHandler : IQueryHandler, List> - where TEntity : Entity, IAggregateRoot + public async Task> HandleAsync(GetEntititesQuery query, CancellationToken cancellationToken = default) { - private readonly IRepository _repository; - - public GetEntititesQueryHandler(IRepository repository) - { - _repository = repository; - } - - public async Task> HandleAsync(GetEntititesQuery query, CancellationToken cancellationToken = default) - { - return await _repository.ToListAsync(_repository.GetQueryableSet()); - } + return await _repository.ToListAsync(_repository.GetQueryableSet()); } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Common/Queries/GetEntityByIdQuery.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Common/Queries/GetEntityByIdQuery.cs index 6b5c1a6a2..056f1aae9 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Common/Queries/GetEntityByIdQuery.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Common/Queries/GetEntityByIdQuery.cs @@ -6,35 +6,34 @@ using System.Threading; using System.Threading.Tasks; -namespace ClassifiedAds.Application +namespace ClassifiedAds.Application; + +public class GetEntityByIdQuery : IQuery + where TEntity : Entity, IAggregateRoot +{ + public Guid Id { get; set; } + public bool ThrowNotFoundIfNull { get; set; } +} + +internal class GetEntityByIdQueryHandler : IQueryHandler, TEntity> +where TEntity : Entity, IAggregateRoot { - public class GetEntityByIdQuery : IQuery - where TEntity : Entity, IAggregateRoot + private readonly IRepository _repository; + + public GetEntityByIdQueryHandler(IRepository repository) { - public Guid Id { get; set; } - public bool ThrowNotFoundIfNull { get; set; } + _repository = repository; } - internal class GetEntityByIdQueryHandler : IQueryHandler, TEntity> - where TEntity : Entity, IAggregateRoot + public async Task HandleAsync(GetEntityByIdQuery query, CancellationToken cancellationToken = default) { - private readonly IRepository _repository; + var entity = await _repository.FirstOrDefaultAsync(_repository.GetQueryableSet().Where(x => x.Id == query.Id)); - public GetEntityByIdQueryHandler(IRepository repository) + if (query.ThrowNotFoundIfNull && entity == null) { - _repository = repository; + throw new NotFoundException($"Entity {query.Id} not found."); } - public async Task HandleAsync(GetEntityByIdQuery query, CancellationToken cancellationToken = default) - { - var entity = await _repository.FirstOrDefaultAsync(_repository.GetQueryableSet().Where(x => x.Id == query.Id)); - - if (query.ThrowNotFoundIfNull && entity == null) - { - throw new NotFoundException($"Entity {query.Id} not found."); - } - - return entity; - } + return entity; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Common/Queries/IQuery.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Common/Queries/IQuery.cs index 36f768af6..23f355d03 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Common/Queries/IQuery.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Common/Queries/IQuery.cs @@ -1,6 +1,5 @@ -namespace ClassifiedAds.Application +namespace ClassifiedAds.Application; + +public interface IQuery { - public interface IQuery - { - } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Common/Queries/IQueryHandler.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Common/Queries/IQueryHandler.cs index 821fbe070..79f39df95 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Common/Queries/IQueryHandler.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Common/Queries/IQueryHandler.cs @@ -1,11 +1,10 @@ using System.Threading; using System.Threading.Tasks; -namespace ClassifiedAds.Application +namespace ClassifiedAds.Application; + +public interface IQueryHandler + where TQuery : IQuery { - public interface IQueryHandler - where TQuery : IQuery - { - Task HandleAsync(TQuery query, CancellationToken cancellationToken = default); - } + Task HandleAsync(TQuery query, CancellationToken cancellationToken = default); } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Common/Services/ICrudService.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Common/Services/ICrudService.cs index bf01b375d..4881663b3 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Common/Services/ICrudService.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Common/Services/ICrudService.cs @@ -4,21 +4,20 @@ using System.Threading; using System.Threading.Tasks; -namespace ClassifiedAds.Application +namespace ClassifiedAds.Application; + +public interface ICrudService + where T : Entity, IAggregateRoot { - public interface ICrudService - where T : Entity, IAggregateRoot - { - Task> GetAsync(CancellationToken cancellationToken = default); + Task> GetAsync(CancellationToken cancellationToken = default); - Task GetByIdAsync(Guid id, CancellationToken cancellationToken = default); + Task GetByIdAsync(Guid id, CancellationToken cancellationToken = default); - Task AddOrUpdateAsync(T entity, CancellationToken cancellationToken = default); + Task AddOrUpdateAsync(T entity, CancellationToken cancellationToken = default); - Task AddAsync(T entity, CancellationToken cancellationToken = default); + Task AddAsync(T entity, CancellationToken cancellationToken = default); - Task UpdateAsync(T entity, CancellationToken cancellationToken = default); + Task UpdateAsync(T entity, CancellationToken cancellationToken = default); - Task DeleteAsync(T entity, CancellationToken cancellationToken = default); - } + Task DeleteAsync(T entity, CancellationToken cancellationToken = default); } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Common/Utils.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Common/Utils.cs index 8ba48e017..3a9c75f45 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Common/Utils.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Common/Utils.cs @@ -1,20 +1,19 @@ using System; -namespace ClassifiedAds.Application +namespace ClassifiedAds.Application; + +internal static class Utils { - internal static class Utils + public static bool IsHandlerInterface(Type type) { - public static bool IsHandlerInterface(Type type) + if (!type.IsGenericType) { - if (!type.IsGenericType) - { - return false; - } + return false; + } - var typeDefinition = type.GetGenericTypeDefinition(); + var typeDefinition = type.GetGenericTypeDefinition(); - return typeDefinition == typeof(ICommandHandler<>) - || typeDefinition == typeof(IQueryHandler<,>); - } + return typeDefinition == typeof(ICommandHandler<>) + || typeDefinition == typeof(IQueryHandler<,>); } } \ No newline at end of file diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Decorators/AuditLog/AuditLogAttribute.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Decorators/AuditLog/AuditLogAttribute.cs index 7fa379a29..3b779af88 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Decorators/AuditLog/AuditLogAttribute.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Decorators/AuditLog/AuditLogAttribute.cs @@ -1,9 +1,8 @@ using System; -namespace ClassifiedAds.Application.Decorators.AuditLog +namespace ClassifiedAds.Application.Decorators.AuditLog; + +[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = true)] +public sealed class AuditLogAttribute : Attribute { - [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = true)] - public sealed class AuditLogAttribute : Attribute - { - } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Decorators/AuditLog/AuditLogCommandDecorator.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Decorators/AuditLog/AuditLogCommandDecorator.cs index 91e47f012..e65ebd2ab 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Decorators/AuditLog/AuditLogCommandDecorator.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Decorators/AuditLog/AuditLogCommandDecorator.cs @@ -3,24 +3,23 @@ using System.Threading; using System.Threading.Tasks; -namespace ClassifiedAds.Application.Decorators.AuditLog +namespace ClassifiedAds.Application.Decorators.AuditLog; + +[Mapping(Type = typeof(AuditLogAttribute))] +public class AuditLogCommandDecorator : ICommandHandler + where TCommand : ICommand { - [Mapping(Type = typeof(AuditLogAttribute))] - public class AuditLogCommandDecorator : ICommandHandler - where TCommand : ICommand - { - private readonly ICommandHandler _handler; + private readonly ICommandHandler _handler; - public AuditLogCommandDecorator(ICommandHandler handler) - { - _handler = handler; - } + public AuditLogCommandDecorator(ICommandHandler handler) + { + _handler = handler; + } - public async Task HandleAsync(TCommand command, CancellationToken cancellationToken = default) - { - var commandJson = JsonSerializer.Serialize(command); - Console.WriteLine($"Command of type {command.GetType().Name}: {commandJson}"); - await _handler.HandleAsync(command, cancellationToken); - } + public async Task HandleAsync(TCommand command, CancellationToken cancellationToken = default) + { + var commandJson = JsonSerializer.Serialize(command); + Console.WriteLine($"Command of type {command.GetType().Name}: {commandJson}"); + await _handler.HandleAsync(command, cancellationToken); } } \ No newline at end of file diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Decorators/AuditLog/AuditLogQueryDecorator.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Decorators/AuditLog/AuditLogQueryDecorator.cs index 554e10316..ee99f93f9 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Decorators/AuditLog/AuditLogQueryDecorator.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Decorators/AuditLog/AuditLogQueryDecorator.cs @@ -3,24 +3,23 @@ using System.Threading; using System.Threading.Tasks; -namespace ClassifiedAds.Application.Decorators.AuditLog +namespace ClassifiedAds.Application.Decorators.AuditLog; + +[Mapping(Type = typeof(AuditLogAttribute))] +public class AuditLogQueryDecorator : IQueryHandler + where TQuery : IQuery { - [Mapping(Type = typeof(AuditLogAttribute))] - public class AuditLogQueryDecorator : IQueryHandler - where TQuery : IQuery - { - private readonly IQueryHandler _handler; + private readonly IQueryHandler _handler; - public AuditLogQueryDecorator(IQueryHandler handler) - { - _handler = handler; - } + public AuditLogQueryDecorator(IQueryHandler handler) + { + _handler = handler; + } - public Task HandleAsync(TQuery query, CancellationToken cancellationToken = default) - { - string queryJson = JsonSerializer.Serialize(query); - Console.WriteLine($"Query of type {query.GetType().Name}: {queryJson}"); - return _handler.HandleAsync(query, cancellationToken); - } + public Task HandleAsync(TQuery query, CancellationToken cancellationToken = default) + { + string queryJson = JsonSerializer.Serialize(query); + Console.WriteLine($"Query of type {query.GetType().Name}: {queryJson}"); + return _handler.HandleAsync(query, cancellationToken); } } \ No newline at end of file diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Decorators/DatabaseRetry/DatabaseRetryAttribute.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Decorators/DatabaseRetry/DatabaseRetryAttribute.cs index 64c966f47..24d8ad74e 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Decorators/DatabaseRetry/DatabaseRetryAttribute.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Decorators/DatabaseRetry/DatabaseRetryAttribute.cs @@ -1,15 +1,14 @@ using System; -namespace ClassifiedAds.Application.Decorators.DatabaseRetry +namespace ClassifiedAds.Application.Decorators.DatabaseRetry; + +[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = true)] +public sealed class DatabaseRetryAttribute : Attribute { - [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = true)] - public sealed class DatabaseRetryAttribute : Attribute - { - public int RetryTimes { get; } + public int RetryTimes { get; } - public DatabaseRetryAttribute(int retryTimes = 3) - { - RetryTimes = retryTimes; - } + public DatabaseRetryAttribute(int retryTimes = 3) + { + RetryTimes = retryTimes; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Decorators/DatabaseRetry/DatabaseRetryCommandDecorator.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Decorators/DatabaseRetry/DatabaseRetryCommandDecorator.cs index dba343719..05aae506f 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Decorators/DatabaseRetry/DatabaseRetryCommandDecorator.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Decorators/DatabaseRetry/DatabaseRetryCommandDecorator.cs @@ -1,23 +1,22 @@ using System.Threading; using System.Threading.Tasks; -namespace ClassifiedAds.Application.Decorators.DatabaseRetry +namespace ClassifiedAds.Application.Decorators.DatabaseRetry; + +[Mapping(Type = typeof(DatabaseRetryAttribute))] +public class DatabaseRetryCommandDecorator : DatabaseRetryDecoratorBase, ICommandHandler + where TCommand : ICommand { - [Mapping(Type = typeof(DatabaseRetryAttribute))] - public class DatabaseRetryCommandDecorator : DatabaseRetryDecoratorBase, ICommandHandler - where TCommand : ICommand - { - private readonly ICommandHandler _handler; + private readonly ICommandHandler _handler; - public DatabaseRetryCommandDecorator(ICommandHandler handler, DatabaseRetryAttribute options) - { - DatabaseRetryOptions = options; - _handler = handler; - } + public DatabaseRetryCommandDecorator(ICommandHandler handler, DatabaseRetryAttribute options) + { + DatabaseRetryOptions = options; + _handler = handler; + } - public async Task HandleAsync(TCommand command, CancellationToken cancellationToken = default) - { - await WrapExecutionAsync(() => _handler.HandleAsync(command, cancellationToken)); - } + public async Task HandleAsync(TCommand command, CancellationToken cancellationToken = default) + { + await WrapExecutionAsync(() => _handler.HandleAsync(command, cancellationToken)); } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Decorators/DatabaseRetry/DatabaseRetryDecoratorBase.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Decorators/DatabaseRetry/DatabaseRetryDecoratorBase.cs index 54147b9e5..3caaffdd4 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Decorators/DatabaseRetry/DatabaseRetryDecoratorBase.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Decorators/DatabaseRetry/DatabaseRetryDecoratorBase.cs @@ -1,67 +1,66 @@ using System; using System.Threading.Tasks; -namespace ClassifiedAds.Application.Decorators.DatabaseRetry +namespace ClassifiedAds.Application.Decorators.DatabaseRetry; + +public abstract class DatabaseRetryDecoratorBase { - public abstract class DatabaseRetryDecoratorBase + protected DatabaseRetryAttribute DatabaseRetryOptions { get; set; } + + protected void WrapExecution(Action action) { - protected DatabaseRetryAttribute DatabaseRetryOptions { get; set; } + int executedTimes = 0; - protected void WrapExecution(Action action) + while (true) { - int executedTimes = 0; - - while (true) + try { - try - { - executedTimes++; - action(); - return; - } - catch (Exception ex) + executedTimes++; + action(); + return; + } + catch (Exception ex) + { + if (executedTimes >= DatabaseRetryOptions.RetryTimes || !IsDatabaseException(ex)) { - if (executedTimes >= DatabaseRetryOptions.RetryTimes || !IsDatabaseException(ex)) - { - throw; - } + throw; } } } + } - protected async Task WrapExecutionAsync(Func action) - { - int executedTimes = 0; + protected async Task WrapExecutionAsync(Func action) + { + int executedTimes = 0; - while (true) + while (true) + { + try { - try - { - executedTimes++; - await action(); - return; - } - catch (Exception ex) + executedTimes++; + await action(); + return; + } + catch (Exception ex) + { + if (executedTimes >= DatabaseRetryOptions.RetryTimes || !IsDatabaseException(ex)) { - if (executedTimes >= DatabaseRetryOptions.RetryTimes || !IsDatabaseException(ex)) - { - throw; - } + throw; } } } + } - private static bool IsDatabaseException(Exception exception) - { - string message = exception.InnerException?.Message; - - if (message == null) - { - return false; - } + private static bool IsDatabaseException(Exception exception) + { + string message = exception.InnerException?.Message; - return message.Contains("The connection is broken and recovery is not possible") - || message.Contains("error occurred while establishing a connection"); + if (message == null) + { + return false; } + + return message.Contains("The connection is broken and recovery is not possible") + || message.Contains("error occurred while establishing a connection"); } } \ No newline at end of file diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Decorators/DatabaseRetry/DatabaseRetryQueryDecorator.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Decorators/DatabaseRetry/DatabaseRetryQueryDecorator.cs index 0cf32c8ce..b3965de49 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Decorators/DatabaseRetry/DatabaseRetryQueryDecorator.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Decorators/DatabaseRetry/DatabaseRetryQueryDecorator.cs @@ -1,25 +1,24 @@ using System.Threading; using System.Threading.Tasks; -namespace ClassifiedAds.Application.Decorators.DatabaseRetry +namespace ClassifiedAds.Application.Decorators.DatabaseRetry; + +[Mapping(Type = typeof(DatabaseRetryAttribute))] +public class DatabaseRetryQueryDecorator : DatabaseRetryDecoratorBase, IQueryHandler + where TQuery : IQuery { - [Mapping(Type = typeof(DatabaseRetryAttribute))] - public class DatabaseRetryQueryDecorator : DatabaseRetryDecoratorBase, IQueryHandler - where TQuery : IQuery - { - private readonly IQueryHandler _handler; + private readonly IQueryHandler _handler; - public DatabaseRetryQueryDecorator(IQueryHandler handler, DatabaseRetryAttribute options) - { - DatabaseRetryOptions = options; - _handler = handler; - } + public DatabaseRetryQueryDecorator(IQueryHandler handler, DatabaseRetryAttribute options) + { + DatabaseRetryOptions = options; + _handler = handler; + } - public async Task HandleAsync(TQuery query, CancellationToken cancellationToken = default) - { - Task result = default; - await WrapExecutionAsync(() => result = _handler.HandleAsync(query, cancellationToken)); - return await result; - } + public async Task HandleAsync(TQuery query, CancellationToken cancellationToken = default) + { + Task result = default; + await WrapExecutionAsync(() => result = _handler.HandleAsync(query, cancellationToken)); + return await result; } } \ No newline at end of file diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Decorators/Mappings.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Decorators/Mappings.cs index 6c569bd38..c7b1ac7e8 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Decorators/Mappings.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Decorators/Mappings.cs @@ -4,44 +4,43 @@ using System.Linq; using System.Reflection; -namespace ClassifiedAds.Application.Decorators +namespace ClassifiedAds.Application.Decorators; + +internal static class Mappings { - internal static class Mappings + static Mappings() { - static Mappings() + var decorators = Assembly.GetExecutingAssembly().GetTypes(); + foreach (var type in decorators) { - var decorators = Assembly.GetExecutingAssembly().GetTypes(); - foreach (var type in decorators) + if (type.HasInterface(typeof(ICommandHandler<>))) { - if (type.HasInterface(typeof(ICommandHandler<>))) - { - var decoratorAttribute = (MappingAttribute)type.GetCustomAttributes(false).FirstOrDefault(x => x.GetType() == typeof(MappingAttribute)); + var decoratorAttribute = (MappingAttribute)type.GetCustomAttributes(false).FirstOrDefault(x => x.GetType() == typeof(MappingAttribute)); - if (decoratorAttribute != null) - { - AttributeToCommandHandler[decoratorAttribute.Type] = type; - } - } - else if (type.HasInterface(typeof(IQueryHandler<,>))) + if (decoratorAttribute != null) { - var decoratorAttribute = (MappingAttribute)type.GetCustomAttributes(false).FirstOrDefault(x => x.GetType() == typeof(MappingAttribute)); + AttributeToCommandHandler[decoratorAttribute.Type] = type; + } + } + else if (type.HasInterface(typeof(IQueryHandler<,>))) + { + var decoratorAttribute = (MappingAttribute)type.GetCustomAttributes(false).FirstOrDefault(x => x.GetType() == typeof(MappingAttribute)); - if (decoratorAttribute != null) - { - AttributeToQueryHandler[decoratorAttribute.Type] = type; - } + if (decoratorAttribute != null) + { + AttributeToQueryHandler[decoratorAttribute.Type] = type; } } } + } - public static readonly Dictionary AttributeToCommandHandler = new Dictionary(); + public static readonly Dictionary AttributeToCommandHandler = new Dictionary(); - public static readonly Dictionary AttributeToQueryHandler = new Dictionary(); - } + public static readonly Dictionary AttributeToQueryHandler = new Dictionary(); +} - [AttributeUsage(AttributeTargets.Class)] - public sealed class MappingAttribute : Attribute - { - public Type Type { get; set; } - } +[AttributeUsage(AttributeTargets.Class)] +public sealed class MappingAttribute : Attribute +{ + public Type Type { get; set; } } \ No newline at end of file diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Roles/Commands/AddClaimCommand.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Roles/Commands/AddClaimCommand.cs index 173db10c2..72d498bb4 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Roles/Commands/AddClaimCommand.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Roles/Commands/AddClaimCommand.cs @@ -3,27 +3,26 @@ using System.Threading; using System.Threading.Tasks; -namespace ClassifiedAds.Application.Roles.Commands +namespace ClassifiedAds.Application.Roles.Commands; + +public class AddClaimCommand : ICommand +{ + public Role Role { get; set; } + public RoleClaim Claim { get; set; } +} + +internal class AddClaimCommandHandler : ICommandHandler { - public class AddClaimCommand : ICommand + private readonly IRoleRepository _roleRepository; + + public AddClaimCommandHandler(IRoleRepository roleRepository) { - public Role Role { get; set; } - public RoleClaim Claim { get; set; } + _roleRepository = roleRepository; } - internal class AddClaimCommandHandler : ICommandHandler + public async Task HandleAsync(AddClaimCommand command, CancellationToken cancellationToken = default) { - private readonly IRoleRepository _roleRepository; - - public AddClaimCommandHandler(IRoleRepository roleRepository) - { - _roleRepository = roleRepository; - } - - public async Task HandleAsync(AddClaimCommand command, CancellationToken cancellationToken = default) - { - command.Role.Claims.Add(command.Claim); - await _roleRepository.UnitOfWork.SaveChangesAsync(); - } + command.Role.Claims.Add(command.Claim); + await _roleRepository.UnitOfWork.SaveChangesAsync(); } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Roles/Commands/AddUpdateRoleCommand .cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Roles/Commands/AddUpdateRoleCommand .cs index 1446e29a0..1b4e33a91 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Roles/Commands/AddUpdateRoleCommand .cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Roles/Commands/AddUpdateRoleCommand .cs @@ -3,26 +3,25 @@ using System.Threading; using System.Threading.Tasks; -namespace ClassifiedAds.Application.Roles.Commands +namespace ClassifiedAds.Application.Roles.Commands; + +public class AddUpdateRoleCommand : ICommand +{ + public Role Role { get; set; } +} + +internal class AddUpdateRoleCommandHandler : ICommandHandler { - public class AddUpdateRoleCommand : ICommand + private readonly IRoleRepository _roleRepository; + + public AddUpdateRoleCommandHandler(IRoleRepository roleRepository) { - public Role Role { get; set; } + _roleRepository = roleRepository; } - internal class AddUpdateRoleCommandHandler : ICommandHandler + public async Task HandleAsync(AddUpdateRoleCommand command, CancellationToken cancellationToken = default) { - private readonly IRoleRepository _roleRepository; - - public AddUpdateRoleCommandHandler(IRoleRepository roleRepository) - { - _roleRepository = roleRepository; - } - - public async Task HandleAsync(AddUpdateRoleCommand command, CancellationToken cancellationToken = default) - { - await _roleRepository.AddOrUpdateAsync(command.Role); - await _roleRepository.UnitOfWork.SaveChangesAsync(); - } + await _roleRepository.AddOrUpdateAsync(command.Role); + await _roleRepository.UnitOfWork.SaveChangesAsync(); } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Roles/Commands/DeleteClaimCommand.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Roles/Commands/DeleteClaimCommand.cs index b960cc95c..e13c67594 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Roles/Commands/DeleteClaimCommand.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Roles/Commands/DeleteClaimCommand.cs @@ -3,27 +3,26 @@ using System.Threading; using System.Threading.Tasks; -namespace ClassifiedAds.Application.Roles.Commands +namespace ClassifiedAds.Application.Roles.Commands; + +public class DeleteClaimCommand : ICommand +{ + public Role Role { get; set; } + public RoleClaim Claim { get; set; } +} + +internal class DeleteClaimCommandHandler : ICommandHandler { - public class DeleteClaimCommand : ICommand + private readonly IRoleRepository _roleRepository; + + public DeleteClaimCommandHandler(IRoleRepository roleRepository) { - public Role Role { get; set; } - public RoleClaim Claim { get; set; } + _roleRepository = roleRepository; } - internal class DeleteClaimCommandHandler : ICommandHandler + public async Task HandleAsync(DeleteClaimCommand command, CancellationToken cancellationToken = default) { - private readonly IRoleRepository _roleRepository; - - public DeleteClaimCommandHandler(IRoleRepository roleRepository) - { - _roleRepository = roleRepository; - } - - public async Task HandleAsync(DeleteClaimCommand command, CancellationToken cancellationToken = default) - { - command.Role.Claims.Remove(command.Claim); - await _roleRepository.UnitOfWork.SaveChangesAsync(); - } + command.Role.Claims.Remove(command.Claim); + await _roleRepository.UnitOfWork.SaveChangesAsync(); } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Roles/Commands/DeleteRoleCommand.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Roles/Commands/DeleteRoleCommand.cs index 630ab34b9..0a04e1891 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Roles/Commands/DeleteRoleCommand.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Roles/Commands/DeleteRoleCommand.cs @@ -3,26 +3,25 @@ using System.Threading; using System.Threading.Tasks; -namespace ClassifiedAds.Application.Roles.Commands +namespace ClassifiedAds.Application.Roles.Commands; + +public class DeleteRoleCommand : ICommand +{ + public Role Role { get; set; } +} + +internal class DeleteRoleCommandHandler : ICommandHandler { - public class DeleteRoleCommand : ICommand + private readonly IRoleRepository _roleRepository; + + public DeleteRoleCommandHandler(IRoleRepository roleRepository) { - public Role Role { get; set; } + _roleRepository = roleRepository; } - internal class DeleteRoleCommandHandler : ICommandHandler + public async Task HandleAsync(DeleteRoleCommand command, CancellationToken cancellationToken = default) { - private readonly IRoleRepository _roleRepository; - - public DeleteRoleCommandHandler(IRoleRepository roleRepository) - { - _roleRepository = roleRepository; - } - - public async Task HandleAsync(DeleteRoleCommand command, CancellationToken cancellationToken = default) - { - _roleRepository.Delete(command.Role); - await _roleRepository.UnitOfWork.SaveChangesAsync(); - } + _roleRepository.Delete(command.Role); + await _roleRepository.UnitOfWork.SaveChangesAsync(); } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Roles/Queries/GetRoleQuery.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Roles/Queries/GetRoleQuery.cs index f3e4b3715..81b2589f9 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Roles/Queries/GetRoleQuery.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Roles/Queries/GetRoleQuery.cs @@ -5,37 +5,36 @@ using System.Threading; using System.Threading.Tasks; -namespace ClassifiedAds.Application.Roles.Queries +namespace ClassifiedAds.Application.Roles.Queries; + +public class GetRoleQuery : IQuery +{ + public Guid Id { get; set; } + public bool IncludeClaims { get; set; } + public bool IncludeUserRoles { get; set; } + public bool IncludeUsers { get; set; } + public bool AsNoTracking { get; set; } +} + +internal class GetRoleQueryHandler : IQueryHandler { - public class GetRoleQuery : IQuery + private readonly IRoleRepository _roleRepository; + + public GetRoleQueryHandler(IRoleRepository roleRepository) { - public Guid Id { get; set; } - public bool IncludeClaims { get; set; } - public bool IncludeUserRoles { get; set; } - public bool IncludeUsers { get; set; } - public bool AsNoTracking { get; set; } + _roleRepository = roleRepository; } - internal class GetRoleQueryHandler : IQueryHandler + public Task HandleAsync(GetRoleQuery query, CancellationToken cancellationToken = default) { - private readonly IRoleRepository _roleRepository; - - public GetRoleQueryHandler(IRoleRepository roleRepository) - { - _roleRepository = roleRepository; - } - - public Task HandleAsync(GetRoleQuery query, CancellationToken cancellationToken = default) + var db = _roleRepository.Get(new RoleQueryOptions { - var db = _roleRepository.Get(new RoleQueryOptions - { - IncludeClaims = query.IncludeClaims, - IncludeUserRoles = query.IncludeUserRoles, - IncludeUsers = query.IncludeUsers, - AsNoTracking = query.AsNoTracking, - }); + IncludeClaims = query.IncludeClaims, + IncludeUserRoles = query.IncludeUserRoles, + IncludeUsers = query.IncludeUsers, + AsNoTracking = query.AsNoTracking, + }); - return _roleRepository.FirstOrDefaultAsync(db.Where(x => x.Id == query.Id)); - } + return _roleRepository.FirstOrDefaultAsync(db.Where(x => x.Id == query.Id)); } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Roles/Queries/GetRolesQuery.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Roles/Queries/GetRolesQuery.cs index a3f049784..c36aa5e4c 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Roles/Queries/GetRolesQuery.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Roles/Queries/GetRolesQuery.cs @@ -5,34 +5,33 @@ using System.Threading; using System.Threading.Tasks; -namespace ClassifiedAds.Application.Roles.Queries +namespace ClassifiedAds.Application.Roles.Queries; + +public class GetRolesQuery : IQuery> +{ + public bool IncludeClaims { get; set; } + public bool IncludeUserRoles { get; set; } + public bool AsNoTracking { get; set; } +} + +internal class GetRolesQueryHandler : IQueryHandler> { - public class GetRolesQuery : IQuery> + private readonly IRoleRepository _roleRepository; + + public GetRolesQueryHandler(IRoleRepository roleRepository) { - public bool IncludeClaims { get; set; } - public bool IncludeUserRoles { get; set; } - public bool AsNoTracking { get; set; } + _roleRepository = roleRepository; } - internal class GetRolesQueryHandler : IQueryHandler> + public async Task> HandleAsync(GetRolesQuery query, CancellationToken cancellationToken = default) { - private readonly IRoleRepository _roleRepository; - - public GetRolesQueryHandler(IRoleRepository roleRepository) - { - _roleRepository = roleRepository; - } - - public async Task> HandleAsync(GetRolesQuery query, CancellationToken cancellationToken = default) + var db = _roleRepository.Get(new RoleQueryOptions { - var db = _roleRepository.Get(new RoleQueryOptions - { - IncludeClaims = query.IncludeClaims, - IncludeUserRoles = query.IncludeUserRoles, - AsNoTracking = query.AsNoTracking, - }); + IncludeClaims = query.IncludeClaims, + IncludeUserRoles = query.IncludeUserRoles, + AsNoTracking = query.AsNoTracking, + }); - return await _roleRepository.ToListAsync(db); - } + return await _roleRepository.ToListAsync(db); } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Users/Commands/AddClaimCommand.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Users/Commands/AddClaimCommand.cs index 828819618..f3fa820e2 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Users/Commands/AddClaimCommand.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Users/Commands/AddClaimCommand.cs @@ -3,28 +3,27 @@ using System.Threading; using System.Threading.Tasks; -namespace ClassifiedAds.Application.Users.Commands +namespace ClassifiedAds.Application.Users.Commands; + +public class AddClaimCommand : ICommand +{ + public User User { get; set; } + public UserClaim Claim { get; set; } +} + +internal class AddClaimCommandHandler : ICommandHandler { - public class AddClaimCommand : ICommand + private readonly IUserRepository _userRepository; + + public AddClaimCommandHandler(IUserRepository userRepository) { - public User User { get; set; } - public UserClaim Claim { get; set; } + _userRepository = userRepository; } - internal class AddClaimCommandHandler : ICommandHandler + public async Task HandleAsync(AddClaimCommand command, CancellationToken cancellationToken = default) { - private readonly IUserRepository _userRepository; - - public AddClaimCommandHandler(IUserRepository userRepository) - { - _userRepository = userRepository; - } - - public async Task HandleAsync(AddClaimCommand command, CancellationToken cancellationToken = default) - { - command.User.Claims.Add(command.Claim); - await _userRepository.AddOrUpdateAsync(command.User); - await _userRepository.UnitOfWork.SaveChangesAsync(); - } + command.User.Claims.Add(command.Claim); + await _userRepository.AddOrUpdateAsync(command.User); + await _userRepository.UnitOfWork.SaveChangesAsync(); } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Users/Commands/AddRoleCommand .cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Users/Commands/AddRoleCommand .cs index 852574eb5..41d033179 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Users/Commands/AddRoleCommand .cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Users/Commands/AddRoleCommand .cs @@ -3,28 +3,27 @@ using System.Threading; using System.Threading.Tasks; -namespace ClassifiedAds.Application.Users.Commands +namespace ClassifiedAds.Application.Users.Commands; + +public class AddRoleCommand : ICommand +{ + public User User { get; set; } + public UserRole Role { get; set; } +} + +internal class AddRoleCommandHandler : ICommandHandler { - public class AddRoleCommand : ICommand + private readonly IUserRepository _userRepository; + + public AddRoleCommandHandler(IUserRepository userRepository) { - public User User { get; set; } - public UserRole Role { get; set; } + _userRepository = userRepository; } - internal class AddRoleCommandHandler : ICommandHandler + public async Task HandleAsync(AddRoleCommand command, CancellationToken cancellationToken = default) { - private readonly IUserRepository _userRepository; - - public AddRoleCommandHandler(IUserRepository userRepository) - { - _userRepository = userRepository; - } - - public async Task HandleAsync(AddRoleCommand command, CancellationToken cancellationToken = default) - { - command.User.UserRoles.Add(command.Role); - await _userRepository.AddOrUpdateAsync(command.User); - await _userRepository.UnitOfWork.SaveChangesAsync(); - } + command.User.UserRoles.Add(command.Role); + await _userRepository.AddOrUpdateAsync(command.User); + await _userRepository.UnitOfWork.SaveChangesAsync(); } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Users/Commands/DeleteClaimCommand.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Users/Commands/DeleteClaimCommand.cs index d38f7b51c..adca04cf5 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Users/Commands/DeleteClaimCommand.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Users/Commands/DeleteClaimCommand.cs @@ -3,28 +3,27 @@ using System.Threading; using System.Threading.Tasks; -namespace ClassifiedAds.Application.Users.Commands +namespace ClassifiedAds.Application.Users.Commands; + +public class DeleteClaimCommand : ICommand +{ + public User User { get; set; } + public UserClaim Claim { get; set; } +} + +internal class DeleteClaimCommandHandler : ICommandHandler { - public class DeleteClaimCommand : ICommand + private readonly IUserRepository _userRepository; + + public DeleteClaimCommandHandler(IUserRepository userRepository) { - public User User { get; set; } - public UserClaim Claim { get; set; } + _userRepository = userRepository; } - internal class DeleteClaimCommandHandler : ICommandHandler + public async Task HandleAsync(DeleteClaimCommand command, CancellationToken cancellationToken = default) { - private readonly IUserRepository _userRepository; - - public DeleteClaimCommandHandler(IUserRepository userRepository) - { - _userRepository = userRepository; - } - - public async Task HandleAsync(DeleteClaimCommand command, CancellationToken cancellationToken = default) - { - command.User.Claims.Remove(command.Claim); - await _userRepository.AddOrUpdateAsync(command.User); - await _userRepository.UnitOfWork.SaveChangesAsync(); - } + command.User.Claims.Remove(command.Claim); + await _userRepository.AddOrUpdateAsync(command.User); + await _userRepository.UnitOfWork.SaveChangesAsync(); } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Users/Commands/DeleteRoleCommand.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Users/Commands/DeleteRoleCommand.cs index 189c4db8e..06246541a 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Users/Commands/DeleteRoleCommand.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Users/Commands/DeleteRoleCommand.cs @@ -3,28 +3,27 @@ using System.Threading; using System.Threading.Tasks; -namespace ClassifiedAds.Application.Users.Commands +namespace ClassifiedAds.Application.Users.Commands; + +public class DeleteRoleCommand : ICommand +{ + public User User { get; set; } + public UserRole Role { get; set; } +} + +internal class DeleteRoleCommandHandler : ICommandHandler { - public class DeleteRoleCommand : ICommand + private readonly IUserRepository _userRepository; + + public DeleteRoleCommandHandler(IUserRepository userRepository) { - public User User { get; set; } - public UserRole Role { get; set; } + _userRepository = userRepository; } - internal class DeleteRoleCommandHandler : ICommandHandler + public async Task HandleAsync(DeleteRoleCommand command, CancellationToken cancellationToken = default) { - private readonly IUserRepository _userRepository; - - public DeleteRoleCommandHandler(IUserRepository userRepository) - { - _userRepository = userRepository; - } - - public async Task HandleAsync(DeleteRoleCommand command, CancellationToken cancellationToken = default) - { - command.User.UserRoles.Remove(command.Role); - await _userRepository.AddOrUpdateAsync(command.User); - await _userRepository.UnitOfWork.SaveChangesAsync(); - } + command.User.UserRoles.Remove(command.Role); + await _userRepository.AddOrUpdateAsync(command.User); + await _userRepository.UnitOfWork.SaveChangesAsync(); } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Users/Commands/DeleteUserCommand.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Users/Commands/DeleteUserCommand.cs index 2865eba0a..cb0fa52b1 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Users/Commands/DeleteUserCommand.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Users/Commands/DeleteUserCommand.cs @@ -3,26 +3,25 @@ using System.Threading; using System.Threading.Tasks; -namespace ClassifiedAds.Application.Users.Commands +namespace ClassifiedAds.Application.Users.Commands; + +public class DeleteUserCommand : ICommand +{ + public User User { get; set; } +} + +internal class DeleteUserCommandHandler : ICommandHandler { - public class DeleteUserCommand : ICommand + private readonly IUserRepository _userRepository; + + public DeleteUserCommandHandler(IUserRepository userRepository) { - public User User { get; set; } + _userRepository = userRepository; } - internal class DeleteUserCommandHandler : ICommandHandler + public async Task HandleAsync(DeleteUserCommand command, CancellationToken cancellationToken = default) { - private readonly IUserRepository _userRepository; - - public DeleteUserCommandHandler(IUserRepository userRepository) - { - _userRepository = userRepository; - } - - public async Task HandleAsync(DeleteUserCommand command, CancellationToken cancellationToken = default) - { - _userRepository.Delete(command.User); - await _userRepository.UnitOfWork.SaveChangesAsync(); - } + _userRepository.Delete(command.User); + await _userRepository.UnitOfWork.SaveChangesAsync(); } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Users/DTOs/UserDTO.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Users/DTOs/UserDTO.cs index 37b94bcd9..bddbf4fab 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Users/DTOs/UserDTO.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Users/DTOs/UserDTO.cs @@ -1,40 +1,39 @@ using System; using System.Collections.Generic; -namespace ClassifiedAds.Application.Users.DTOs +namespace ClassifiedAds.Application.Users.DTOs; + +public class UserDTO { - public class UserDTO - { - public string UserName { get; set; } + public string UserName { get; set; } - public string NormalizedUserName { get; set; } + public string NormalizedUserName { get; set; } - public string Email { get; set; } + public string Email { get; set; } - public string NormalizedEmail { get; set; } + public string NormalizedEmail { get; set; } - public bool EmailConfirmed { get; set; } + public bool EmailConfirmed { get; set; } - public string PhoneNumber { get; set; } + public string PhoneNumber { get; set; } - public bool PhoneNumberConfirmed { get; set; } + public bool PhoneNumberConfirmed { get; set; } - public bool TwoFactorEnabled { get; set; } + public bool TwoFactorEnabled { get; set; } - public string ConcurrencyStamp { get; set; } + public string ConcurrencyStamp { get; set; } - public string SecurityStamp { get; set; } + public string SecurityStamp { get; set; } - public bool LockoutEnabled { get; set; } + public bool LockoutEnabled { get; set; } - public DateTimeOffset? LockoutEnd { get; set; } + public DateTimeOffset? LockoutEnd { get; set; } - public int AccessFailedCount { get; set; } + public int AccessFailedCount { get; set; } - // public IList Tokens { get; set; } + // public IList Tokens { get; set; } - // public IList Claims { get; set; } + // public IList Claims { get; set; } - // public IList UserRoles { get; set; } - } + // public IList UserRoles { get; set; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Users/Queries/GetUserQuery.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Users/Queries/GetUserQuery.cs index 753aa3fd8..73c693db0 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Users/Queries/GetUserQuery.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Users/Queries/GetUserQuery.cs @@ -5,37 +5,36 @@ using System.Threading; using System.Threading.Tasks; -namespace ClassifiedAds.Application.Users.Queries +namespace ClassifiedAds.Application.Users.Queries; + +public class GetUserQuery : IQuery +{ + public Guid Id { get; set; } + public bool IncludeClaims { get; set; } + public bool IncludeUserRoles { get; set; } + public bool IncludeRoles { get; set; } + public bool AsNoTracking { get; set; } +} + +internal class GetUserQueryHandler : IQueryHandler { - public class GetUserQuery : IQuery + private readonly IUserRepository _userRepository; + + public GetUserQueryHandler(IUserRepository userRepository) { - public Guid Id { get; set; } - public bool IncludeClaims { get; set; } - public bool IncludeUserRoles { get; set; } - public bool IncludeRoles { get; set; } - public bool AsNoTracking { get; set; } + _userRepository = userRepository; } - internal class GetUserQueryHandler : IQueryHandler + public Task HandleAsync(GetUserQuery query, CancellationToken cancellationToken = default) { - private readonly IUserRepository _userRepository; - - public GetUserQueryHandler(IUserRepository userRepository) - { - _userRepository = userRepository; - } - - public Task HandleAsync(GetUserQuery query, CancellationToken cancellationToken = default) + var db = _userRepository.Get(new UserQueryOptions { - var db = _userRepository.Get(new UserQueryOptions - { - IncludeClaims = query.IncludeClaims, - IncludeUserRoles = query.IncludeUserRoles, - IncludeRoles = query.IncludeRoles, - AsNoTracking = query.AsNoTracking, - }); + IncludeClaims = query.IncludeClaims, + IncludeUserRoles = query.IncludeUserRoles, + IncludeRoles = query.IncludeRoles, + AsNoTracking = query.AsNoTracking, + }); - return _userRepository.FirstOrDefaultAsync(db.Where(x => x.Id == query.Id)); - } + return _userRepository.FirstOrDefaultAsync(db.Where(x => x.Id == query.Id)); } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Users/Queries/GetUsersQuery.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Users/Queries/GetUsersQuery.cs index ff65d861a..ef0b276e5 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Users/Queries/GetUsersQuery.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Users/Queries/GetUsersQuery.cs @@ -4,36 +4,35 @@ using System.Threading; using System.Threading.Tasks; -namespace ClassifiedAds.Application.Users.Queries +namespace ClassifiedAds.Application.Users.Queries; + +public class GetUsersQuery : IQuery> +{ + public bool IncludeClaims { get; set; } + public bool IncludeUserRoles { get; set; } + public bool IncludeRoles { get; set; } + public bool AsNoTracking { get; set; } +} + +internal class GetUsersQueryHandler : IQueryHandler> { - public class GetUsersQuery : IQuery> + private readonly IUserRepository _userRepository; + + public GetUsersQueryHandler(IUserRepository userRepository) { - public bool IncludeClaims { get; set; } - public bool IncludeUserRoles { get; set; } - public bool IncludeRoles { get; set; } - public bool AsNoTracking { get; set; } + _userRepository = userRepository; } - internal class GetUsersQueryHandler : IQueryHandler> + public async Task> HandleAsync(GetUsersQuery query, CancellationToken cancellationToken = default) { - private readonly IUserRepository _userRepository; - - public GetUsersQueryHandler(IUserRepository userRepository) - { - _userRepository = userRepository; - } - - public async Task> HandleAsync(GetUsersQuery query, CancellationToken cancellationToken = default) + var db = _userRepository.Get(new UserQueryOptions { - var db = _userRepository.Get(new UserQueryOptions - { - IncludeClaims = query.IncludeClaims, - IncludeUserRoles = query.IncludeUserRoles, - IncludeRoles = query.IncludeRoles, - AsNoTracking = query.AsNoTracking, - }); + IncludeClaims = query.IncludeClaims, + IncludeUserRoles = query.IncludeUserRoles, + IncludeRoles = query.IncludeRoles, + AsNoTracking = query.AsNoTracking, + }); - return await _userRepository.ToListAsync(db); - } + return await _userRepository.ToListAsync(db); } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Users/Services/IUserService.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Users/Services/IUserService.cs index 800fa5bb8..b38d7a4c3 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Users/Services/IUserService.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Application/Users/Services/IUserService.cs @@ -1,8 +1,7 @@ using ClassifiedAds.Domain.Entities; -namespace ClassifiedAds.Application.Users.Services +namespace ClassifiedAds.Application.Users.Services; + +public interface IUserService : ICrudService { - public interface IUserService : ICrudService - { - } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.CrossCuttingConcerns/CircuitBreakers/CircuitBreakerOpenException.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.CrossCuttingConcerns/CircuitBreakers/CircuitBreakerOpenException.cs index 3890a4df2..9898cdf47 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.CrossCuttingConcerns/CircuitBreakers/CircuitBreakerOpenException.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.CrossCuttingConcerns/CircuitBreakers/CircuitBreakerOpenException.cs @@ -1,8 +1,7 @@ using System; -namespace ClassifiedAds.CrossCuttingConcerns.CircuitBreakers +namespace ClassifiedAds.CrossCuttingConcerns.CircuitBreakers; + +public class CircuitBreakerOpenException : Exception { - public class CircuitBreakerOpenException : Exception - { - } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.CrossCuttingConcerns/CircuitBreakers/ICircuitBreaker.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.CrossCuttingConcerns/CircuitBreakers/ICircuitBreaker.cs index 949461d73..abadf80bf 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.CrossCuttingConcerns/CircuitBreakers/ICircuitBreaker.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.CrossCuttingConcerns/CircuitBreakers/ICircuitBreaker.cs @@ -1,22 +1,21 @@ using System; -namespace ClassifiedAds.CrossCuttingConcerns.CircuitBreakers +namespace ClassifiedAds.CrossCuttingConcerns.CircuitBreakers; + +public interface ICircuitBreaker { - public interface ICircuitBreaker - { - public string Name { get; set; } + public string Name { get; set; } - public CircuitStatus Status { get; set; } + public CircuitStatus Status { get; set; } - public DateTimeOffset LastStatusUpdated { get; set; } + public DateTimeOffset LastStatusUpdated { get; set; } - void EnsureOkStatus(); - } + void EnsureOkStatus(); +} - public enum CircuitStatus - { - Closed = 1, - Open = 2, - HalfOpen = 3, - } +public enum CircuitStatus +{ + Closed = 1, + Open = 2, + HalfOpen = 3, } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.CrossCuttingConcerns/CircuitBreakers/ICircuitBreakerManager.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.CrossCuttingConcerns/CircuitBreakers/ICircuitBreakerManager.cs index 6afa96006..e49466103 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.CrossCuttingConcerns/CircuitBreakers/ICircuitBreakerManager.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.CrossCuttingConcerns/CircuitBreakers/ICircuitBreakerManager.cs @@ -1,13 +1,12 @@ using System; -namespace ClassifiedAds.CrossCuttingConcerns.CircuitBreakers +namespace ClassifiedAds.CrossCuttingConcerns.CircuitBreakers; + +public interface ICircuitBreakerManager { - public interface ICircuitBreakerManager - { - ICircuitBreaker GetCircuitBreaker(string name, TimeSpan openTime); + ICircuitBreaker GetCircuitBreaker(string name, TimeSpan openTime); - void LogSuccess(ICircuitBreaker circuitBreaker); + void LogSuccess(ICircuitBreaker circuitBreaker); - void LogFailure(ICircuitBreaker circuitBreaker, int maximumNumberOfFailures, TimeSpan period); - } + void LogFailure(ICircuitBreaker circuitBreaker, int maximumNumberOfFailures, TimeSpan period); } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.CrossCuttingConcerns/DateTimes/IDateTimeProvider.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.CrossCuttingConcerns/DateTimes/IDateTimeProvider.cs index 1a6ca7092..4f557057b 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.CrossCuttingConcerns/DateTimes/IDateTimeProvider.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.CrossCuttingConcerns/DateTimes/IDateTimeProvider.cs @@ -1,15 +1,14 @@ using System; -namespace ClassifiedAds.CrossCuttingConcerns.DateTimes +namespace ClassifiedAds.CrossCuttingConcerns.DateTimes; + +public interface IDateTimeProvider { - public interface IDateTimeProvider - { - DateTime Now { get; } + DateTime Now { get; } - DateTime UtcNow { get; } + DateTime UtcNow { get; } - DateTimeOffset OffsetNow { get; } + DateTimeOffset OffsetNow { get; } - DateTimeOffset OffsetUtcNow { get; } - } + DateTimeOffset OffsetUtcNow { get; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.CrossCuttingConcerns/Exceptions/NotFoundException.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.CrossCuttingConcerns/Exceptions/NotFoundException.cs index be8453b67..504bef549 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.CrossCuttingConcerns/Exceptions/NotFoundException.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.CrossCuttingConcerns/Exceptions/NotFoundException.cs @@ -1,17 +1,16 @@ using System; -namespace ClassifiedAds.CrossCuttingConcerns.Exceptions +namespace ClassifiedAds.CrossCuttingConcerns.Exceptions; + +public class NotFoundException : Exception { - public class NotFoundException : Exception + public NotFoundException() + : base() { - public NotFoundException() - : base() - { - } + } - public NotFoundException(string message) - : base(message) - { - } + public NotFoundException(string message) + : base(message) + { } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.CrossCuttingConcerns/Exceptions/ValidationException.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.CrossCuttingConcerns/Exceptions/ValidationException.cs index f29861d1d..8c98a8492 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.CrossCuttingConcerns/Exceptions/ValidationException.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.CrossCuttingConcerns/Exceptions/ValidationException.cs @@ -1,25 +1,24 @@ using System; -namespace ClassifiedAds.CrossCuttingConcerns.Exceptions +namespace ClassifiedAds.CrossCuttingConcerns.Exceptions; + +public class ValidationException : Exception { - public class ValidationException : Exception + public static void Requires(bool expected, string errorMessage) { - public static void Requires(bool expected, string errorMessage) + if (!expected) { - if (!expected) - { - throw new ValidationException(errorMessage); - } + throw new ValidationException(errorMessage); } + } - public ValidationException(string message) - : base(message) - { - } + public ValidationException(string message) + : base(message) + { + } - public ValidationException(string message, Exception innerException) - : base(message, innerException) - { - } + public ValidationException(string message, Exception innerException) + : base(message, innerException) + { } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.CrossCuttingConcerns/ExtensionMethods/CloningExtensions.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.CrossCuttingConcerns/ExtensionMethods/CloningExtensions.cs index 4410be804..2d6593de5 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.CrossCuttingConcerns/ExtensionMethods/CloningExtensions.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.CrossCuttingConcerns/ExtensionMethods/CloningExtensions.cs @@ -1,34 +1,33 @@ using System.Reflection; using System.Text.Json; -namespace ClassifiedAds.CrossCuttingConcerns.ExtensionMethods +namespace ClassifiedAds.CrossCuttingConcerns.ExtensionMethods; + +/// +/// https://stackoverflow.com/questions/78536/deep-cloning-objects +/// +public static class CloningExtensions { + public static T ShallowClone(this T source) + { + var methodInfo = typeof(T).GetMethod("MemberwiseClone", BindingFlags.Instance | BindingFlags.NonPublic); + return (T)methodInfo.Invoke(source, null); + } + /// - /// https://stackoverflow.com/questions/78536/deep-cloning-objects + /// Perform a deep Copy of the object, using Json as a serialisation method. NOTE: Private members are not cloned using this method. /// - public static class CloningExtensions + /// The type of object being copied. + /// The object instance to copy. + /// The copied object. + public static T DeepCloneJson(this T source) { - public static T ShallowClone(this T source) + // Don't serialize a null object, simply return the default for that object + if (ReferenceEquals(source, null)) { - var methodInfo = typeof(T).GetMethod("MemberwiseClone", BindingFlags.Instance | BindingFlags.NonPublic); - return (T)methodInfo.Invoke(source, null); + return default(T); } - /// - /// Perform a deep Copy of the object, using Json as a serialisation method. NOTE: Private members are not cloned using this method. - /// - /// The type of object being copied. - /// The object instance to copy. - /// The copied object. - public static T DeepCloneJson(this T source) - { - // Don't serialize a null object, simply return the default for that object - if (ReferenceEquals(source, null)) - { - return default(T); - } - - return JsonSerializer.Deserialize(JsonSerializer.Serialize(source)); - } + return JsonSerializer.Deserialize(JsonSerializer.Serialize(source)); } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.CrossCuttingConcerns/ExtensionMethods/DateTimeExtensions.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.CrossCuttingConcerns/ExtensionMethods/DateTimeExtensions.cs index e0e4beb54..bd157fcf9 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.CrossCuttingConcerns/ExtensionMethods/DateTimeExtensions.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.CrossCuttingConcerns/ExtensionMethods/DateTimeExtensions.cs @@ -1,17 +1,16 @@ using System; -namespace ClassifiedAds.CrossCuttingConcerns.ExtensionMethods +namespace ClassifiedAds.CrossCuttingConcerns.ExtensionMethods; + +public static class DateTimeExtensions { - public static class DateTimeExtensions + public static DateTime FirstDayOfMonth(this DateTime date) { - public static DateTime FirstDayOfMonth(this DateTime date) - { - return new DateTime(date.Year, date.Month, 1); - } + return new DateTime(date.Year, date.Month, 1); + } - public static DateTime LastDayOfMonth(this DateTime date) - { - return new DateTime(date.Year, date.Month, 1).AddMonths(1).AddDays(-1); - } + public static DateTime LastDayOfMonth(this DateTime date) + { + return new DateTime(date.Year, date.Month, 1).AddMonths(1).AddDays(-1); } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.CrossCuttingConcerns/ExtensionMethods/DecimalExtensions.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.CrossCuttingConcerns/ExtensionMethods/DecimalExtensions.cs index 961abde2d..70a55def0 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.CrossCuttingConcerns/ExtensionMethods/DecimalExtensions.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.CrossCuttingConcerns/ExtensionMethods/DecimalExtensions.cs @@ -1,15 +1,14 @@ -namespace ClassifiedAds.CrossCuttingConcerns.ExtensionMethods +namespace ClassifiedAds.CrossCuttingConcerns.ExtensionMethods; + +public static class DecimalExtensions { - public static class DecimalExtensions + public static decimal Negate(this decimal d) { - public static decimal Negate(this decimal d) - { - return decimal.Negate(d); - } + return decimal.Negate(d); + } - public static decimal? Negate(this decimal? d) - { - return d.HasValue ? decimal.Negate(d.Value) : (decimal?)null; - } + public static decimal? Negate(this decimal? d) + { + return d.HasValue ? decimal.Negate(d.Value) : (decimal?)null; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.CrossCuttingConcerns/ExtensionMethods/GuidExtensions.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.CrossCuttingConcerns/ExtensionMethods/GuidExtensions.cs index ec89aa55a..8c5c91ee5 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.CrossCuttingConcerns/ExtensionMethods/GuidExtensions.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.CrossCuttingConcerns/ExtensionMethods/GuidExtensions.cs @@ -1,12 +1,11 @@ using System; -namespace ClassifiedAds.CrossCuttingConcerns.ExtensionMethods +namespace ClassifiedAds.CrossCuttingConcerns.ExtensionMethods; + +public static class GuidExtensions { - public static class GuidExtensions + public static bool IsNullOrEmpty(this Guid? guid) { - public static bool IsNullOrEmpty(this Guid? guid) - { - return guid == null || guid == Guid.Empty; - } + return guid == null || guid == Guid.Empty; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.CrossCuttingConcerns/ExtensionMethods/HttpClientExtensions.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.CrossCuttingConcerns/ExtensionMethods/HttpClientExtensions.cs index baf05ee67..2cfb8b40e 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.CrossCuttingConcerns/ExtensionMethods/HttpClientExtensions.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.CrossCuttingConcerns/ExtensionMethods/HttpClientExtensions.cs @@ -3,19 +3,18 @@ using System.Net.Http.Headers; using System.Text; -namespace ClassifiedAds.CrossCuttingConcerns.ExtensionMethods +namespace ClassifiedAds.CrossCuttingConcerns.ExtensionMethods; + +public static class HttpClientExtensions { - public static class HttpClientExtensions + public static void UseBasicAuthentication(this HttpClient client, string userName, string password) { - public static void UseBasicAuthentication(this HttpClient client, string userName, string password) - { - var byteArray = Encoding.UTF8.GetBytes(userName + ":" + password); - client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(byteArray)); - } + var byteArray = Encoding.UTF8.GetBytes(userName + ":" + password); + client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(byteArray)); + } - public static void UseBearerToken(this HttpClient client, string token) - { - client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token); - } + public static void UseBearerToken(this HttpClient client, string token) + { + client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token); } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.CrossCuttingConcerns/ExtensionMethods/HttpContentExtensions.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.CrossCuttingConcerns/ExtensionMethods/HttpContentExtensions.cs index 3b6b4c707..d734f6e26 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.CrossCuttingConcerns/ExtensionMethods/HttpContentExtensions.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.CrossCuttingConcerns/ExtensionMethods/HttpContentExtensions.cs @@ -3,35 +3,34 @@ using System.Text.Json; using System.Threading.Tasks; -namespace ClassifiedAds.CrossCuttingConcerns.ExtensionMethods +namespace ClassifiedAds.CrossCuttingConcerns.ExtensionMethods; + +public static class HttpContentExtensions { - public static class HttpContentExtensions + public static async Task ReadAs(this HttpContent httpContent) { - public static async Task ReadAs(this HttpContent httpContent) - { - var json = await httpContent.ReadAsStringAsync(); - - if (string.IsNullOrWhiteSpace(json)) - { - return default; - } + var json = await httpContent.ReadAsStringAsync(); - return JsonSerializer.Deserialize(json, new JsonSerializerOptions - { - PropertyNameCaseInsensitive = true, - }); - } - - public static StringContent AsStringContent(this object obj, string contentType) + if (string.IsNullOrWhiteSpace(json)) { - var content = new StringContent(JsonSerializer.Serialize(obj)); - content.Headers.ContentType = new MediaTypeHeaderValue(contentType); - return content; + return default; } - public static StringContent AsJsonContent(this object obj) + return JsonSerializer.Deserialize(json, new JsonSerializerOptions { - return obj.AsStringContent("application/json"); - } + PropertyNameCaseInsensitive = true, + }); + } + + public static StringContent AsStringContent(this object obj, string contentType) + { + var content = new StringContent(JsonSerializer.Serialize(obj)); + content.Headers.ContentType = new MediaTypeHeaderValue(contentType); + return content; + } + + public static StringContent AsJsonContent(this object obj) + { + return obj.AsStringContent("application/json"); } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.CrossCuttingConcerns/ExtensionMethods/IQueryableExtensions.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.CrossCuttingConcerns/ExtensionMethods/IQueryableExtensions.cs index 1f88a140e..1ef028312 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.CrossCuttingConcerns/ExtensionMethods/IQueryableExtensions.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.CrossCuttingConcerns/ExtensionMethods/IQueryableExtensions.cs @@ -3,13 +3,12 @@ using System.Linq; using System.Text; -namespace ClassifiedAds.CrossCuttingConcerns.ExtensionMethods +namespace ClassifiedAds.CrossCuttingConcerns.ExtensionMethods; + +public static class IQueryableExtensions { - public static class IQueryableExtensions + public static IQueryable Paged(this IQueryable source, int page, int pageSize) { - public static IQueryable Paged(this IQueryable source, int page, int pageSize) - { - return source.Skip((page - 1) * pageSize).Take(pageSize); - } + return source.Skip((page - 1) * pageSize).Take(pageSize); } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.CrossCuttingConcerns/ExtensionMethods/ListExtensions.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.CrossCuttingConcerns/ExtensionMethods/ListExtensions.cs index 8b63b5319..3d51a0f9b 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.CrossCuttingConcerns/ExtensionMethods/ListExtensions.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.CrossCuttingConcerns/ExtensionMethods/ListExtensions.cs @@ -2,22 +2,21 @@ using System.Collections.Generic; using System.Text; -namespace ClassifiedAds.CrossCuttingConcerns.ExtensionMethods +namespace ClassifiedAds.CrossCuttingConcerns.ExtensionMethods; + +public static class ListExtensions { - public static class ListExtensions + public static List Combines(this List collection1, List collection2) { - public static List Combines(this List collection1, List collection2) - { - collection1.AddRange(collection2); - return collection1; - } + collection1.AddRange(collection2); + return collection1; + } - public static ICollection Combines(this ICollection collection1, ICollection collection2) - { - var list = new List(); - list.AddRange(collection1); - list.AddRange(collection2); - return list; - } + public static ICollection Combines(this ICollection collection1, ICollection collection2) + { + var list = new List(); + list.AddRange(collection1); + list.AddRange(collection2); + return list; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.CrossCuttingConcerns/ExtensionMethods/ObjectExtensions.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.CrossCuttingConcerns/ExtensionMethods/ObjectExtensions.cs index ce61cd046..f91fc5d84 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.CrossCuttingConcerns/ExtensionMethods/ObjectExtensions.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.CrossCuttingConcerns/ExtensionMethods/ObjectExtensions.cs @@ -1,19 +1,18 @@ using System.Text.Json; using System.Text.Json.Serialization; -namespace ClassifiedAds.CrossCuttingConcerns.ExtensionMethods +namespace ClassifiedAds.CrossCuttingConcerns.ExtensionMethods; + +public static class ObjectExtensions { - public static class ObjectExtensions + public static string AsJsonString(this object obj) { - public static string AsJsonString(this object obj) + var content = JsonSerializer.Serialize(obj, new JsonSerializerOptions { - var content = JsonSerializer.Serialize(obj, new JsonSerializerOptions - { - WriteIndented = true, - DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull, - ReferenceHandler = ReferenceHandler.IgnoreCycles, - }); - return content; - } + WriteIndented = true, + DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull, + ReferenceHandler = ReferenceHandler.IgnoreCycles, + }); + return content; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.CrossCuttingConcerns/ExtensionMethods/StringExtensions.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.CrossCuttingConcerns/ExtensionMethods/StringExtensions.cs index 51c46edd8..8c7a0fc82 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.CrossCuttingConcerns/ExtensionMethods/StringExtensions.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.CrossCuttingConcerns/ExtensionMethods/StringExtensions.cs @@ -4,70 +4,69 @@ using System.Linq; using System.Text; -namespace ClassifiedAds.CrossCuttingConcerns.ExtensionMethods +namespace ClassifiedAds.CrossCuttingConcerns.ExtensionMethods; + +public static class StringExtensions { - public static class StringExtensions + public static string Left(this string value, int length) { - public static string Left(this string value, int length) - { - length = Math.Abs(length); - return string.IsNullOrEmpty(value) ? value : value.Substring(0, Math.Min(value.Length, length)); - } + length = Math.Abs(length); + return string.IsNullOrEmpty(value) ? value : value.Substring(0, Math.Min(value.Length, length)); + } - public static string Right(this string value, int length) - { - length = Math.Abs(length); - return string.IsNullOrEmpty(value) ? value : value.Substring(value.Length - Math.Min(value.Length, length)); - } + public static string Right(this string value, int length) + { + length = Math.Abs(length); + return string.IsNullOrEmpty(value) ? value : value.Substring(value.Length - Math.Min(value.Length, length)); + } - public static bool In(this string value, List list) - { - return list.Contains(value, StringComparer.OrdinalIgnoreCase); - } + public static bool In(this string value, List list) + { + return list.Contains(value, StringComparer.OrdinalIgnoreCase); + } - public static bool NotIn(this string value, List list) - { - return !In(value, list); - } + public static bool NotIn(this string value, List list) + { + return !In(value, list); + } - public static bool EqualsIgnoreCase(this string source, string toCheck) - { - return string.Equals(source, toCheck, StringComparison.OrdinalIgnoreCase); - } + public static bool EqualsIgnoreCase(this string source, string toCheck) + { + return string.Equals(source, toCheck, StringComparison.OrdinalIgnoreCase); + } - public static string ToBase64(this string src) - { - byte[] b = Encoding.UTF8.GetBytes(src); - return Convert.ToBase64String(b); - } + public static string ToBase64(this string src) + { + byte[] b = Encoding.UTF8.GetBytes(src); + return Convert.ToBase64String(b); + } - public static string ToBase64(this string src, Encoding encoding) - { - byte[] b = encoding.GetBytes(src); - return Convert.ToBase64String(b); - } + public static string ToBase64(this string src, Encoding encoding) + { + byte[] b = encoding.GetBytes(src); + return Convert.ToBase64String(b); + } - public static string FromBase64String(this string src) - { - byte[] b = Convert.FromBase64String(src); - return Encoding.UTF8.GetString(b); - } + public static string FromBase64String(this string src) + { + byte[] b = Convert.FromBase64String(src); + return Encoding.UTF8.GetString(b); + } - public static string FromBase64String(this string src, Encoding encoding) - { - byte[] b = Convert.FromBase64String(src); - return encoding.GetString(b); - } + public static string FromBase64String(this string src, Encoding encoding) + { + byte[] b = Convert.FromBase64String(src); + return encoding.GetString(b); + } - public static string Remove(this string source, params string[] removedValues) - { - removedValues.ToList().ForEach(x => source = source.Replace(x, string.Empty)); - return source; - } + public static string Remove(this string source, params string[] removedValues) + { + removedValues.ToList().ForEach(x => source = source.Replace(x, string.Empty)); + return source; + } - public static string ToUpperInvariantCulture(this string source) - { - return source.ToUpper(CultureInfo.InvariantCulture); - } + public static string ToUpperInvariantCulture(this string source) + { + return source.ToUpper(CultureInfo.InvariantCulture); } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.CrossCuttingConcerns/ExtensionMethods/TypeExtensions.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.CrossCuttingConcerns/ExtensionMethods/TypeExtensions.cs index 0e6f3f98a..dc52ae24a 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.CrossCuttingConcerns/ExtensionMethods/TypeExtensions.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.CrossCuttingConcerns/ExtensionMethods/TypeExtensions.cs @@ -2,58 +2,57 @@ using System.Linq; using System.Text; -namespace ClassifiedAds.CrossCuttingConcerns.ExtensionMethods +namespace ClassifiedAds.CrossCuttingConcerns.ExtensionMethods; + +public static class TypeExtensions { - public static class TypeExtensions + public static bool HasInterface(this Type type, Type interfaceType) { - public static bool HasInterface(this Type type, Type interfaceType) - { - return type.GetInterfacesOf(interfaceType).Length > 0; - } + return type.GetInterfacesOf(interfaceType).Length > 0; + } - public static Type[] GetInterfacesOf(this Type type, Type interfaceType) - { - return type.FindInterfaces((i, _) => i.GetGenericTypeDefinitionSafe() == interfaceType, null); - } + public static Type[] GetInterfacesOf(this Type type, Type interfaceType) + { + return type.FindInterfaces((i, _) => i.GetGenericTypeDefinitionSafe() == interfaceType, null); + } - public static Type GetGenericTypeDefinitionSafe(this Type type) - { - return type.IsGenericType - ? type.GetGenericTypeDefinition() - : type; - } + public static Type GetGenericTypeDefinitionSafe(this Type type) + { + return type.IsGenericType + ? type.GetGenericTypeDefinition() + : type; + } - public static Type MakeGenericTypeSafe(this Type type, params Type[] typeArguments) - { - return type.IsGenericType && !type.GenericTypeArguments.Any() - ? type.MakeGenericType(typeArguments) - : type; - } + public static Type MakeGenericTypeSafe(this Type type, params Type[] typeArguments) + { + return type.IsGenericType && !type.GenericTypeArguments.Any() + ? type.MakeGenericType(typeArguments) + : type; + } + + public static string GenerateMappingCode(this Type type) + { + var names = type.GetProperties().Select(x => x.Name); - public static string GenerateMappingCode(this Type type) + var text1 = new StringBuilder(); + var text2 = new StringBuilder(); + var text3 = new StringBuilder(); + var text4 = new StringBuilder(); + + foreach (var name in names) { - var names = type.GetProperties().Select(x => x.Name); - - var text1 = new StringBuilder(); - var text2 = new StringBuilder(); - var text3 = new StringBuilder(); - var text4 = new StringBuilder(); - - foreach (var name in names) - { - text1.Append($"a.{name} = {name};{Environment.NewLine}"); - text2.Append($"{name} = b.{name};{Environment.NewLine}"); - text3.Append($"{name} = b.{name},{Environment.NewLine}"); - text4.Append($"a.{name} = b.{name};{Environment.NewLine}"); - } - - return text1.ToString() - + "--------------------------------------" + Environment.NewLine - + text2.ToString() - + "--------------------------------------" + Environment.NewLine - + text3.ToString() - + "--------------------------------------" + Environment.NewLine - + text4.ToString(); + text1.Append($"a.{name} = {name};{Environment.NewLine}"); + text2.Append($"{name} = b.{name};{Environment.NewLine}"); + text3.Append($"{name} = b.{name},{Environment.NewLine}"); + text4.Append($"a.{name} = b.{name};{Environment.NewLine}"); } + + return text1.ToString() + + "--------------------------------------" + Environment.NewLine + + text2.ToString() + + "--------------------------------------" + Environment.NewLine + + text3.ToString() + + "--------------------------------------" + Environment.NewLine + + text4.ToString(); } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.CrossCuttingConcerns/Locks/CouldNotAcquireLockException.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.CrossCuttingConcerns/Locks/CouldNotAcquireLockException.cs index 7f60533bb..f144c015c 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.CrossCuttingConcerns/Locks/CouldNotAcquireLockException.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.CrossCuttingConcerns/Locks/CouldNotAcquireLockException.cs @@ -1,21 +1,20 @@ using System; -namespace ClassifiedAds.CrossCuttingConcerns.Locks +namespace ClassifiedAds.CrossCuttingConcerns.Locks; + +public class CouldNotAcquireLockException : Exception { - public class CouldNotAcquireLockException : Exception + public CouldNotAcquireLockException() { - public CouldNotAcquireLockException() - { - } + } - public CouldNotAcquireLockException(string message) - : base(message) - { - } + public CouldNotAcquireLockException(string message) + : base(message) + { + } - public CouldNotAcquireLockException(string message, Exception innerException) - : base(message, innerException) - { - } + public CouldNotAcquireLockException(string message, Exception innerException) + : base(message, innerException) + { } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.CrossCuttingConcerns/Locks/IDistributedLock.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.CrossCuttingConcerns/Locks/IDistributedLock.cs index f54333dca..e8b0b797f 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.CrossCuttingConcerns/Locks/IDistributedLock.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.CrossCuttingConcerns/Locks/IDistributedLock.cs @@ -1,11 +1,10 @@ using System; -namespace ClassifiedAds.CrossCuttingConcerns.Locks +namespace ClassifiedAds.CrossCuttingConcerns.Locks; + +public interface IDistributedLock : IDisposable { - public interface IDistributedLock : IDisposable - { - IDistributedLockScope Acquire(string lockName); + IDistributedLockScope Acquire(string lockName); - IDistributedLockScope TryAcquire(string lockName); - } + IDistributedLockScope TryAcquire(string lockName); } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.CrossCuttingConcerns/Locks/IDistributedLockScope.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.CrossCuttingConcerns/Locks/IDistributedLockScope.cs index 11f258a00..1cf2dc610 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.CrossCuttingConcerns/Locks/IDistributedLockScope.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.CrossCuttingConcerns/Locks/IDistributedLockScope.cs @@ -1,9 +1,8 @@ using System; -namespace ClassifiedAds.CrossCuttingConcerns.Locks +namespace ClassifiedAds.CrossCuttingConcerns.Locks; + +public interface IDistributedLockScope : IDisposable { - public interface IDistributedLockScope : IDisposable - { - bool StillHoldingLock(); - } + bool StillHoldingLock(); } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.CrossCuttingConcerns/Locks/ILockManager.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.CrossCuttingConcerns/Locks/ILockManager.cs index 1fd92e1ed..519e34f16 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.CrossCuttingConcerns/Locks/ILockManager.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.CrossCuttingConcerns/Locks/ILockManager.cs @@ -1,19 +1,18 @@ using System; -namespace ClassifiedAds.CrossCuttingConcerns.Locks +namespace ClassifiedAds.CrossCuttingConcerns.Locks; + +public interface ILockManager { - public interface ILockManager - { - bool AcquireLock(string entityName, string entityId, string ownerId, TimeSpan expirationIn); + bool AcquireLock(string entityName, string entityId, string ownerId, TimeSpan expirationIn); - bool ExtendLock(string entityName, string entityId, string ownerId, TimeSpan expirationIn); + bool ExtendLock(string entityName, string entityId, string ownerId, TimeSpan expirationIn); - bool ReleaseLock(string entityName, string entityId, string ownerId); + bool ReleaseLock(string entityName, string entityId, string ownerId); - bool ReleaseLocks(string ownerId); + bool ReleaseLocks(string ownerId); - bool ReleaseExpiredLocks(); + bool ReleaseExpiredLocks(); - void EnsureAcquiringLock(string entityName, string entityId, string ownerId, TimeSpan expirationIn); - } + void EnsureAcquiringLock(string entityName, string entityId, string ownerId, TimeSpan expirationIn); } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.CrossCuttingConcerns/Tenants/IConnectionStringResolver.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.CrossCuttingConcerns/Tenants/IConnectionStringResolver.cs index 0694486c3..559fdee6b 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.CrossCuttingConcerns/Tenants/IConnectionStringResolver.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.CrossCuttingConcerns/Tenants/IConnectionStringResolver.cs @@ -1,9 +1,8 @@ -namespace ClassifiedAds.CrossCuttingConcerns.Tenants +namespace ClassifiedAds.CrossCuttingConcerns.Tenants; + +public interface IConnectionStringResolver { - public interface IConnectionStringResolver - { - string ConnectionString { get; } + string ConnectionString { get; } - string MigrationsAssembly { get; } - } + string MigrationsAssembly { get; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.CrossCuttingConcerns/Tenants/ITenantResolver.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.CrossCuttingConcerns/Tenants/ITenantResolver.cs index 45561b0fc..0bc4e5389 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.CrossCuttingConcerns/Tenants/ITenantResolver.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.CrossCuttingConcerns/Tenants/ITenantResolver.cs @@ -1,14 +1,13 @@ -namespace ClassifiedAds.CrossCuttingConcerns.Tenants +namespace ClassifiedAds.CrossCuttingConcerns.Tenants; + +public interface ITenantResolver { - public interface ITenantResolver - { - Tenant Tenant { get; } - } + Tenant Tenant { get; } +} - public class Tenant - { - public string Id { get; } - public string Name { get; } - public string ConnectionString { get; } - } +public class Tenant +{ + public string Id { get; } + public string Name { get; } + public string ConnectionString { get; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/DomainServicesCollectionExtensions.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/DomainServicesCollectionExtensions.cs index 965e0d758..04f3bb5a1 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/DomainServicesCollectionExtensions.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/DomainServicesCollectionExtensions.cs @@ -1,13 +1,12 @@ using ClassifiedAds.Domain.Services; -namespace Microsoft.Extensions.DependencyInjection +namespace Microsoft.Extensions.DependencyInjection; + +public static class DomainServicesCollectionExtensions { - public static class DomainServicesCollectionExtensions + public static IServiceCollection AddDomainServices(this IServiceCollection services) { - public static IServiceCollection AddDomainServices(this IServiceCollection services) - { - services.AddScoped(); - return services; - } + services.AddScoped(); + return services; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Entities/AuditLogEntry.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Entities/AuditLogEntry.cs index 6810010cb..d7eb2a453 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Entities/AuditLogEntry.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Entities/AuditLogEntry.cs @@ -1,15 +1,14 @@ using System; -namespace ClassifiedAds.Domain.Entities +namespace ClassifiedAds.Domain.Entities; + +public class AuditLogEntry : Entity, IAggregateRoot { - public class AuditLogEntry : Entity, IAggregateRoot - { - public Guid UserId { get; set; } + public Guid UserId { get; set; } - public string Action { get; set; } + public string Action { get; set; } - public string ObjectId { get; set; } + public string ObjectId { get; set; } - public string Log { get; set; } - } + public string Log { get; set; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Entities/ConfigurationEntry.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Entities/ConfigurationEntry.cs index 2e72408af..7f290d90f 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Entities/ConfigurationEntry.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Entities/ConfigurationEntry.cs @@ -1,15 +1,14 @@ using System; -namespace ClassifiedAds.Domain.Entities +namespace ClassifiedAds.Domain.Entities; + +public class ConfigurationEntry : Entity, IAggregateRoot { - public class ConfigurationEntry : Entity, IAggregateRoot - { - public string Key { get; set; } + public string Key { get; set; } - public string Value { get; set; } + public string Value { get; set; } - public string Description { get; set; } + public string Description { get; set; } - public bool IsSensitive { get; set; } - } + public bool IsSensitive { get; set; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Entities/CustomMigrationHistory.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Entities/CustomMigrationHistory.cs index ca6c124cb..75bb65184 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Entities/CustomMigrationHistory.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Entities/CustomMigrationHistory.cs @@ -1,9 +1,8 @@ using System; -namespace ClassifiedAds.Domain.Entities +namespace ClassifiedAds.Domain.Entities; + +public class CustomMigrationHistory : Entity { - public class CustomMigrationHistory : Entity - { - public string MigrationName { get; set; } - } + public string MigrationName { get; set; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Entities/Entity.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Entities/Entity.cs index 3fa5c1bc6..44a080609 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Entities/Entity.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Entities/Entity.cs @@ -1,17 +1,16 @@ using System; using System.ComponentModel.DataAnnotations; -namespace ClassifiedAds.Domain.Entities +namespace ClassifiedAds.Domain.Entities; + +public abstract class Entity : IHasKey, ITrackable { - public abstract class Entity : IHasKey, ITrackable - { - public TKey Id { get; set; } + public TKey Id { get; set; } - [Timestamp] - public byte[] RowVersion { get; set; } + [Timestamp] + public byte[] RowVersion { get; set; } - public DateTimeOffset CreatedDateTime { get; set; } + public DateTimeOffset CreatedDateTime { get; set; } - public DateTimeOffset? UpdatedDateTime { get; set; } - } + public DateTimeOffset? UpdatedDateTime { get; set; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Entities/IAggregateRoot.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Entities/IAggregateRoot.cs index ca07e790d..d03d320b2 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Entities/IAggregateRoot.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Entities/IAggregateRoot.cs @@ -1,6 +1,5 @@ -namespace ClassifiedAds.Domain.Entities +namespace ClassifiedAds.Domain.Entities; + +public interface IAggregateRoot { - public interface IAggregateRoot - { - } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Entities/IHasKey.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Entities/IHasKey.cs index dca9d6566..fc48bd326 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Entities/IHasKey.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Entities/IHasKey.cs @@ -1,7 +1,6 @@ -namespace ClassifiedAds.Domain.Entities +namespace ClassifiedAds.Domain.Entities; + +public interface IHasKey { - public interface IHasKey - { - T Id { get; set; } - } + T Id { get; set; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Entities/ITrackable.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Entities/ITrackable.cs index e44ac0f44..d8c2e33fc 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Entities/ITrackable.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Entities/ITrackable.cs @@ -1,13 +1,12 @@ using System; -namespace ClassifiedAds.Domain.Entities +namespace ClassifiedAds.Domain.Entities; + +public interface ITrackable { - public interface ITrackable - { - byte[] RowVersion { get; set; } + byte[] RowVersion { get; set; } - DateTimeOffset CreatedDateTime { get; set; } + DateTimeOffset CreatedDateTime { get; set; } - DateTimeOffset? UpdatedDateTime { get; set; } - } + DateTimeOffset? UpdatedDateTime { get; set; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Entities/LocalizationEntry.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Entities/LocalizationEntry.cs index b74a69eb5..658176253 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Entities/LocalizationEntry.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Entities/LocalizationEntry.cs @@ -1,15 +1,14 @@ using System; -namespace ClassifiedAds.Domain.Entities +namespace ClassifiedAds.Domain.Entities; + +public class LocalizationEntry : Entity, IAggregateRoot { - public class LocalizationEntry : Entity, IAggregateRoot - { - public string Name { get; set; } + public string Name { get; set; } - public string Value { get; set; } + public string Value { get; set; } - public string Culture { get; set; } + public string Culture { get; set; } - public string Description { get; set; } - } + public string Description { get; set; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Entities/Lock.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Entities/Lock.cs index 3b5ccf66e..a4b4ce414 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Entities/Lock.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Entities/Lock.cs @@ -1,17 +1,16 @@ using System; -namespace ClassifiedAds.Domain.Entities +namespace ClassifiedAds.Domain.Entities; + +public class Lock { - public class Lock - { - public string EntityId { get; set; } + public string EntityId { get; set; } - public string EntityName { get; set; } + public string EntityName { get; set; } - public string OwnerId { get; set; } + public string OwnerId { get; set; } - public DateTimeOffset? AcquiredDateTime { get; set; } + public DateTimeOffset? AcquiredDateTime { get; set; } - public DateTimeOffset? ExpiredDateTime { get; set; } - } + public DateTimeOffset? ExpiredDateTime { get; set; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Entities/OutboxEvent.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Entities/OutboxEvent.cs index 9e84a70c3..41e53b44a 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Entities/OutboxEvent.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Entities/OutboxEvent.cs @@ -1,17 +1,16 @@ using System; -namespace ClassifiedAds.Domain.Entities +namespace ClassifiedAds.Domain.Entities; + +public class OutboxEvent : Entity, IAggregateRoot { - public class OutboxEvent : Entity, IAggregateRoot - { - public string EventType { get; set; } + public string EventType { get; set; } - public Guid TriggeredById { get; set; } + public Guid TriggeredById { get; set; } - public string ObjectId { get; set; } + public string ObjectId { get; set; } - public string Message { get; set; } + public string Message { get; set; } - public bool Published { get; set; } - } + public bool Published { get; set; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Entities/PasswordHistory.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Entities/PasswordHistory.cs index b22ea7112..c55bd6d43 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Entities/PasswordHistory.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Entities/PasswordHistory.cs @@ -1,13 +1,12 @@ using System; -namespace ClassifiedAds.Domain.Entities +namespace ClassifiedAds.Domain.Entities; + +public class PasswordHistory : Entity { - public class PasswordHistory : Entity - { - public Guid UserId { get; set; } + public Guid UserId { get; set; } - public string PasswordHash { get; set; } + public string PasswordHash { get; set; } - public virtual User User { get; set; } - } + public virtual User User { get; set; } } \ No newline at end of file diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Entities/Role.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Entities/Role.cs index 8aea58cec..e5dded8bf 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Entities/Role.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Entities/Role.cs @@ -1,18 +1,17 @@ using System; using System.Collections.Generic; -namespace ClassifiedAds.Domain.Entities +namespace ClassifiedAds.Domain.Entities; + +public class Role : Entity, IAggregateRoot { - public class Role : Entity, IAggregateRoot - { - public virtual string Name { get; set; } + public virtual string Name { get; set; } - public virtual string NormalizedName { get; set; } + public virtual string NormalizedName { get; set; } - public virtual string ConcurrencyStamp { get; set; } + public virtual string ConcurrencyStamp { get; set; } - public IList Claims { get; set; } + public IList Claims { get; set; } - public IList UserRoles { get; set; } - } + public IList UserRoles { get; set; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Entities/RoleClaim.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Entities/RoleClaim.cs index aff2cb420..a1d87d2b4 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Entities/RoleClaim.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Entities/RoleClaim.cs @@ -1,12 +1,11 @@ using System; -namespace ClassifiedAds.Domain.Entities +namespace ClassifiedAds.Domain.Entities; + +public class RoleClaim : Entity { - public class RoleClaim : Entity - { - public string Type { get; set; } - public string Value { get; set; } + public string Type { get; set; } + public string Value { get; set; } - public Role Role { get; set; } - } + public Role Role { get; set; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Entities/User.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Entities/User.cs index 11d8ea3d9..d72b3aec4 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Entities/User.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Entities/User.cs @@ -1,44 +1,43 @@ using System; using System.Collections.Generic; -namespace ClassifiedAds.Domain.Entities +namespace ClassifiedAds.Domain.Entities; + +public class User : Entity, IAggregateRoot { - public class User : Entity, IAggregateRoot - { - public string UserName { get; set; } + public string UserName { get; set; } - public string NormalizedUserName { get; set; } + public string NormalizedUserName { get; set; } - public string Email { get; set; } + public string Email { get; set; } - public string NormalizedEmail { get; set; } + public string NormalizedEmail { get; set; } - public bool EmailConfirmed { get; set; } + public bool EmailConfirmed { get; set; } - public string PasswordHash { get; set; } + public string PasswordHash { get; set; } - public string PhoneNumber { get; set; } + public string PhoneNumber { get; set; } - public bool PhoneNumberConfirmed { get; set; } + public bool PhoneNumberConfirmed { get; set; } - public bool TwoFactorEnabled { get; set; } + public bool TwoFactorEnabled { get; set; } - public string ConcurrencyStamp { get; set; } + public string ConcurrencyStamp { get; set; } - public string SecurityStamp { get; set; } + public string SecurityStamp { get; set; } - public bool LockoutEnabled { get; set; } + public bool LockoutEnabled { get; set; } - public DateTimeOffset? LockoutEnd { get; set; } + public DateTimeOffset? LockoutEnd { get; set; } - public int AccessFailedCount { get; set; } + public int AccessFailedCount { get; set; } - public IList Tokens { get; set; } + public IList Tokens { get; set; } - public IList Claims { get; set; } + public IList Claims { get; set; } - public IList UserRoles { get; set; } + public IList UserRoles { get; set; } - public IList PasswordHistories { get; set; } - } + public IList PasswordHistories { get; set; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Entities/UserClaim.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Entities/UserClaim.cs index 86f595b87..1934ba8bf 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Entities/UserClaim.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Entities/UserClaim.cs @@ -1,12 +1,11 @@ using System; -namespace ClassifiedAds.Domain.Entities +namespace ClassifiedAds.Domain.Entities; + +public class UserClaim : Entity { - public class UserClaim : Entity - { - public string Type { get; set; } - public string Value { get; set; } + public string Type { get; set; } + public string Value { get; set; } - public User User { get; set; } - } + public User User { get; set; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Entities/UserRole.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Entities/UserRole.cs index fb810607b..7d04c33c1 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Entities/UserRole.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Entities/UserRole.cs @@ -1,15 +1,14 @@ using System; -namespace ClassifiedAds.Domain.Entities +namespace ClassifiedAds.Domain.Entities; + +public class UserRole : Entity { - public class UserRole : Entity - { - public Guid UserId { get; set; } + public Guid UserId { get; set; } - public Guid RoleId { get; set; } + public Guid RoleId { get; set; } - public User User { get; set; } + public User User { get; set; } - public Role Role { get; set; } - } + public Role Role { get; set; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Entities/UserToken.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Entities/UserToken.cs index 9f2337439..699421dc6 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Entities/UserToken.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Entities/UserToken.cs @@ -1,15 +1,14 @@ using System; -namespace ClassifiedAds.Domain.Entities +namespace ClassifiedAds.Domain.Entities; + +public class UserToken : Entity { - public class UserToken : Entity - { - public Guid UserId { get; set; } + public Guid UserId { get; set; } - public string LoginProvider { get; set; } + public string LoginProvider { get; set; } - public string TokenName { get; set; } + public string TokenName { get; set; } - public string TokenValue { get; set; } - } + public string TokenValue { get; set; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Events/EntityCreatedEvent.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Events/EntityCreatedEvent.cs index dac4362d4..dc38b1c7a 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Events/EntityCreatedEvent.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Events/EntityCreatedEvent.cs @@ -1,19 +1,18 @@ using ClassifiedAds.Domain.Entities; using System; -namespace ClassifiedAds.Domain.Events +namespace ClassifiedAds.Domain.Events; + +public class EntityCreatedEvent : IDomainEvent + where T : Entity { - public class EntityCreatedEvent : IDomainEvent - where T : Entity + public EntityCreatedEvent(T entity, DateTime eventDateTime) { - public EntityCreatedEvent(T entity, DateTime eventDateTime) - { - Entity = entity; - EventDateTime = eventDateTime; - } + Entity = entity; + EventDateTime = eventDateTime; + } - public T Entity { get; } + public T Entity { get; } - public DateTime EventDateTime { get; } - } + public DateTime EventDateTime { get; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Events/EntityDeletedEvent.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Events/EntityDeletedEvent.cs index f18210580..ba183f6da 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Events/EntityDeletedEvent.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Events/EntityDeletedEvent.cs @@ -1,19 +1,18 @@ using ClassifiedAds.Domain.Entities; using System; -namespace ClassifiedAds.Domain.Events +namespace ClassifiedAds.Domain.Events; + +public class EntityDeletedEvent : IDomainEvent + where T : Entity { - public class EntityDeletedEvent : IDomainEvent - where T : Entity + public EntityDeletedEvent(T entity, DateTime eventDateTime) { - public EntityDeletedEvent(T entity, DateTime eventDateTime) - { - Entity = entity; - EventDateTime = eventDateTime; - } + Entity = entity; + EventDateTime = eventDateTime; + } - public T Entity { get; } + public T Entity { get; } - public DateTime EventDateTime { get; } - } + public DateTime EventDateTime { get; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Events/EntityUpdatedEvent.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Events/EntityUpdatedEvent.cs index c99d8482e..74b7489b2 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Events/EntityUpdatedEvent.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Events/EntityUpdatedEvent.cs @@ -1,19 +1,18 @@ using ClassifiedAds.Domain.Entities; using System; -namespace ClassifiedAds.Domain.Events +namespace ClassifiedAds.Domain.Events; + +public class EntityUpdatedEvent : IDomainEvent + where T : Entity { - public class EntityUpdatedEvent : IDomainEvent - where T : Entity + public EntityUpdatedEvent(T entity, DateTime eventDateTime) { - public EntityUpdatedEvent(T entity, DateTime eventDateTime) - { - Entity = entity; - EventDateTime = eventDateTime; - } + Entity = entity; + EventDateTime = eventDateTime; + } - public T Entity { get; } + public T Entity { get; } - public DateTime EventDateTime { get; } - } + public DateTime EventDateTime { get; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Events/IDomainEvent.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Events/IDomainEvent.cs index 70f75ff3a..37b9b1bff 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Events/IDomainEvent.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Events/IDomainEvent.cs @@ -2,9 +2,8 @@ using System.Collections.Generic; using System.Text; -namespace ClassifiedAds.Domain.Events +namespace ClassifiedAds.Domain.Events; + +public interface IDomainEvent { - public interface IDomainEvent - { - } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Events/IDomainEventHandler.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Events/IDomainEventHandler.cs index 1f9936290..d21ed6186 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Events/IDomainEventHandler.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Events/IDomainEventHandler.cs @@ -1,11 +1,10 @@ using System.Threading; using System.Threading.Tasks; -namespace ClassifiedAds.Domain.Events +namespace ClassifiedAds.Domain.Events; + +public interface IDomainEventHandler + where T : IDomainEvent { - public interface IDomainEventHandler - where T : IDomainEvent - { - Task HandleAsync(T domainEvent, CancellationToken cancellationToken = default); - } + Task HandleAsync(T domainEvent, CancellationToken cancellationToken = default); } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Identity/ICurrentUser.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Identity/ICurrentUser.cs index 6a6f3bcfa..a4dec7c51 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Identity/ICurrentUser.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Identity/ICurrentUser.cs @@ -1,11 +1,10 @@ using System; -namespace ClassifiedAds.Domain.Identity +namespace ClassifiedAds.Domain.Identity; + +public interface ICurrentUser { - public interface ICurrentUser - { - bool IsAuthenticated { get; } + bool IsAuthenticated { get; } - Guid UserId { get; } - } + Guid UserId { get; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Identity/IPasswordHasher.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Identity/IPasswordHasher.cs index cc06dc03a..a9281a9fa 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Identity/IPasswordHasher.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Identity/IPasswordHasher.cs @@ -1,9 +1,8 @@ using ClassifiedAds.Domain.Entities; -namespace ClassifiedAds.Domain.Identity +namespace ClassifiedAds.Domain.Identity; + +public interface IPasswordHasher { - public interface IPasswordHasher - { - bool VerifyHashedPassword(User user, string hashedPassword, string providedPassword); - } + bool VerifyHashedPassword(User user, string hashedPassword, string providedPassword); } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Infrastructure/MessageBrokers/IMessageReceiver.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Infrastructure/MessageBrokers/IMessageReceiver.cs index 83e3a937b..04f4998ac 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Infrastructure/MessageBrokers/IMessageReceiver.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Infrastructure/MessageBrokers/IMessageReceiver.cs @@ -1,9 +1,8 @@ using System; -namespace ClassifiedAds.Domain.Infrastructure.MessageBrokers +namespace ClassifiedAds.Domain.Infrastructure.MessageBrokers; + +public interface IMessageReceiver { - public interface IMessageReceiver - { - void Receive(Action action); - } + void Receive(Action action); } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Infrastructure/MessageBrokers/IMessageSender.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Infrastructure/MessageBrokers/IMessageSender.cs index 899691d11..7a7d312da 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Infrastructure/MessageBrokers/IMessageSender.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Infrastructure/MessageBrokers/IMessageSender.cs @@ -1,10 +1,9 @@ using System.Threading; using System.Threading.Tasks; -namespace ClassifiedAds.Domain.Infrastructure.MessageBrokers +namespace ClassifiedAds.Domain.Infrastructure.MessageBrokers; + +public interface IMessageSender { - public interface IMessageSender - { - Task SendAsync(T message, MetaData metaData = null, CancellationToken cancellationToken = default); - } + Task SendAsync(T message, MetaData metaData = null, CancellationToken cancellationToken = default); } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Infrastructure/MessageBrokers/Message.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Infrastructure/MessageBrokers/Message.cs index 33f456c0c..9f5fa000e 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Infrastructure/MessageBrokers/Message.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Infrastructure/MessageBrokers/Message.cs @@ -1,22 +1,21 @@ using System.Text; using System.Text.Json; -namespace ClassifiedAds.Domain.Infrastructure.MessageBrokers +namespace ClassifiedAds.Domain.Infrastructure.MessageBrokers; + +public class Message { - public class Message - { - public MetaData MetaData { get; set; } + public MetaData MetaData { get; set; } - public T Data { get; set; } + public T Data { get; set; } - public string SerializeObject() - { - return JsonSerializer.Serialize(this); - } + public string SerializeObject() + { + return JsonSerializer.Serialize(this); + } - public byte[] GetBytes() - { - return Encoding.UTF8.GetBytes(SerializeObject()); - } + public byte[] GetBytes() + { + return Encoding.UTF8.GetBytes(SerializeObject()); } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Infrastructure/MessageBrokers/MetaData.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Infrastructure/MessageBrokers/MetaData.cs index c8b73d619..d2c0de30c 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Infrastructure/MessageBrokers/MetaData.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Infrastructure/MessageBrokers/MetaData.cs @@ -1,17 +1,16 @@ using System; -namespace ClassifiedAds.Domain.Infrastructure.MessageBrokers +namespace ClassifiedAds.Domain.Infrastructure.MessageBrokers; + +public class MetaData { - public class MetaData - { - public string MessageId { get; set; } + public string MessageId { get; set; } - public string MessageVersion { get; set; } + public string MessageVersion { get; set; } - public string CorrelationId { get; set; } + public string CorrelationId { get; set; } - public DateTimeOffset? CreationDateTime { get; set; } + public DateTimeOffset? CreationDateTime { get; set; } - public DateTimeOffset? EnqueuedDateTime { get; set; } - } + public DateTimeOffset? EnqueuedDateTime { get; set; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Infrastructure/Storages/IFileStorageManager.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Infrastructure/Storages/IFileStorageManager.cs index 4e68db615..dbd91ab85 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Infrastructure/Storages/IFileStorageManager.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Infrastructure/Storages/IFileStorageManager.cs @@ -3,27 +3,26 @@ using System.Threading; using System.Threading.Tasks; -namespace ClassifiedAds.Domain.Infrastructure.Storages +namespace ClassifiedAds.Domain.Infrastructure.Storages; + +public interface IFileStorageManager { - public interface IFileStorageManager - { - Task CreateAsync(IFileEntry fileEntry, Stream stream, CancellationToken cancellationToken = default); + Task CreateAsync(IFileEntry fileEntry, Stream stream, CancellationToken cancellationToken = default); - Task ReadAsync(IFileEntry fileEntry, CancellationToken cancellationToken = default); + Task ReadAsync(IFileEntry fileEntry, CancellationToken cancellationToken = default); - Task DeleteAsync(IFileEntry fileEntry, CancellationToken cancellationToken = default); + Task DeleteAsync(IFileEntry fileEntry, CancellationToken cancellationToken = default); - Task ArchiveAsync(IFileEntry fileEntry, CancellationToken cancellationToken = default); + Task ArchiveAsync(IFileEntry fileEntry, CancellationToken cancellationToken = default); - Task UnArchiveAsync(IFileEntry fileEntry, CancellationToken cancellationToken = default); - } + Task UnArchiveAsync(IFileEntry fileEntry, CancellationToken cancellationToken = default); +} - public interface IFileEntry - { - public Guid Id { get; set; } +public interface IFileEntry +{ + public Guid Id { get; set; } - public string FileName { get; set; } + public string FileName { get; set; } - public string FileLocation { get; set; } - } + public string FileLocation { get; set; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Notification/IEmailNotification.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Notification/IEmailNotification.cs index f729dec9d..724794988 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Notification/IEmailNotification.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Notification/IEmailNotification.cs @@ -1,25 +1,24 @@ using System.Threading; using System.Threading.Tasks; -namespace ClassifiedAds.Domain.Notification +namespace ClassifiedAds.Domain.Notification; + +public interface IEmailNotification { - public interface IEmailNotification - { - Task SendAsync(IEmailMessage emailMessage, CancellationToken cancellationToken = default); - } + Task SendAsync(IEmailMessage emailMessage, CancellationToken cancellationToken = default); +} - public interface IEmailMessage - { - public string From { get; set; } +public interface IEmailMessage +{ + public string From { get; set; } - public string Tos { get; set; } + public string Tos { get; set; } - public string CCs { get; set; } + public string CCs { get; set; } - public string BCCs { get; set; } + public string BCCs { get; set; } - public string Subject { get; set; } + public string Subject { get; set; } - public string Body { get; set; } - } + public string Body { get; set; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Notification/ISmsNotification.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Notification/ISmsNotification.cs index ac2a700ec..86695fd4c 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Notification/ISmsNotification.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Notification/ISmsNotification.cs @@ -1,17 +1,16 @@ using System.Threading; using System.Threading.Tasks; -namespace ClassifiedAds.Domain.Notification +namespace ClassifiedAds.Domain.Notification; + +public interface ISmsNotification { - public interface ISmsNotification - { - Task SendAsync(ISmsMessage smsMessage, CancellationToken cancellationToken = default); - } + Task SendAsync(ISmsMessage smsMessage, CancellationToken cancellationToken = default); +} - public interface ISmsMessage - { - public string Message { get; set; } +public interface ISmsMessage +{ + public string Message { get; set; } - public string PhoneNumber { get; set; } - } + public string PhoneNumber { get; set; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Notification/IWebNotification.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Notification/IWebNotification.cs index 157d614a4..2db5b76b3 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Notification/IWebNotification.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Notification/IWebNotification.cs @@ -1,10 +1,9 @@ using System.Threading; using System.Threading.Tasks; -namespace ClassifiedAds.Domain.Notification +namespace ClassifiedAds.Domain.Notification; + +public interface IWebNotification { - public interface IWebNotification - { - Task SendAsync(T message, CancellationToken cancellationToken = default); - } + Task SendAsync(T message, CancellationToken cancellationToken = default); } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Repositories/IAuditLogEntryRepository.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Repositories/IAuditLogEntryRepository.cs index 8098145fa..edbcec9eb 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Repositories/IAuditLogEntryRepository.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Repositories/IAuditLogEntryRepository.cs @@ -2,19 +2,18 @@ using System; using System.Linq; -namespace ClassifiedAds.Domain.Repositories +namespace ClassifiedAds.Domain.Repositories; + +public class AuditLogEntryQueryOptions { - public class AuditLogEntryQueryOptions - { - public Guid UserId { get; set; } + public Guid UserId { get; set; } - public string ObjectId { get; set; } + public string ObjectId { get; set; } - public bool AsNoTracking { get; set; } - } + public bool AsNoTracking { get; set; } +} - public interface IAuditLogEntryRepository : IRepository - { - IQueryable Get(AuditLogEntryQueryOptions queryOptions); - } +public interface IAuditLogEntryRepository : IRepository +{ + IQueryable Get(AuditLogEntryQueryOptions queryOptions); } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Repositories/IConcurrencyHandler.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Repositories/IConcurrencyHandler.cs index f3eac4bfc..41a1256c9 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Repositories/IConcurrencyHandler.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Repositories/IConcurrencyHandler.cs @@ -1,11 +1,10 @@ using System; -namespace ClassifiedAds.Domain.Repositories +namespace ClassifiedAds.Domain.Repositories; + +public interface IConcurrencyHandler { - public interface IConcurrencyHandler - { - void SetRowVersion(TEntity entity, byte[] version); + void SetRowVersion(TEntity entity, byte[] version); - bool IsDbUpdateConcurrencyException(Exception ex); - } + bool IsDbUpdateConcurrencyException(Exception ex); } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Repositories/IRepository.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Repositories/IRepository.cs index 0f4c4f85a..11f7cb4ff 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Repositories/IRepository.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Repositories/IRepository.cs @@ -6,37 +6,36 @@ using System.Threading; using System.Threading.Tasks; -namespace ClassifiedAds.Domain.Repositories +namespace ClassifiedAds.Domain.Repositories; + +public interface IRepository : IConcurrencyHandler + where TEntity : Entity, IAggregateRoot { - public interface IRepository : IConcurrencyHandler - where TEntity : Entity, IAggregateRoot - { - IUnitOfWork UnitOfWork { get; } + IUnitOfWork UnitOfWork { get; } - IQueryable GetQueryableSet(); + IQueryable GetQueryableSet(); - Task AddOrUpdateAsync(TEntity entity, CancellationToken cancellationToken = default); + Task AddOrUpdateAsync(TEntity entity, CancellationToken cancellationToken = default); - Task AddAsync(TEntity entity, CancellationToken cancellationToken = default); + Task AddAsync(TEntity entity, CancellationToken cancellationToken = default); - Task UpdateAsync(TEntity entity, CancellationToken cancellationToken = default); + Task UpdateAsync(TEntity entity, CancellationToken cancellationToken = default); - void Delete(TEntity entity); + void Delete(TEntity entity); - Task FirstOrDefaultAsync(IQueryable query); + Task FirstOrDefaultAsync(IQueryable query); - Task SingleOrDefaultAsync(IQueryable query); + Task SingleOrDefaultAsync(IQueryable query); - Task> ToListAsync(IQueryable query); + Task> ToListAsync(IQueryable query); - void BulkInsert(IEnumerable entities); + void BulkInsert(IEnumerable entities); - void BulkInsert(IEnumerable entities, Expression> columnNamesSelector); + void BulkInsert(IEnumerable entities, Expression> columnNamesSelector); - void BulkUpdate(IEnumerable entities, Expression> columnNamesSelector); + void BulkUpdate(IEnumerable entities, Expression> columnNamesSelector); - void BulkMerge(IEnumerable entities, Expression> idSelector, Expression> updateColumnNamesSelector, Expression> insertColumnNamesSelector); + void BulkMerge(IEnumerable entities, Expression> idSelector, Expression> updateColumnNamesSelector, Expression> insertColumnNamesSelector); - void BulkDelete(IEnumerable entities); - } + void BulkDelete(IEnumerable entities); } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Repositories/IRoleRepository.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Repositories/IRoleRepository.cs index 3150db1d6..2805ca2d8 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Repositories/IRoleRepository.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Repositories/IRoleRepository.cs @@ -2,18 +2,17 @@ using System; using System.Linq; -namespace ClassifiedAds.Domain.Repositories +namespace ClassifiedAds.Domain.Repositories; + +public class RoleQueryOptions { - public class RoleQueryOptions - { - public bool IncludeClaims { get; set; } - public bool IncludeUserRoles { get; set; } - public bool IncludeUsers { get; set; } - public bool AsNoTracking { get; set; } - } + public bool IncludeClaims { get; set; } + public bool IncludeUserRoles { get; set; } + public bool IncludeUsers { get; set; } + public bool AsNoTracking { get; set; } +} - public interface IRoleRepository : IRepository - { - IQueryable Get(RoleQueryOptions queryOptions); - } +public interface IRoleRepository : IRepository +{ + IQueryable Get(RoleQueryOptions queryOptions); } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Repositories/IUnitOfWork.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Repositories/IUnitOfWork.cs index 311f436cf..a40cf1283 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Repositories/IUnitOfWork.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Repositories/IUnitOfWork.cs @@ -3,16 +3,15 @@ using System.Threading; using System.Threading.Tasks; -namespace ClassifiedAds.Domain.Repositories +namespace ClassifiedAds.Domain.Repositories; + +public interface IUnitOfWork { - public interface IUnitOfWork - { - Task SaveChangesAsync(CancellationToken cancellationToken = default); + Task SaveChangesAsync(CancellationToken cancellationToken = default); - Task BeginTransactionAsync(IsolationLevel isolationLevel = IsolationLevel.ReadCommitted, CancellationToken cancellationToken = default); + Task BeginTransactionAsync(IsolationLevel isolationLevel = IsolationLevel.ReadCommitted, CancellationToken cancellationToken = default); - Task BeginTransactionAsync(IsolationLevel isolationLevel = IsolationLevel.ReadCommitted, string lockName = null, CancellationToken cancellationToken = default); + Task BeginTransactionAsync(IsolationLevel isolationLevel = IsolationLevel.ReadCommitted, string lockName = null, CancellationToken cancellationToken = default); - Task CommitTransactionAsync(CancellationToken cancellationToken = default); - } + Task CommitTransactionAsync(CancellationToken cancellationToken = default); } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Repositories/IUserRepository.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Repositories/IUserRepository.cs index dfcccd30f..175d01f1b 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Repositories/IUserRepository.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Repositories/IUserRepository.cs @@ -2,20 +2,19 @@ using System; using System.Linq; -namespace ClassifiedAds.Domain.Repositories +namespace ClassifiedAds.Domain.Repositories; + +public class UserQueryOptions { - public class UserQueryOptions - { - public bool IncludePasswordHistories { get; set; } - public bool IncludeClaims { get; set; } - public bool IncludeUserRoles { get; set; } - public bool IncludeRoles { get; set; } - public bool IncludeTokens { get; set; } - public bool AsNoTracking { get; set; } - } + public bool IncludePasswordHistories { get; set; } + public bool IncludeClaims { get; set; } + public bool IncludeUserRoles { get; set; } + public bool IncludeRoles { get; set; } + public bool IncludeTokens { get; set; } + public bool AsNoTracking { get; set; } +} - public interface IUserRepository : IRepository - { - IQueryable Get(UserQueryOptions queryOptions); - } +public interface IUserRepository : IRepository +{ + IQueryable Get(UserQueryOptions queryOptions); } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Services/ProductService.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Services/ProductService.cs index 37f85c710..86ea0fd3c 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Services/ProductService.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/Services/ProductService.cs @@ -1,6 +1,5 @@ -namespace ClassifiedAds.Domain.Services +namespace ClassifiedAds.Domain.Services; + +public class ProductService { - public class ProductService - { - } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/ValueObjects/Address.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/ValueObjects/Address.cs index 85e292d49..0fa9b2f9b 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/ValueObjects/Address.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/ValueObjects/Address.cs @@ -1,29 +1,28 @@ using System.Collections.Generic; -namespace ClassifiedAds.Domain.ValueObjects +namespace ClassifiedAds.Domain.ValueObjects; + +public class Address : ValueObject { - public class Address : ValueObject - { - public string Street { get; private set; } - public string City { get; private set; } - public string ZipCode { get; private set; } + public string Street { get; private set; } + public string City { get; private set; } + public string ZipCode { get; private set; } - private Address() - { - } + private Address() + { + } - public Address(string street, string city, string zipCode) - { - Street = street; - City = city; - ZipCode = zipCode; - } + public Address(string street, string city, string zipCode) + { + Street = street; + City = city; + ZipCode = zipCode; + } - protected override IEnumerable GetEqualityComponents() - { - yield return Street; - yield return City; - yield return ZipCode; - } + protected override IEnumerable GetEqualityComponents() + { + yield return Street; + yield return City; + yield return ZipCode; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/ValueObjects/Money.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/ValueObjects/Money.cs index c27e775fd..4e117bba4 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/ValueObjects/Money.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/ValueObjects/Money.cs @@ -1,27 +1,26 @@ using System.Collections.Generic; -namespace ClassifiedAds.Domain.ValueObjects +namespace ClassifiedAds.Domain.ValueObjects; + +public class Money : ValueObject { - public class Money : ValueObject - { - public decimal Amount { get; } + public decimal Amount { get; } - public string Currency { get; } + public string Currency { get; } - private Money() - { - } + private Money() + { + } - public Money(decimal amount, string currency) - { - Amount = amount; - Currency = currency; - } + public Money(decimal amount, string currency) + { + Amount = amount; + Currency = currency; + } - protected override IEnumerable GetEqualityComponents() - { - yield return Amount; - yield return Currency; - } + protected override IEnumerable GetEqualityComponents() + { + yield return Amount; + yield return Currency; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/ValueObjects/ValueObject.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/ValueObjects/ValueObject.cs index ab8ec5393..b40adb67f 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/ValueObjects/ValueObject.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Domain/ValueObjects/ValueObject.cs @@ -2,59 +2,58 @@ using System.Collections.Generic; using System.Linq; -namespace ClassifiedAds.Domain.ValueObjects +namespace ClassifiedAds.Domain.ValueObjects; + +public abstract class ValueObject { - public abstract class ValueObject - { - protected abstract IEnumerable GetEqualityComponents(); + protected abstract IEnumerable GetEqualityComponents(); - public override bool Equals(object obj) + public override bool Equals(object obj) + { + if (obj == null) { - if (obj == null) - { - return false; - } - - if (GetType() != obj.GetType()) - { - throw new ArgumentException($"Invalid comparison of Value Objects of different types: {GetType()} and {obj.GetType()}"); - } - - var valueObject = (ValueObject)obj; - - return GetEqualityComponents().SequenceEqual(valueObject.GetEqualityComponents()); + return false; } - public override int GetHashCode() + if (GetType() != obj.GetType()) { - return GetEqualityComponents() - .Aggregate(1, (current, obj) => - { - unchecked - { - return (current * 23) + (obj?.GetHashCode() ?? 0); - } - }); + throw new ArgumentException($"Invalid comparison of Value Objects of different types: {GetType()} and {obj.GetType()}"); } - public static bool operator ==(ValueObject a, ValueObject b) - { - if (ReferenceEquals(a, null) && ReferenceEquals(b, null)) - { - return true; - } + var valueObject = (ValueObject)obj; - if (ReferenceEquals(a, null) || ReferenceEquals(b, null)) + return GetEqualityComponents().SequenceEqual(valueObject.GetEqualityComponents()); + } + + public override int GetHashCode() + { + return GetEqualityComponents() + .Aggregate(1, (current, obj) => { - return false; - } + unchecked + { + return (current * 23) + (obj?.GetHashCode() ?? 0); + } + }); + } - return a.Equals(b); + public static bool operator ==(ValueObject a, ValueObject b) + { + if (ReferenceEquals(a, null) && ReferenceEquals(b, null)) + { + return true; } - public static bool operator !=(ValueObject a, ValueObject b) + if (ReferenceEquals(a, null) || ReferenceEquals(b, null)) { - return !(a == b); + return false; } + + return a.Equals(b); + } + + public static bool operator !=(ValueObject a, ValueObject b) + { + return !(a == b); } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/IdentityHostingStartup.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/IdentityHostingStartup.cs index d0c5e9a35..dba3902ce 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/IdentityHostingStartup.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/IdentityHostingStartup.cs @@ -1,12 +1,11 @@ using Microsoft.AspNetCore.Hosting; [assembly: HostingStartup(typeof(ClassifiedAds.IdentityServer.Areas.Identity.IdentityHostingStartup))] -namespace ClassifiedAds.IdentityServer.Areas.Identity +namespace ClassifiedAds.IdentityServer.Areas.Identity; + +public class IdentityHostingStartup : IHostingStartup { - public class IdentityHostingStartup : IHostingStartup + public void Configure(IWebHostBuilder builder) { - public void Configure(IWebHostBuilder builder) - { - } } } \ No newline at end of file diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/AccessDenied.cshtml.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/AccessDenied.cshtml.cs index 2a50edd8e..21d34c5ad 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/AccessDenied.cshtml.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/AccessDenied.cshtml.cs @@ -4,14 +4,13 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc.RazorPages; -namespace ClassifiedAds.IdentityServer.Areas.Identity.Pages.Account +namespace ClassifiedAds.IdentityServer.Areas.Identity.Pages.Account; + +public class AccessDeniedModel : PageModel { - public class AccessDeniedModel : PageModel + public void OnGet() { - public void OnGet() - { - } } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/ConfirmEmail.cshtml.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/ConfirmEmail.cshtml.cs index feb00abb1..beab48c9c 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/ConfirmEmail.cshtml.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/ConfirmEmail.cshtml.cs @@ -10,38 +10,37 @@ using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.AspNetCore.WebUtilities; -namespace ClassifiedAds.IdentityServer.Areas.Identity.Pages.Account +namespace ClassifiedAds.IdentityServer.Areas.Identity.Pages.Account; + +[AllowAnonymous] +public class ConfirmEmailModel : PageModel { - [AllowAnonymous] - public class ConfirmEmailModel : PageModel + private readonly UserManager _userManager; + + public ConfirmEmailModel(UserManager userManager) { - private readonly UserManager _userManager; + _userManager = userManager; + } - public ConfirmEmailModel(UserManager userManager) + [TempData] + public string StatusMessage { get; set; } + + public async Task OnGetAsync(string userId, string code) + { + if (userId == null || code == null) { - _userManager = userManager; + return RedirectToPage("/Index"); } - [TempData] - public string StatusMessage { get; set; } - - public async Task OnGetAsync(string userId, string code) + var user = await _userManager.FindByIdAsync(userId); + if (user == null) { - if (userId == null || code == null) - { - return RedirectToPage("/Index"); - } - - var user = await _userManager.FindByIdAsync(userId); - if (user == null) - { - return NotFound($"Unable to load user with ID '{userId}'."); - } - - code = Encoding.UTF8.GetString(WebEncoders.Base64UrlDecode(code)); - var result = await _userManager.ConfirmEmailAsync(user, code); - StatusMessage = result.Succeeded ? "Thank you for confirming your email." : "Error confirming your email."; - return Page(); + return NotFound($"Unable to load user with ID '{userId}'."); } + + code = Encoding.UTF8.GetString(WebEncoders.Base64UrlDecode(code)); + var result = await _userManager.ConfirmEmailAsync(user, code); + StatusMessage = result.Succeeded ? "Thank you for confirming your email." : "Error confirming your email."; + return Page(); } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/ConfirmEmailChange.cshtml.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/ConfirmEmailChange.cshtml.cs index 5c4ac32cb..931f524f1 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/ConfirmEmailChange.cshtml.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/ConfirmEmailChange.cshtml.cs @@ -10,56 +10,55 @@ using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.AspNetCore.WebUtilities; -namespace ClassifiedAds.IdentityServer.Areas.Identity.Pages.Account +namespace ClassifiedAds.IdentityServer.Areas.Identity.Pages.Account; + +[AllowAnonymous] +public class ConfirmEmailChangeModel : PageModel { - [AllowAnonymous] - public class ConfirmEmailChangeModel : PageModel + private readonly UserManager _userManager; + private readonly SignInManager _signInManager; + + public ConfirmEmailChangeModel(UserManager userManager, SignInManager signInManager) { - private readonly UserManager _userManager; - private readonly SignInManager _signInManager; + _userManager = userManager; + _signInManager = signInManager; + } + + [TempData] + public string StatusMessage { get; set; } - public ConfirmEmailChangeModel(UserManager userManager, SignInManager signInManager) + public async Task OnGetAsync(string userId, string email, string code) + { + if (userId == null || email == null || code == null) { - _userManager = userManager; - _signInManager = signInManager; + return RedirectToPage("/Index"); } - [TempData] - public string StatusMessage { get; set; } - - public async Task OnGetAsync(string userId, string email, string code) + var user = await _userManager.FindByIdAsync(userId); + if (user == null) { - if (userId == null || email == null || code == null) - { - return RedirectToPage("/Index"); - } - - var user = await _userManager.FindByIdAsync(userId); - if (user == null) - { - return NotFound($"Unable to load user with ID '{userId}'."); - } - - code = Encoding.UTF8.GetString(WebEncoders.Base64UrlDecode(code)); - var result = await _userManager.ChangeEmailAsync(user, email, code); - if (!result.Succeeded) - { - StatusMessage = "Error changing email."; - return Page(); - } + return NotFound($"Unable to load user with ID '{userId}'."); + } - // In our UI email and user name are one and the same, so when we update the email - // we need to update the user name. - var setUserNameResult = await _userManager.SetUserNameAsync(user, email); - if (!setUserNameResult.Succeeded) - { - StatusMessage = "Error changing user name."; - return Page(); - } + code = Encoding.UTF8.GetString(WebEncoders.Base64UrlDecode(code)); + var result = await _userManager.ChangeEmailAsync(user, email, code); + if (!result.Succeeded) + { + StatusMessage = "Error changing email."; + return Page(); + } - await _signInManager.RefreshSignInAsync(user); - StatusMessage = "Thank you for confirming your email change."; + // In our UI email and user name are one and the same, so when we update the email + // we need to update the user name. + var setUserNameResult = await _userManager.SetUserNameAsync(user, email); + if (!setUserNameResult.Succeeded) + { + StatusMessage = "Error changing user name."; return Page(); } + + await _signInManager.RefreshSignInAsync(user); + StatusMessage = "Thank you for confirming your email change."; + return Page(); } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/ExternalLogin.cshtml.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/ExternalLogin.cshtml.cs index 0f3dfd9be..5287d5e0a 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/ExternalLogin.cshtml.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/ExternalLogin.cshtml.cs @@ -15,155 +15,154 @@ using Microsoft.AspNetCore.WebUtilities; using Microsoft.Extensions.Logging; -namespace ClassifiedAds.IdentityServer.Areas.Identity.Pages.Account +namespace ClassifiedAds.IdentityServer.Areas.Identity.Pages.Account; + +[AllowAnonymous] +public class ExternalLoginModel : PageModel { - [AllowAnonymous] - public class ExternalLoginModel : PageModel + private readonly SignInManager _signInManager; + private readonly UserManager _userManager; + private readonly IEmailSender _emailSender; + private readonly ILogger _logger; + + public ExternalLoginModel( + SignInManager signInManager, + UserManager userManager, + ILogger logger, + IEmailSender emailSender) { - private readonly SignInManager _signInManager; - private readonly UserManager _userManager; - private readonly IEmailSender _emailSender; - private readonly ILogger _logger; - - public ExternalLoginModel( - SignInManager signInManager, - UserManager userManager, - ILogger logger, - IEmailSender emailSender) - { - _signInManager = signInManager; - _userManager = userManager; - _logger = logger; - _emailSender = emailSender; - } + _signInManager = signInManager; + _userManager = userManager; + _logger = logger; + _emailSender = emailSender; + } + + [BindProperty] + public InputModel Input { get; set; } + + public string ProviderDisplayName { get; set; } + + public string ReturnUrl { get; set; } - [BindProperty] - public InputModel Input { get; set; } + [TempData] + public string ErrorMessage { get; set; } - public string ProviderDisplayName { get; set; } + public class InputModel + { + [Required] + [EmailAddress] + public string Email { get; set; } + } - public string ReturnUrl { get; set; } + public IActionResult OnGetAsync() + { + return RedirectToPage("./Login"); + } - [TempData] - public string ErrorMessage { get; set; } + public IActionResult OnPost(string provider, string returnUrl = null) + { + // Request a redirect to the external login provider. + var redirectUrl = Url.Page("./ExternalLogin", pageHandler: "Callback", values: new { returnUrl }); + var properties = _signInManager.ConfigureExternalAuthenticationProperties(provider, redirectUrl); + return new ChallengeResult(provider, properties); + } - public class InputModel + public async Task OnGetCallbackAsync(string returnUrl = null, string remoteError = null) + { + returnUrl = returnUrl ?? Url.Content("~/"); + if (remoteError != null) { - [Required] - [EmailAddress] - public string Email { get; set; } + ErrorMessage = $"Error from external provider: {remoteError}"; + return RedirectToPage("./Login", new {ReturnUrl = returnUrl }); } - - public IActionResult OnGetAsync() + var info = await _signInManager.GetExternalLoginInfoAsync(); + if (info == null) { - return RedirectToPage("./Login"); + ErrorMessage = "Error loading external login information."; + return RedirectToPage("./Login", new { ReturnUrl = returnUrl }); } - public IActionResult OnPost(string provider, string returnUrl = null) + // Sign in the user with this external login provider if the user already has a login. + var result = await _signInManager.ExternalLoginSignInAsync(info.LoginProvider, info.ProviderKey, isPersistent: false, bypassTwoFactor : true); + if (result.Succeeded) { - // Request a redirect to the external login provider. - var redirectUrl = Url.Page("./ExternalLogin", pageHandler: "Callback", values: new { returnUrl }); - var properties = _signInManager.ConfigureExternalAuthenticationProperties(provider, redirectUrl); - return new ChallengeResult(provider, properties); + _logger.LogInformation("{Name} logged in with {LoginProvider} provider.", info.Principal.Identity.Name, info.LoginProvider); + return LocalRedirect(returnUrl); } - - public async Task OnGetCallbackAsync(string returnUrl = null, string remoteError = null) + if (result.IsLockedOut) { - returnUrl = returnUrl ?? Url.Content("~/"); - if (remoteError != null) - { - ErrorMessage = $"Error from external provider: {remoteError}"; - return RedirectToPage("./Login", new {ReturnUrl = returnUrl }); - } - var info = await _signInManager.GetExternalLoginInfoAsync(); - if (info == null) - { - ErrorMessage = "Error loading external login information."; - return RedirectToPage("./Login", new { ReturnUrl = returnUrl }); - } - - // Sign in the user with this external login provider if the user already has a login. - var result = await _signInManager.ExternalLoginSignInAsync(info.LoginProvider, info.ProviderKey, isPersistent: false, bypassTwoFactor : true); - if (result.Succeeded) - { - _logger.LogInformation("{Name} logged in with {LoginProvider} provider.", info.Principal.Identity.Name, info.LoginProvider); - return LocalRedirect(returnUrl); - } - if (result.IsLockedOut) - { - return RedirectToPage("./Lockout"); - } - else + return RedirectToPage("./Lockout"); + } + else + { + // If the user does not have an account, then ask the user to create an account. + ReturnUrl = returnUrl; + ProviderDisplayName = info.ProviderDisplayName; + if (info.Principal.HasClaim(c => c.Type == ClaimTypes.Email)) { - // If the user does not have an account, then ask the user to create an account. - ReturnUrl = returnUrl; - ProviderDisplayName = info.ProviderDisplayName; - if (info.Principal.HasClaim(c => c.Type == ClaimTypes.Email)) + Input = new InputModel { - Input = new InputModel - { - Email = info.Principal.FindFirstValue(ClaimTypes.Email) - }; - } - return Page(); + Email = info.Principal.FindFirstValue(ClaimTypes.Email) + }; } + return Page(); + } + } + + public async Task OnPostConfirmationAsync(string returnUrl = null) + { + returnUrl = returnUrl ?? Url.Content("~/"); + // Get the information about the user from the external login provider + var info = await _signInManager.GetExternalLoginInfoAsync(); + if (info == null) + { + ErrorMessage = "Error loading external login information during confirmation."; + return RedirectToPage("./Login", new { ReturnUrl = returnUrl }); } - public async Task OnPostConfirmationAsync(string returnUrl = null) + if (ModelState.IsValid) { - returnUrl = returnUrl ?? Url.Content("~/"); - // Get the information about the user from the external login provider - var info = await _signInManager.GetExternalLoginInfoAsync(); - if (info == null) - { - ErrorMessage = "Error loading external login information during confirmation."; - return RedirectToPage("./Login", new { ReturnUrl = returnUrl }); - } + var user = new User { UserName = Input.Email, Email = Input.Email }; - if (ModelState.IsValid) + var result = await _userManager.CreateAsync(user); + if (result.Succeeded) { - var user = new User { UserName = Input.Email, Email = Input.Email }; - - var result = await _userManager.CreateAsync(user); + result = await _userManager.AddLoginAsync(user, info); if (result.Succeeded) { - result = await _userManager.AddLoginAsync(user, info); - if (result.Succeeded) + _logger.LogInformation("User created an account using {Name} provider.", info.LoginProvider); + + var userId = await _userManager.GetUserIdAsync(user); + var code = await _userManager.GenerateEmailConfirmationTokenAsync(user); + code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code)); + var callbackUrl = Url.Page( + "/Account/ConfirmEmail", + pageHandler: null, + values: new { area = "Identity", userId = userId, code = code }, + protocol: Request.Scheme); + + await _emailSender.SendEmailAsync(Input.Email, "Confirm your email", + $"Please confirm your account by clicking here."); + + // If account confirmation is required, we need to show the link if we don't have a real email sender + if (_userManager.Options.SignIn.RequireConfirmedAccount) { - _logger.LogInformation("User created an account using {Name} provider.", info.LoginProvider); - - var userId = await _userManager.GetUserIdAsync(user); - var code = await _userManager.GenerateEmailConfirmationTokenAsync(user); - code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code)); - var callbackUrl = Url.Page( - "/Account/ConfirmEmail", - pageHandler: null, - values: new { area = "Identity", userId = userId, code = code }, - protocol: Request.Scheme); - - await _emailSender.SendEmailAsync(Input.Email, "Confirm your email", - $"Please confirm your account by clicking here."); - - // If account confirmation is required, we need to show the link if we don't have a real email sender - if (_userManager.Options.SignIn.RequireConfirmedAccount) - { - return RedirectToPage("./RegisterConfirmation", new { Email = Input.Email }); - } + return RedirectToPage("./RegisterConfirmation", new { Email = Input.Email }); + } - await _signInManager.SignInAsync(user, isPersistent: false, info.LoginProvider); + await _signInManager.SignInAsync(user, isPersistent: false, info.LoginProvider); - return LocalRedirect(returnUrl); - } - } - foreach (var error in result.Errors) - { - ModelState.AddModelError(string.Empty, error.Description); + return LocalRedirect(returnUrl); } } - - ProviderDisplayName = info.ProviderDisplayName; - ReturnUrl = returnUrl; - return Page(); + foreach (var error in result.Errors) + { + ModelState.AddModelError(string.Empty, error.Description); + } } + + ProviderDisplayName = info.ProviderDisplayName; + ReturnUrl = returnUrl; + return Page(); } } \ No newline at end of file diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/ForgotPassword.cshtml.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/ForgotPassword.cshtml.cs index d2880ef6e..677944a3b 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/ForgotPassword.cshtml.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/ForgotPassword.cshtml.cs @@ -12,60 +12,59 @@ using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.AspNetCore.WebUtilities; -namespace ClassifiedAds.IdentityServer.Areas.Identity.Pages.Account +namespace ClassifiedAds.IdentityServer.Areas.Identity.Pages.Account; + +[AllowAnonymous] +public class ForgotPasswordModel : PageModel { - [AllowAnonymous] - public class ForgotPasswordModel : PageModel - { - private readonly UserManager _userManager; - private readonly IEmailSender _emailSender; + private readonly UserManager _userManager; + private readonly IEmailSender _emailSender; - public ForgotPasswordModel(UserManager userManager, IEmailSender emailSender) - { - _userManager = userManager; - _emailSender = emailSender; - } + public ForgotPasswordModel(UserManager userManager, IEmailSender emailSender) + { + _userManager = userManager; + _emailSender = emailSender; + } - [BindProperty] - public InputModel Input { get; set; } + [BindProperty] + public InputModel Input { get; set; } - public class InputModel - { - [Required] - [EmailAddress] - public string Email { get; set; } - } + public class InputModel + { + [Required] + [EmailAddress] + public string Email { get; set; } + } - public async Task OnPostAsync() + public async Task OnPostAsync() + { + if (ModelState.IsValid) { - if (ModelState.IsValid) + var user = await _userManager.FindByEmailAsync(Input.Email); + if (user == null || !(await _userManager.IsEmailConfirmedAsync(user))) { - var user = await _userManager.FindByEmailAsync(Input.Email); - if (user == null || !(await _userManager.IsEmailConfirmedAsync(user))) - { - // Don't reveal that the user does not exist or is not confirmed - return RedirectToPage("./ForgotPasswordConfirmation"); - } - - // For more information on how to enable account confirmation and password reset please - // visit https://go.microsoft.com/fwlink/?LinkID=532713 - var code = await _userManager.GeneratePasswordResetTokenAsync(user); - code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code)); - var callbackUrl = Url.Page( - "/Account/ResetPassword", - pageHandler: null, - values: new { area = "Identity", code }, - protocol: Request.Scheme); - - await _emailSender.SendEmailAsync( - Input.Email, - "Reset Password", - $"Please reset your password by clicking here."); - + // Don't reveal that the user does not exist or is not confirmed return RedirectToPage("./ForgotPasswordConfirmation"); } - return Page(); + // For more information on how to enable account confirmation and password reset please + // visit https://go.microsoft.com/fwlink/?LinkID=532713 + var code = await _userManager.GeneratePasswordResetTokenAsync(user); + code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code)); + var callbackUrl = Url.Page( + "/Account/ResetPassword", + pageHandler: null, + values: new { area = "Identity", code }, + protocol: Request.Scheme); + + await _emailSender.SendEmailAsync( + Input.Email, + "Reset Password", + $"Please reset your password by clicking here."); + + return RedirectToPage("./ForgotPasswordConfirmation"); } + + return Page(); } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/ForgotPasswordConfirmation.cshtml.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/ForgotPasswordConfirmation.cshtml.cs index a80521e0a..a1086657e 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/ForgotPasswordConfirmation.cshtml.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/ForgotPasswordConfirmation.cshtml.cs @@ -4,13 +4,12 @@ using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc.RazorPages; -namespace ClassifiedAds.IdentityServer.Areas.Identity.Pages.Account +namespace ClassifiedAds.IdentityServer.Areas.Identity.Pages.Account; + +[AllowAnonymous] +public class ForgotPasswordConfirmation : PageModel { - [AllowAnonymous] - public class ForgotPasswordConfirmation : PageModel + public void OnGet() { - public void OnGet() - { - } } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/Lockout.cshtml.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/Lockout.cshtml.cs index ffbcd0fc4..d04ca352b 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/Lockout.cshtml.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/Lockout.cshtml.cs @@ -5,14 +5,13 @@ using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc.RazorPages; -namespace ClassifiedAds.IdentityServer.Areas.Identity.Pages.Account +namespace ClassifiedAds.IdentityServer.Areas.Identity.Pages.Account; + +[AllowAnonymous] +public class LockoutModel : PageModel { - [AllowAnonymous] - public class LockoutModel : PageModel + public void OnGet() { - public void OnGet() - { - } } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/Login.cshtml.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/Login.cshtml.cs index 5fe7e8e1f..aebb0dedb 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/Login.cshtml.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/Login.cshtml.cs @@ -13,99 +13,98 @@ using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.Extensions.Logging; -namespace ClassifiedAds.IdentityServer.Areas.Identity.Pages.Account +namespace ClassifiedAds.IdentityServer.Areas.Identity.Pages.Account; + +[AllowAnonymous] +public class LoginModel : PageModel { - [AllowAnonymous] - public class LoginModel : PageModel + private readonly UserManager _userManager; + private readonly SignInManager _signInManager; + private readonly ILogger _logger; + + public LoginModel(SignInManager signInManager, + ILogger logger, + UserManager userManager) { - private readonly UserManager _userManager; - private readonly SignInManager _signInManager; - private readonly ILogger _logger; + _userManager = userManager; + _signInManager = signInManager; + _logger = logger; + } - public LoginModel(SignInManager signInManager, - ILogger logger, - UserManager userManager) - { - _userManager = userManager; - _signInManager = signInManager; - _logger = logger; - } + [BindProperty] + public InputModel Input { get; set; } - [BindProperty] - public InputModel Input { get; set; } + public IList ExternalLogins { get; set; } - public IList ExternalLogins { get; set; } + public string ReturnUrl { get; set; } - public string ReturnUrl { get; set; } + [TempData] + public string ErrorMessage { get; set; } - [TempData] - public string ErrorMessage { get; set; } + public class InputModel + { + [Required] + [EmailAddress] + public string Email { get; set; } - public class InputModel - { - [Required] - [EmailAddress] - public string Email { get; set; } + [Required] + [DataType(DataType.Password)] + public string Password { get; set; } - [Required] - [DataType(DataType.Password)] - public string Password { get; set; } + [Display(Name = "Remember me?")] + public bool RememberMe { get; set; } + } - [Display(Name = "Remember me?")] - public bool RememberMe { get; set; } + public async Task OnGetAsync(string returnUrl = null) + { + if (!string.IsNullOrEmpty(ErrorMessage)) + { + ModelState.AddModelError(string.Empty, ErrorMessage); } - public async Task OnGetAsync(string returnUrl = null) - { - if (!string.IsNullOrEmpty(ErrorMessage)) - { - ModelState.AddModelError(string.Empty, ErrorMessage); - } + returnUrl ??= Url.Content("~/"); - returnUrl ??= Url.Content("~/"); + // Clear the existing external cookie to ensure a clean login process + await HttpContext.SignOutAsync(IdentityConstants.ExternalScheme); - // Clear the existing external cookie to ensure a clean login process - await HttpContext.SignOutAsync(IdentityConstants.ExternalScheme); + ExternalLogins = (await _signInManager.GetExternalAuthenticationSchemesAsync()).ToList(); - ExternalLogins = (await _signInManager.GetExternalAuthenticationSchemesAsync()).ToList(); + ReturnUrl = returnUrl; + } - ReturnUrl = returnUrl; - } + public async Task OnPostAsync(string returnUrl = null) + { + returnUrl ??= Url.Content("~/"); - public async Task OnPostAsync(string returnUrl = null) + ExternalLogins = (await _signInManager.GetExternalAuthenticationSchemesAsync()).ToList(); + + if (ModelState.IsValid) { - returnUrl ??= Url.Content("~/"); - - ExternalLogins = (await _signInManager.GetExternalAuthenticationSchemesAsync()).ToList(); - - if (ModelState.IsValid) + // This doesn't count login failures towards account lockout + // To enable password failures to trigger account lockout, set lockoutOnFailure: true + var result = await _signInManager.PasswordSignInAsync(Input.Email, Input.Password, Input.RememberMe, lockoutOnFailure: false); + if (result.Succeeded) { - // This doesn't count login failures towards account lockout - // To enable password failures to trigger account lockout, set lockoutOnFailure: true - var result = await _signInManager.PasswordSignInAsync(Input.Email, Input.Password, Input.RememberMe, lockoutOnFailure: false); - if (result.Succeeded) - { - _logger.LogInformation("User logged in."); - return LocalRedirect(returnUrl); - } - if (result.RequiresTwoFactor) - { - return RedirectToPage("./LoginWith2fa", new { ReturnUrl = returnUrl, RememberMe = Input.RememberMe }); - } - if (result.IsLockedOut) - { - _logger.LogWarning("User account locked out."); - return RedirectToPage("./Lockout"); - } - else - { - ModelState.AddModelError(string.Empty, "Invalid login attempt."); - return Page(); - } + _logger.LogInformation("User logged in."); + return LocalRedirect(returnUrl); + } + if (result.RequiresTwoFactor) + { + return RedirectToPage("./LoginWith2fa", new { ReturnUrl = returnUrl, RememberMe = Input.RememberMe }); + } + if (result.IsLockedOut) + { + _logger.LogWarning("User account locked out."); + return RedirectToPage("./Lockout"); + } + else + { + ModelState.AddModelError(string.Empty, "Invalid login attempt."); + return Page(); } - - // If we got this far, something failed, redisplay form - return Page(); } + + // If we got this far, something failed, redisplay form + return Page(); } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/LoginWith2fa.cshtml.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/LoginWith2fa.cshtml.cs index c25a101b7..bff5fbf11 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/LoginWith2fa.cshtml.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/LoginWith2fa.cshtml.cs @@ -10,90 +10,89 @@ using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.Extensions.Logging; -namespace ClassifiedAds.IdentityServer.Areas.Identity.Pages.Account +namespace ClassifiedAds.IdentityServer.Areas.Identity.Pages.Account; + +[AllowAnonymous] +public class LoginWith2faModel : PageModel { - [AllowAnonymous] - public class LoginWith2faModel : PageModel + private readonly SignInManager _signInManager; + private readonly ILogger _logger; + + public LoginWith2faModel(SignInManager signInManager, ILogger logger) + { + _signInManager = signInManager; + _logger = logger; + } + + [BindProperty] + public InputModel Input { get; set; } + + public bool RememberMe { get; set; } + + public string ReturnUrl { get; set; } + + public class InputModel + { + [Required] + [StringLength(7, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 6)] + [DataType(DataType.Text)] + [Display(Name = "Authenticator code")] + public string TwoFactorCode { get; set; } + + [Display(Name = "Remember this machine")] + public bool RememberMachine { get; set; } + } + + public async Task OnGetAsync(bool rememberMe, string returnUrl = null) { - private readonly SignInManager _signInManager; - private readonly ILogger _logger; + // Ensure the user has gone through the username & password screen first + var user = await _signInManager.GetTwoFactorAuthenticationUserAsync(); - public LoginWith2faModel(SignInManager signInManager, ILogger logger) + if (user == null) { - _signInManager = signInManager; - _logger = logger; + throw new InvalidOperationException($"Unable to load two-factor authentication user."); } - [BindProperty] - public InputModel Input { get; set; } - - public bool RememberMe { get; set; } + ReturnUrl = returnUrl; + RememberMe = rememberMe; - public string ReturnUrl { get; set; } + return Page(); + } - public class InputModel + public async Task OnPostAsync(bool rememberMe, string returnUrl = null) + { + if (!ModelState.IsValid) { - [Required] - [StringLength(7, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 6)] - [DataType(DataType.Text)] - [Display(Name = "Authenticator code")] - public string TwoFactorCode { get; set; } - - [Display(Name = "Remember this machine")] - public bool RememberMachine { get; set; } + return Page(); } - public async Task OnGetAsync(bool rememberMe, string returnUrl = null) + returnUrl = returnUrl ?? Url.Content("~/"); + + var user = await _signInManager.GetTwoFactorAuthenticationUserAsync(); + if (user == null) { - // Ensure the user has gone through the username & password screen first - var user = await _signInManager.GetTwoFactorAuthenticationUserAsync(); + throw new InvalidOperationException($"Unable to load two-factor authentication user."); + } - if (user == null) - { - throw new InvalidOperationException($"Unable to load two-factor authentication user."); - } + var authenticatorCode = Input.TwoFactorCode.Replace(" ", string.Empty).Replace("-", string.Empty); - ReturnUrl = returnUrl; - RememberMe = rememberMe; + var result = await _signInManager.TwoFactorAuthenticatorSignInAsync(authenticatorCode, rememberMe, Input.RememberMachine); - return Page(); + if (result.Succeeded) + { + _logger.LogInformation("User with ID '{UserId}' logged in with 2fa.", user.Id); + return LocalRedirect(returnUrl); } - - public async Task OnPostAsync(bool rememberMe, string returnUrl = null) + else if (result.IsLockedOut) { - if (!ModelState.IsValid) - { - return Page(); - } - - returnUrl = returnUrl ?? Url.Content("~/"); - - var user = await _signInManager.GetTwoFactorAuthenticationUserAsync(); - if (user == null) - { - throw new InvalidOperationException($"Unable to load two-factor authentication user."); - } - - var authenticatorCode = Input.TwoFactorCode.Replace(" ", string.Empty).Replace("-", string.Empty); - - var result = await _signInManager.TwoFactorAuthenticatorSignInAsync(authenticatorCode, rememberMe, Input.RememberMachine); - - if (result.Succeeded) - { - _logger.LogInformation("User with ID '{UserId}' logged in with 2fa.", user.Id); - return LocalRedirect(returnUrl); - } - else if (result.IsLockedOut) - { - _logger.LogWarning("User with ID '{UserId}' account locked out.", user.Id); - return RedirectToPage("./Lockout"); - } - else - { - _logger.LogWarning("Invalid authenticator code entered for user with ID '{UserId}'.", user.Id); - ModelState.AddModelError(string.Empty, "Invalid authenticator code."); - return Page(); - } + _logger.LogWarning("User with ID '{UserId}' account locked out.", user.Id); + return RedirectToPage("./Lockout"); + } + else + { + _logger.LogWarning("Invalid authenticator code entered for user with ID '{UserId}'.", user.Id); + ModelState.AddModelError(string.Empty, "Invalid authenticator code."); + return Page(); } } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/LoginWithRecoveryCode.cshtml.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/LoginWithRecoveryCode.cshtml.cs index af8a8f176..bc196f05a 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/LoginWithRecoveryCode.cshtml.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/LoginWithRecoveryCode.cshtml.cs @@ -10,81 +10,80 @@ using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.Extensions.Logging; -namespace ClassifiedAds.IdentityServer.Areas.Identity.Pages.Account +namespace ClassifiedAds.IdentityServer.Areas.Identity.Pages.Account; + +[AllowAnonymous] +public class LoginWithRecoveryCodeModel : PageModel { - [AllowAnonymous] - public class LoginWithRecoveryCodeModel : PageModel + private readonly SignInManager _signInManager; + private readonly ILogger _logger; + + public LoginWithRecoveryCodeModel(SignInManager signInManager, ILogger logger) { - private readonly SignInManager _signInManager; - private readonly ILogger _logger; + _signInManager = signInManager; + _logger = logger; + } - public LoginWithRecoveryCodeModel(SignInManager signInManager, ILogger logger) - { - _signInManager = signInManager; - _logger = logger; - } + [BindProperty] + public InputModel Input { get; set; } - [BindProperty] - public InputModel Input { get; set; } + public string ReturnUrl { get; set; } - public string ReturnUrl { get; set; } + public class InputModel + { + [BindProperty] + [Required] + [DataType(DataType.Text)] + [Display(Name = "Recovery Code")] + public string RecoveryCode { get; set; } + } - public class InputModel + public async Task OnGetAsync(string returnUrl = null) + { + // Ensure the user has gone through the username & password screen first + var user = await _signInManager.GetTwoFactorAuthenticationUserAsync(); + if (user == null) { - [BindProperty] - [Required] - [DataType(DataType.Text)] - [Display(Name = "Recovery Code")] - public string RecoveryCode { get; set; } + throw new InvalidOperationException($"Unable to load two-factor authentication user."); } - public async Task OnGetAsync(string returnUrl = null) - { - // Ensure the user has gone through the username & password screen first - var user = await _signInManager.GetTwoFactorAuthenticationUserAsync(); - if (user == null) - { - throw new InvalidOperationException($"Unable to load two-factor authentication user."); - } + ReturnUrl = returnUrl; - ReturnUrl = returnUrl; + return Page(); + } + public async Task OnPostAsync(string returnUrl = null) + { + if (!ModelState.IsValid) + { return Page(); } - public async Task OnPostAsync(string returnUrl = null) + var user = await _signInManager.GetTwoFactorAuthenticationUserAsync(); + if (user == null) { - if (!ModelState.IsValid) - { - return Page(); - } - - var user = await _signInManager.GetTwoFactorAuthenticationUserAsync(); - if (user == null) - { - throw new InvalidOperationException($"Unable to load two-factor authentication user."); - } + throw new InvalidOperationException($"Unable to load two-factor authentication user."); + } - var recoveryCode = Input.RecoveryCode.Replace(" ", string.Empty); + var recoveryCode = Input.RecoveryCode.Replace(" ", string.Empty); - var result = await _signInManager.TwoFactorRecoveryCodeSignInAsync(recoveryCode); + var result = await _signInManager.TwoFactorRecoveryCodeSignInAsync(recoveryCode); - if (result.Succeeded) - { - _logger.LogInformation("User with ID '{UserId}' logged in with a recovery code.", user.Id); - return LocalRedirect(returnUrl ?? Url.Content("~/")); - } - if (result.IsLockedOut) - { - _logger.LogWarning("User with ID '{UserId}' account locked out.", user.Id); - return RedirectToPage("./Lockout"); - } - else - { - _logger.LogWarning("Invalid recovery code entered for user with ID '{UserId}' ", user.Id); - ModelState.AddModelError(string.Empty, "Invalid recovery code entered."); - return Page(); - } + if (result.Succeeded) + { + _logger.LogInformation("User with ID '{UserId}' logged in with a recovery code.", user.Id); + return LocalRedirect(returnUrl ?? Url.Content("~/")); + } + if (result.IsLockedOut) + { + _logger.LogWarning("User with ID '{UserId}' account locked out.", user.Id); + return RedirectToPage("./Lockout"); + } + else + { + _logger.LogWarning("Invalid recovery code entered for user with ID '{UserId}' ", user.Id); + ModelState.AddModelError(string.Empty, "Invalid recovery code entered."); + return Page(); } } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/Logout.cshtml.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/Logout.cshtml.cs index f17b0fd77..8ef6879d3 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/Logout.cshtml.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/Logout.cshtml.cs @@ -9,36 +9,35 @@ using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.Extensions.Logging; -namespace ClassifiedAds.IdentityServer.Areas.Identity.Pages.Account +namespace ClassifiedAds.IdentityServer.Areas.Identity.Pages.Account; + +[AllowAnonymous] +public class LogoutModel : PageModel { - [AllowAnonymous] - public class LogoutModel : PageModel + private readonly SignInManager _signInManager; + private readonly ILogger _logger; + + public LogoutModel(SignInManager signInManager, ILogger logger) { - private readonly SignInManager _signInManager; - private readonly ILogger _logger; + _signInManager = signInManager; + _logger = logger; + } - public LogoutModel(SignInManager signInManager, ILogger logger) - { - _signInManager = signInManager; - _logger = logger; - } + public void OnGet() + { + } - public void OnGet() + public async Task OnPost(string returnUrl = null) + { + await _signInManager.SignOutAsync(); + _logger.LogInformation("User logged out."); + if (returnUrl != null) { + return LocalRedirect(returnUrl); } - - public async Task OnPost(string returnUrl = null) + else { - await _signInManager.SignOutAsync(); - _logger.LogInformation("User logged out."); - if (returnUrl != null) - { - return LocalRedirect(returnUrl); - } - else - { - return RedirectToPage(); - } + return RedirectToPage(); } } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/Manage/ChangePassword.cshtml.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/Manage/ChangePassword.cshtml.cs index 79f764055..ff4d4dead 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/Manage/ChangePassword.cshtml.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/Manage/ChangePassword.cshtml.cs @@ -8,94 +8,93 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.Extensions.Logging; -namespace ClassifiedAds.IdentityServer.Areas.Identity.Pages.Account.Manage +namespace ClassifiedAds.IdentityServer.Areas.Identity.Pages.Account.Manage; + +public class ChangePasswordModel : PageModel { - public class ChangePasswordModel : PageModel + private readonly UserManager _userManager; + private readonly SignInManager _signInManager; + private readonly ILogger _logger; + + public ChangePasswordModel( + UserManager userManager, + SignInManager signInManager, + ILogger logger) { - private readonly UserManager _userManager; - private readonly SignInManager _signInManager; - private readonly ILogger _logger; + _userManager = userManager; + _signInManager = signInManager; + _logger = logger; + } - public ChangePasswordModel( - UserManager userManager, - SignInManager signInManager, - ILogger logger) - { - _userManager = userManager; - _signInManager = signInManager; - _logger = logger; - } + [BindProperty] + public InputModel Input { get; set; } - [BindProperty] - public InputModel Input { get; set; } + [TempData] + public string StatusMessage { get; set; } - [TempData] - public string StatusMessage { get; set; } + public class InputModel + { + [Required] + [DataType(DataType.Password)] + [Display(Name = "Current password")] + public string OldPassword { get; set; } - public class InputModel - { - [Required] - [DataType(DataType.Password)] - [Display(Name = "Current password")] - public string OldPassword { get; set; } + [Required] + [StringLength(100, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 6)] + [DataType(DataType.Password)] + [Display(Name = "New password")] + public string NewPassword { get; set; } - [Required] - [StringLength(100, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 6)] - [DataType(DataType.Password)] - [Display(Name = "New password")] - public string NewPassword { get; set; } + [DataType(DataType.Password)] + [Display(Name = "Confirm new password")] + [Compare("NewPassword", ErrorMessage = "The new password and confirmation password do not match.")] + public string ConfirmPassword { get; set; } + } - [DataType(DataType.Password)] - [Display(Name = "Confirm new password")] - [Compare("NewPassword", ErrorMessage = "The new password and confirmation password do not match.")] - public string ConfirmPassword { get; set; } + public async Task OnGetAsync() + { + var user = await _userManager.GetUserAsync(User); + if (user == null) + { + return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'."); } - public async Task OnGetAsync() + var hasPassword = await _userManager.HasPasswordAsync(user); + if (!hasPassword) { - var user = await _userManager.GetUserAsync(User); - if (user == null) - { - return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'."); - } + return RedirectToPage("./SetPassword"); + } - var hasPassword = await _userManager.HasPasswordAsync(user); - if (!hasPassword) - { - return RedirectToPage("./SetPassword"); - } + return Page(); + } + public async Task OnPostAsync() + { + if (!ModelState.IsValid) + { return Page(); } - public async Task OnPostAsync() + var user = await _userManager.GetUserAsync(User); + if (user == null) { - if (!ModelState.IsValid) - { - return Page(); - } - - var user = await _userManager.GetUserAsync(User); - if (user == null) - { - return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'."); - } + return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'."); + } - var changePasswordResult = await _userManager.ChangePasswordAsync(user, Input.OldPassword, Input.NewPassword); - if (!changePasswordResult.Succeeded) + var changePasswordResult = await _userManager.ChangePasswordAsync(user, Input.OldPassword, Input.NewPassword); + if (!changePasswordResult.Succeeded) + { + foreach (var error in changePasswordResult.Errors) { - foreach (var error in changePasswordResult.Errors) - { - ModelState.AddModelError(string.Empty, error.Description); - } - return Page(); + ModelState.AddModelError(string.Empty, error.Description); } + return Page(); + } - await _signInManager.RefreshSignInAsync(user); - _logger.LogInformation("User changed their password successfully."); - StatusMessage = "Your password has been changed."; + await _signInManager.RefreshSignInAsync(user); + _logger.LogInformation("User changed their password successfully."); + StatusMessage = "Your password has been changed."; - return RedirectToPage(); - } + return RedirectToPage(); } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/Manage/DeletePersonalData.cshtml.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/Manage/DeletePersonalData.cshtml.cs index 3ca45366d..c8a181fc7 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/Manage/DeletePersonalData.cshtml.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/Manage/DeletePersonalData.cshtml.cs @@ -7,78 +7,77 @@ using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.Extensions.Logging; -namespace ClassifiedAds.IdentityServer.Areas.Identity.Pages.Account.Manage +namespace ClassifiedAds.IdentityServer.Areas.Identity.Pages.Account.Manage; + +public class DeletePersonalDataModel : PageModel { - public class DeletePersonalDataModel : PageModel + private readonly UserManager _userManager; + private readonly SignInManager _signInManager; + private readonly ILogger _logger; + + public DeletePersonalDataModel( + UserManager userManager, + SignInManager signInManager, + ILogger logger) { - private readonly UserManager _userManager; - private readonly SignInManager _signInManager; - private readonly ILogger _logger; + _userManager = userManager; + _signInManager = signInManager; + _logger = logger; + } - public DeletePersonalDataModel( - UserManager userManager, - SignInManager signInManager, - ILogger logger) - { - _userManager = userManager; - _signInManager = signInManager; - _logger = logger; - } + [BindProperty] + public InputModel Input { get; set; } + + public class InputModel + { + [Required] + [DataType(DataType.Password)] + public string Password { get; set; } + } - [BindProperty] - public InputModel Input { get; set; } + public bool RequirePassword { get; set; } - public class InputModel + public async Task OnGet() + { + var user = await _userManager.GetUserAsync(User); + if (user == null) { - [Required] - [DataType(DataType.Password)] - public string Password { get; set; } + return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'."); } - public bool RequirePassword { get; set; } + RequirePassword = await _userManager.HasPasswordAsync(user); + return Page(); + } - public async Task OnGet() + public async Task OnPostAsync() + { + var user = await _userManager.GetUserAsync(User); + if (user == null) { - var user = await _userManager.GetUserAsync(User); - if (user == null) - { - return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'."); - } - - RequirePassword = await _userManager.HasPasswordAsync(user); - return Page(); + return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'."); } - public async Task OnPostAsync() + RequirePassword = await _userManager.HasPasswordAsync(user); + if (RequirePassword) { - var user = await _userManager.GetUserAsync(User); - if (user == null) - { - return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'."); - } - - RequirePassword = await _userManager.HasPasswordAsync(user); - if (RequirePassword) + if (!await _userManager.CheckPasswordAsync(user, Input.Password)) { - if (!await _userManager.CheckPasswordAsync(user, Input.Password)) - { - ModelState.AddModelError(string.Empty, "Incorrect password."); - return Page(); - } + ModelState.AddModelError(string.Empty, "Incorrect password."); + return Page(); } + } - var result = await _userManager.DeleteAsync(user); - var userId = await _userManager.GetUserIdAsync(user); - if (!result.Succeeded) - { - throw new InvalidOperationException($"Unexpected error occurred deleting user with ID '{userId}'."); - } + var result = await _userManager.DeleteAsync(user); + var userId = await _userManager.GetUserIdAsync(user); + if (!result.Succeeded) + { + throw new InvalidOperationException($"Unexpected error occurred deleting user with ID '{userId}'."); + } - await _signInManager.SignOutAsync(); + await _signInManager.SignOutAsync(); - _logger.LogInformation("User with ID '{UserId}' deleted themselves.", userId); + _logger.LogInformation("User with ID '{UserId}' deleted themselves.", userId); - return Redirect("~/"); - } + return Redirect("~/"); } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/Manage/Disable2fa.cshtml.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/Manage/Disable2fa.cshtml.cs index 5659fa019..bd2704b17 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/Manage/Disable2fa.cshtml.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/Manage/Disable2fa.cshtml.cs @@ -8,57 +8,56 @@ using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.Extensions.Logging; -namespace ClassifiedAds.IdentityServer.Areas.Identity.Pages.Account.Manage +namespace ClassifiedAds.IdentityServer.Areas.Identity.Pages.Account.Manage; + +public class Disable2faModel : PageModel { - public class Disable2faModel : PageModel + private readonly UserManager _userManager; + private readonly ILogger _logger; + + public Disable2faModel( + UserManager userManager, + ILogger logger) { - private readonly UserManager _userManager; - private readonly ILogger _logger; + _userManager = userManager; + _logger = logger; + } + + [TempData] + public string StatusMessage { get; set; } - public Disable2faModel( - UserManager userManager, - ILogger logger) + public async Task OnGet() + { + var user = await _userManager.GetUserAsync(User); + if (user == null) { - _userManager = userManager; - _logger = logger; + return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'."); } - [TempData] - public string StatusMessage { get; set; } - - public async Task OnGet() + if (!await _userManager.GetTwoFactorEnabledAsync(user)) { - var user = await _userManager.GetUserAsync(User); - if (user == null) - { - return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'."); - } + throw new InvalidOperationException($"Cannot disable 2FA for user with ID '{_userManager.GetUserId(User)}' as it's not currently enabled."); + } - if (!await _userManager.GetTwoFactorEnabledAsync(user)) - { - throw new InvalidOperationException($"Cannot disable 2FA for user with ID '{_userManager.GetUserId(User)}' as it's not currently enabled."); - } + return Page(); + } - return Page(); + public async Task OnPostAsync() + { + var user = await _userManager.GetUserAsync(User); + if (user == null) + { + return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'."); } - public async Task OnPostAsync() + var disable2faResult = await _userManager.SetTwoFactorEnabledAsync(user, false); + if (!disable2faResult.Succeeded) { - var user = await _userManager.GetUserAsync(User); - if (user == null) - { - return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'."); - } - - var disable2faResult = await _userManager.SetTwoFactorEnabledAsync(user, false); - if (!disable2faResult.Succeeded) - { - throw new InvalidOperationException($"Unexpected error occurred disabling 2FA for user with ID '{_userManager.GetUserId(User)}'."); - } - - _logger.LogInformation("User with ID '{UserId}' has disabled 2fa.", _userManager.GetUserId(User)); - StatusMessage = "2fa has been disabled. You can reenable 2fa when you setup an authenticator app"; - return RedirectToPage("./TwoFactorAuthentication"); + throw new InvalidOperationException($"Unexpected error occurred disabling 2FA for user with ID '{_userManager.GetUserId(User)}'."); } + + _logger.LogInformation("User with ID '{UserId}' has disabled 2fa.", _userManager.GetUserId(User)); + StatusMessage = "2fa has been disabled. You can reenable 2fa when you setup an authenticator app"; + return RedirectToPage("./TwoFactorAuthentication"); } } \ No newline at end of file diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/Manage/DownloadPersonalData.cshtml.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/Manage/DownloadPersonalData.cshtml.cs index 9e685e3f7..82e77ce55 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/Manage/DownloadPersonalData.cshtml.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/Manage/DownloadPersonalData.cshtml.cs @@ -10,48 +10,47 @@ using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.Extensions.Logging; -namespace ClassifiedAds.IdentityServer.Areas.Identity.Pages.Account.Manage +namespace ClassifiedAds.IdentityServer.Areas.Identity.Pages.Account.Manage; + +public class DownloadPersonalDataModel : PageModel { - public class DownloadPersonalDataModel : PageModel + private readonly UserManager _userManager; + private readonly ILogger _logger; + + public DownloadPersonalDataModel( + UserManager userManager, + ILogger logger) { - private readonly UserManager _userManager; - private readonly ILogger _logger; + _userManager = userManager; + _logger = logger; + } - public DownloadPersonalDataModel( - UserManager userManager, - ILogger logger) + public async Task OnPostAsync() + { + var user = await _userManager.GetUserAsync(User); + if (user == null) { - _userManager = userManager; - _logger = logger; + return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'."); } - public async Task OnPostAsync() + _logger.LogInformation("User with ID '{UserId}' asked for their personal data.", _userManager.GetUserId(User)); + + // Only include personal data for download + var personalData = new Dictionary(); + var personalDataProps = typeof(User).GetProperties().Where( + prop => Attribute.IsDefined(prop, typeof(PersonalDataAttribute))); + foreach (var p in personalDataProps) { - var user = await _userManager.GetUserAsync(User); - if (user == null) - { - return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'."); - } - - _logger.LogInformation("User with ID '{UserId}' asked for their personal data.", _userManager.GetUserId(User)); - - // Only include personal data for download - var personalData = new Dictionary(); - var personalDataProps = typeof(User).GetProperties().Where( - prop => Attribute.IsDefined(prop, typeof(PersonalDataAttribute))); - foreach (var p in personalDataProps) - { - personalData.Add(p.Name, p.GetValue(user)?.ToString() ?? "null"); - } - - var logins = await _userManager.GetLoginsAsync(user); - foreach (var l in logins) - { - personalData.Add($"{l.LoginProvider} external login provider key", l.ProviderKey); - } - - Response.Headers.Add("Content-Disposition", "attachment; filename=PersonalData.json"); - return new FileContentResult(JsonSerializer.SerializeToUtf8Bytes(personalData), "application/json"); + personalData.Add(p.Name, p.GetValue(user)?.ToString() ?? "null"); } + + var logins = await _userManager.GetLoginsAsync(user); + foreach (var l in logins) + { + personalData.Add($"{l.LoginProvider} external login provider key", l.ProviderKey); + } + + Response.Headers.Add("Content-Disposition", "attachment; filename=PersonalData.json"); + return new FileContentResult(JsonSerializer.SerializeToUtf8Bytes(personalData), "application/json"); } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/Manage/Email.cshtml.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/Manage/Email.cshtml.cs index 369e6ed03..3f4a59cea 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/Manage/Email.cshtml.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/Manage/Email.cshtml.cs @@ -12,136 +12,135 @@ using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.AspNetCore.WebUtilities; -namespace ClassifiedAds.IdentityServer.Areas.Identity.Pages.Account.Manage +namespace ClassifiedAds.IdentityServer.Areas.Identity.Pages.Account.Manage; + +public partial class EmailModel : PageModel { - public partial class EmailModel : PageModel + private readonly UserManager _userManager; + private readonly SignInManager _signInManager; + private readonly IEmailSender _emailSender; + + public EmailModel( + UserManager userManager, + SignInManager signInManager, + IEmailSender emailSender) { - private readonly UserManager _userManager; - private readonly SignInManager _signInManager; - private readonly IEmailSender _emailSender; - - public EmailModel( - UserManager userManager, - SignInManager signInManager, - IEmailSender emailSender) - { - _userManager = userManager; - _signInManager = signInManager; - _emailSender = emailSender; - } + _userManager = userManager; + _signInManager = signInManager; + _emailSender = emailSender; + } - public string Username { get; set; } + public string Username { get; set; } - public string Email { get; set; } + public string Email { get; set; } - public bool IsEmailConfirmed { get; set; } + public bool IsEmailConfirmed { get; set; } - [TempData] - public string StatusMessage { get; set; } + [TempData] + public string StatusMessage { get; set; } - [BindProperty] - public InputModel Input { get; set; } + [BindProperty] + public InputModel Input { get; set; } - public class InputModel - { - [Required] - [EmailAddress] - [Display(Name = "New email")] - public string NewEmail { get; set; } - } + public class InputModel + { + [Required] + [EmailAddress] + [Display(Name = "New email")] + public string NewEmail { get; set; } + } + + private async Task LoadAsync(User user) + { + var email = await _userManager.GetEmailAsync(user); + Email = email; - private async Task LoadAsync(User user) + Input = new InputModel { - var email = await _userManager.GetEmailAsync(user); - Email = email; + NewEmail = email, + }; - Input = new InputModel - { - NewEmail = email, - }; + IsEmailConfirmed = await _userManager.IsEmailConfirmedAsync(user); + } - IsEmailConfirmed = await _userManager.IsEmailConfirmedAsync(user); + public async Task OnGetAsync() + { + var user = await _userManager.GetUserAsync(User); + if (user == null) + { + return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'."); } - public async Task OnGetAsync() - { - var user = await _userManager.GetUserAsync(User); - if (user == null) - { - return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'."); - } + await LoadAsync(user); + return Page(); + } - await LoadAsync(user); - return Page(); + public async Task OnPostChangeEmailAsync() + { + var user = await _userManager.GetUserAsync(User); + if (user == null) + { + return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'."); } - public async Task OnPostChangeEmailAsync() + if (!ModelState.IsValid) { - var user = await _userManager.GetUserAsync(User); - if (user == null) - { - return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'."); - } - - if (!ModelState.IsValid) - { - await LoadAsync(user); - return Page(); - } - - var email = await _userManager.GetEmailAsync(user); - if (Input.NewEmail != email) - { - var userId = await _userManager.GetUserIdAsync(user); - var code = await _userManager.GenerateChangeEmailTokenAsync(user, Input.NewEmail); - var callbackUrl = Url.Page( - "/Account/ConfirmEmailChange", - pageHandler: null, - values: new { userId = userId, email = Input.NewEmail, code = code }, - protocol: Request.Scheme); - await _emailSender.SendEmailAsync( - Input.NewEmail, - "Confirm your email", - $"Please confirm your account by clicking here."); - - StatusMessage = "Confirmation link to change email sent. Please check your email."; - return RedirectToPage(); - } - - StatusMessage = "Your email is unchanged."; - return RedirectToPage(); + await LoadAsync(user); + return Page(); } - public async Task OnPostSendVerificationEmailAsync() + var email = await _userManager.GetEmailAsync(user); + if (Input.NewEmail != email) { - var user = await _userManager.GetUserAsync(User); - if (user == null) - { - return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'."); - } - - if (!ModelState.IsValid) - { - await LoadAsync(user); - return Page(); - } - var userId = await _userManager.GetUserIdAsync(user); - var email = await _userManager.GetEmailAsync(user); - var code = await _userManager.GenerateEmailConfirmationTokenAsync(user); - code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code)); + var code = await _userManager.GenerateChangeEmailTokenAsync(user, Input.NewEmail); var callbackUrl = Url.Page( - "/Account/ConfirmEmail", + "/Account/ConfirmEmailChange", pageHandler: null, - values: new { area = "Identity", userId = userId, code = code }, + values: new { userId = userId, email = Input.NewEmail, code = code }, protocol: Request.Scheme); await _emailSender.SendEmailAsync( - email, + Input.NewEmail, "Confirm your email", $"Please confirm your account by clicking here."); - StatusMessage = "Verification email sent. Please check your email."; + StatusMessage = "Confirmation link to change email sent. Please check your email."; return RedirectToPage(); } + + StatusMessage = "Your email is unchanged."; + return RedirectToPage(); + } + + public async Task OnPostSendVerificationEmailAsync() + { + var user = await _userManager.GetUserAsync(User); + if (user == null) + { + return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'."); + } + + if (!ModelState.IsValid) + { + await LoadAsync(user); + return Page(); + } + + var userId = await _userManager.GetUserIdAsync(user); + var email = await _userManager.GetEmailAsync(user); + var code = await _userManager.GenerateEmailConfirmationTokenAsync(user); + code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code)); + var callbackUrl = Url.Page( + "/Account/ConfirmEmail", + pageHandler: null, + values: new { area = "Identity", userId = userId, code = code }, + protocol: Request.Scheme); + await _emailSender.SendEmailAsync( + email, + "Confirm your email", + $"Please confirm your account by clicking here."); + + StatusMessage = "Verification email sent. Please check your email."; + return RedirectToPage(); } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/Manage/EnableAuthenticator.cshtml.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/Manage/EnableAuthenticator.cshtml.cs index 76bf5c917..01cc2028a 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/Manage/EnableAuthenticator.cshtml.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/Manage/EnableAuthenticator.cshtml.cs @@ -12,146 +12,145 @@ using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.Extensions.Logging; -namespace ClassifiedAds.IdentityServer.Areas.Identity.Pages.Account.Manage +namespace ClassifiedAds.IdentityServer.Areas.Identity.Pages.Account.Manage; + +public class EnableAuthenticatorModel : PageModel { - public class EnableAuthenticatorModel : PageModel - { - private readonly UserManager _userManager; - private readonly ILogger _logger; - private readonly UrlEncoder _urlEncoder; + private readonly UserManager _userManager; + private readonly ILogger _logger; + private readonly UrlEncoder _urlEncoder; - private const string AuthenticatorUriFormat = "otpauth://totp/{0}:{1}?secret={2}&issuer={0}&digits=6"; + private const string AuthenticatorUriFormat = "otpauth://totp/{0}:{1}?secret={2}&issuer={0}&digits=6"; - public EnableAuthenticatorModel( - UserManager userManager, - ILogger logger, - UrlEncoder urlEncoder) - { - _userManager = userManager; - _logger = logger; - _urlEncoder = urlEncoder; - } + public EnableAuthenticatorModel( + UserManager userManager, + ILogger logger, + UrlEncoder urlEncoder) + { + _userManager = userManager; + _logger = logger; + _urlEncoder = urlEncoder; + } - public string SharedKey { get; set; } + public string SharedKey { get; set; } - public string AuthenticatorUri { get; set; } + public string AuthenticatorUri { get; set; } - [TempData] - public string[] RecoveryCodes { get; set; } + [TempData] + public string[] RecoveryCodes { get; set; } - [TempData] - public string StatusMessage { get; set; } + [TempData] + public string StatusMessage { get; set; } - [BindProperty] - public InputModel Input { get; set; } + [BindProperty] + public InputModel Input { get; set; } - public class InputModel + public class InputModel + { + [Required] + [StringLength(7, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 6)] + [DataType(DataType.Text)] + [Display(Name = "Verification Code")] + public string Code { get; set; } + } + + public async Task OnGetAsync() + { + var user = await _userManager.GetUserAsync(User); + if (user == null) { - [Required] - [StringLength(7, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 6)] - [DataType(DataType.Text)] - [Display(Name = "Verification Code")] - public string Code { get; set; } + return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'."); } - public async Task OnGetAsync() + await LoadSharedKeyAndQrCodeUriAsync(user); + + return Page(); + } + + public async Task OnPostAsync() + { + var user = await _userManager.GetUserAsync(User); + if (user == null) { - var user = await _userManager.GetUserAsync(User); - if (user == null) - { - return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'."); - } + return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'."); + } + if (!ModelState.IsValid) + { await LoadSharedKeyAndQrCodeUriAsync(user); - return Page(); } - public async Task OnPostAsync() + // Strip spaces and hypens + var verificationCode = Input.Code.Replace(" ", string.Empty).Replace("-", string.Empty); + + var is2faTokenValid = await _userManager.VerifyTwoFactorTokenAsync( + user, _userManager.Options.Tokens.AuthenticatorTokenProvider, verificationCode); + + if (!is2faTokenValid) { - var user = await _userManager.GetUserAsync(User); - if (user == null) - { - return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'."); - } - - if (!ModelState.IsValid) - { - await LoadSharedKeyAndQrCodeUriAsync(user); - return Page(); - } - - // Strip spaces and hypens - var verificationCode = Input.Code.Replace(" ", string.Empty).Replace("-", string.Empty); - - var is2faTokenValid = await _userManager.VerifyTwoFactorTokenAsync( - user, _userManager.Options.Tokens.AuthenticatorTokenProvider, verificationCode); - - if (!is2faTokenValid) - { - ModelState.AddModelError("Input.Code", "Verification code is invalid."); - await LoadSharedKeyAndQrCodeUriAsync(user); - return Page(); - } - - await _userManager.SetTwoFactorEnabledAsync(user, true); - var userId = await _userManager.GetUserIdAsync(user); - _logger.LogInformation("User with ID '{UserId}' has enabled 2FA with an authenticator app.", userId); - - StatusMessage = "Your authenticator app has been verified."; - - if (await _userManager.CountRecoveryCodesAsync(user) == 0) - { - var recoveryCodes = await _userManager.GenerateNewTwoFactorRecoveryCodesAsync(user, 10); - RecoveryCodes = recoveryCodes.ToArray(); - return RedirectToPage("./ShowRecoveryCodes"); - } - else - { - return RedirectToPage("./TwoFactorAuthentication"); - } + ModelState.AddModelError("Input.Code", "Verification code is invalid."); + await LoadSharedKeyAndQrCodeUriAsync(user); + return Page(); } - private async Task LoadSharedKeyAndQrCodeUriAsync(User user) + await _userManager.SetTwoFactorEnabledAsync(user, true); + var userId = await _userManager.GetUserIdAsync(user); + _logger.LogInformation("User with ID '{UserId}' has enabled 2FA with an authenticator app.", userId); + + StatusMessage = "Your authenticator app has been verified."; + + if (await _userManager.CountRecoveryCodesAsync(user) == 0) { - // Load the authenticator key & QR code URI to display on the form - var unformattedKey = await _userManager.GetAuthenticatorKeyAsync(user); - if (string.IsNullOrEmpty(unformattedKey)) - { - await _userManager.ResetAuthenticatorKeyAsync(user); - unformattedKey = await _userManager.GetAuthenticatorKeyAsync(user); - } - - SharedKey = FormatKey(unformattedKey); - - var email = await _userManager.GetEmailAsync(user); - AuthenticatorUri = GenerateQrCodeUri(email, unformattedKey); + var recoveryCodes = await _userManager.GenerateNewTwoFactorRecoveryCodesAsync(user, 10); + RecoveryCodes = recoveryCodes.ToArray(); + return RedirectToPage("./ShowRecoveryCodes"); } + else + { + return RedirectToPage("./TwoFactorAuthentication"); + } + } - private string FormatKey(string unformattedKey) + private async Task LoadSharedKeyAndQrCodeUriAsync(User user) + { + // Load the authenticator key & QR code URI to display on the form + var unformattedKey = await _userManager.GetAuthenticatorKeyAsync(user); + if (string.IsNullOrEmpty(unformattedKey)) { - var result = new StringBuilder(); - int currentPosition = 0; - while (currentPosition + 4 < unformattedKey.Length) - { - result.Append(unformattedKey.Substring(currentPosition, 4)).Append(" "); - currentPosition += 4; - } - if (currentPosition < unformattedKey.Length) - { - result.Append(unformattedKey.Substring(currentPosition)); - } - - return result.ToString().ToLowerInvariant(); + await _userManager.ResetAuthenticatorKeyAsync(user); + unformattedKey = await _userManager.GetAuthenticatorKeyAsync(user); } - private string GenerateQrCodeUri(string email, string unformattedKey) + SharedKey = FormatKey(unformattedKey); + + var email = await _userManager.GetEmailAsync(user); + AuthenticatorUri = GenerateQrCodeUri(email, unformattedKey); + } + + private string FormatKey(string unformattedKey) + { + var result = new StringBuilder(); + int currentPosition = 0; + while (currentPosition + 4 < unformattedKey.Length) + { + result.Append(unformattedKey.Substring(currentPosition, 4)).Append(" "); + currentPosition += 4; + } + if (currentPosition < unformattedKey.Length) { - return string.Format( - AuthenticatorUriFormat, - _urlEncoder.Encode("ClassifiedAds.IdentityServer"), - _urlEncoder.Encode(email), - unformattedKey); + result.Append(unformattedKey.Substring(currentPosition)); } + + return result.ToString().ToLowerInvariant(); + } + + private string GenerateQrCodeUri(string email, string unformattedKey) + { + return string.Format( + AuthenticatorUriFormat, + _urlEncoder.Encode("ClassifiedAds.IdentityServer"), + _urlEncoder.Encode(email), + unformattedKey); } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/Manage/ExternalLogins.cshtml.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/Manage/ExternalLogins.cshtml.cs index d18a5d2b2..ff3931ccd 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/Manage/ExternalLogins.cshtml.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/Manage/ExternalLogins.cshtml.cs @@ -8,102 +8,101 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; -namespace ClassifiedAds.IdentityServer.Areas.Identity.Pages.Account.Manage +namespace ClassifiedAds.IdentityServer.Areas.Identity.Pages.Account.Manage; + +public class ExternalLoginsModel : PageModel { - public class ExternalLoginsModel : PageModel + private readonly UserManager _userManager; + private readonly SignInManager _signInManager; + + public ExternalLoginsModel( + UserManager userManager, + SignInManager signInManager) { - private readonly UserManager _userManager; - private readonly SignInManager _signInManager; + _userManager = userManager; + _signInManager = signInManager; + } - public ExternalLoginsModel( - UserManager userManager, - SignInManager signInManager) - { - _userManager = userManager; - _signInManager = signInManager; - } + public IList CurrentLogins { get; set; } - public IList CurrentLogins { get; set; } + public IList OtherLogins { get; set; } - public IList OtherLogins { get; set; } + public bool ShowRemoveButton { get; set; } - public bool ShowRemoveButton { get; set; } + [TempData] + public string StatusMessage { get; set; } - [TempData] - public string StatusMessage { get; set; } + public async Task OnGetAsync() + { + var user = await _userManager.GetUserAsync(User); + if (user == null) + { + return NotFound($"Unable to load user with ID '{user.Id}'."); + } - public async Task OnGetAsync() + CurrentLogins = await _userManager.GetLoginsAsync(user); + OtherLogins = (await _signInManager.GetExternalAuthenticationSchemesAsync()) + .Where(auth => CurrentLogins.All(ul => auth.Name != ul.LoginProvider)) + .ToList(); + ShowRemoveButton = user.PasswordHash != null || CurrentLogins.Count > 1; + return Page(); + } + + public async Task OnPostRemoveLoginAsync(string loginProvider, string providerKey) + { + var user = await _userManager.GetUserAsync(User); + if (user == null) { - var user = await _userManager.GetUserAsync(User); - if (user == null) - { - return NotFound($"Unable to load user with ID '{user.Id}'."); - } - - CurrentLogins = await _userManager.GetLoginsAsync(user); - OtherLogins = (await _signInManager.GetExternalAuthenticationSchemesAsync()) - .Where(auth => CurrentLogins.All(ul => auth.Name != ul.LoginProvider)) - .ToList(); - ShowRemoveButton = user.PasswordHash != null || CurrentLogins.Count > 1; - return Page(); + return NotFound($"Unable to load user with ID '{user.Id}'."); } - public async Task OnPostRemoveLoginAsync(string loginProvider, string providerKey) + var result = await _userManager.RemoveLoginAsync(user, loginProvider, providerKey); + if (!result.Succeeded) { - var user = await _userManager.GetUserAsync(User); - if (user == null) - { - return NotFound($"Unable to load user with ID '{user.Id}'."); - } - - var result = await _userManager.RemoveLoginAsync(user, loginProvider, providerKey); - if (!result.Succeeded) - { - StatusMessage = "The external login was not removed."; - return RedirectToPage(); - } - - await _signInManager.RefreshSignInAsync(user); - StatusMessage = "The external login was removed."; + StatusMessage = "The external login was not removed."; return RedirectToPage(); } - public async Task OnPostLinkLoginAsync(string provider) + await _signInManager.RefreshSignInAsync(user); + StatusMessage = "The external login was removed."; + return RedirectToPage(); + } + + public async Task OnPostLinkLoginAsync(string provider) + { + // Clear the existing external cookie to ensure a clean login process + await HttpContext.SignOutAsync(IdentityConstants.ExternalScheme); + // Request a redirect to the external login provider to link a login for the current user + var redirectUrl = Url.Page("./ExternalLogins", pageHandler: "LinkLoginCallback"); + var properties = _signInManager.ConfigureExternalAuthenticationProperties(provider, redirectUrl, _userManager.GetUserId(User)); + return new ChallengeResult(provider, properties); + } + + public async Task OnGetLinkLoginCallbackAsync() + { + var user = await _userManager.GetUserAsync(User); + if (user == null) { - // Clear the existing external cookie to ensure a clean login process - await HttpContext.SignOutAsync(IdentityConstants.ExternalScheme); - // Request a redirect to the external login provider to link a login for the current user - var redirectUrl = Url.Page("./ExternalLogins", pageHandler: "LinkLoginCallback"); - var properties = _signInManager.ConfigureExternalAuthenticationProperties(provider, redirectUrl, _userManager.GetUserId(User)); - return new ChallengeResult(provider, properties); + return NotFound($"Unable to load user with ID '{user.Id}'."); } - public async Task OnGetLinkLoginCallbackAsync() + var info = await _signInManager.GetExternalLoginInfoAsync(user.Id.ToString()); + if (info == null) { - var user = await _userManager.GetUserAsync(User); - if (user == null) - { - return NotFound($"Unable to load user with ID '{user.Id}'."); - } - - var info = await _signInManager.GetExternalLoginInfoAsync(user.Id.ToString()); - if (info == null) - { - throw new InvalidOperationException($"Unexpected error occurred loading external login info for user with ID '{user.Id}'."); - } - - var result = await _userManager.AddLoginAsync(user, info); - if (!result.Succeeded) - { - StatusMessage = "The external login was not added. External logins can only be associated with one account."; - return RedirectToPage(); - } - - // Clear the existing external cookie to ensure a clean login process - await HttpContext.SignOutAsync(IdentityConstants.ExternalScheme); - - StatusMessage = "The external login was added."; + throw new InvalidOperationException($"Unexpected error occurred loading external login info for user with ID '{user.Id}'."); + } + + var result = await _userManager.AddLoginAsync(user, info); + if (!result.Succeeded) + { + StatusMessage = "The external login was not added. External logins can only be associated with one account."; return RedirectToPage(); } + + // Clear the existing external cookie to ensure a clean login process + await HttpContext.SignOutAsync(IdentityConstants.ExternalScheme); + + StatusMessage = "The external login was added."; + return RedirectToPage(); } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/Manage/GenerateRecoveryCodes.cshtml.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/Manage/GenerateRecoveryCodes.cshtml.cs index 5c175ce7e..fc74e0b73 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/Manage/GenerateRecoveryCodes.cshtml.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/Manage/GenerateRecoveryCodes.cshtml.cs @@ -8,66 +8,65 @@ using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.Extensions.Logging; -namespace ClassifiedAds.IdentityServer.Areas.Identity.Pages.Account.Manage +namespace ClassifiedAds.IdentityServer.Areas.Identity.Pages.Account.Manage; + +public class GenerateRecoveryCodesModel : PageModel { - public class GenerateRecoveryCodesModel : PageModel + private readonly UserManager _userManager; + private readonly ILogger _logger; + + public GenerateRecoveryCodesModel( + UserManager userManager, + ILogger logger) { - private readonly UserManager _userManager; - private readonly ILogger _logger; + _userManager = userManager; + _logger = logger; + } - public GenerateRecoveryCodesModel( - UserManager userManager, - ILogger logger) - { - _userManager = userManager; - _logger = logger; - } + [TempData] + public string[] RecoveryCodes { get; set; } - [TempData] - public string[] RecoveryCodes { get; set; } + [TempData] + public string StatusMessage { get; set; } - [TempData] - public string StatusMessage { get; set; } + public async Task OnGetAsync() + { + var user = await _userManager.GetUserAsync(User); + if (user == null) + { + return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'."); + } - public async Task OnGetAsync() + var isTwoFactorEnabled = await _userManager.GetTwoFactorEnabledAsync(user); + if (!isTwoFactorEnabled) { - var user = await _userManager.GetUserAsync(User); - if (user == null) - { - return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'."); - } + var userId = await _userManager.GetUserIdAsync(user); + throw new InvalidOperationException($"Cannot generate recovery codes for user with ID '{userId}' because they do not have 2FA enabled."); + } - var isTwoFactorEnabled = await _userManager.GetTwoFactorEnabledAsync(user); - if (!isTwoFactorEnabled) - { - var userId = await _userManager.GetUserIdAsync(user); - throw new InvalidOperationException($"Cannot generate recovery codes for user with ID '{userId}' because they do not have 2FA enabled."); - } + return Page(); + } - return Page(); + public async Task OnPostAsync() + { + var user = await _userManager.GetUserAsync(User); + if (user == null) + { + return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'."); } - public async Task OnPostAsync() + var isTwoFactorEnabled = await _userManager.GetTwoFactorEnabledAsync(user); + var userId = await _userManager.GetUserIdAsync(user); + if (!isTwoFactorEnabled) { - var user = await _userManager.GetUserAsync(User); - if (user == null) - { - return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'."); - } - - var isTwoFactorEnabled = await _userManager.GetTwoFactorEnabledAsync(user); - var userId = await _userManager.GetUserIdAsync(user); - if (!isTwoFactorEnabled) - { - throw new InvalidOperationException($"Cannot generate recovery codes for user with ID '{userId}' as they do not have 2FA enabled."); - } + throw new InvalidOperationException($"Cannot generate recovery codes for user with ID '{userId}' as they do not have 2FA enabled."); + } - var recoveryCodes = await _userManager.GenerateNewTwoFactorRecoveryCodesAsync(user, 10); - RecoveryCodes = recoveryCodes.ToArray(); + var recoveryCodes = await _userManager.GenerateNewTwoFactorRecoveryCodesAsync(user, 10); + RecoveryCodes = recoveryCodes.ToArray(); - _logger.LogInformation("User with ID '{UserId}' has generated new 2FA recovery codes.", userId); - StatusMessage = "You have generated new recovery codes."; - return RedirectToPage("./ShowRecoveryCodes"); - } + _logger.LogInformation("User with ID '{UserId}' has generated new 2FA recovery codes.", userId); + StatusMessage = "You have generated new recovery codes."; + return RedirectToPage("./ShowRecoveryCodes"); } } \ No newline at end of file diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/Manage/Index.cshtml.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/Manage/Index.cshtml.cs index 62f7c4905..cbb171760 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/Manage/Index.cshtml.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/Manage/Index.cshtml.cs @@ -8,89 +8,88 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; -namespace ClassifiedAds.IdentityServer.Areas.Identity.Pages.Account.Manage +namespace ClassifiedAds.IdentityServer.Areas.Identity.Pages.Account.Manage; + +public partial class IndexModel : PageModel { - public partial class IndexModel : PageModel + private readonly UserManager _userManager; + private readonly SignInManager _signInManager; + + public IndexModel( + UserManager userManager, + SignInManager signInManager) { - private readonly UserManager _userManager; - private readonly SignInManager _signInManager; + _userManager = userManager; + _signInManager = signInManager; + } - public IndexModel( - UserManager userManager, - SignInManager signInManager) - { - _userManager = userManager; - _signInManager = signInManager; - } + public string Username { get; set; } - public string Username { get; set; } + [TempData] + public string StatusMessage { get; set; } - [TempData] - public string StatusMessage { get; set; } + [BindProperty] + public InputModel Input { get; set; } - [BindProperty] - public InputModel Input { get; set; } + public class InputModel + { + [Phone] + [Display(Name = "Phone number")] + public string PhoneNumber { get; set; } + } - public class InputModel + private async Task LoadAsync(User user) + { + var userName = await _userManager.GetUserNameAsync(user); + var phoneNumber = await _userManager.GetPhoneNumberAsync(user); + + Username = userName; + + Input = new InputModel { - [Phone] - [Display(Name = "Phone number")] - public string PhoneNumber { get; set; } - } + PhoneNumber = phoneNumber + }; + } - private async Task LoadAsync(User user) + public async Task OnGetAsync() + { + var user = await _userManager.GetUserAsync(User); + if (user == null) { - var userName = await _userManager.GetUserNameAsync(user); - var phoneNumber = await _userManager.GetPhoneNumberAsync(user); + return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'."); + } - Username = userName; + await LoadAsync(user); + return Page(); + } - Input = new InputModel - { - PhoneNumber = phoneNumber - }; + public async Task OnPostAsync() + { + var user = await _userManager.GetUserAsync(User); + if (user == null) + { + return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'."); } - public async Task OnGetAsync() + if (!ModelState.IsValid) { - var user = await _userManager.GetUserAsync(User); - if (user == null) - { - return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'."); - } - await LoadAsync(user); return Page(); } - public async Task OnPostAsync() + var phoneNumber = await _userManager.GetPhoneNumberAsync(user); + if (Input.PhoneNumber != phoneNumber) { - var user = await _userManager.GetUserAsync(User); - if (user == null) - { - return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'."); - } - - if (!ModelState.IsValid) + var setPhoneResult = await _userManager.SetPhoneNumberAsync(user, Input.PhoneNumber); + if (!setPhoneResult.Succeeded) { - await LoadAsync(user); - return Page(); + StatusMessage = "Unexpected error when trying to set phone number."; + return RedirectToPage(); } - - var phoneNumber = await _userManager.GetPhoneNumberAsync(user); - if (Input.PhoneNumber != phoneNumber) - { - var setPhoneResult = await _userManager.SetPhoneNumberAsync(user, Input.PhoneNumber); - if (!setPhoneResult.Succeeded) - { - StatusMessage = "Unexpected error when trying to set phone number."; - return RedirectToPage(); - } - } - - await _signInManager.RefreshSignInAsync(user); - StatusMessage = "Your profile has been updated"; - return RedirectToPage(); } + + await _signInManager.RefreshSignInAsync(user); + StatusMessage = "Your profile has been updated"; + return RedirectToPage(); } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/Manage/ManageNavPages.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/Manage/ManageNavPages.cs index c033438fe..a14fb3912 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/Manage/ManageNavPages.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/Manage/ManageNavPages.cs @@ -4,47 +4,46 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc.Rendering; -namespace ClassifiedAds.IdentityServer.Areas.Identity.Pages.Account.Manage +namespace ClassifiedAds.IdentityServer.Areas.Identity.Pages.Account.Manage; + +public static class ManageNavPages { - public static class ManageNavPages - { - public static string Index => "Index"; + public static string Index => "Index"; - public static string Email => "Email"; + public static string Email => "Email"; - public static string ChangePassword => "ChangePassword"; + public static string ChangePassword => "ChangePassword"; - public static string DownloadPersonalData => "DownloadPersonalData"; + public static string DownloadPersonalData => "DownloadPersonalData"; - public static string DeletePersonalData => "DeletePersonalData"; + public static string DeletePersonalData => "DeletePersonalData"; - public static string ExternalLogins => "ExternalLogins"; + public static string ExternalLogins => "ExternalLogins"; - public static string PersonalData => "PersonalData"; + public static string PersonalData => "PersonalData"; - public static string TwoFactorAuthentication => "TwoFactorAuthentication"; + public static string TwoFactorAuthentication => "TwoFactorAuthentication"; - public static string IndexNavClass(ViewContext viewContext) => PageNavClass(viewContext, Index); + public static string IndexNavClass(ViewContext viewContext) => PageNavClass(viewContext, Index); - public static string EmailNavClass(ViewContext viewContext) => PageNavClass(viewContext, Email); + public static string EmailNavClass(ViewContext viewContext) => PageNavClass(viewContext, Email); - public static string ChangePasswordNavClass(ViewContext viewContext) => PageNavClass(viewContext, ChangePassword); + public static string ChangePasswordNavClass(ViewContext viewContext) => PageNavClass(viewContext, ChangePassword); - public static string DownloadPersonalDataNavClass(ViewContext viewContext) => PageNavClass(viewContext, DownloadPersonalData); + public static string DownloadPersonalDataNavClass(ViewContext viewContext) => PageNavClass(viewContext, DownloadPersonalData); - public static string DeletePersonalDataNavClass(ViewContext viewContext) => PageNavClass(viewContext, DeletePersonalData); + public static string DeletePersonalDataNavClass(ViewContext viewContext) => PageNavClass(viewContext, DeletePersonalData); - public static string ExternalLoginsNavClass(ViewContext viewContext) => PageNavClass(viewContext, ExternalLogins); + public static string ExternalLoginsNavClass(ViewContext viewContext) => PageNavClass(viewContext, ExternalLogins); - public static string PersonalDataNavClass(ViewContext viewContext) => PageNavClass(viewContext, PersonalData); + public static string PersonalDataNavClass(ViewContext viewContext) => PageNavClass(viewContext, PersonalData); - public static string TwoFactorAuthenticationNavClass(ViewContext viewContext) => PageNavClass(viewContext, TwoFactorAuthentication); + public static string TwoFactorAuthenticationNavClass(ViewContext viewContext) => PageNavClass(viewContext, TwoFactorAuthentication); - private static string PageNavClass(ViewContext viewContext, string page) - { - var activePage = viewContext.ViewData["ActivePage"] as string - ?? System.IO.Path.GetFileNameWithoutExtension(viewContext.ActionDescriptor.DisplayName); - return string.Equals(activePage, page, StringComparison.OrdinalIgnoreCase) ? "active" : null; - } + private static string PageNavClass(ViewContext viewContext, string page) + { + var activePage = viewContext.ViewData["ActivePage"] as string + ?? System.IO.Path.GetFileNameWithoutExtension(viewContext.ActionDescriptor.DisplayName); + return string.Equals(activePage, page, StringComparison.OrdinalIgnoreCase) ? "active" : null; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/Manage/PersonalData.cshtml.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/Manage/PersonalData.cshtml.cs index fe2a3ebfa..cdc7f5a55 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/Manage/PersonalData.cshtml.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/Manage/PersonalData.cshtml.cs @@ -5,30 +5,29 @@ using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.Extensions.Logging; -namespace ClassifiedAds.IdentityServer.Areas.Identity.Pages.Account.Manage +namespace ClassifiedAds.IdentityServer.Areas.Identity.Pages.Account.Manage; + +public class PersonalDataModel : PageModel { - public class PersonalDataModel : PageModel + private readonly UserManager _userManager; + private readonly ILogger _logger; + + public PersonalDataModel( + UserManager userManager, + ILogger logger) { - private readonly UserManager _userManager; - private readonly ILogger _logger; + _userManager = userManager; + _logger = logger; + } - public PersonalDataModel( - UserManager userManager, - ILogger logger) + public async Task OnGet() + { + var user = await _userManager.GetUserAsync(User); + if (user == null) { - _userManager = userManager; - _logger = logger; + return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'."); } - public async Task OnGet() - { - var user = await _userManager.GetUserAsync(User); - if (user == null) - { - return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'."); - } - - return Page(); - } + return Page(); } } \ No newline at end of file diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/Manage/ResetAuthenticator.cshtml.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/Manage/ResetAuthenticator.cshtml.cs index fb815156a..bdbe5e75f 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/Manage/ResetAuthenticator.cshtml.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/Manage/ResetAuthenticator.cshtml.cs @@ -8,54 +8,53 @@ using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.Extensions.Logging; -namespace ClassifiedAds.IdentityServer.Areas.Identity.Pages.Account.Manage +namespace ClassifiedAds.IdentityServer.Areas.Identity.Pages.Account.Manage; + +public class ResetAuthenticatorModel : PageModel { - public class ResetAuthenticatorModel : PageModel + UserManager _userManager; + private readonly SignInManager _signInManager; + ILogger _logger; + + public ResetAuthenticatorModel( + UserManager userManager, + SignInManager signInManager, + ILogger logger) { - UserManager _userManager; - private readonly SignInManager _signInManager; - ILogger _logger; - - public ResetAuthenticatorModel( - UserManager userManager, - SignInManager signInManager, - ILogger logger) - { - _userManager = userManager; - _signInManager = signInManager; - _logger = logger; - } + _userManager = userManager; + _signInManager = signInManager; + _logger = logger; + } - [TempData] - public string StatusMessage { get; set; } + [TempData] + public string StatusMessage { get; set; } - public async Task OnGet() + public async Task OnGet() + { + var user = await _userManager.GetUserAsync(User); + if (user == null) { - var user = await _userManager.GetUserAsync(User); - if (user == null) - { - return NotFound($"Unable to load user with ID '{user.Id}'."); - } - - return Page(); + return NotFound($"Unable to load user with ID '{user.Id}'."); } - public async Task OnPostAsync() + return Page(); + } + + public async Task OnPostAsync() + { + var user = await _userManager.GetUserAsync(User); + if (user == null) { - var user = await _userManager.GetUserAsync(User); - if (user == null) - { - return NotFound($"Unable to load user with ID 'user.Id'."); - } + return NotFound($"Unable to load user with ID 'user.Id'."); + } - await _userManager.SetTwoFactorEnabledAsync(user, false); - await _userManager.ResetAuthenticatorKeyAsync(user); - _logger.LogInformation("User with ID '{UserId}' has reset their authentication app key.", user.Id); + await _userManager.SetTwoFactorEnabledAsync(user, false); + await _userManager.ResetAuthenticatorKeyAsync(user); + _logger.LogInformation("User with ID '{UserId}' has reset their authentication app key.", user.Id); - await _signInManager.RefreshSignInAsync(user); - StatusMessage = "Your authenticator app key has been reset, you will need to configure your authenticator app using the new key."; + await _signInManager.RefreshSignInAsync(user); + StatusMessage = "Your authenticator app key has been reset, you will need to configure your authenticator app using the new key."; - return RedirectToPage("./EnableAuthenticator"); - } + return RedirectToPage("./EnableAuthenticator"); } } \ No newline at end of file diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/Manage/SetPassword.cshtml.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/Manage/SetPassword.cshtml.cs index f3a501633..b2cbcc9a7 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/Manage/SetPassword.cshtml.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/Manage/SetPassword.cshtml.cs @@ -8,86 +8,85 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; -namespace ClassifiedAds.IdentityServer.Areas.Identity.Pages.Account.Manage +namespace ClassifiedAds.IdentityServer.Areas.Identity.Pages.Account.Manage; + +public class SetPasswordModel : PageModel { - public class SetPasswordModel : PageModel + private readonly UserManager _userManager; + private readonly SignInManager _signInManager; + + public SetPasswordModel( + UserManager userManager, + SignInManager signInManager) { - private readonly UserManager _userManager; - private readonly SignInManager _signInManager; + _userManager = userManager; + _signInManager = signInManager; + } - public SetPasswordModel( - UserManager userManager, - SignInManager signInManager) - { - _userManager = userManager; - _signInManager = signInManager; - } + [BindProperty] + public InputModel Input { get; set; } + + [TempData] + public string StatusMessage { get; set; } - [BindProperty] - public InputModel Input { get; set; } + public class InputModel + { + [Required] + [StringLength(100, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 6)] + [DataType(DataType.Password)] + [Display(Name = "New password")] + public string NewPassword { get; set; } - [TempData] - public string StatusMessage { get; set; } + [DataType(DataType.Password)] + [Display(Name = "Confirm new password")] + [Compare("NewPassword", ErrorMessage = "The new password and confirmation password do not match.")] + public string ConfirmPassword { get; set; } + } - public class InputModel + public async Task OnGetAsync() + { + var user = await _userManager.GetUserAsync(User); + if (user == null) { - [Required] - [StringLength(100, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 6)] - [DataType(DataType.Password)] - [Display(Name = "New password")] - public string NewPassword { get; set; } - - [DataType(DataType.Password)] - [Display(Name = "Confirm new password")] - [Compare("NewPassword", ErrorMessage = "The new password and confirmation password do not match.")] - public string ConfirmPassword { get; set; } + return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'."); } - public async Task OnGetAsync() - { - var user = await _userManager.GetUserAsync(User); - if (user == null) - { - return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'."); - } + var hasPassword = await _userManager.HasPasswordAsync(user); - var hasPassword = await _userManager.HasPasswordAsync(user); + if (hasPassword) + { + return RedirectToPage("./ChangePassword"); + } - if (hasPassword) - { - return RedirectToPage("./ChangePassword"); - } + return Page(); + } + public async Task OnPostAsync() + { + if (!ModelState.IsValid) + { return Page(); } - public async Task OnPostAsync() + var user = await _userManager.GetUserAsync(User); + if (user == null) { - if (!ModelState.IsValid) - { - return Page(); - } - - var user = await _userManager.GetUserAsync(User); - if (user == null) - { - return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'."); - } + return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'."); + } - var addPasswordResult = await _userManager.AddPasswordAsync(user, Input.NewPassword); - if (!addPasswordResult.Succeeded) + var addPasswordResult = await _userManager.AddPasswordAsync(user, Input.NewPassword); + if (!addPasswordResult.Succeeded) + { + foreach (var error in addPasswordResult.Errors) { - foreach (var error in addPasswordResult.Errors) - { - ModelState.AddModelError(string.Empty, error.Description); - } - return Page(); + ModelState.AddModelError(string.Empty, error.Description); } + return Page(); + } - await _signInManager.RefreshSignInAsync(user); - StatusMessage = "Your password has been set."; + await _signInManager.RefreshSignInAsync(user); + StatusMessage = "Your password has been set."; - return RedirectToPage(); - } + return RedirectToPage(); } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/Manage/ShowRecoveryCodes.cshtml.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/Manage/ShowRecoveryCodes.cshtml.cs index d89aa29e7..16d1d1595 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/Manage/ShowRecoveryCodes.cshtml.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/Manage/ShowRecoveryCodes.cshtml.cs @@ -8,24 +8,23 @@ using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.Extensions.Logging; -namespace ClassifiedAds.IdentityServer.Areas.Identity.Pages.Account.Manage +namespace ClassifiedAds.IdentityServer.Areas.Identity.Pages.Account.Manage; + +public class ShowRecoveryCodesModel : PageModel { - public class ShowRecoveryCodesModel : PageModel - { - [TempData] - public string[] RecoveryCodes { get; set; } + [TempData] + public string[] RecoveryCodes { get; set; } - [TempData] - public string StatusMessage { get; set; } + [TempData] + public string StatusMessage { get; set; } - public IActionResult OnGet() + public IActionResult OnGet() + { + if (RecoveryCodes == null || RecoveryCodes.Length == 0) { - if (RecoveryCodes == null || RecoveryCodes.Length == 0) - { - return RedirectToPage("./TwoFactorAuthentication"); - } - - return Page(); + return RedirectToPage("./TwoFactorAuthentication"); } + + return Page(); } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/Manage/TwoFactorAuthentication.cshtml.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/Manage/TwoFactorAuthentication.cshtml.cs index 9b2ed779f..48d9be7ab 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/Manage/TwoFactorAuthentication.cshtml.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/Manage/TwoFactorAuthentication.cshtml.cs @@ -8,65 +8,64 @@ using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.Extensions.Logging; -namespace ClassifiedAds.IdentityServer.Areas.Identity.Pages.Account.Manage +namespace ClassifiedAds.IdentityServer.Areas.Identity.Pages.Account.Manage; + +public class TwoFactorAuthenticationModel : PageModel { - public class TwoFactorAuthenticationModel : PageModel - { - private const string AuthenicatorUriFormat = "otpauth://totp/{0}:{1}?secret={2}&issuer={0}"; + private const string AuthenicatorUriFormat = "otpauth://totp/{0}:{1}?secret={2}&issuer={0}"; - private readonly UserManager _userManager; - private readonly SignInManager _signInManager; - private readonly ILogger _logger; + private readonly UserManager _userManager; + private readonly SignInManager _signInManager; + private readonly ILogger _logger; - public TwoFactorAuthenticationModel( - UserManager userManager, - SignInManager signInManager, - ILogger logger) - { - _userManager = userManager; - _signInManager = signInManager; - _logger = logger; - } + public TwoFactorAuthenticationModel( + UserManager userManager, + SignInManager signInManager, + ILogger logger) + { + _userManager = userManager; + _signInManager = signInManager; + _logger = logger; + } - public bool HasAuthenticator { get; set; } + public bool HasAuthenticator { get; set; } - public int RecoveryCodesLeft { get; set; } + public int RecoveryCodesLeft { get; set; } - [BindProperty] - public bool Is2faEnabled { get; set; } + [BindProperty] + public bool Is2faEnabled { get; set; } - public bool IsMachineRemembered { get; set; } + public bool IsMachineRemembered { get; set; } - [TempData] - public string StatusMessage { get; set; } + [TempData] + public string StatusMessage { get; set; } - public async Task OnGet() + public async Task OnGet() + { + var user = await _userManager.GetUserAsync(User); + if (user == null) { - var user = await _userManager.GetUserAsync(User); - if (user == null) - { - return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'."); - } + return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'."); + } - HasAuthenticator = await _userManager.GetAuthenticatorKeyAsync(user) != null; - Is2faEnabled = await _userManager.GetTwoFactorEnabledAsync(user); - IsMachineRemembered = await _signInManager.IsTwoFactorClientRememberedAsync(user); - RecoveryCodesLeft = await _userManager.CountRecoveryCodesAsync(user); + HasAuthenticator = await _userManager.GetAuthenticatorKeyAsync(user) != null; + Is2faEnabled = await _userManager.GetTwoFactorEnabledAsync(user); + IsMachineRemembered = await _signInManager.IsTwoFactorClientRememberedAsync(user); + RecoveryCodesLeft = await _userManager.CountRecoveryCodesAsync(user); - return Page(); - } + return Page(); + } - public async Task OnPost() + public async Task OnPost() + { + var user = await _userManager.GetUserAsync(User); + if (user == null) { - var user = await _userManager.GetUserAsync(User); - if (user == null) - { - return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'."); - } - - await _signInManager.ForgetTwoFactorClientAsync(); - StatusMessage = "The current browser has been forgotten. When you login again from this browser you will be prompted for your 2fa code."; - return RedirectToPage(); + return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'."); } + + await _signInManager.ForgetTwoFactorClientAsync(); + StatusMessage = "The current browser has been forgotten. When you login again from this browser you will be prompted for your 2fa code."; + return RedirectToPage(); } } \ No newline at end of file diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/Register.cshtml.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/Register.cshtml.cs index 5e68949da..7dc59404d 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/Register.cshtml.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/Register.cshtml.cs @@ -15,101 +15,100 @@ using Microsoft.AspNetCore.WebUtilities; using Microsoft.Extensions.Logging; -namespace ClassifiedAds.IdentityServer.Areas.Identity.Pages.Account +namespace ClassifiedAds.IdentityServer.Areas.Identity.Pages.Account; + +[AllowAnonymous] +public class RegisterModel : PageModel { - [AllowAnonymous] - public class RegisterModel : PageModel - { - private readonly SignInManager _signInManager; - private readonly UserManager _userManager; - private readonly ILogger _logger; - private readonly IEmailSender _emailSender; + private readonly SignInManager _signInManager; + private readonly UserManager _userManager; + private readonly ILogger _logger; + private readonly IEmailSender _emailSender; - public RegisterModel( - UserManager userManager, - SignInManager signInManager, - ILogger logger, - IEmailSender emailSender) - { - _userManager = userManager; - _signInManager = signInManager; - _logger = logger; - _emailSender = emailSender; - } + public RegisterModel( + UserManager userManager, + SignInManager signInManager, + ILogger logger, + IEmailSender emailSender) + { + _userManager = userManager; + _signInManager = signInManager; + _logger = logger; + _emailSender = emailSender; + } - [BindProperty] - public InputModel Input { get; set; } + [BindProperty] + public InputModel Input { get; set; } - public string ReturnUrl { get; set; } + public string ReturnUrl { get; set; } - public IList ExternalLogins { get; set; } + public IList ExternalLogins { get; set; } - public class InputModel - { - [Required] - [EmailAddress] - [Display(Name = "Email")] - public string Email { get; set; } + public class InputModel + { + [Required] + [EmailAddress] + [Display(Name = "Email")] + public string Email { get; set; } - [Required] - [StringLength(100, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 6)] - [DataType(DataType.Password)] - [Display(Name = "Password")] - public string Password { get; set; } + [Required] + [StringLength(100, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 6)] + [DataType(DataType.Password)] + [Display(Name = "Password")] + public string Password { get; set; } - [DataType(DataType.Password)] - [Display(Name = "Confirm password")] - [Compare("Password", ErrorMessage = "The password and confirmation password do not match.")] - public string ConfirmPassword { get; set; } - } + [DataType(DataType.Password)] + [Display(Name = "Confirm password")] + [Compare("Password", ErrorMessage = "The password and confirmation password do not match.")] + public string ConfirmPassword { get; set; } + } - public async Task OnGetAsync(string returnUrl = null) - { - ReturnUrl = returnUrl; - ExternalLogins = (await _signInManager.GetExternalAuthenticationSchemesAsync()).ToList(); - } + public async Task OnGetAsync(string returnUrl = null) + { + ReturnUrl = returnUrl; + ExternalLogins = (await _signInManager.GetExternalAuthenticationSchemesAsync()).ToList(); + } - public async Task OnPostAsync(string returnUrl = null) + public async Task OnPostAsync(string returnUrl = null) + { + returnUrl ??= Url.Content("~/"); + ExternalLogins = (await _signInManager.GetExternalAuthenticationSchemesAsync()).ToList(); + if (ModelState.IsValid) { - returnUrl ??= Url.Content("~/"); - ExternalLogins = (await _signInManager.GetExternalAuthenticationSchemesAsync()).ToList(); - if (ModelState.IsValid) + var user = new User { UserName = Input.Email, Email = Input.Email }; + var result = await _userManager.CreateAsync(user, Input.Password); + if (result.Succeeded) { - var user = new User { UserName = Input.Email, Email = Input.Email }; - var result = await _userManager.CreateAsync(user, Input.Password); - if (result.Succeeded) - { - _logger.LogInformation("User created a new account with password."); + _logger.LogInformation("User created a new account with password."); - var code = await _userManager.GenerateEmailConfirmationTokenAsync(user); - code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code)); - var callbackUrl = Url.Page( - "/Account/ConfirmEmail", - pageHandler: null, - values: new { area = "Identity", userId = user.Id, code = code, returnUrl = returnUrl }, - protocol: Request.Scheme); + var code = await _userManager.GenerateEmailConfirmationTokenAsync(user); + code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code)); + var callbackUrl = Url.Page( + "/Account/ConfirmEmail", + pageHandler: null, + values: new { area = "Identity", userId = user.Id, code = code, returnUrl = returnUrl }, + protocol: Request.Scheme); - await _emailSender.SendEmailAsync(Input.Email, "Confirm your email", - $"Please confirm your account by clicking here."); + await _emailSender.SendEmailAsync(Input.Email, "Confirm your email", + $"Please confirm your account by clicking here."); - if (_userManager.Options.SignIn.RequireConfirmedAccount) - { - return RedirectToPage("RegisterConfirmation", new { email = Input.Email, returnUrl = returnUrl }); - } - else - { - await _signInManager.SignInAsync(user, isPersistent: false); - return LocalRedirect(returnUrl); - } + if (_userManager.Options.SignIn.RequireConfirmedAccount) + { + return RedirectToPage("RegisterConfirmation", new { email = Input.Email, returnUrl = returnUrl }); } - foreach (var error in result.Errors) + else { - ModelState.AddModelError(string.Empty, error.Description); + await _signInManager.SignInAsync(user, isPersistent: false); + return LocalRedirect(returnUrl); } } - - // If we got this far, something failed, redisplay form - return Page(); + foreach (var error in result.Errors) + { + ModelState.AddModelError(string.Empty, error.Description); + } } + + // If we got this far, something failed, redisplay form + return Page(); } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/RegisterConfirmation.cshtml.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/RegisterConfirmation.cshtml.cs index 059e62ed7..d6bd7d484 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/RegisterConfirmation.cshtml.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/RegisterConfirmation.cshtml.cs @@ -8,55 +8,54 @@ using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.AspNetCore.WebUtilities; -namespace ClassifiedAds.IdentityServer.Areas.Identity.Pages.Account +namespace ClassifiedAds.IdentityServer.Areas.Identity.Pages.Account; + +[AllowAnonymous] +public class RegisterConfirmationModel : PageModel { - [AllowAnonymous] - public class RegisterConfirmationModel : PageModel + private readonly UserManager _userManager; + private readonly IEmailSender _sender; + + public RegisterConfirmationModel(UserManager userManager, IEmailSender sender) { - private readonly UserManager _userManager; - private readonly IEmailSender _sender; + _userManager = userManager; + _sender = sender; + } - public RegisterConfirmationModel(UserManager userManager, IEmailSender sender) - { - _userManager = userManager; - _sender = sender; - } + public string Email { get; set; } + + public bool DisplayConfirmAccountLink { get; set; } - public string Email { get; set; } + public string EmailConfirmationUrl { get; set; } - public bool DisplayConfirmAccountLink { get; set; } + public async Task OnGetAsync(string email, string returnUrl = null) + { + if (email == null) + { + return RedirectToPage("/Index"); + } - public string EmailConfirmationUrl { get; set; } + var user = await _userManager.FindByEmailAsync(email); + if (user == null) + { + return NotFound($"Unable to load user with email '{email}'."); + } - public async Task OnGetAsync(string email, string returnUrl = null) + Email = email; + // Once you add a real email sender, you should remove this code that lets you confirm the account + DisplayConfirmAccountLink = true; + if (DisplayConfirmAccountLink) { - if (email == null) - { - return RedirectToPage("/Index"); - } - - var user = await _userManager.FindByEmailAsync(email); - if (user == null) - { - return NotFound($"Unable to load user with email '{email}'."); - } - - Email = email; - // Once you add a real email sender, you should remove this code that lets you confirm the account - DisplayConfirmAccountLink = true; - if (DisplayConfirmAccountLink) - { - var userId = await _userManager.GetUserIdAsync(user); - var code = await _userManager.GenerateEmailConfirmationTokenAsync(user); - code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code)); - EmailConfirmationUrl = Url.Page( - "/Account/ConfirmEmail", - pageHandler: null, - values: new { area = "Identity", userId = userId, code = code, returnUrl = returnUrl }, - protocol: Request.Scheme); - } - - return Page(); + var userId = await _userManager.GetUserIdAsync(user); + var code = await _userManager.GenerateEmailConfirmationTokenAsync(user); + code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code)); + EmailConfirmationUrl = Url.Page( + "/Account/ConfirmEmail", + pageHandler: null, + values: new { area = "Identity", userId = userId, code = code, returnUrl = returnUrl }, + protocol: Request.Scheme); } + + return Page(); } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/ResendEmailConfirmation.cshtml.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/ResendEmailConfirmation.cshtml.cs index e26f46d7e..52e6858d0 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/ResendEmailConfirmation.cshtml.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/ResendEmailConfirmation.cshtml.cs @@ -12,63 +12,62 @@ using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.AspNetCore.WebUtilities; -namespace ClassifiedAds.IdentityServer.Areas.Identity.Pages.Account +namespace ClassifiedAds.IdentityServer.Areas.Identity.Pages.Account; + +[AllowAnonymous] +public class ResendEmailConfirmationModel : PageModel { - [AllowAnonymous] - public class ResendEmailConfirmationModel : PageModel + private readonly UserManager _userManager; + private readonly IEmailSender _emailSender; + + public ResendEmailConfirmationModel(UserManager userManager, IEmailSender emailSender) { - private readonly UserManager _userManager; - private readonly IEmailSender _emailSender; + _userManager = userManager; + _emailSender = emailSender; + } - public ResendEmailConfirmationModel(UserManager userManager, IEmailSender emailSender) - { - _userManager = userManager; - _emailSender = emailSender; - } + [BindProperty] + public InputModel Input { get; set; } - [BindProperty] - public InputModel Input { get; set; } + public class InputModel + { + [Required] + [EmailAddress] + public string Email { get; set; } + } - public class InputModel - { - [Required] - [EmailAddress] - public string Email { get; set; } - } + public void OnGet() + { + } - public void OnGet() + public async Task OnPostAsync() + { + if (!ModelState.IsValid) { + return Page(); } - public async Task OnPostAsync() + var user = await _userManager.FindByEmailAsync(Input.Email); + if (user == null) { - if (!ModelState.IsValid) - { - return Page(); - } - - var user = await _userManager.FindByEmailAsync(Input.Email); - if (user == null) - { - ModelState.AddModelError(string.Empty, "Verification email sent. Please check your email."); - return Page(); - } - - var userId = await _userManager.GetUserIdAsync(user); - var code = await _userManager.GenerateEmailConfirmationTokenAsync(user); - code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code)); - var callbackUrl = Url.Page( - "/Account/ConfirmEmail", - pageHandler: null, - values: new { userId = userId, code = code }, - protocol: Request.Scheme); - await _emailSender.SendEmailAsync( - Input.Email, - "Confirm your email", - $"Please confirm your account by clicking here."); - ModelState.AddModelError(string.Empty, "Verification email sent. Please check your email."); return Page(); } + + var userId = await _userManager.GetUserIdAsync(user); + var code = await _userManager.GenerateEmailConfirmationTokenAsync(user); + code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code)); + var callbackUrl = Url.Page( + "/Account/ConfirmEmail", + pageHandler: null, + values: new { userId = userId, code = code }, + protocol: Request.Scheme); + await _emailSender.SendEmailAsync( + Input.Email, + "Confirm your email", + $"Please confirm your account by clicking here."); + + ModelState.AddModelError(string.Empty, "Verification email sent. Please check your email."); + return Page(); } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/ResetPassword.cshtml.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/ResetPassword.cshtml.cs index 3fbd7597a..046222bf5 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/ResetPassword.cshtml.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/ResetPassword.cshtml.cs @@ -11,81 +11,80 @@ using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.AspNetCore.WebUtilities; -namespace ClassifiedAds.IdentityServer.Areas.Identity.Pages.Account +namespace ClassifiedAds.IdentityServer.Areas.Identity.Pages.Account; + +[AllowAnonymous] +public class ResetPasswordModel : PageModel { - [AllowAnonymous] - public class ResetPasswordModel : PageModel + private readonly UserManager _userManager; + + public ResetPasswordModel(UserManager userManager) { - private readonly UserManager _userManager; + _userManager = userManager; + } - public ResetPasswordModel(UserManager userManager) - { - _userManager = userManager; - } + [BindProperty] + public InputModel Input { get; set; } - [BindProperty] - public InputModel Input { get; set; } + public class InputModel + { + [Required] + [EmailAddress] + public string Email { get; set; } - public class InputModel - { - [Required] - [EmailAddress] - public string Email { get; set; } + [Required] + [StringLength(100, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 6)] + [DataType(DataType.Password)] + public string Password { get; set; } - [Required] - [StringLength(100, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 6)] - [DataType(DataType.Password)] - public string Password { get; set; } + [DataType(DataType.Password)] + [Display(Name = "Confirm password")] + [Compare("Password", ErrorMessage = "The password and confirmation password do not match.")] + public string ConfirmPassword { get; set; } - [DataType(DataType.Password)] - [Display(Name = "Confirm password")] - [Compare("Password", ErrorMessage = "The password and confirmation password do not match.")] - public string ConfirmPassword { get; set; } + public string Code { get; set; } + } - public string Code { get; set; } + public IActionResult OnGet(string code = null) + { + if (code == null) + { + return BadRequest("A code must be supplied for password reset."); } - - public IActionResult OnGet(string code = null) + else { - if (code == null) + Input = new InputModel { - return BadRequest("A code must be supplied for password reset."); - } - else - { - Input = new InputModel - { - Code = Encoding.UTF8.GetString(WebEncoders.Base64UrlDecode(code)) - }; - return Page(); - } + Code = Encoding.UTF8.GetString(WebEncoders.Base64UrlDecode(code)) + }; + return Page(); } + } - public async Task OnPostAsync() + public async Task OnPostAsync() + { + if (!ModelState.IsValid) { - if (!ModelState.IsValid) - { - return Page(); - } + return Page(); + } - var user = await _userManager.FindByEmailAsync(Input.Email); - if (user == null) - { - // Don't reveal that the user does not exist - return RedirectToPage("./ResetPasswordConfirmation"); - } + var user = await _userManager.FindByEmailAsync(Input.Email); + if (user == null) + { + // Don't reveal that the user does not exist + return RedirectToPage("./ResetPasswordConfirmation"); + } - var result = await _userManager.ResetPasswordAsync(user, Input.Code, Input.Password); - if (result.Succeeded) - { - return RedirectToPage("./ResetPasswordConfirmation"); - } + var result = await _userManager.ResetPasswordAsync(user, Input.Code, Input.Password); + if (result.Succeeded) + { + return RedirectToPage("./ResetPasswordConfirmation"); + } - foreach (var error in result.Errors) - { - ModelState.AddModelError(string.Empty, error.Description); - } - return Page(); + foreach (var error in result.Errors) + { + ModelState.AddModelError(string.Empty, error.Description); } + return Page(); } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/ResetPasswordConfirmation.cshtml.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/ResetPasswordConfirmation.cshtml.cs index 3b4e191cb..8fbe0f0a6 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/ResetPasswordConfirmation.cshtml.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Account/ResetPasswordConfirmation.cshtml.cs @@ -5,14 +5,13 @@ using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc.RazorPages; -namespace ClassifiedAds.IdentityServer.Areas.Identity.Pages.Account +namespace ClassifiedAds.IdentityServer.Areas.Identity.Pages.Account; + +[AllowAnonymous] +public class ResetPasswordConfirmationModel : PageModel { - [AllowAnonymous] - public class ResetPasswordConfirmationModel : PageModel + public void OnGet() { - public void OnGet() - { - } } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Error.cshtml.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Error.cshtml.cs index efeac0e21..76528f3f2 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Error.cshtml.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Areas/Identity/Pages/Error.cshtml.cs @@ -8,19 +8,18 @@ using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Identity; -namespace ClassifiedAds.IdentityServer.Areas.Identity.Pages +namespace ClassifiedAds.IdentityServer.Areas.Identity.Pages; + +[AllowAnonymous] +[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)] +public class ErrorModel : PageModel { - [AllowAnonymous] - [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)] - public class ErrorModel : PageModel - { - public string RequestId { get; set; } + public string RequestId { get; set; } - public bool ShowRequestId => !string.IsNullOrEmpty(RequestId); + public bool ShowRequestId => !string.IsNullOrEmpty(RequestId); - public void OnGet() - { - RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier; - } + public void OnGet() + { + RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/ConfigurationOptions/AppSettings.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/ConfigurationOptions/AppSettings.cs index cf50eaa69..31eef2c62 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/ConfigurationOptions/AppSettings.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/ConfigurationOptions/AppSettings.cs @@ -5,26 +5,25 @@ using ClassifiedAds.Infrastructure.Monitoring; using System.Collections.Generic; -namespace ClassifiedAds.IdentityServer.ConfigurationOptions +namespace ClassifiedAds.IdentityServer.ConfigurationOptions; + +public class AppSettings { - public class AppSettings - { - public ConnectionStrings ConnectionStrings { get; set; } + public ConnectionStrings ConnectionStrings { get; set; } - public IdentityServerOptions IdentityServer { get; set; } + public IdentityServerOptions IdentityServer { get; set; } - public LoggingOptions Logging { get; set; } + public LoggingOptions Logging { get; set; } - public CachingOptions Caching { get; set; } + public CachingOptions Caching { get; set; } - public MonitoringOptions Monitoring { get; set; } + public MonitoringOptions Monitoring { get; set; } - public Dictionary SecurityHeaders { get; set; } + public Dictionary SecurityHeaders { get; set; } - public InterceptorsOptions Interceptors { get; set; } + public InterceptorsOptions Interceptors { get; set; } - public ExternalLoginOptions ExternalLogin { get; set; } + public ExternalLoginOptions ExternalLogin { get; set; } - public CookiePolicyOptions CookiePolicyOptions { get; set; } - } + public CookiePolicyOptions CookiePolicyOptions { get; set; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/ConfigurationOptions/ConnectionStrings.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/ConfigurationOptions/ConnectionStrings.cs index b93aa9be6..844e07349 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/ConfigurationOptions/ConnectionStrings.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/ConfigurationOptions/ConnectionStrings.cs @@ -1,9 +1,8 @@ -namespace ClassifiedAds.IdentityServer.ConfigurationOptions +namespace ClassifiedAds.IdentityServer.ConfigurationOptions; + +public class ConnectionStrings { - public class ConnectionStrings - { - public string ClassifiedAds { get; set; } + public string ClassifiedAds { get; set; } - public string IdentityServer { get; set; } - } + public string IdentityServer { get; set; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/ConfigurationOptions/CookiePolicyOptions.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/ConfigurationOptions/CookiePolicyOptions.cs index 0023eb4d3..12d4d6ae8 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/ConfigurationOptions/CookiePolicyOptions.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/ConfigurationOptions/CookiePolicyOptions.cs @@ -1,7 +1,6 @@ -namespace ClassifiedAds.IdentityServer.ConfigurationOptions +namespace ClassifiedAds.IdentityServer.ConfigurationOptions; + +public class CookiePolicyOptions: Microsoft.AspNetCore.Builder.CookiePolicyOptions { - public class CookiePolicyOptions: Microsoft.AspNetCore.Builder.CookiePolicyOptions - { - public bool IsEnabled { get; set; } - } + public bool IsEnabled { get; set; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/ConfigurationOptions/ExternalLogin/AzureActiveDirectoryOptions.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/ConfigurationOptions/ExternalLogin/AzureActiveDirectoryOptions.cs index dbfea9ca9..a2821f962 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/ConfigurationOptions/ExternalLogin/AzureActiveDirectoryOptions.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/ConfigurationOptions/ExternalLogin/AzureActiveDirectoryOptions.cs @@ -1,13 +1,12 @@ -namespace ClassifiedAds.IdentityServer.ConfigurationOptions.ExternalLogin +namespace ClassifiedAds.IdentityServer.ConfigurationOptions.ExternalLogin; + +public class AzureActiveDirectoryOptions { - public class AzureActiveDirectoryOptions - { - public bool IsEnabled { get; set; } + public bool IsEnabled { get; set; } - public string Authority { get; set; } + public string Authority { get; set; } - public string ClientId { get; set; } + public string ClientId { get; set; } - public string ClientSecret { get; set; } - } + public string ClientSecret { get; set; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/ConfigurationOptions/ExternalLogin/ExternalLoginOptions.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/ConfigurationOptions/ExternalLogin/ExternalLoginOptions.cs index fa4b83f99..e7d10501c 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/ConfigurationOptions/ExternalLogin/ExternalLoginOptions.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/ConfigurationOptions/ExternalLogin/ExternalLoginOptions.cs @@ -1,13 +1,12 @@ -namespace ClassifiedAds.IdentityServer.ConfigurationOptions.ExternalLogin +namespace ClassifiedAds.IdentityServer.ConfigurationOptions.ExternalLogin; + +public class ExternalLoginOptions { - public class ExternalLoginOptions - { - public AzureActiveDirectoryOptions AzureActiveDirectory { get; set; } + public AzureActiveDirectoryOptions AzureActiveDirectory { get; set; } - public MicrosoftOptions Microsoft { get; set; } + public MicrosoftOptions Microsoft { get; set; } - public GoogleOptions Google { get; set; } + public GoogleOptions Google { get; set; } - public FacebookOptions Facebook { get; set; } - } + public FacebookOptions Facebook { get; set; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/ConfigurationOptions/ExternalLogin/FacebookOptions.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/ConfigurationOptions/ExternalLogin/FacebookOptions.cs index 8f45346e0..884312f7d 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/ConfigurationOptions/ExternalLogin/FacebookOptions.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/ConfigurationOptions/ExternalLogin/FacebookOptions.cs @@ -1,11 +1,10 @@ -namespace ClassifiedAds.IdentityServer.ConfigurationOptions.ExternalLogin +namespace ClassifiedAds.IdentityServer.ConfigurationOptions.ExternalLogin; + +public class FacebookOptions { - public class FacebookOptions - { - public bool IsEnabled { get; set; } + public bool IsEnabled { get; set; } - public string AppId { get; set; } + public string AppId { get; set; } - public string AppSecret { get; set; } - } + public string AppSecret { get; set; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/ConfigurationOptions/ExternalLogin/GoogleOptions.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/ConfigurationOptions/ExternalLogin/GoogleOptions.cs index 21a3cdf0b..4ba23fe68 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/ConfigurationOptions/ExternalLogin/GoogleOptions.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/ConfigurationOptions/ExternalLogin/GoogleOptions.cs @@ -1,11 +1,10 @@ -namespace ClassifiedAds.IdentityServer.ConfigurationOptions.ExternalLogin +namespace ClassifiedAds.IdentityServer.ConfigurationOptions.ExternalLogin; + +public class GoogleOptions { - public class GoogleOptions - { - public bool IsEnabled { get; set; } + public bool IsEnabled { get; set; } - public string ClientId { get; set; } + public string ClientId { get; set; } - public string ClientSecret { get; set; } - } + public string ClientSecret { get; set; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/ConfigurationOptions/ExternalLogin/MicrosoftOptions.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/ConfigurationOptions/ExternalLogin/MicrosoftOptions.cs index 7ef122f5c..3ba6b107a 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/ConfigurationOptions/ExternalLogin/MicrosoftOptions.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/ConfigurationOptions/ExternalLogin/MicrosoftOptions.cs @@ -1,11 +1,10 @@ -namespace ClassifiedAds.IdentityServer.ConfigurationOptions.ExternalLogin +namespace ClassifiedAds.IdentityServer.ConfigurationOptions.ExternalLogin; + +public class MicrosoftOptions { - public class MicrosoftOptions - { - public bool IsEnabled { get; set; } + public bool IsEnabled { get; set; } - public string ClientId { get; set; } + public string ClientId { get; set; } - public string ClientSecret { get; set; } - } + public string ClientSecret { get; set; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/ConfigurationOptions/IdentityServerOptions.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/ConfigurationOptions/IdentityServerOptions.cs index f5930dc74..a75bebb12 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/ConfigurationOptions/IdentityServerOptions.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/ConfigurationOptions/IdentityServerOptions.cs @@ -1,9 +1,8 @@ using CryptographyHelper.Certificates; -namespace ClassifiedAds.IdentityServer.ConfigurationOptions +namespace ClassifiedAds.IdentityServer.ConfigurationOptions; + +public class IdentityServerOptions : IdentityServer4.Configuration.IdentityServerOptions { - public class IdentityServerOptions : IdentityServer4.Configuration.IdentityServerOptions - { - public CertificateOption Certificate { get; set; } - } + public CertificateOption Certificate { get; set; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Controllers/ApiResourceController.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Controllers/ApiResourceController.cs index 09cb4fac1..1f0a91497 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Controllers/ApiResourceController.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Controllers/ApiResourceController.cs @@ -8,238 +8,237 @@ using System.Linq; using System.Text.Json; -namespace ClassifiedAds.IdentityServer.Controllers +namespace ClassifiedAds.IdentityServer.Controllers; + +public class ApiResourceController : Controller { - public class ApiResourceController : Controller + private readonly ConfigurationDbContext _configurationDbContext; + + public ApiResourceController(ConfigurationDbContext configurationDbContext) { - private readonly ConfigurationDbContext _configurationDbContext; + _configurationDbContext = configurationDbContext; + } - public ApiResourceController(ConfigurationDbContext configurationDbContext) - { - _configurationDbContext = configurationDbContext; - } + public IActionResult Index() + { + var apis = _configurationDbContext.ApiResources.ToList(); + return View(apis); + } - public IActionResult Index() - { - var apis = _configurationDbContext.ApiResources.ToList(); - return View(apis); - } + public IActionResult Add() + { + return View(nameof(Edit), new ApiResourceModel()); + } - public IActionResult Add() + public IActionResult Edit(int id) + { + var identity = _configurationDbContext.ApiResources + .Include(x => x.UserClaims) + .FirstOrDefault(x => x.Id == id); + return View(ApiResourceModel.FromEntity(identity)); + } + + [HttpPost] + public IActionResult Edit(ApiResourceModel model) + { + ApiResource api; + if (model.Id == 0) { - return View(nameof(Edit), new ApiResourceModel()); + api = new ApiResource + { + UserClaims = new List(), + }; + _configurationDbContext.ApiResources.Add(api); } - - public IActionResult Edit(int id) + else { - var identity = _configurationDbContext.ApiResources + api = _configurationDbContext.ApiResources .Include(x => x.UserClaims) - .FirstOrDefault(x => x.Id == id); - return View(ApiResourceModel.FromEntity(identity)); + .FirstOrDefault(x => x.Id == model.Id); + api.UserClaims.Clear(); } - [HttpPost] - public IActionResult Edit(ApiResourceModel model) - { - ApiResource api; - if (model.Id == 0) - { - api = new ApiResource - { - UserClaims = new List(), - }; - _configurationDbContext.ApiResources.Add(api); - } - else - { - api = _configurationDbContext.ApiResources - .Include(x => x.UserClaims) - .FirstOrDefault(x => x.Id == model.Id); - api.UserClaims.Clear(); - } + model.UpdateEntity(api); - model.UpdateEntity(api); + if (!string.IsNullOrEmpty(model.UserClaimsItems)) + { + var userClaims = JsonSerializer.Deserialize>(model.UserClaimsItems); - if (!string.IsNullOrEmpty(model.UserClaimsItems)) + api.UserClaims.AddRange(userClaims.Select(x => new ApiResourceClaim { - var userClaims = JsonSerializer.Deserialize>(model.UserClaimsItems); + Type = x, + })); + } - api.UserClaims.AddRange(userClaims.Select(x => new ApiResourceClaim - { - Type = x, - })); - } + _configurationDbContext.SaveChanges(); - _configurationDbContext.SaveChanges(); + return RedirectToAction(nameof(Edit), new { id = api.Id }); + } - return RedirectToAction(nameof(Edit), new { id = api.Id }); - } + public IActionResult Delete(int id) + { + var api = _configurationDbContext.ApiResources + .FirstOrDefault(x => x.Id == id); + return View(ApiResourceModel.FromEntity(api)); + } - public IActionResult Delete(int id) - { - var api = _configurationDbContext.ApiResources - .FirstOrDefault(x => x.Id == id); - return View(ApiResourceModel.FromEntity(api)); - } + [HttpPost] + public IActionResult Delete(ApiResourceModel model) + { + var api = _configurationDbContext.ApiResources + .FirstOrDefault(x => x.Id == model.Id); - [HttpPost] - public IActionResult Delete(ApiResourceModel model) - { - var api = _configurationDbContext.ApiResources - .FirstOrDefault(x => x.Id == model.Id); + _configurationDbContext.ApiResources.Remove(api); + _configurationDbContext.SaveChanges(); - _configurationDbContext.ApiResources.Remove(api); - _configurationDbContext.SaveChanges(); + return RedirectToAction(nameof(Index)); + } - return RedirectToAction(nameof(Index)); - } + public IActionResult Properties(int id) + { + var api = _configurationDbContext.ApiResources + .Include(x => x.Properties) + .FirstOrDefault(x => x.Id == id); + return View(PropertiesModel.FromEntity(api)); + } - public IActionResult Properties(int id) - { - var api = _configurationDbContext.ApiResources - .Include(x => x.Properties) - .FirstOrDefault(x => x.Id == id); - return View(PropertiesModel.FromEntity(api)); - } + [HttpPost] + public IActionResult AddProperty(PropertiesModel model) + { + var api = _configurationDbContext.ApiResources + .Include(x => x.Properties) + .FirstOrDefault(x => x.Id == model.ApiResourceId); - [HttpPost] - public IActionResult AddProperty(PropertiesModel model) + api.Properties.Add(new ApiResourceProperty { - var api = _configurationDbContext.ApiResources - .Include(x => x.Properties) - .FirstOrDefault(x => x.Id == model.ApiResourceId); + Key = model.Key, + Value = model.Value, + }); - api.Properties.Add(new ApiResourceProperty - { - Key = model.Key, - Value = model.Value, - }); + _configurationDbContext.SaveChanges(); - _configurationDbContext.SaveChanges(); + return RedirectToAction(nameof(Properties), new { id = api.Id }); + } - return RedirectToAction(nameof(Properties), new { id = api.Id }); - } + [HttpGet] + public IActionResult DeleteProperty(int id) + { + var prop = _configurationDbContext.Set() + .Include(x => x.ApiResource) + .FirstOrDefault(x => x.Id == id); + return View(ApiResourcePropertyModel.FromEntity(prop)); + } - [HttpGet] - public IActionResult DeleteProperty(int id) - { - var prop = _configurationDbContext.Set() - .Include(x => x.ApiResource) - .FirstOrDefault(x => x.Id == id); - return View(ApiResourcePropertyModel.FromEntity(prop)); - } + [HttpPost] + public IActionResult DeleteProperty(ApiResourcePropertyModel model) + { + var api = _configurationDbContext.ApiResources + .Include(x => x.Properties) + .FirstOrDefault(x => x.Id == model.ApiResource.Id); + var prop = api.Properties.FirstOrDefault(x => x.Id == model.Id); + api.Properties.Remove(prop); + _configurationDbContext.SaveChanges(); + + return RedirectToAction(nameof(Properties), new { id = api.Id }); + } - [HttpPost] - public IActionResult DeleteProperty(ApiResourcePropertyModel model) - { - var api = _configurationDbContext.ApiResources - .Include(x => x.Properties) - .FirstOrDefault(x => x.Id == model.ApiResource.Id); - var prop = api.Properties.FirstOrDefault(x => x.Id == model.Id); - api.Properties.Remove(prop); - _configurationDbContext.SaveChanges(); - - return RedirectToAction(nameof(Properties), new { id = api.Id }); - } + public IActionResult Secrets(int id) + { + var api = _configurationDbContext.ApiResources + .Include(x => x.Secrets) + .FirstOrDefault(x => x.Id == id); + return View(SecretsModel.FromEntity(api)); + } - public IActionResult Secrets(int id) - { - var api = _configurationDbContext.ApiResources - .Include(x => x.Secrets) - .FirstOrDefault(x => x.Id == id); - return View(SecretsModel.FromEntity(api)); - } + [HttpPost] + public IActionResult Secrets(SecretsModel model) + { + var api = _configurationDbContext.ApiResources + .Include(x => x.Secrets) + .FirstOrDefault(x => x.Id == model.ApiResourceId); - [HttpPost] - public IActionResult Secrets(SecretsModel model) + var secret = new ApiResourceSecret { - var api = _configurationDbContext.ApiResources - .Include(x => x.Secrets) - .FirstOrDefault(x => x.Id == model.ApiResourceId); - - var secret = new ApiResourceSecret - { - Created = DateTime.UtcNow, - }; + Created = DateTime.UtcNow, + }; - model.HashSecret(); - model.UpdateEntity(secret); - api.Secrets.Add(secret); + model.HashSecret(); + model.UpdateEntity(secret); + api.Secrets.Add(secret); - _configurationDbContext.SaveChanges(); + _configurationDbContext.SaveChanges(); - return RedirectToAction(nameof(Secrets), new { id = api.Id }); - } + return RedirectToAction(nameof(Secrets), new { id = api.Id }); + } - [HttpGet] - public IActionResult DeleteSecret(int id) - { - var secret = _configurationDbContext.Set() - .Include(x => x.ApiResource) - .FirstOrDefault(x => x.Id == id); - return View(SecretModel.FromEntity(secret)); - } + [HttpGet] + public IActionResult DeleteSecret(int id) + { + var secret = _configurationDbContext.Set() + .Include(x => x.ApiResource) + .FirstOrDefault(x => x.Id == id); + return View(SecretModel.FromEntity(secret)); + } - [HttpPost] - public IActionResult DeleteSecret(SecretModel model) - { - var api = _configurationDbContext.ApiResources - .Include(x => x.Secrets) - .FirstOrDefault(x => x.Id == model.ApiResourceId); - var secret = api.Secrets.FirstOrDefault(x => x.Id == model.Id); - api.Secrets.Remove(secret); - _configurationDbContext.SaveChanges(); - - return RedirectToAction(nameof(Secrets), new { id = api.Id }); - } + [HttpPost] + public IActionResult DeleteSecret(SecretModel model) + { + var api = _configurationDbContext.ApiResources + .Include(x => x.Secrets) + .FirstOrDefault(x => x.Id == model.ApiResourceId); + var secret = api.Secrets.FirstOrDefault(x => x.Id == model.Id); + api.Secrets.Remove(secret); + _configurationDbContext.SaveChanges(); + + return RedirectToAction(nameof(Secrets), new { id = api.Id }); + } - public IActionResult Scopes(int id) - { - var api = _configurationDbContext.ApiResources - .Include(x => x.Scopes) - .FirstOrDefault(x => x.Id == id); + public IActionResult Scopes(int id) + { + var api = _configurationDbContext.ApiResources + .Include(x => x.Scopes) + .FirstOrDefault(x => x.Id == id); - var apiScopes = _configurationDbContext.ApiScopes.ToList(); - var model = ScopesModel.FromEntity(api); - model.ApiScopes = apiScopes; + var apiScopes = _configurationDbContext.ApiScopes.ToList(); + var model = ScopesModel.FromEntity(api); + model.ApiScopes = apiScopes; - return View(model); - } + return View(model); + } - [HttpPost] - public IActionResult AddScope(ScopeModel model) - { - var api = _configurationDbContext.ApiResources - .Include(x => x.Scopes) - .FirstOrDefault(x => x.Id == model.ApiResourceId); + [HttpPost] + public IActionResult AddScope(ScopeModel model) + { + var api = _configurationDbContext.ApiResources + .Include(x => x.Scopes) + .FirstOrDefault(x => x.Id == model.ApiResourceId); - api.Scopes.Add(new ApiResourceScope { Scope = model.Scope }); + api.Scopes.Add(new ApiResourceScope { Scope = model.Scope }); - _configurationDbContext.SaveChanges(); + _configurationDbContext.SaveChanges(); - return RedirectToAction(nameof(Scopes), new { id = api.Id }); - } + return RedirectToAction(nameof(Scopes), new { id = api.Id }); + } - [HttpGet] - public IActionResult DeleteScope(int apiId, int scopeId) - { - var scope = _configurationDbContext.Set() - .Include(x => x.ApiResource) - .FirstOrDefault(x => x.Id == scopeId); - return View(ScopeModel.FromEntity(scope)); - } + [HttpGet] + public IActionResult DeleteScope(int apiId, int scopeId) + { + var scope = _configurationDbContext.Set() + .Include(x => x.ApiResource) + .FirstOrDefault(x => x.Id == scopeId); + return View(ScopeModel.FromEntity(scope)); + } - [HttpPost] - public IActionResult DeleteScope(ScopeModel model) - { - var api = _configurationDbContext.ApiResources - .Include(x => x.Scopes) - .FirstOrDefault(x => x.Id == model.ApiResourceId); - var scope = api.Scopes.FirstOrDefault(x => x.Id == model.Id); - api.Scopes.Remove(scope); - _configurationDbContext.SaveChanges(); - - return RedirectToAction(nameof(Scopes), new { id = api.Id }); - } + [HttpPost] + public IActionResult DeleteScope(ScopeModel model) + { + var api = _configurationDbContext.ApiResources + .Include(x => x.Scopes) + .FirstOrDefault(x => x.Id == model.ApiResourceId); + var scope = api.Scopes.FirstOrDefault(x => x.Id == model.Id); + api.Scopes.Remove(scope); + _configurationDbContext.SaveChanges(); + + return RedirectToAction(nameof(Scopes), new { id = api.Id }); } } \ No newline at end of file diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Controllers/ApiScopeController.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Controllers/ApiScopeController.cs index 720454652..bac0998f9 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Controllers/ApiScopeController.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Controllers/ApiScopeController.cs @@ -7,104 +7,103 @@ using System.Linq; using System.Text.Json; -namespace ClassifiedAds.IdentityServer.Controllers +namespace ClassifiedAds.IdentityServer.Controllers; + +public class ApiScopeController : Controller { - public class ApiScopeController : Controller + private readonly ConfigurationDbContext _configurationDbContext; + + public ApiScopeController(ConfigurationDbContext configurationDbContext) { - private readonly ConfigurationDbContext _configurationDbContext; + _configurationDbContext = configurationDbContext; + } - public ApiScopeController(ConfigurationDbContext configurationDbContext) - { - _configurationDbContext = configurationDbContext; - } + public IActionResult Scopes(int id) + { + var api = _configurationDbContext.ApiScopes + .Include(x => x.UserClaims) + .Include(x => x.Properties) + .FirstOrDefault(x => x.Id == id); + return View(ApiScopeModel.FromEntity(api)); + } - public IActionResult Scopes(int id) + public IActionResult Edit(int id) + { + if (id != 0) { var api = _configurationDbContext.ApiScopes - .Include(x => x.UserClaims) - .Include(x => x.Properties) - .FirstOrDefault(x => x.Id == id); + .Include(x => x.UserClaims) + .Include(x => x.Properties) + .FirstOrDefault(x => x.Id == id); + return View(ApiScopeModel.FromEntity(api)); } - - public IActionResult Edit(int id) + else { - if (id != 0) - { - var api = _configurationDbContext.ApiScopes - .Include(x => x.UserClaims) - .Include(x => x.Properties) - .FirstOrDefault(x => x.Id == id); - - return View(ApiScopeModel.FromEntity(api)); - } - else + return View(new ApiScopeModel { - return View(new ApiScopeModel - { - }); - } + }); } + } - [HttpPost] - public IActionResult Edit(ApiScopeModel model) - { - ApiScope api; + [HttpPost] + public IActionResult Edit(ApiScopeModel model) + { + ApiScope api; - if (model.Id == 0) + if (model.Id == 0) + { + api = new ApiScope { - api = new ApiScope - { - }; - } - else - { - api = _configurationDbContext.ApiScopes - .Include(x => x.UserClaims) - .Include(x => x.Properties) - .FirstOrDefault(x => x.Id == model.Id); - } + }; + } + else + { + api = _configurationDbContext.ApiScopes + .Include(x => x.UserClaims) + .Include(x => x.Properties) + .FirstOrDefault(x => x.Id == model.Id); + } - model.UpdateEntity(api); + model.UpdateEntity(api); - if (!string.IsNullOrEmpty(model.UserClaimsItems)) - { - var userClaims = JsonSerializer.Deserialize>(model.UserClaimsItems); + if (!string.IsNullOrEmpty(model.UserClaimsItems)) + { + var userClaims = JsonSerializer.Deserialize>(model.UserClaimsItems); - api.UserClaims.AddRange(userClaims.Select(x => new ApiScopeClaim - { - Type = x, - })); - } + api.UserClaims.AddRange(userClaims.Select(x => new ApiScopeClaim + { + Type = x, + })); + } - _configurationDbContext.SaveChanges(); + _configurationDbContext.SaveChanges(); - return RedirectToAction(nameof(Scopes), new { id = api.Id }); - } + return RedirectToAction(nameof(Scopes), new { id = api.Id }); + } - [HttpGet] - public IActionResult Delete(int id) - { - var api = _configurationDbContext.ApiScopes - .Include(x => x.UserClaims) - .Include(x => x.Properties) - .FirstOrDefault(x => x.Id == id); - return View(ApiScopeModel.FromEntity(api)); - } + [HttpGet] + public IActionResult Delete(int id) + { + var api = _configurationDbContext.ApiScopes + .Include(x => x.UserClaims) + .Include(x => x.Properties) + .FirstOrDefault(x => x.Id == id); + return View(ApiScopeModel.FromEntity(api)); + } - [HttpPost] - public IActionResult Delete(ApiScopeModel model) - { - var api = _configurationDbContext.ApiScopes - .Include(x => x.UserClaims) - .Include(x => x.Properties) - .FirstOrDefault(x => x.Id == model.Id); + [HttpPost] + public IActionResult Delete(ApiScopeModel model) + { + var api = _configurationDbContext.ApiScopes + .Include(x => x.UserClaims) + .Include(x => x.Properties) + .FirstOrDefault(x => x.Id == model.Id); - _configurationDbContext.ApiScopes.Remove(api); - _configurationDbContext.SaveChanges(); + _configurationDbContext.ApiScopes.Remove(api); + _configurationDbContext.SaveChanges(); - return RedirectToAction(nameof(Scopes), new { id = api.Id }); - } + return RedirectToAction(nameof(Scopes), new { id = api.Id }); } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Controllers/ClientController.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Controllers/ClientController.cs index 211513d6f..000719266 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Controllers/ClientController.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Controllers/ClientController.cs @@ -8,336 +8,335 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; -namespace ClassifiedAds.IdentityServer.Controllers +namespace ClassifiedAds.IdentityServer.Controllers; + +public class ClientController : Controller { - public class ClientController : Controller - { - private readonly ConfigurationDbContext _configurationDbContext; + private readonly ConfigurationDbContext _configurationDbContext; - public ClientController(ConfigurationDbContext configurationDbContext) - { - _configurationDbContext = configurationDbContext; - } + public ClientController(ConfigurationDbContext configurationDbContext) + { + _configurationDbContext = configurationDbContext; + } - public IActionResult Index() - { - var clients = _configurationDbContext.Clients - .Include(x => x.AllowedGrantTypes) - .Include(x => x.RedirectUris) - .Include(x => x.PostLogoutRedirectUris) - .Include(x => x.AllowedScopes) - .Include(x => x.ClientSecrets) - .Include(x => x.Claims) - .Include(x => x.IdentityProviderRestrictions) - .Include(x => x.AllowedCorsOrigins) - .Include(x => x.Properties) - .AsNoTracking() - .ToList(); + public IActionResult Index() + { + var clients = _configurationDbContext.Clients + .Include(x => x.AllowedGrantTypes) + .Include(x => x.RedirectUris) + .Include(x => x.PostLogoutRedirectUris) + .Include(x => x.AllowedScopes) + .Include(x => x.ClientSecrets) + .Include(x => x.Claims) + .Include(x => x.IdentityProviderRestrictions) + .Include(x => x.AllowedCorsOrigins) + .Include(x => x.Properties) + .AsNoTracking() + .ToList(); + + var models = clients.Select(x => ClientModel.FromEntity(x)).ToList(); + + return View(models); + } - var models = clients.Select(x => ClientModel.FromEntity(x)).ToList(); + public IActionResult Add() + { + var client = new ClientModel(); + return View(nameof(Edit), client); + } - return View(models); - } + public IActionResult Edit(int id) + { + var client = _configurationDbContext.Clients + .Include(x => x.AllowedGrantTypes) + .Include(x => x.RedirectUris) + .Include(x => x.PostLogoutRedirectUris) + .Include(x => x.AllowedScopes) + .Include(x => x.ClientSecrets) + .Include(x => x.Claims) + .Include(x => x.IdentityProviderRestrictions) + .Include(x => x.AllowedCorsOrigins) + .Include(x => x.Properties) + .Where(x => x.Id == id) + .AsNoTracking() + .FirstOrDefault(); + + var model = ClientModel.FromEntity(client); + + return View(model); + } - public IActionResult Add() + [HttpPost] + public IActionResult Edit(ClientModel model) + { + Client client; + if (model.Id == 0) { - var client = new ClientModel(); - return View(nameof(Edit), client); + model.SetDefaultValues(); + client = new Client(); + _configurationDbContext.Clients.Add(client); } - - public IActionResult Edit(int id) + else { - var client = _configurationDbContext.Clients - .Include(x => x.AllowedGrantTypes) - .Include(x => x.RedirectUris) - .Include(x => x.PostLogoutRedirectUris) - .Include(x => x.AllowedScopes) - .Include(x => x.ClientSecrets) - .Include(x => x.Claims) - .Include(x => x.IdentityProviderRestrictions) - .Include(x => x.AllowedCorsOrigins) - .Include(x => x.Properties) - .Where(x => x.Id == id) - .AsNoTracking() - .FirstOrDefault(); - - var model = ClientModel.FromEntity(client); + model.ConvertItemsToList(); - return View(model); + client = _configurationDbContext.Clients + .Include(x => x.AllowedGrantTypes) + .Include(x => x.RedirectUris) + .Include(x => x.PostLogoutRedirectUris) + .Include(x => x.AllowedScopes) + .Include(x => x.ClientSecrets) + .Include(x => x.Claims) + .Include(x => x.IdentityProviderRestrictions) + .Include(x => x.AllowedCorsOrigins) + .Include(x => x.Properties) + .Where(x => x.Id == model.Id) + .FirstOrDefault(); + client.Updated = DateTime.UtcNow; } - [HttpPost] - public IActionResult Edit(ClientModel model) - { - Client client; - if (model.Id == 0) - { - model.SetDefaultValues(); - client = new Client(); - _configurationDbContext.Clients.Add(client); - } - else - { - model.ConvertItemsToList(); + model.UpdateEntity(client); + _configurationDbContext.SaveChanges(); - client = _configurationDbContext.Clients - .Include(x => x.AllowedGrantTypes) - .Include(x => x.RedirectUris) - .Include(x => x.PostLogoutRedirectUris) - .Include(x => x.AllowedScopes) - .Include(x => x.ClientSecrets) - .Include(x => x.Claims) - .Include(x => x.IdentityProviderRestrictions) - .Include(x => x.AllowedCorsOrigins) - .Include(x => x.Properties) - .Where(x => x.Id == model.Id) - .FirstOrDefault(); - client.Updated = DateTime.UtcNow; - } + return RedirectToAction(nameof(Edit), new { id = client.Id }); + } - model.UpdateEntity(client); - _configurationDbContext.SaveChanges(); + public IActionResult Clone(int id) + { + var client = _configurationDbContext.Clients + .Include(x => x.AllowedGrantTypes) + .Include(x => x.RedirectUris) + .Include(x => x.PostLogoutRedirectUris) + .Include(x => x.AllowedScopes) + .Include(x => x.ClientSecrets) + .Include(x => x.Claims) + .Include(x => x.IdentityProviderRestrictions) + .Include(x => x.AllowedCorsOrigins) + .Include(x => x.Properties) + .Where(x => x.Id == id) + .AsNoTracking() + .FirstOrDefault(); + + var model = ClientModel.FromEntity(client); + model.OriginalClientId = model.ClientId; + model.ClientId = $"Clone_From_{model.ClientId}_{DateTime.Now.ToString("yyyyMMddhhmmssfff")}"; + + return View(model); + } - return RedirectToAction(nameof(Edit), new { id = client.Id }); - } + [HttpPost] + public IActionResult Clone(ClientModel model) + { + Client client = new Client(); + model.ConvertItemsToList(); + model.UpdateEntity(client); - public IActionResult Clone(int id) - { - var client = _configurationDbContext.Clients - .Include(x => x.AllowedGrantTypes) - .Include(x => x.RedirectUris) - .Include(x => x.PostLogoutRedirectUris) - .Include(x => x.AllowedScopes) - .Include(x => x.ClientSecrets) - .Include(x => x.Claims) - .Include(x => x.IdentityProviderRestrictions) - .Include(x => x.AllowedCorsOrigins) - .Include(x => x.Properties) - .Where(x => x.Id == id) - .AsNoTracking() - .FirstOrDefault(); + _configurationDbContext.Clients.Add(client); + _configurationDbContext.SaveChanges(); - var model = ClientModel.FromEntity(client); - model.OriginalClientId = model.ClientId; - model.ClientId = $"Clone_From_{model.ClientId}_{DateTime.Now.ToString("yyyyMMddhhmmssfff")}"; + return RedirectToAction(nameof(Edit), new { id = client.Id }); + } - return View(model); - } + public IActionResult Delete(int id) + { + var client = _configurationDbContext.Clients + .Where(x => x.Id == id) + .AsNoTracking() + .FirstOrDefault(); - [HttpPost] - public IActionResult Clone(ClientModel model) - { - Client client = new Client(); - model.ConvertItemsToList(); - model.UpdateEntity(client); + var model = ClientModel.FromEntity(client); - _configurationDbContext.Clients.Add(client); - _configurationDbContext.SaveChanges(); + return View(model); + } - return RedirectToAction(nameof(Edit), new { id = client.Id }); - } + [HttpPost] + public IActionResult Delete(ClientModel model) + { + var client = _configurationDbContext.Clients + .FirstOrDefault(x => x.Id == model.Id); - public IActionResult Delete(int id) - { - var client = _configurationDbContext.Clients - .Where(x => x.Id == id) - .AsNoTracking() - .FirstOrDefault(); + _configurationDbContext.Clients.Remove(client); + _configurationDbContext.SaveChanges(); - var model = ClientModel.FromEntity(client); + return RedirectToAction(nameof(Index)); + } - return View(model); - } + public IActionResult GetScopes() + { + var identityResources = _configurationDbContext.IdentityResources + .Select(x => x.Name).ToList(); - [HttpPost] - public IActionResult Delete(ClientModel model) - { - var client = _configurationDbContext.Clients - .FirstOrDefault(x => x.Id == model.Id); + var apiScopes = _configurationDbContext.ApiResources + .Select(x => x.Name).ToList(); - _configurationDbContext.Clients.Remove(client); - _configurationDbContext.SaveChanges(); + var scopes = identityResources.Concat(apiScopes).ToList(); - return RedirectToAction(nameof(Index)); - } + return Ok(scopes); + } - public IActionResult GetScopes() - { - var identityResources = _configurationDbContext.IdentityResources - .Select(x => x.Name).ToList(); + public IActionResult GetGrantTypes() + { + var allowedGrantypes = new List + { + "implicit", + "client_credentials", + "authorization_code", + "hybrid", + "password", + "urn:ietf:params:oauth:grant-type:device_code", + }; - var apiScopes = _configurationDbContext.ApiResources - .Select(x => x.Name).ToList(); + return Ok(allowedGrantypes); + } - var scopes = identityResources.Concat(apiScopes).ToList(); + public IActionResult Properties(int id) + { + var client = _configurationDbContext.Clients + .Include(x => x.Properties) + .FirstOrDefault(x => x.Id == id); + return View(PropertiesModel.FromEntity(client)); + } - return Ok(scopes); - } + [HttpPost] + public IActionResult AddProperty(PropertiesModel model) + { + var client = _configurationDbContext.Clients + .Include(x => x.Properties) + .FirstOrDefault(x => x.Id == model.Client.Id); - public IActionResult GetGrantTypes() + client.Properties.Add(new ClientProperty { - var allowedGrantypes = new List - { - "implicit", - "client_credentials", - "authorization_code", - "hybrid", - "password", - "urn:ietf:params:oauth:grant-type:device_code", - }; - - return Ok(allowedGrantypes); - } + Key = model.Key, + Value = model.Value, + }); - public IActionResult Properties(int id) - { - var client = _configurationDbContext.Clients - .Include(x => x.Properties) - .FirstOrDefault(x => x.Id == id); - return View(PropertiesModel.FromEntity(client)); - } + _configurationDbContext.SaveChanges(); - [HttpPost] - public IActionResult AddProperty(PropertiesModel model) - { - var client = _configurationDbContext.Clients - .Include(x => x.Properties) - .FirstOrDefault(x => x.Id == model.Client.Id); + return RedirectToAction(nameof(Properties), new { id = client.Id }); + } - client.Properties.Add(new ClientProperty - { - Key = model.Key, - Value = model.Value, - }); + [HttpGet] + public IActionResult DeleteProperty(int id) + { + var prop = _configurationDbContext.Set() + .Include(x => x.Client) + .FirstOrDefault(x => x.Id == id); + return View(PropertyModel.FromEntity(prop)); + } - _configurationDbContext.SaveChanges(); + [HttpPost] + public IActionResult DeleteProperty(PropertyModel model) + { + var client = _configurationDbContext.Clients + .Include(x => x.Properties) + .FirstOrDefault(x => x.Id == model.Client.Id); + var prop = client.Properties.FirstOrDefault(x => x.Id == model.Id); + client.Properties.Remove(prop); + _configurationDbContext.SaveChanges(); - return RedirectToAction(nameof(Properties), new { id = client.Id }); - } + return RedirectToAction(nameof(Properties), new { id = client.Id }); + } - [HttpGet] - public IActionResult DeleteProperty(int id) - { - var prop = _configurationDbContext.Set() - .Include(x => x.Client) - .FirstOrDefault(x => x.Id == id); - return View(PropertyModel.FromEntity(prop)); - } + public IActionResult Secrets(int id) + { + var client = _configurationDbContext.Clients + .Include(x => x.ClientSecrets) + .FirstOrDefault(x => x.Id == id); + return View(SecretsModel.FromEntity(client)); + } - [HttpPost] - public IActionResult DeleteProperty(PropertyModel model) - { - var client = _configurationDbContext.Clients - .Include(x => x.Properties) - .FirstOrDefault(x => x.Id == model.Client.Id); - var prop = client.Properties.FirstOrDefault(x => x.Id == model.Id); - client.Properties.Remove(prop); - _configurationDbContext.SaveChanges(); - - return RedirectToAction(nameof(Properties), new { id = client.Id }); - } + [HttpPost] + public IActionResult Secrets(SecretsModel model) + { + var client = _configurationDbContext.Clients + .Include(x => x.ClientSecrets) + .FirstOrDefault(x => x.Id == model.Client.Id); - public IActionResult Secrets(int id) + var secret = new ClientSecret { - var client = _configurationDbContext.Clients - .Include(x => x.ClientSecrets) - .FirstOrDefault(x => x.Id == id); - return View(SecretsModel.FromEntity(client)); - } + Created = DateTime.UtcNow, + }; - [HttpPost] - public IActionResult Secrets(SecretsModel model) - { - var client = _configurationDbContext.Clients - .Include(x => x.ClientSecrets) - .FirstOrDefault(x => x.Id == model.Client.Id); + model.HashSecret(); + model.UpdateEntity(secret); + client.ClientSecrets.Add(secret); - var secret = new ClientSecret - { - Created = DateTime.UtcNow, - }; + _configurationDbContext.SaveChanges(); - model.HashSecret(); - model.UpdateEntity(secret); - client.ClientSecrets.Add(secret); + return RedirectToAction(nameof(Secrets), new { id = client.Id }); + } - _configurationDbContext.SaveChanges(); + [HttpGet] + public IActionResult DeleteSecret(int id) + { + var secret = _configurationDbContext.Set() + .Include(x => x.Client) + .FirstOrDefault(x => x.Id == id); + return View(SecretModel.FromEntity(secret)); + } - return RedirectToAction(nameof(Secrets), new { id = client.Id }); - } + [HttpPost] + public IActionResult DeleteSecret(SecretModel model) + { + var client = _configurationDbContext.Clients + .Include(x => x.ClientSecrets) + .FirstOrDefault(x => x.Id == model.Client.Id); + var secret = client.ClientSecrets.FirstOrDefault(x => x.Id == model.Id); + client.ClientSecrets.Remove(secret); + _configurationDbContext.SaveChanges(); - [HttpGet] - public IActionResult DeleteSecret(int id) - { - var secret = _configurationDbContext.Set() - .Include(x => x.Client) - .FirstOrDefault(x => x.Id == id); - return View(SecretModel.FromEntity(secret)); - } + return RedirectToAction(nameof(Secrets), new { id = client.Id }); + } - [HttpPost] - public IActionResult DeleteSecret(SecretModel model) - { - var client = _configurationDbContext.Clients - .Include(x => x.ClientSecrets) - .FirstOrDefault(x => x.Id == model.Client.Id); - var secret = client.ClientSecrets.FirstOrDefault(x => x.Id == model.Id); - client.ClientSecrets.Remove(secret); - _configurationDbContext.SaveChanges(); - - return RedirectToAction(nameof(Secrets), new { id = client.Id }); - } + public IActionResult Claims(int id) + { + var client = _configurationDbContext.Clients + .Include(x => x.Claims) + .FirstOrDefault(x => x.Id == id); - public IActionResult Claims(int id) - { - var client = _configurationDbContext.Clients - .Include(x => x.Claims) - .FirstOrDefault(x => x.Id == id); + return View(ClaimsModel.FromEntity(client)); + } - return View(ClaimsModel.FromEntity(client)); - } + [HttpPost] + public IActionResult Claims(ClaimModel model) + { + var client = _configurationDbContext.Clients + .Include(x => x.Claims) + .FirstOrDefault(x => x.Id == model.Client.Id); - [HttpPost] - public IActionResult Claims(ClaimModel model) + client.Claims.Add(new ClientClaim { - var client = _configurationDbContext.Clients - .Include(x => x.Claims) - .FirstOrDefault(x => x.Id == model.Client.Id); - - client.Claims.Add(new ClientClaim - { - Type = model.Type, - Value = model.Value, - }); + Type = model.Type, + Value = model.Value, + }); - _configurationDbContext.SaveChanges(); + _configurationDbContext.SaveChanges(); - return RedirectToAction(nameof(Claims), new { id = client.Id }); - } + return RedirectToAction(nameof(Claims), new { id = client.Id }); + } - public IActionResult DeleteClaim(int id) - { - var claim = _configurationDbContext.Set() - .Include(x => x.Client) - .FirstOrDefault(x => x.Id == id); + public IActionResult DeleteClaim(int id) + { + var claim = _configurationDbContext.Set() + .Include(x => x.Client) + .FirstOrDefault(x => x.Id == id); - return View(ClaimModel.FromEntity(claim)); - } + return View(ClaimModel.FromEntity(claim)); + } - [HttpPost] - public IActionResult DeleteClaim(ClaimModel model) - { - var client = _configurationDbContext.Clients - .Include(x => x.Claims) - .FirstOrDefault(x => x.Id == model.Client.Id); + [HttpPost] + public IActionResult DeleteClaim(ClaimModel model) + { + var client = _configurationDbContext.Clients + .Include(x => x.Claims) + .FirstOrDefault(x => x.Id == model.Client.Id); - var claim = client.Claims.FirstOrDefault(x => x.Id == model.Id); + var claim = client.Claims.FirstOrDefault(x => x.Id == model.Id); - client.Claims.Remove(claim); + client.Claims.Remove(claim); - _configurationDbContext.SaveChanges(); + _configurationDbContext.SaveChanges(); - return RedirectToAction(nameof(Claims), new { id = client.Id }); - } + return RedirectToAction(nameof(Claims), new { id = client.Id }); } } \ No newline at end of file diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Controllers/GrantController.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Controllers/GrantController.cs index 87301bae5..0294647fe 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Controllers/GrantController.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Controllers/GrantController.cs @@ -4,13 +4,12 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; -namespace ClassifiedAds.IdentityServer.Controllers +namespace ClassifiedAds.IdentityServer.Controllers; + +public class GrantController : Controller { - public class GrantController : Controller + public IActionResult Index() { - public IActionResult Index() - { - return View(); - } + return View(); } } \ No newline at end of file diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Controllers/IdentityResourceController.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Controllers/IdentityResourceController.cs index 443a89ca2..3de64f68b 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Controllers/IdentityResourceController.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Controllers/IdentityResourceController.cs @@ -7,164 +7,163 @@ using System.Linq; using System.Text.Json; -namespace ClassifiedAds.IdentityServer.Controllers +namespace ClassifiedAds.IdentityServer.Controllers; + +public class IdentityResourceController : Controller { - public class IdentityResourceController : Controller + private readonly ConfigurationDbContext _configurationDbContext; + + public IdentityResourceController(ConfigurationDbContext configurationDbContext) { - private readonly ConfigurationDbContext _configurationDbContext; + _configurationDbContext = configurationDbContext; + } - public IdentityResourceController(ConfigurationDbContext configurationDbContext) - { - _configurationDbContext = configurationDbContext; - } + public IActionResult Index() + { + var itentities = _configurationDbContext.IdentityResources.ToList(); + return View(itentities.ToModels().ToList()); + } - public IActionResult Index() - { - var itentities = _configurationDbContext.IdentityResources.ToList(); - return View(itentities.ToModels().ToList()); - } + public IActionResult Add() + { + return View(nameof(Edit), new IdentityResourceModel()); + } - public IActionResult Add() + public IActionResult Edit(int id) + { + var identity = _configurationDbContext.IdentityResources + .Include(x => x.UserClaims) + .FirstOrDefault(x => x.Id == id); + return View(identity.ToModel()); + } + + [HttpPost] + public IActionResult Edit(IdentityResourceModel model) + { + IdentityResource identity; + if (model.Id == 0) { - return View(nameof(Edit), new IdentityResourceModel()); + identity = new IdentityResource + { + UserClaims = new List(), + }; + _configurationDbContext.IdentityResources.Add(identity); } - - public IActionResult Edit(int id) + else { - var identity = _configurationDbContext.IdentityResources + identity = _configurationDbContext.IdentityResources .Include(x => x.UserClaims) - .FirstOrDefault(x => x.Id == id); - return View(identity.ToModel()); + .FirstOrDefault(x => x.Id == model.Id); + identity.UserClaims.Clear(); } - [HttpPost] - public IActionResult Edit(IdentityResourceModel model) - { - IdentityResource identity; - if (model.Id == 0) - { - identity = new IdentityResource - { - UserClaims = new List(), - }; - _configurationDbContext.IdentityResources.Add(identity); - } - else - { - identity = _configurationDbContext.IdentityResources - .Include(x => x.UserClaims) - .FirstOrDefault(x => x.Id == model.Id); - identity.UserClaims.Clear(); - } + model.UpdateEntity(identity); - model.UpdateEntity(identity); + if (!string.IsNullOrEmpty(model.UserClaimsItems)) + { + model.UserClaims = JsonSerializer.Deserialize>(model.UserClaimsItems); - if (!string.IsNullOrEmpty(model.UserClaimsItems)) + identity.UserClaims.AddRange(model.UserClaims.Select(x => new IdentityResourceClaim { - model.UserClaims = JsonSerializer.Deserialize>(model.UserClaimsItems); + Type = x, + })); + } - identity.UserClaims.AddRange(model.UserClaims.Select(x => new IdentityResourceClaim - { - Type = x, - })); - } + _configurationDbContext.SaveChanges(); - _configurationDbContext.SaveChanges(); + return RedirectToAction(nameof(Edit), new { id = identity.Id }); + } - return RedirectToAction(nameof(Edit), new { id = identity.Id }); - } + public IActionResult Delete(int id) + { + var identity = _configurationDbContext.IdentityResources + .Include(x => x.UserClaims) + .FirstOrDefault(x => x.Id == id); + return View(identity.ToModel()); + } - public IActionResult Delete(int id) - { - var identity = _configurationDbContext.IdentityResources - .Include(x => x.UserClaims) - .FirstOrDefault(x => x.Id == id); - return View(identity.ToModel()); - } + [HttpPost] + public IActionResult Delete(IdentityResourceModel model) + { + var identity = _configurationDbContext.IdentityResources + .FirstOrDefault(x => x.Id == model.Id); - [HttpPost] - public IActionResult Delete(IdentityResourceModel model) - { - var identity = _configurationDbContext.IdentityResources - .FirstOrDefault(x => x.Id == model.Id); + _configurationDbContext.IdentityResources.Remove(identity); + _configurationDbContext.SaveChanges(); - _configurationDbContext.IdentityResources.Remove(identity); - _configurationDbContext.SaveChanges(); + return RedirectToAction(nameof(Index)); + } - return RedirectToAction(nameof(Index)); - } + public IActionResult Properties(int id) + { + var identity = _configurationDbContext.IdentityResources + .Include(x => x.Properties) + .FirstOrDefault(x => x.Id == id); + return View(PropertiesModel.FromEntity(identity)); + } - public IActionResult Properties(int id) - { - var identity = _configurationDbContext.IdentityResources - .Include(x => x.Properties) - .FirstOrDefault(x => x.Id == id); - return View(PropertiesModel.FromEntity(identity)); - } + [HttpPost] + public IActionResult AddProperty(PropertiesModel model) + { + var identity = _configurationDbContext.IdentityResources + .Include(x => x.Properties) + .FirstOrDefault(x => x.Id == model.IdentityResourceId); - [HttpPost] - public IActionResult AddProperty(PropertiesModel model) + identity.Properties.Add(new IdentityResourceProperty { - var identity = _configurationDbContext.IdentityResources - .Include(x => x.Properties) - .FirstOrDefault(x => x.Id == model.IdentityResourceId); + Key = model.Key, + Value = model.Value, + }); - identity.Properties.Add(new IdentityResourceProperty - { - Key = model.Key, - Value = model.Value, - }); - - _configurationDbContext.SaveChanges(); + _configurationDbContext.SaveChanges(); - return RedirectToAction(nameof(Properties), new { id = identity.Id }); - } + return RedirectToAction(nameof(Properties), new { id = identity.Id }); + } - [HttpGet] - public IActionResult DeleteProperty(int id) - { - var prop = _configurationDbContext.Set() - .Include(x => x.IdentityResource) - .FirstOrDefault(x => x.Id == id); - return View(IdentityResourcePropertyModel.FromEntity(prop)); - } + [HttpGet] + public IActionResult DeleteProperty(int id) + { + var prop = _configurationDbContext.Set() + .Include(x => x.IdentityResource) + .FirstOrDefault(x => x.Id == id); + return View(IdentityResourcePropertyModel.FromEntity(prop)); + } - [HttpPost] - public IActionResult DeleteProperty(IdentityResourcePropertyModel model) - { - var identity = _configurationDbContext.IdentityResources - .Include(x => x.Properties) - .FirstOrDefault(x => x.Id == model.IdentityResource.Id); - var prop = identity.Properties.FirstOrDefault(x => x.Id == model.Id); - identity.Properties.Remove(prop); - _configurationDbContext.SaveChanges(); - - return RedirectToAction(nameof(Properties), new { id = identity.Id }); - } + [HttpPost] + public IActionResult DeleteProperty(IdentityResourcePropertyModel model) + { + var identity = _configurationDbContext.IdentityResources + .Include(x => x.Properties) + .FirstOrDefault(x => x.Id == model.IdentityResource.Id); + var prop = identity.Properties.FirstOrDefault(x => x.Id == model.Id); + identity.Properties.Remove(prop); + _configurationDbContext.SaveChanges(); + + return RedirectToAction(nameof(Properties), new { id = identity.Id }); + } - public IActionResult GetClaims() + public IActionResult GetClaims() + { + // http://openid.net/specs/openid-connect-core-1_0.html#StandardClaims + var standardClaims = new List { - // http://openid.net/specs/openid-connect-core-1_0.html#StandardClaims - var standardClaims = new List - { - "name", - "given_name", - "family_name", - "middle_name", - "nickname", - "preferred_username", - "profile", - "picture", - "website", - "gender", - "birthdate", - "zoneinfo", - "locale", - "address", - "updated_at", - }; - - return Ok(standardClaims); - } + "name", + "given_name", + "family_name", + "middle_name", + "nickname", + "preferred_username", + "profile", + "picture", + "website", + "gender", + "birthdate", + "zoneinfo", + "locale", + "address", + "updated_at", + }; + + return Ok(standardClaims); } } \ No newline at end of file diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Controllers/RoleController.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Controllers/RoleController.cs index f3650a088..252e95d69 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Controllers/RoleController.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Controllers/RoleController.cs @@ -8,136 +8,135 @@ using ClassifiedAds.IdentityServer.Models.RoleModels; using Microsoft.AspNetCore.Mvc; -namespace ClassifiedAds.IdentityServer.Controllers +namespace ClassifiedAds.IdentityServer.Controllers; + +public class RoleController : Controller { - public class RoleController : Controller + private readonly Dispatcher _dispatcher; + + public RoleController(Dispatcher dispatcher) { - private readonly Dispatcher _dispatcher; + _dispatcher = dispatcher; + } - public RoleController(Dispatcher dispatcher) + public async Task Index() + { + var roles = await _dispatcher.DispatchAsync(new GetRolesQuery { AsNoTracking = true }); + return View(roles); + } + + public async Task Edit(Guid id) + { + Role role; + if (id == Guid.Empty) { - _dispatcher = dispatcher; + role = new Role(); } - - public async Task Index() + else { - var roles = await _dispatcher.DispatchAsync(new GetRolesQuery { AsNoTracking = true }); - return View(roles); + role = await _dispatcher.DispatchAsync(new GetRoleQuery { Id = id, AsNoTracking = true }); } - public async Task Edit(Guid id) - { - Role role; - if (id == Guid.Empty) - { - role = new Role(); - } - else - { - role = await _dispatcher.DispatchAsync(new GetRoleQuery { Id = id, AsNoTracking = true }); - } + var model = role; - var model = role; + return View(model); + } - return View(model); - } + [HttpPost] + public async Task Edit(Role model) + { + Role role; - [HttpPost] - public async Task Edit(Role model) + if (model.Id == Guid.Empty) { - Role role; - - if (model.Id == Guid.Empty) - { - role = new Role - { - Name = model.Name, - NormalizedName = model.Name.ToUpper(), - }; - - await _dispatcher.DispatchAsync(new AddUpdateRoleCommand { Role = role }); - } - else + role = new Role { - role = await _dispatcher.DispatchAsync(new GetRoleQuery { Id = model.Id }); - role.Name = model.Name; - role.NormalizedName = model.Name.ToUpper(); - await _dispatcher.DispatchAsync(new AddUpdateRoleCommand { Role = role }); - } + Name = model.Name, + NormalizedName = model.Name.ToUpper(), + }; - return RedirectToAction(nameof(Edit), new { role.Id }); + await _dispatcher.DispatchAsync(new AddUpdateRoleCommand { Role = role }); } - - public async Task Delete(Guid id) + else { - var role = await _dispatcher.DispatchAsync(new GetRoleQuery { Id = id, AsNoTracking = true }); - return View(role); + role = await _dispatcher.DispatchAsync(new GetRoleQuery { Id = model.Id }); + role.Name = model.Name; + role.NormalizedName = model.Name.ToUpper(); + await _dispatcher.DispatchAsync(new AddUpdateRoleCommand { Role = role }); } - [HttpPost] - public async Task Delete(Role model) - { - var role = await _dispatcher.DispatchAsync(new GetRoleQuery { Id = model.Id }); - await _dispatcher.DispatchAsync(new DeleteRoleCommand { Role = role }); + return RedirectToAction(nameof(Edit), new { role.Id }); + } - return RedirectToAction(nameof(Index)); - } + public async Task Delete(Guid id) + { + var role = await _dispatcher.DispatchAsync(new GetRoleQuery { Id = id, AsNoTracking = true }); + return View(role); + } - public async Task Claims(Guid id) - { - var role = await _dispatcher.DispatchAsync(new GetRoleQuery { Id = id, IncludeClaims = true, AsNoTracking = true }); + [HttpPost] + public async Task Delete(Role model) + { + var role = await _dispatcher.DispatchAsync(new GetRoleQuery { Id = model.Id }); + await _dispatcher.DispatchAsync(new DeleteRoleCommand { Role = role }); - return View(ClaimsModel.FromEntity(role)); - } + return RedirectToAction(nameof(Index)); + } + + public async Task Claims(Guid id) + { + var role = await _dispatcher.DispatchAsync(new GetRoleQuery { Id = id, IncludeClaims = true, AsNoTracking = true }); - [HttpPost] - public async Task Claims(ClaimModel model) + return View(ClaimsModel.FromEntity(role)); + } + + [HttpPost] + public async Task Claims(ClaimModel model) + { + var role = await _dispatcher.DispatchAsync(new GetRoleQuery { Id = model.Role.Id, IncludeClaims = true }); + + var claim = new RoleClaim { - var role = await _dispatcher.DispatchAsync(new GetRoleQuery { Id = model.Role.Id, IncludeClaims = true }); + Type = model.Type, + Value = model.Value, + }; - var claim = new RoleClaim - { - Type = model.Type, - Value = model.Value, - }; + await _dispatcher.DispatchAsync(new AddClaimCommand { Role = role, Claim = claim }); - await _dispatcher.DispatchAsync(new AddClaimCommand { Role = role, Claim = claim }); + return RedirectToAction(nameof(Claims), new { id = role.Id }); + } - return RedirectToAction(nameof(Claims), new { id = role.Id }); - } + public async Task DeleteClaim(Guid roleId, Guid claimId) + { + var role = await _dispatcher.DispatchAsync(new GetRoleQuery { Id = roleId, IncludeClaims = true, AsNoTracking = true }); + var claim = role.Claims.FirstOrDefault(x => x.Id == claimId); - public async Task DeleteClaim(Guid roleId, Guid claimId) - { - var role = await _dispatcher.DispatchAsync(new GetRoleQuery { Id = roleId, IncludeClaims = true, AsNoTracking = true }); - var claim = role.Claims.FirstOrDefault(x => x.Id == claimId); + return View(ClaimModel.FromEntity(claim)); + } - return View(ClaimModel.FromEntity(claim)); - } + [HttpPost] + public async Task DeleteClaim(ClaimModel model) + { + var role = await _dispatcher.DispatchAsync(new GetRoleQuery { Id = model.Role.Id, IncludeClaims = true }); - [HttpPost] - public async Task DeleteClaim(ClaimModel model) - { - var role = await _dispatcher.DispatchAsync(new GetRoleQuery { Id = model.Role.Id, IncludeClaims = true }); + var claim = role.Claims.FirstOrDefault(x => x.Id == model.Id); - var claim = role.Claims.FirstOrDefault(x => x.Id == model.Id); + await _dispatcher.DispatchAsync(new DeleteClaimCommand { Role = role, Claim = claim }); - await _dispatcher.DispatchAsync(new DeleteClaimCommand { Role = role, Claim = claim }); + return RedirectToAction(nameof(Claims), new { id = role.Id }); + } - return RedirectToAction(nameof(Claims), new { id = role.Id }); - } + public async Task Users(Guid id) + { + var role = await _dispatcher.DispatchAsync(new GetRoleQuery { Id = id, IncludeUsers = true, AsNoTracking = true }); - public async Task Users(Guid id) + var users = role.UserRoles.Select(x => x.User).ToList(); + var model = new UsersModel { - var role = await _dispatcher.DispatchAsync(new GetRoleQuery { Id = id, IncludeUsers = true, AsNoTracking = true }); - - var users = role.UserRoles.Select(x => x.User).ToList(); - var model = new UsersModel - { - Role = role, - Users = users, - }; + Role = role, + Users = users, + }; - return View(model); - } + return View(model); } } \ No newline at end of file diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Controllers/UserController.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Controllers/UserController.cs index 261cd5f6a..6a881107a 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Controllers/UserController.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Controllers/UserController.cs @@ -12,219 +12,218 @@ using System.Linq; using System.Threading.Tasks; -namespace ClassifiedAds.IdentityServer.Controllers +namespace ClassifiedAds.IdentityServer.Controllers; + +public class UserController : Controller { - public class UserController : Controller + private readonly Dispatcher _dispatcher; + private readonly UserManager _userManager; + private readonly IDateTimeProvider _dateTimeProvider; + + public UserController(Dispatcher dispatcher, + UserManager userManager, + ILogger logger, + IDateTimeProvider dateTimeProvider) { - private readonly Dispatcher _dispatcher; - private readonly UserManager _userManager; - private readonly IDateTimeProvider _dateTimeProvider; - - public UserController(Dispatcher dispatcher, - UserManager userManager, - ILogger logger, - IDateTimeProvider dateTimeProvider) - { - _dispatcher = dispatcher; - _userManager = userManager; - _dateTimeProvider = dateTimeProvider; - logger.LogInformation("UserController"); - } + _dispatcher = dispatcher; + _userManager = userManager; + _dateTimeProvider = dateTimeProvider; + logger.LogInformation("UserController"); + } - public async Task Index() - { - var users = await _dispatcher.DispatchAsync(new GetUsersQuery { AsNoTracking = true }); - return View(users); - } + public async Task Index() + { + var users = await _dispatcher.DispatchAsync(new GetUsersQuery { AsNoTracking = true }); + return View(users); + } - public async Task Profile(Guid id) - { - var user = id != Guid.Empty - ? await _dispatcher.DispatchAsync(new GetUserQuery { Id = id, AsNoTracking = true }) - : new User(); - return View(user); - } + public async Task Profile(Guid id) + { + var user = id != Guid.Empty + ? await _dispatcher.DispatchAsync(new GetUserQuery { Id = id, AsNoTracking = true }) + : new User(); + return View(user); + } - [HttpPost] - public async Task Profile(User model) + [HttpPost] + public async Task Profile(User model) + { + User user; + if (model.Id != Guid.Empty) { - User user; - if (model.Id != Guid.Empty) - { - user = await _dispatcher.DispatchAsync(new GetUserQuery { Id = model.Id }); - } - else - { - user = new User(); - } - - user.UserName = model.UserName; - user.NormalizedUserName = model.UserName.ToUpper(); - user.Email = model.Email; - user.NormalizedEmail = model.Email.ToUpper(); - user.EmailConfirmed = model.EmailConfirmed; - user.PhoneNumber = model.PhoneNumber; - user.PhoneNumberConfirmed = model.PhoneNumberConfirmed; - user.TwoFactorEnabled = model.TwoFactorEnabled; - user.LockoutEnabled = model.LockoutEnabled; - user.LockoutEnd = model.LockoutEnd; - user.AccessFailedCount = model.AccessFailedCount; - - _ = model.Id != Guid.Empty - ? await _userManager.UpdateAsync(user) - : await _userManager.CreateAsync(user); - - return RedirectToAction(nameof(Profile), new { user.Id }); + user = await _dispatcher.DispatchAsync(new GetUserQuery { Id = model.Id }); } - - public async Task ChangePassword(Guid id) + else { - var user = await _dispatcher.DispatchAsync(new GetUserQuery { Id = id, AsNoTracking = true }); - return View(ChangePasswordModel.FromEntity(user)); + user = new User(); } - public async Task Delete(Guid id) - { - var user = await _dispatcher.DispatchAsync(new GetUserQuery { Id = id, AsNoTracking = true }); - return View(user); - } + user.UserName = model.UserName; + user.NormalizedUserName = model.UserName.ToUpper(); + user.Email = model.Email; + user.NormalizedEmail = model.Email.ToUpper(); + user.EmailConfirmed = model.EmailConfirmed; + user.PhoneNumber = model.PhoneNumber; + user.PhoneNumberConfirmed = model.PhoneNumberConfirmed; + user.TwoFactorEnabled = model.TwoFactorEnabled; + user.LockoutEnabled = model.LockoutEnabled; + user.LockoutEnd = model.LockoutEnd; + user.AccessFailedCount = model.AccessFailedCount; - [HttpPost] - public async Task Delete(User model) - { - var user = await _dispatcher.DispatchAsync(new GetUserQuery { Id = model.Id }); - await _dispatcher.DispatchAsync(new DeleteUserCommand { User = user }); - return RedirectToAction(nameof(Index)); - } + _ = model.Id != Guid.Empty + ? await _userManager.UpdateAsync(user) + : await _userManager.CreateAsync(user); - [HttpPost] - public async Task ChangePassword(ChangePasswordModel model) - { - if (!ModelState.IsValid) - { - return View(model); - } + return RedirectToAction(nameof(Profile), new { user.Id }); + } - var user = await _dispatcher.DispatchAsync(new GetUserQuery { Id = model.Id }); - var token = await _userManager.GeneratePasswordResetTokenAsync(user); - var rs = await _userManager.ResetPasswordAsync(user, token, model.ConfirmPassword); + public async Task ChangePassword(Guid id) + { + var user = await _dispatcher.DispatchAsync(new GetUserQuery { Id = id, AsNoTracking = true }); + return View(ChangePasswordModel.FromEntity(user)); + } - if (rs.Succeeded) - { - return RedirectToAction(nameof(Profile), new { model.Id }); - } + public async Task Delete(Guid id) + { + var user = await _dispatcher.DispatchAsync(new GetUserQuery { Id = id, AsNoTracking = true }); + return View(user); + } - foreach (var error in rs.Errors) - { - ModelState.AddModelError(string.Empty, error.Description); - } + [HttpPost] + public async Task Delete(User model) + { + var user = await _dispatcher.DispatchAsync(new GetUserQuery { Id = model.Id }); + await _dispatcher.DispatchAsync(new DeleteUserCommand { User = user }); + return RedirectToAction(nameof(Index)); + } - return View(ChangePasswordModel.FromEntity(user)); + [HttpPost] + public async Task ChangePassword(ChangePasswordModel model) + { + if (!ModelState.IsValid) + { + return View(model); } - public async Task Claims(Guid id) + var user = await _dispatcher.DispatchAsync(new GetUserQuery { Id = model.Id }); + var token = await _userManager.GeneratePasswordResetTokenAsync(user); + var rs = await _userManager.ResetPasswordAsync(user, token, model.ConfirmPassword); + + if (rs.Succeeded) { - var user = await _dispatcher.DispatchAsync(new GetUserQuery { Id = id, IncludeClaims = true, AsNoTracking = true }); - return View(ClaimsModel.FromEntity(user)); + return RedirectToAction(nameof(Profile), new { model.Id }); } - [HttpPost] - public async Task Claims(ClaimModel model) + foreach (var error in rs.Errors) { - var user = await _dispatcher.DispatchAsync(new GetUserQuery { Id = model.User.Id, IncludeClaims = true }); - await _dispatcher.DispatchAsync(new AddClaimCommand - { - User = user, - Claim = new UserClaim - { - Type = model.Type, - Value = model.Value, - }, - }); - - return RedirectToAction(nameof(Claims), new { id = user.Id }); + ModelState.AddModelError(string.Empty, error.Description); } - public async Task DeleteClaim(Guid userId, Guid claimId) - { - var user = await _dispatcher.DispatchAsync(new GetUserQuery { Id = userId, IncludeClaims = true, AsNoTracking = true }); - var claim = user.Claims.FirstOrDefault(x => x.Id == claimId); + return View(ChangePasswordModel.FromEntity(user)); + } - return View(ClaimModel.FromEntity(claim)); - } + public async Task Claims(Guid id) + { + var user = await _dispatcher.DispatchAsync(new GetUserQuery { Id = id, IncludeClaims = true, AsNoTracking = true }); + return View(ClaimsModel.FromEntity(user)); + } - [HttpPost] - public async Task DeleteClaim(ClaimModel model) + [HttpPost] + public async Task Claims(ClaimModel model) + { + var user = await _dispatcher.DispatchAsync(new GetUserQuery { Id = model.User.Id, IncludeClaims = true }); + await _dispatcher.DispatchAsync(new AddClaimCommand { - var user = await _dispatcher.DispatchAsync(new GetUserQuery { Id = model.User.Id, IncludeClaims = true }); + User = user, + Claim = new UserClaim + { + Type = model.Type, + Value = model.Value, + }, + }); - var claim = user.Claims.FirstOrDefault(x => x.Id == model.Id); + return RedirectToAction(nameof(Claims), new { id = user.Id }); + } - await _dispatcher.DispatchAsync(new DeleteClaimCommand - { - User = user, - Claim = claim, - }); + public async Task DeleteClaim(Guid userId, Guid claimId) + { + var user = await _dispatcher.DispatchAsync(new GetUserQuery { Id = userId, IncludeClaims = true, AsNoTracking = true }); + var claim = user.Claims.FirstOrDefault(x => x.Id == claimId); - return RedirectToAction(nameof(Claims), new { id = user.Id }); - } + return View(ClaimModel.FromEntity(claim)); + } + + [HttpPost] + public async Task DeleteClaim(ClaimModel model) + { + var user = await _dispatcher.DispatchAsync(new GetUserQuery { Id = model.User.Id, IncludeClaims = true }); - public async Task Roles(Guid id) + var claim = user.Claims.FirstOrDefault(x => x.Id == model.Id); + + await _dispatcher.DispatchAsync(new DeleteClaimCommand { - var user = await _dispatcher.DispatchAsync(new GetUserQuery { Id = id, IncludeRoles = true, AsNoTracking = true }); + User = user, + Claim = claim, + }); - var roles = await _dispatcher.DispatchAsync(new GetRolesQuery { AsNoTracking = true }); + return RedirectToAction(nameof(Claims), new { id = user.Id }); + } - var model = new RolesModel - { - User = user, - UserRoles = user.UserRoles.Select(x => new RoleModel { Role = x.Role, RoleId = x.RoleId }).ToList(), - Roles = roles.Where(x => !user.UserRoles.Any(y => y.RoleId == x.Id)).ToList(), - }; + public async Task Roles(Guid id) + { + var user = await _dispatcher.DispatchAsync(new GetUserQuery { Id = id, IncludeRoles = true, AsNoTracking = true }); - return View(model); - } + var roles = await _dispatcher.DispatchAsync(new GetRolesQuery { AsNoTracking = true }); - [HttpPost] - public async Task Roles(RolesModel model) + var model = new RolesModel { - var user = await _dispatcher.DispatchAsync(new GetUserQuery { Id = model.User.Id, IncludeUserRoles = true }); + User = user, + UserRoles = user.UserRoles.Select(x => new RoleModel { Role = x.Role, RoleId = x.RoleId }).ToList(), + Roles = roles.Where(x => !user.UserRoles.Any(y => y.RoleId == x.Id)).ToList(), + }; - await _dispatcher.DispatchAsync(new AddRoleCommand - { - User = user, - Role = new UserRole - { - RoleId = model.Role.RoleId, - }, - }); - - return RedirectToAction(nameof(Roles), new { model.User.Id }); - } + return View(model); + } + + [HttpPost] + public async Task Roles(RolesModel model) + { + var user = await _dispatcher.DispatchAsync(new GetUserQuery { Id = model.User.Id, IncludeUserRoles = true }); - public async Task DeleteRole(Guid id, Guid roleId) + await _dispatcher.DispatchAsync(new AddRoleCommand { - var user = await _dispatcher.DispatchAsync(new GetUserQuery { Id = id, IncludeRoles = true, AsNoTracking = true }); - var role = user.UserRoles.FirstOrDefault(x => x.RoleId == roleId); - var model = new RoleModel { User = user, Role = role.Role }; + User = user, + Role = new UserRole + { + RoleId = model.Role.RoleId, + }, + }); - return View(model); - } + return RedirectToAction(nameof(Roles), new { model.User.Id }); + } - [HttpPost] - public async Task DeleteRole(RoleModel model) - { - var user = await _dispatcher.DispatchAsync(new GetUserQuery { Id = model.User.Id, IncludeUserRoles = true }); + public async Task DeleteRole(Guid id, Guid roleId) + { + var user = await _dispatcher.DispatchAsync(new GetUserQuery { Id = id, IncludeRoles = true, AsNoTracking = true }); + var role = user.UserRoles.FirstOrDefault(x => x.RoleId == roleId); + var model = new RoleModel { User = user, Role = role.Role }; - var role = user.UserRoles.FirstOrDefault(x => x.RoleId == model.Role.Id); + return View(model); + } - await _dispatcher.DispatchAsync(new DeleteRoleCommand - { - User = user, - Role = role, - }); + [HttpPost] + public async Task DeleteRole(RoleModel model) + { + var user = await _dispatcher.DispatchAsync(new GetUserQuery { Id = model.User.Id, IncludeUserRoles = true }); - return RedirectToAction(nameof(Roles), new { model.User.Id }); - } + var role = user.UserRoles.FirstOrDefault(x => x.RoleId == model.Role.Id); + + await _dispatcher.DispatchAsync(new DeleteRoleCommand + { + User = user, + Role = role, + }); + + return RedirectToAction(nameof(Roles), new { model.User.Id }); } } \ No newline at end of file diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/ApiResourceModels/ApiResourceModel.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/ApiResourceModels/ApiResourceModel.cs index e153bd8e3..cd11030c6 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/ApiResourceModels/ApiResourceModel.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/ApiResourceModels/ApiResourceModel.cs @@ -4,52 +4,51 @@ using System.Linq; using System.Threading.Tasks; -namespace ClassifiedAds.IdentityServer.Models.ApiResourceModels +namespace ClassifiedAds.IdentityServer.Models.ApiResourceModels; + +public class ApiResourceModel { - public class ApiResourceModel - { - public int Id { get; set; } - public bool Enabled { get; set; } - public string Name { get; set; } - public string DisplayName { get; set; } - public string Description { get; set; } - public List Secrets { get; set; } - public List Scopes { get; set; } - public List UserClaims { get; set; } - public string UserClaimsItems { get; set; } - public List Properties { get; set; } - public DateTime Created { get; set; } - public DateTime? Updated { get; set; } - public DateTime? LastAccessed { get; set; } - public bool NonEditable { get; set; } + public int Id { get; set; } + public bool Enabled { get; set; } + public string Name { get; set; } + public string DisplayName { get; set; } + public string Description { get; set; } + public List Secrets { get; set; } + public List Scopes { get; set; } + public List UserClaims { get; set; } + public string UserClaimsItems { get; set; } + public List Properties { get; set; } + public DateTime Created { get; set; } + public DateTime? Updated { get; set; } + public DateTime? LastAccessed { get; set; } + public bool NonEditable { get; set; } - public static ApiResourceModel FromEntity(ApiResource apiResource) + public static ApiResourceModel FromEntity(ApiResource apiResource) + { + return new ApiResourceModel { - return new ApiResourceModel - { - Id = apiResource.Id, - Enabled = apiResource.Enabled, - Name = apiResource.Name, - DisplayName = apiResource.DisplayName, - Description = apiResource.Description, - Secrets = apiResource.Secrets, - Scopes = apiResource.Scopes, - UserClaims = apiResource.UserClaims, - Properties = apiResource.Properties, - Created = apiResource.Created, - Updated = apiResource.Updated, - LastAccessed = apiResource.LastAccessed, - NonEditable = apiResource.NonEditable, - }; - } + Id = apiResource.Id, + Enabled = apiResource.Enabled, + Name = apiResource.Name, + DisplayName = apiResource.DisplayName, + Description = apiResource.Description, + Secrets = apiResource.Secrets, + Scopes = apiResource.Scopes, + UserClaims = apiResource.UserClaims, + Properties = apiResource.Properties, + Created = apiResource.Created, + Updated = apiResource.Updated, + LastAccessed = apiResource.LastAccessed, + NonEditable = apiResource.NonEditable, + }; + } - public void UpdateEntity(ApiResource entity) - { - entity.Enabled = Enabled; - entity.Name = Name; - entity.DisplayName = DisplayName; - entity.Description = Description; - entity.NonEditable = NonEditable; - } + public void UpdateEntity(ApiResource entity) + { + entity.Enabled = Enabled; + entity.Name = Name; + entity.DisplayName = DisplayName; + entity.Description = Description; + entity.NonEditable = NonEditable; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/ApiResourceModels/ApiResourcePropertyModel.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/ApiResourceModels/ApiResourcePropertyModel.cs index 5c9225ae5..76316f2b1 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/ApiResourceModels/ApiResourcePropertyModel.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/ApiResourceModels/ApiResourcePropertyModel.cs @@ -1,27 +1,26 @@ using IdentityServer4.EntityFramework.Entities; -namespace ClassifiedAds.IdentityServer.Models.ApiResourceModels +namespace ClassifiedAds.IdentityServer.Models.ApiResourceModels; + +public class ApiResourcePropertyModel { - public class ApiResourcePropertyModel - { - public int Id { get; set; } - public string Key { get; set; } - public string Value { get; set; } - public ApiResourceModel ApiResource { get; set; } + public int Id { get; set; } + public string Key { get; set; } + public string Value { get; set; } + public ApiResourceModel ApiResource { get; set; } - public static ApiResourcePropertyModel FromEntity(ApiResourceProperty entity) + public static ApiResourcePropertyModel FromEntity(ApiResourceProperty entity) + { + return new ApiResourcePropertyModel { - return new ApiResourcePropertyModel + Id = entity.Id, + Key = entity.Key, + Value = entity.Value, + ApiResource = new ApiResourceModel { - Id = entity.Id, - Key = entity.Key, - Value = entity.Value, - ApiResource = new ApiResourceModel - { - Id = entity.ApiResource.Id, - Name = entity.ApiResource.Name, - }, - }; - } + Id = entity.ApiResource.Id, + Name = entity.ApiResource.Name, + }, + }; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/ApiResourceModels/PropertiesModel.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/ApiResourceModels/PropertiesModel.cs index 2ab1657d8..65da923f7 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/ApiResourceModels/PropertiesModel.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/ApiResourceModels/PropertiesModel.cs @@ -2,29 +2,28 @@ using System.Collections.Generic; using System.Linq; -namespace ClassifiedAds.IdentityServer.Models.ApiResourceModels +namespace ClassifiedAds.IdentityServer.Models.ApiResourceModels; + +public class PropertiesModel { - public class PropertiesModel - { - public int ApiResourceId { get; set; } - public string ApiResourceName { get; set; } - public string Key { get; set; } - public string Value { get; set; } - public List Properties { get; set; } + public int ApiResourceId { get; set; } + public string ApiResourceName { get; set; } + public string Key { get; set; } + public string Value { get; set; } + public List Properties { get; set; } - public static PropertiesModel FromEntity(ApiResource apiResource) + public static PropertiesModel FromEntity(ApiResource apiResource) + { + return new PropertiesModel { - return new PropertiesModel + ApiResourceId = apiResource.Id, + ApiResourceName = apiResource.Name, + Properties = apiResource.Properties?.Select(x => new ApiResourcePropertyModel { - ApiResourceId = apiResource.Id, - ApiResourceName = apiResource.Name, - Properties = apiResource.Properties?.Select(x => new ApiResourcePropertyModel - { - Id = x.Id, - Key = x.Key, - Value = x.Value, - })?.ToList(), - }; - } + Id = x.Id, + Key = x.Key, + Value = x.Value, + })?.ToList(), + }; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/ApiResourceModels/ScopeModel.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/ApiResourceModels/ScopeModel.cs index c2640fa66..e3dfe50e5 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/ApiResourceModels/ScopeModel.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/ApiResourceModels/ScopeModel.cs @@ -4,31 +4,30 @@ using System.Linq; using System.Threading.Tasks; -namespace ClassifiedAds.IdentityServer.Models.ApiResourceModels +namespace ClassifiedAds.IdentityServer.Models.ApiResourceModels; + +public class ScopeModel { - public class ScopeModel - { - public int Id { get; set; } - public string Scope { get; set; } - public int ApiResourceId { get; set; } - public ApiResource ApiResource { get; set; } - public string ApiResourceName { get; set; } + public int Id { get; set; } + public string Scope { get; set; } + public int ApiResourceId { get; set; } + public ApiResource ApiResource { get; set; } + public string ApiResourceName { get; set; } - public static ScopeModel FromEntity(ApiResourceScope apiScope) + public static ScopeModel FromEntity(ApiResourceScope apiScope) + { + return new ScopeModel { - return new ScopeModel - { - Id = apiScope.Id, - Scope = apiScope.Scope, - ApiResourceId = apiScope.ApiResourceId, - ApiResourceName = apiScope.ApiResource.Name, - ApiResource = apiScope.ApiResource, - }; - } + Id = apiScope.Id, + Scope = apiScope.Scope, + ApiResourceId = apiScope.ApiResourceId, + ApiResourceName = apiScope.ApiResource.Name, + ApiResource = apiScope.ApiResource, + }; + } - public void UpdateEntity(ApiResourceScope entity) - { - entity.Scope = Scope; - } + public void UpdateEntity(ApiResourceScope entity) + { + entity.Scope = Scope; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/ApiResourceModels/ScopesModel.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/ApiResourceModels/ScopesModel.cs index 0a442f8ca..f63e40aec 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/ApiResourceModels/ScopesModel.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/ApiResourceModels/ScopesModel.cs @@ -4,27 +4,26 @@ using System.Linq; using System.Threading.Tasks; -namespace ClassifiedAds.IdentityServer.Models.ApiResourceModels +namespace ClassifiedAds.IdentityServer.Models.ApiResourceModels; + +public class ScopesModel : ScopeModel { - public class ScopesModel : ScopeModel - { - public List Scopes { get; set; } + public List Scopes { get; set; } - public List ApiScopes { get; set; } + public List ApiScopes { get; set; } - public void UpdateEntity(ApiScope entity) - { + public void UpdateEntity(ApiScope entity) + { - } + } - public static ScopesModel FromEntity(ApiResource apiResource) + public static ScopesModel FromEntity(ApiResource apiResource) + { + return new ScopesModel { - return new ScopesModel - { - ApiResourceId = apiResource.Id, - ApiResourceName = apiResource.Name, - Scopes = apiResource.Scopes?.Select(x => FromEntity(x))?.ToList(), - }; - } + ApiResourceId = apiResource.Id, + ApiResourceName = apiResource.Name, + Scopes = apiResource.Scopes?.Select(x => FromEntity(x))?.ToList(), + }; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/ApiResourceModels/SecretModel.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/ApiResourceModels/SecretModel.cs index 8cc38c4ae..e3f9f5875 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/ApiResourceModels/SecretModel.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/ApiResourceModels/SecretModel.cs @@ -4,34 +4,33 @@ using System.Linq; using System.Threading.Tasks; -namespace ClassifiedAds.IdentityServer.Models.ApiResourceModels +namespace ClassifiedAds.IdentityServer.Models.ApiResourceModels; + +public class SecretModel { - public class SecretModel - { - public int Id { get; set; } - public string Description { get; set; } - public string Value { get; set; } - public DateTime? Expiration { get; set; } - public string Type { get; set; } - public string HashType { get; set; } - public DateTime Created { get; set; } - public int ApiResourceId { get; set; } - public string ApiResourceName { get; set; } - public ApiResourceModel ApiResource { get; set; } + public int Id { get; set; } + public string Description { get; set; } + public string Value { get; set; } + public DateTime? Expiration { get; set; } + public string Type { get; set; } + public string HashType { get; set; } + public DateTime Created { get; set; } + public int ApiResourceId { get; set; } + public string ApiResourceName { get; set; } + public ApiResourceModel ApiResource { get; set; } - public static SecretModel FromEntity(ApiResourceSecret secret) + public static SecretModel FromEntity(ApiResourceSecret secret) + { + return new SecretModel { - return new SecretModel - { - Id = secret.Id, - Description = secret.Description, - Value = secret.Value, - Expiration = secret.Expiration, - Type = secret.Type, - Created = secret.Created, - ApiResourceId = secret.ApiResource.Id, - ApiResourceName = secret.ApiResource.Name, - }; - } + Id = secret.Id, + Description = secret.Description, + Value = secret.Value, + Expiration = secret.Expiration, + Type = secret.Type, + Created = secret.Created, + ApiResourceId = secret.ApiResource.Id, + ApiResourceName = secret.ApiResource.Name, + }; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/ApiResourceModels/SecretsModel.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/ApiResourceModels/SecretsModel.cs index e66ae3d6e..1a856c334 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/ApiResourceModels/SecretsModel.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/ApiResourceModels/SecretsModel.cs @@ -5,57 +5,56 @@ using System.Linq; using System.Threading.Tasks; -namespace ClassifiedAds.IdentityServer.Models.ApiResourceModels +namespace ClassifiedAds.IdentityServer.Models.ApiResourceModels; + +public class SecretsModel : SecretModel { - public class SecretsModel : SecretModel + public List Secrets { get; set; } + public List TypeList { get; } = new List { - public List Secrets { get; set; } - public List TypeList { get; } = new List - { - "SharedSecret", - "X509Thumbprint", - "X509Name", - "X509CertificateBase64", - }; - public List HashTypes { get; } = new List - { - "Sha256", - "Sha512", - }; + "SharedSecret", + "X509Thumbprint", + "X509Name", + "X509CertificateBase64", + }; + public List HashTypes { get; } = new List + { + "Sha256", + "Sha512", + }; - public void HashSecret() + public void HashSecret() + { + if (Type != "SharedSecret") { - if (Type != "SharedSecret") - { - return; - } - - if (HashType == "Sha256") - { - Value = Value.Sha256(); - } - else if (HashType == "Sha512") - { - Value = Value.Sha512(); - } + return; } - public void UpdateEntity(IdentityServer4.EntityFramework.Entities.Secret entity) + if (HashType == "Sha256") { - entity.Description = Description; - entity.Value = Value; - entity.Expiration = Expiration; - entity.Type = Type; + Value = Value.Sha256(); } - - public static SecretsModel FromEntity(IdentityServer4.EntityFramework.Entities.ApiResource apiResource) + else if (HashType == "Sha512") { - return new SecretsModel - { - ApiResourceId = apiResource.Id, - ApiResourceName = apiResource.Name, - Secrets = apiResource.Secrets?.Select(x => FromEntity(x))?.ToList(), - }; + Value = Value.Sha512(); } } + + public void UpdateEntity(IdentityServer4.EntityFramework.Entities.Secret entity) + { + entity.Description = Description; + entity.Value = Value; + entity.Expiration = Expiration; + entity.Type = Type; + } + + public static SecretsModel FromEntity(IdentityServer4.EntityFramework.Entities.ApiResource apiResource) + { + return new SecretsModel + { + ApiResourceId = apiResource.Id, + ApiResourceName = apiResource.Name, + Secrets = apiResource.Secrets?.Select(x => FromEntity(x))?.ToList(), + }; + } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/ApiScopeModels/ApiScopeModel.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/ApiScopeModels/ApiScopeModel.cs index 6ce2b741d..1661fe5be 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/ApiScopeModels/ApiScopeModel.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/ApiScopeModels/ApiScopeModel.cs @@ -4,47 +4,46 @@ using System.Linq; using System.Threading.Tasks; -namespace ClassifiedAds.IdentityServer.Models.ApiScopeModels +namespace ClassifiedAds.IdentityServer.Models.ApiScopeModels; + +public class ApiScopeModel { - public class ApiScopeModel - { - public int Id { get; set; } - public bool Enabled { get; set; } - public string Name { get; set; } - public string DisplayName { get; set; } - public string Description { get; set; } - public bool Required { get; set; } - public bool Emphasize { get; set; } - public bool ShowInDiscoveryDocument { get; set; } - public List UserClaims { get; set; } - public string UserClaimsItems { get; set; } - public List Properties { get; set; } + public int Id { get; set; } + public bool Enabled { get; set; } + public string Name { get; set; } + public string DisplayName { get; set; } + public string Description { get; set; } + public bool Required { get; set; } + public bool Emphasize { get; set; } + public bool ShowInDiscoveryDocument { get; set; } + public List UserClaims { get; set; } + public string UserClaimsItems { get; set; } + public List Properties { get; set; } - public static ApiScopeModel FromEntity(ApiScope apiScope) + public static ApiScopeModel FromEntity(ApiScope apiScope) + { + return new ApiScopeModel { - return new ApiScopeModel - { - Id = apiScope.Id, - Enabled = apiScope.Enabled, - Name = apiScope.Name, - DisplayName = apiScope.DisplayName, - Description = apiScope.Description, - Required = apiScope.Required, - Emphasize = apiScope.Emphasize, - ShowInDiscoveryDocument = apiScope.ShowInDiscoveryDocument, - UserClaims = apiScope.UserClaims, - Properties = apiScope.Properties, - }; - } + Id = apiScope.Id, + Enabled = apiScope.Enabled, + Name = apiScope.Name, + DisplayName = apiScope.DisplayName, + Description = apiScope.Description, + Required = apiScope.Required, + Emphasize = apiScope.Emphasize, + ShowInDiscoveryDocument = apiScope.ShowInDiscoveryDocument, + UserClaims = apiScope.UserClaims, + Properties = apiScope.Properties, + }; + } - public void UpdateEntity(ApiScope entity) - { - entity.Name = Name; - entity.DisplayName = DisplayName; - entity.Description = Description; - entity.Required = Required; - entity.Emphasize = Emphasize; - entity.ShowInDiscoveryDocument = ShowInDiscoveryDocument; - } + public void UpdateEntity(ApiScope entity) + { + entity.Name = Name; + entity.DisplayName = DisplayName; + entity.Description = Description; + entity.Required = Required; + entity.Emphasize = Emphasize; + entity.ShowInDiscoveryDocument = ShowInDiscoveryDocument; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/ClientModels/ClaimModel.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/ClientModels/ClaimModel.cs index 117ae9f53..026f0faef 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/ClientModels/ClaimModel.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/ClientModels/ClaimModel.cs @@ -1,23 +1,22 @@ using IdentityServer4.EntityFramework.Entities; -namespace ClassifiedAds.IdentityServer.Models.ClientModels +namespace ClassifiedAds.IdentityServer.Models.ClientModels; + +public class ClaimModel { - public class ClaimModel - { - public int Id { get; set; } - public string Type { get; set; } - public string Value { get; set; } - public ClientModel Client { get; set; } + public int Id { get; set; } + public string Type { get; set; } + public string Value { get; set; } + public ClientModel Client { get; set; } - public static ClaimModel FromEntity(ClientClaim claim) + public static ClaimModel FromEntity(ClientClaim claim) + { + return new ClaimModel { - return new ClaimModel - { - Id = claim.Id, - Type = claim.Type, - Value = claim.Value, - Client = ClientModel.FromEntity(claim.Client), - }; - } + Id = claim.Id, + Type = claim.Type, + Value = claim.Value, + Client = ClientModel.FromEntity(claim.Client), + }; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/ClientModels/ClaimsModel.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/ClientModels/ClaimsModel.cs index e18b56af4..dcf9b7d49 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/ClientModels/ClaimsModel.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/ClientModels/ClaimsModel.cs @@ -2,21 +2,20 @@ using System.Collections.Generic; using System.Linq; -namespace ClassifiedAds.IdentityServer.Models.ClientModels +namespace ClassifiedAds.IdentityServer.Models.ClientModels; + +public class ClaimsModel : ClaimModel { - public class ClaimsModel : ClaimModel + public List Claims { get; set; } + + public static ClaimsModel FromEntity(Client client) { - public List Claims { get; set; } + var clientModel = ClientModel.FromEntity(client); - public static ClaimsModel FromEntity(Client client) + return new ClaimsModel { - var clientModel = ClientModel.FromEntity(client); - - return new ClaimsModel - { - Client = clientModel, - Claims = client.Claims?.Select(x => FromEntity(x))?.ToList(), - }; - } + Client = clientModel, + Claims = client.Claims?.Select(x => FromEntity(x))?.ToList(), + }; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/ClientModels/ClientModel.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/ClientModels/ClientModel.cs index 722a6b5a3..3622e8529 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/ClientModels/ClientModel.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/ClientModels/ClientModel.cs @@ -6,148 +6,147 @@ using System.Linq; using System.Text.Json; -namespace ClassifiedAds.IdentityServer.Models.ClientModels +namespace ClassifiedAds.IdentityServer.Models.ClientModels; + +public enum ClientType +{ + Empty = 0, + WebHybrid = 1, + Spa = 2, + Native = 3, + Machine = 4, + Device = 5, +} + +public class ClientModel : IdentityServer4.Models.Client { - public enum ClientType + public int Id { get; set; } + public ClientType ClientType { get; set; } + public string AllowedGrantTypesItems { get; set; } + public string RedirectUrisItems { get; set; } + public string PostLogoutRedirectUrisItems { get; set; } + public string AllowedScopesItems { get; set; } + public string IdentityProviderRestrictionsItems { get; set; } + public string AllowedCorsOriginsItems { get; set; } + + public string OriginalClientId { get; set; } + + public static ClientModel FromEntity(IdentityServer4.EntityFramework.Entities.Client client) { - Empty = 0, - WebHybrid = 1, - Spa = 2, - Native = 3, - Machine = 4, - Device = 5, + var config = new MapperConfiguration(cfg => cfg.CreateMap()); + var mapper = config.CreateMapper(); + var model = mapper.Map(client.ToModel()); + model.Id = client.Id; + return model; } - public class ClientModel : IdentityServer4.Models.Client + public void SetDefaultValues() { - public int Id { get; set; } - public ClientType ClientType { get; set; } - public string AllowedGrantTypesItems { get; set; } - public string RedirectUrisItems { get; set; } - public string PostLogoutRedirectUrisItems { get; set; } - public string AllowedScopesItems { get; set; } - public string IdentityProviderRestrictionsItems { get; set; } - public string AllowedCorsOriginsItems { get; set; } - - public string OriginalClientId { get; set; } - - public static ClientModel FromEntity(IdentityServer4.EntityFramework.Entities.Client client) + switch (ClientType) { - var config = new MapperConfiguration(cfg => cfg.CreateMap()); - var mapper = config.CreateMapper(); - var model = mapper.Map(client.ToModel()); - model.Id = client.Id; - return model; + case ClientType.Empty: + break; + case ClientType.WebHybrid: + AllowedGrantTypes = AllowedGrantTypes.ToList().Concat(GrantTypes.Hybrid).ToList(); + break; + case ClientType.Spa: + AllowedGrantTypes = AllowedGrantTypes.ToList().Concat(GrantTypes.Code).ToList(); + RequirePkce = true; + RequireClientSecret = false; + break; + case ClientType.Native: + AllowedGrantTypes = AllowedGrantTypes.ToList().Concat(GrantTypes.Hybrid).ToList(); + break; + case ClientType.Machine: + AllowedGrantTypes = AllowedGrantTypes.ToList().Concat(GrantTypes.ResourceOwnerPasswordAndClientCredentials).ToList(); + break; + case ClientType.Device: + AllowedGrantTypes = AllowedGrantTypes.ToList().Concat(GrantTypes.DeviceFlow).ToList(); + RequireClientSecret = false; + AllowOfflineAccess = true; + break; } + } - public void SetDefaultValues() - { - switch (ClientType) - { - case ClientType.Empty: - break; - case ClientType.WebHybrid: - AllowedGrantTypes = AllowedGrantTypes.ToList().Concat(GrantTypes.Hybrid).ToList(); - break; - case ClientType.Spa: - AllowedGrantTypes = AllowedGrantTypes.ToList().Concat(GrantTypes.Code).ToList(); - RequirePkce = true; - RequireClientSecret = false; - break; - case ClientType.Native: - AllowedGrantTypes = AllowedGrantTypes.ToList().Concat(GrantTypes.Hybrid).ToList(); - break; - case ClientType.Machine: - AllowedGrantTypes = AllowedGrantTypes.ToList().Concat(GrantTypes.ResourceOwnerPasswordAndClientCredentials).ToList(); - break; - case ClientType.Device: - AllowedGrantTypes = AllowedGrantTypes.ToList().Concat(GrantTypes.DeviceFlow).ToList(); - RequireClientSecret = false; - AllowOfflineAccess = true; - break; - } - } + public void ConvertItemsToList() + { + AllowedGrantTypes = ConvertItems(AllowedGrantTypesItems); + RedirectUris = ConvertItems(RedirectUrisItems); + PostLogoutRedirectUris = ConvertItems(PostLogoutRedirectUrisItems); + AllowedScopes = ConvertItems(AllowedScopesItems); + IdentityProviderRestrictions = ConvertItems(IdentityProviderRestrictionsItems); + AllowedCorsOrigins = ConvertItems(AllowedCorsOriginsItems); + } - public void ConvertItemsToList() - { - AllowedGrantTypes = ConvertItems(AllowedGrantTypesItems); - RedirectUris = ConvertItems(RedirectUrisItems); - PostLogoutRedirectUris = ConvertItems(PostLogoutRedirectUrisItems); - AllowedScopes = ConvertItems(AllowedScopesItems); - IdentityProviderRestrictions = ConvertItems(IdentityProviderRestrictionsItems); - AllowedCorsOrigins = ConvertItems(AllowedCorsOriginsItems); - } + private List ConvertItems(string items) + { + return string.IsNullOrWhiteSpace(items) + ? new List() + : JsonSerializer.Deserialize>(items); + } - private List ConvertItems(string items) + public void UpdateEntity(IdentityServer4.EntityFramework.Entities.Client entity) + { + entity.Enabled = Enabled; + entity.ClientId = ClientId; + entity.ProtocolType = ProtocolType; + entity.RequireClientSecret = RequireClientSecret; + entity.ClientName = ClientName; + entity.Description = Description; + entity.ClientUri = ClientUri; + entity.LogoUri = LogoUri; + entity.RequireConsent = RequireConsent; + entity.AllowRememberConsent = AllowRememberConsent; + entity.AlwaysIncludeUserClaimsInIdToken = AlwaysIncludeUserClaimsInIdToken; + entity.AllowedGrantTypes = AllowedGrantTypes.Select(x => new ClientGrantType { - return string.IsNullOrWhiteSpace(items) - ? new List() - : JsonSerializer.Deserialize>(items); - } - - public void UpdateEntity(IdentityServer4.EntityFramework.Entities.Client entity) + GrantType = x, + }).ToList(); + entity.RequirePkce = RequirePkce; + entity.AllowPlainTextPkce = AllowPlainTextPkce; + entity.AllowAccessTokensViaBrowser = AllowAccessTokensViaBrowser; + entity.RedirectUris = RedirectUris.Select(x => new ClientRedirectUri { - entity.Enabled = Enabled; - entity.ClientId = ClientId; - entity.ProtocolType = ProtocolType; - entity.RequireClientSecret = RequireClientSecret; - entity.ClientName = ClientName; - entity.Description = Description; - entity.ClientUri = ClientUri; - entity.LogoUri = LogoUri; - entity.RequireConsent = RequireConsent; - entity.AllowRememberConsent = AllowRememberConsent; - entity.AlwaysIncludeUserClaimsInIdToken = AlwaysIncludeUserClaimsInIdToken; - entity.AllowedGrantTypes = AllowedGrantTypes.Select(x => new ClientGrantType - { - GrantType = x, - }).ToList(); - entity.RequirePkce = RequirePkce; - entity.AllowPlainTextPkce = AllowPlainTextPkce; - entity.AllowAccessTokensViaBrowser = AllowAccessTokensViaBrowser; - entity.RedirectUris = RedirectUris.Select(x => new ClientRedirectUri - { - RedirectUri = x, - }).ToList(); - entity.PostLogoutRedirectUris = PostLogoutRedirectUris.Select(x => new ClientPostLogoutRedirectUri - { - PostLogoutRedirectUri = x, - }).ToList(); - entity.FrontChannelLogoutUri = FrontChannelLogoutUri; - entity.FrontChannelLogoutSessionRequired = FrontChannelLogoutSessionRequired; - entity.BackChannelLogoutUri = BackChannelLogoutUri; - entity.BackChannelLogoutSessionRequired = BackChannelLogoutSessionRequired; - entity.AllowOfflineAccess = AllowOfflineAccess; - entity.AllowedScopes = AllowedScopes.Select(x => new ClientScope - { - Scope = x, - }).ToList(); - entity.IdentityTokenLifetime = IdentityTokenLifetime; - entity.AccessTokenLifetime = AccessTokenLifetime; - entity.AuthorizationCodeLifetime = AuthorizationCodeLifetime; - entity.ConsentLifetime = ConsentLifetime; - entity.AbsoluteRefreshTokenLifetime = AbsoluteRefreshTokenLifetime; - entity.SlidingRefreshTokenLifetime = SlidingRefreshTokenLifetime; - entity.RefreshTokenUsage = (int)RefreshTokenUsage; - entity.UpdateAccessTokenClaimsOnRefresh = UpdateAccessTokenClaimsOnRefresh; - entity.RefreshTokenExpiration = (int)RefreshTokenExpiration; - entity.AccessTokenType = (int)AccessTokenType; - entity.EnableLocalLogin = EnableLocalLogin; - entity.IdentityProviderRestrictions = IdentityProviderRestrictions.Select(x => new ClientIdPRestriction - { - Provider = x, - }).ToList(); - entity.IncludeJwtId = IncludeJwtId; - entity.AlwaysSendClientClaims = AlwaysSendClientClaims; - entity.ClientClaimsPrefix = ClientClaimsPrefix; - entity.PairWiseSubjectSalt = PairWiseSubjectSalt; - entity.AllowedCorsOrigins = AllowedCorsOrigins.Select(x => new ClientCorsOrigin - { - Origin = x, - }).ToList(); - entity.UserSsoLifetime = UserSsoLifetime; - entity.UserCodeType = UserCodeType; - entity.DeviceCodeLifetime = DeviceCodeLifetime; - } + RedirectUri = x, + }).ToList(); + entity.PostLogoutRedirectUris = PostLogoutRedirectUris.Select(x => new ClientPostLogoutRedirectUri + { + PostLogoutRedirectUri = x, + }).ToList(); + entity.FrontChannelLogoutUri = FrontChannelLogoutUri; + entity.FrontChannelLogoutSessionRequired = FrontChannelLogoutSessionRequired; + entity.BackChannelLogoutUri = BackChannelLogoutUri; + entity.BackChannelLogoutSessionRequired = BackChannelLogoutSessionRequired; + entity.AllowOfflineAccess = AllowOfflineAccess; + entity.AllowedScopes = AllowedScopes.Select(x => new ClientScope + { + Scope = x, + }).ToList(); + entity.IdentityTokenLifetime = IdentityTokenLifetime; + entity.AccessTokenLifetime = AccessTokenLifetime; + entity.AuthorizationCodeLifetime = AuthorizationCodeLifetime; + entity.ConsentLifetime = ConsentLifetime; + entity.AbsoluteRefreshTokenLifetime = AbsoluteRefreshTokenLifetime; + entity.SlidingRefreshTokenLifetime = SlidingRefreshTokenLifetime; + entity.RefreshTokenUsage = (int)RefreshTokenUsage; + entity.UpdateAccessTokenClaimsOnRefresh = UpdateAccessTokenClaimsOnRefresh; + entity.RefreshTokenExpiration = (int)RefreshTokenExpiration; + entity.AccessTokenType = (int)AccessTokenType; + entity.EnableLocalLogin = EnableLocalLogin; + entity.IdentityProviderRestrictions = IdentityProviderRestrictions.Select(x => new ClientIdPRestriction + { + Provider = x, + }).ToList(); + entity.IncludeJwtId = IncludeJwtId; + entity.AlwaysSendClientClaims = AlwaysSendClientClaims; + entity.ClientClaimsPrefix = ClientClaimsPrefix; + entity.PairWiseSubjectSalt = PairWiseSubjectSalt; + entity.AllowedCorsOrigins = AllowedCorsOrigins.Select(x => new ClientCorsOrigin + { + Origin = x, + }).ToList(); + entity.UserSsoLifetime = UserSsoLifetime; + entity.UserCodeType = UserCodeType; + entity.DeviceCodeLifetime = DeviceCodeLifetime; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/ClientModels/PropertiesModel.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/ClientModels/PropertiesModel.cs index 37baca777..c5e2222b5 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/ClientModels/PropertiesModel.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/ClientModels/PropertiesModel.cs @@ -3,26 +3,25 @@ using System.Collections.Generic; using System.Linq; -namespace ClassifiedAds.IdentityServer.Models.ClientModels +namespace ClassifiedAds.IdentityServer.Models.ClientModels; + +public class PropertiesModel : PropertyModel { - public class PropertiesModel : PropertyModel - { - public List Properties { get; set; } + public List Properties { get; set; } - public static PropertiesModel FromEntity(Client client) + public static PropertiesModel FromEntity(Client client) + { + var clientModel = ClientModel.FromEntity(client); + return new PropertiesModel { - var clientModel = ClientModel.FromEntity(client); - return new PropertiesModel + Client = clientModel, + Properties = client.Properties?.Select(x => new PropertyModel { + Id = x.Id, + Key = x.Key, + Value = x.Value, Client = clientModel, - Properties = client.Properties?.Select(x => new PropertyModel - { - Id = x.Id, - Key = x.Key, - Value = x.Value, - Client = clientModel, - })?.ToList(), - }; - } + })?.ToList(), + }; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/ClientModels/PropertyModel.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/ClientModels/PropertyModel.cs index fbdc7ae14..f0b414dda 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/ClientModels/PropertyModel.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/ClientModels/PropertyModel.cs @@ -4,24 +4,23 @@ using System.Linq; using System.Threading.Tasks; -namespace ClassifiedAds.IdentityServer.Models.ClientModels +namespace ClassifiedAds.IdentityServer.Models.ClientModels; + +public class PropertyModel { - public class PropertyModel - { - public int Id { get; set; } - public string Key { get; set; } - public string Value { get; set; } - public ClientModel Client { get; set; } + public int Id { get; set; } + public string Key { get; set; } + public string Value { get; set; } + public ClientModel Client { get; set; } - public static PropertyModel FromEntity(ClientProperty prop) + public static PropertyModel FromEntity(ClientProperty prop) + { + return new PropertyModel { - return new PropertyModel - { - Id = prop.Id, - Key = prop.Key, - Value = prop.Value, - Client = ClientModel.FromEntity(prop.Client), - }; - } + Id = prop.Id, + Key = prop.Key, + Value = prop.Value, + Client = ClientModel.FromEntity(prop.Client), + }; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/ClientModels/SecretModel.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/ClientModels/SecretModel.cs index 9e581ad29..6f7329d03 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/ClientModels/SecretModel.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/ClientModels/SecretModel.cs @@ -1,31 +1,30 @@ using IdentityServer4.EntityFramework.Entities; using System; -namespace ClassifiedAds.IdentityServer.Models.ClientModels +namespace ClassifiedAds.IdentityServer.Models.ClientModels; + +public class SecretModel { - public class SecretModel - { - public int Id { get; set; } - public string Description { get; set; } - public string Value { get; set; } - public DateTime? Expiration { get; set; } - public string Type { get; set; } - public string HashType { get; set; } - public DateTime Created { get; set; } - public ClientModel Client { get; set; } + public int Id { get; set; } + public string Description { get; set; } + public string Value { get; set; } + public DateTime? Expiration { get; set; } + public string Type { get; set; } + public string HashType { get; set; } + public DateTime Created { get; set; } + public ClientModel Client { get; set; } - public static SecretModel FromEntity(ClientSecret secret) + public static SecretModel FromEntity(ClientSecret secret) + { + return new SecretModel { - return new SecretModel - { - Id = secret.Id, - Description = secret.Description, - Value = secret.Value, - Expiration = secret.Expiration, - Type = secret.Type, - Created = secret.Created, - Client = ClientModel.FromEntity(secret.Client), - }; - } + Id = secret.Id, + Description = secret.Description, + Value = secret.Value, + Expiration = secret.Expiration, + Type = secret.Type, + Created = secret.Created, + Client = ClientModel.FromEntity(secret.Client), + }; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/ClientModels/SecretsModel.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/ClientModels/SecretsModel.cs index 07df9f198..55676b682 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/ClientModels/SecretsModel.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/ClientModels/SecretsModel.cs @@ -2,56 +2,55 @@ using System.Collections.Generic; using System.Linq; -namespace ClassifiedAds.IdentityServer.Models.ClientModels +namespace ClassifiedAds.IdentityServer.Models.ClientModels; + +public class SecretsModel : SecretModel { - public class SecretsModel : SecretModel + public List Secrets { get; set; } + public List TypeList { get; } = new List { - public List Secrets { get; set; } - public List TypeList { get; } = new List - { - "SharedSecret", - "X509Thumbprint", - "X509Name", - "X509CertificateBase64", - }; - public List HashTypes { get; } = new List - { - "Sha256", - "Sha512", - }; + "SharedSecret", + "X509Thumbprint", + "X509Name", + "X509CertificateBase64", + }; + public List HashTypes { get; } = new List + { + "Sha256", + "Sha512", + }; - public void HashSecret() + public void HashSecret() + { + if (Type != "SharedSecret") { - if (Type != "SharedSecret") - { - return; - } - - if (HashType == "Sha256") - { - Value = Value.Sha256(); - } - else if (HashType == "Sha512") - { - Value = Value.Sha512(); - } + return; } - public void UpdateEntity(IdentityServer4.EntityFramework.Entities.Secret entity) + if (HashType == "Sha256") { - entity.Description = Description; - entity.Value = Value; - entity.Expiration = Expiration; - entity.Type = Type; + Value = Value.Sha256(); } - - public static SecretsModel FromEntity(IdentityServer4.EntityFramework.Entities.Client client) + else if (HashType == "Sha512") { - return new SecretsModel - { - Client = ClientModel.FromEntity(client), - Secrets = client.ClientSecrets?.Select(x => FromEntity(x))?.ToList(), - }; + Value = Value.Sha512(); } } + + public void UpdateEntity(IdentityServer4.EntityFramework.Entities.Secret entity) + { + entity.Description = Description; + entity.Value = Value; + entity.Expiration = Expiration; + entity.Type = Type; + } + + public static SecretsModel FromEntity(IdentityServer4.EntityFramework.Entities.Client client) + { + return new SecretsModel + { + Client = ClientModel.FromEntity(client), + Secrets = client.ClientSecrets?.Select(x => FromEntity(x))?.ToList(), + }; + } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/ForgotPasswordModel.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/ForgotPasswordModel.cs index 73dc6e77d..8082b1012 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/ForgotPasswordModel.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/ForgotPasswordModel.cs @@ -1,11 +1,10 @@ using System.ComponentModel.DataAnnotations; -namespace ClassifiedAds.IdentityServer.Models +namespace ClassifiedAds.IdentityServer.Models; + +public class ForgotPasswordModel { - public class ForgotPasswordModel - { - [Required] - [EmailAddress] - public string Email { get; set; } - } + [Required] + [EmailAddress] + public string Email { get; set; } } \ No newline at end of file diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/IdentityResourceModels/IdentityResourceModel.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/IdentityResourceModels/IdentityResourceModel.cs index 423e019dd..b7fa89cd3 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/IdentityResourceModels/IdentityResourceModel.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/IdentityResourceModels/IdentityResourceModel.cs @@ -3,64 +3,63 @@ using System.Collections.Generic; using System.Linq; -namespace ClassifiedAds.IdentityServer.Models.IdentityResourceModels +namespace ClassifiedAds.IdentityServer.Models.IdentityResourceModels; + +public class IdentityResourceModel { - public class IdentityResourceModel - { - public int Id { get; set; } - public bool Enabled { get; set; } - public string Name { get; set; } - public string DisplayName { get; set; } - public string Description { get; set; } - public bool Required { get; set; } - public bool Emphasize { get; set; } - public bool ShowInDiscoveryDocument { get; set; } - public List UserClaims { get; set; } - public string UserClaimsItems { get; set; } - public List Properties { get; set; } - public DateTime Created { get; set; } - public DateTime? Updated { get; set; } - public bool NonEditable { get; set; } + public int Id { get; set; } + public bool Enabled { get; set; } + public string Name { get; set; } + public string DisplayName { get; set; } + public string Description { get; set; } + public bool Required { get; set; } + public bool Emphasize { get; set; } + public bool ShowInDiscoveryDocument { get; set; } + public List UserClaims { get; set; } + public string UserClaimsItems { get; set; } + public List Properties { get; set; } + public DateTime Created { get; set; } + public DateTime? Updated { get; set; } + public bool NonEditable { get; set; } - public void UpdateEntity(IdentityResource entity) - { - entity.Enabled = Enabled; - entity.Name = Name; - entity.DisplayName = DisplayName; - entity.Description = Description; - entity.Required = Required; - entity.Emphasize = Emphasize; - entity.ShowInDiscoveryDocument = ShowInDiscoveryDocument; - entity.Created = Created; - entity.Updated = Updated; - entity.NonEditable = NonEditable; - } + public void UpdateEntity(IdentityResource entity) + { + entity.Enabled = Enabled; + entity.Name = Name; + entity.DisplayName = DisplayName; + entity.Description = Description; + entity.Required = Required; + entity.Emphasize = Emphasize; + entity.ShowInDiscoveryDocument = ShowInDiscoveryDocument; + entity.Created = Created; + entity.Updated = Updated; + entity.NonEditable = NonEditable; } +} - public static class IdentityResourceMappingExtension +public static class IdentityResourceMappingExtension +{ + public static IdentityResourceModel ToModel(this IdentityResource entity) { - public static IdentityResourceModel ToModel(this IdentityResource entity) + return new IdentityResourceModel { - return new IdentityResourceModel - { - Id = entity.Id, - Enabled = entity.Enabled, - Name = entity.Name, - DisplayName = entity.DisplayName, - Description = entity.Description, - Required = entity.Required, - Emphasize = entity.Emphasize, - ShowInDiscoveryDocument = entity.ShowInDiscoveryDocument, - Created = entity.Created, - Updated = entity.Updated, - NonEditable = entity.NonEditable, - UserClaims = entity.UserClaims?.Select(x => x.Type)?.ToList(), - }; - } + Id = entity.Id, + Enabled = entity.Enabled, + Name = entity.Name, + DisplayName = entity.DisplayName, + Description = entity.Description, + Required = entity.Required, + Emphasize = entity.Emphasize, + ShowInDiscoveryDocument = entity.ShowInDiscoveryDocument, + Created = entity.Created, + Updated = entity.Updated, + NonEditable = entity.NonEditable, + UserClaims = entity.UserClaims?.Select(x => x.Type)?.ToList(), + }; + } - public static IEnumerable ToModels(this IEnumerable entities) - { - return entities?.Select(x => x.ToModel()); - } + public static IEnumerable ToModels(this IEnumerable entities) + { + return entities?.Select(x => x.ToModel()); } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/IdentityResourceModels/IdentityResourcePropertyModel.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/IdentityResourceModels/IdentityResourcePropertyModel.cs index bafd5ac8d..a82ded07b 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/IdentityResourceModels/IdentityResourcePropertyModel.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/IdentityResourceModels/IdentityResourcePropertyModel.cs @@ -1,27 +1,26 @@ using IdentityServer4.EntityFramework.Entities; -namespace ClassifiedAds.IdentityServer.Models.IdentityResourceModels +namespace ClassifiedAds.IdentityServer.Models.IdentityResourceModels; + +public class IdentityResourcePropertyModel { - public class IdentityResourcePropertyModel - { - public int Id { get; set; } - public string Key { get; set; } - public string Value { get; set; } - public IdentityResourceModel IdentityResource { get; set; } + public int Id { get; set; } + public string Key { get; set; } + public string Value { get; set; } + public IdentityResourceModel IdentityResource { get; set; } - public static IdentityResourcePropertyModel FromEntity(IdentityResourceProperty entity) + public static IdentityResourcePropertyModel FromEntity(IdentityResourceProperty entity) + { + return new IdentityResourcePropertyModel { - return new IdentityResourcePropertyModel + Id = entity.Id, + Key = entity.Key, + Value = entity.Value, + IdentityResource = new IdentityResourceModel { - Id = entity.Id, - Key = entity.Key, - Value = entity.Value, - IdentityResource = new IdentityResourceModel - { - Id = entity.IdentityResource.Id, - Name = entity.IdentityResource.Name, - }, - }; - } + Id = entity.IdentityResource.Id, + Name = entity.IdentityResource.Name, + }, + }; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/IdentityResourceModels/PropertiesModel.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/IdentityResourceModels/PropertiesModel.cs index 84ab08b32..69e134946 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/IdentityResourceModels/PropertiesModel.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/IdentityResourceModels/PropertiesModel.cs @@ -2,29 +2,28 @@ using System.Collections.Generic; using System.Linq; -namespace ClassifiedAds.IdentityServer.Models.IdentityResourceModels +namespace ClassifiedAds.IdentityServer.Models.IdentityResourceModels; + +public class PropertiesModel { - public class PropertiesModel - { - public int IdentityResourceId { get; set; } - public string IdentityResourceName { get; set; } - public string Key { get; set; } - public string Value { get; set; } - public List Properties { get; set; } + public int IdentityResourceId { get; set; } + public string IdentityResourceName { get; set; } + public string Key { get; set; } + public string Value { get; set; } + public List Properties { get; set; } - public static PropertiesModel FromEntity(IdentityResource identityResource) + public static PropertiesModel FromEntity(IdentityResource identityResource) + { + return new PropertiesModel { - return new PropertiesModel + IdentityResourceId = identityResource.Id, + IdentityResourceName = identityResource.Name, + Properties = identityResource.Properties?.Select(x => new IdentityResourcePropertyModel { - IdentityResourceId = identityResource.Id, - IdentityResourceName = identityResource.Name, - Properties = identityResource.Properties?.Select(x => new IdentityResourcePropertyModel - { - Id = x.Id, - Key = x.Key, - Value = x.Value, - })?.ToList(), - }; - } + Id = x.Id, + Key = x.Key, + Value = x.Value, + })?.ToList(), + }; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/RegisterModel.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/RegisterModel.cs index 5f4fc6c5f..50e0b231e 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/RegisterModel.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/RegisterModel.cs @@ -1,16 +1,15 @@ using System.ComponentModel.DataAnnotations; -namespace ClassifiedAds.IdentityServer.Models +namespace ClassifiedAds.IdentityServer.Models; + +public class RegisterModel { - public class RegisterModel - { - public string UserName { get; set; } + public string UserName { get; set; } - [DataType(DataType.Password)] - public string Password { get; set; } + [DataType(DataType.Password)] + public string Password { get; set; } - [Compare("Password")] - [DataType(DataType.Password)] - public string ConfirmPassword { get; set; } - } + [Compare("Password")] + [DataType(DataType.Password)] + public string ConfirmPassword { get; set; } } \ No newline at end of file diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/ResetPasswordModel.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/ResetPasswordModel.cs index f28a1127c..654a730e8 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/ResetPasswordModel.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/ResetPasswordModel.cs @@ -1,18 +1,17 @@ using System.ComponentModel.DataAnnotations; -namespace ClassifiedAds.IdentityServer.Models +namespace ClassifiedAds.IdentityServer.Models; + +public class ResetPasswordModel { - public class ResetPasswordModel - { - public string Token { get; set; } + public string Token { get; set; } - public string Email { get; set; } + public string Email { get; set; } - [DataType(DataType.Password)] - public string Password { get; set; } + [DataType(DataType.Password)] + public string Password { get; set; } - [Compare("Password")] - [DataType(DataType.Password)] - public string ConfirmPassword { get; set; } - } + [Compare("Password")] + [DataType(DataType.Password)] + public string ConfirmPassword { get; set; } } \ No newline at end of file diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/RoleModels/ClaimModel.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/RoleModels/ClaimModel.cs index bcbc570d5..ac270babd 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/RoleModels/ClaimModel.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/RoleModels/ClaimModel.cs @@ -1,24 +1,23 @@ using ClassifiedAds.Domain.Entities; using System; -namespace ClassifiedAds.IdentityServer.Models.RoleModels +namespace ClassifiedAds.IdentityServer.Models.RoleModels; + +public class ClaimModel { - public class ClaimModel - { - public Guid Id { get; set; } - public string Type { get; set; } - public string Value { get; set; } - public Role Role { get; set; } + public Guid Id { get; set; } + public string Type { get; set; } + public string Value { get; set; } + public Role Role { get; set; } - public static ClaimModel FromEntity(RoleClaim claim) + public static ClaimModel FromEntity(RoleClaim claim) + { + return new ClaimModel { - return new ClaimModel - { - Id = claim.Id, - Type = claim.Type, - Value = claim.Value, - Role = claim.Role, - }; - } + Id = claim.Id, + Type = claim.Type, + Value = claim.Value, + Role = claim.Role, + }; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/RoleModels/ClaimsModel.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/RoleModels/ClaimsModel.cs index 2aef9b5d3..d28ed5ca3 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/RoleModels/ClaimsModel.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/RoleModels/ClaimsModel.cs @@ -2,19 +2,18 @@ using System.Collections.Generic; using System.Linq; -namespace ClassifiedAds.IdentityServer.Models.RoleModels +namespace ClassifiedAds.IdentityServer.Models.RoleModels; + +public class ClaimsModel : ClaimModel { - public class ClaimsModel : ClaimModel - { - public List Claims { get; set; } + public List Claims { get; set; } - public static ClaimsModel FromEntity(Role role) + public static ClaimsModel FromEntity(Role role) + { + return new ClaimsModel { - return new ClaimsModel - { - Role = role, - Claims = role.Claims?.Select(x => FromEntity(x))?.ToList(), - }; - } + Role = role, + Claims = role.Claims?.Select(x => FromEntity(x))?.ToList(), + }; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/RoleModels/RoleModel.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/RoleModels/RoleModel.cs index 5eb2e3fbb..91e283fd0 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/RoleModels/RoleModel.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/RoleModels/RoleModel.cs @@ -4,17 +4,16 @@ using System.Linq; using System.Threading.Tasks; -namespace ClassifiedAds.IdentityServer.Models.RoleModels +namespace ClassifiedAds.IdentityServer.Models.RoleModels; + +public class RoleModel { - public class RoleModel - { - public Guid Id { get; set; } + public Guid Id { get; set; } - public string Name { get; set; } + public string Name { get; set; } - public static RoleModel FromEntity(Role role) - { - return new RoleModel { Id = role.Id, Name = role.Name }; - } + public static RoleModel FromEntity(Role role) + { + return new RoleModel { Id = role.Id, Name = role.Name }; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/RoleModels/UsersModel.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/RoleModels/UsersModel.cs index bc70311a2..25dbb30e4 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/RoleModels/UsersModel.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/RoleModels/UsersModel.cs @@ -2,12 +2,11 @@ using System; using System.Collections.Generic; -namespace ClassifiedAds.IdentityServer.Models.RoleModels +namespace ClassifiedAds.IdentityServer.Models.RoleModels; + +public class UsersModel { - public class UsersModel - { - public Role Role { get; set; } + public Role Role { get; set; } - public List Users { get; set; } - } + public List Users { get; set; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/UserModels/ChangePasswordModel.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/UserModels/ChangePasswordModel.cs index f68f14df4..14a0ce851 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/UserModels/ChangePasswordModel.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/UserModels/ChangePasswordModel.cs @@ -2,24 +2,23 @@ using System; using System.ComponentModel.DataAnnotations; -namespace ClassifiedAds.IdentityServer.Models.UserModels +namespace ClassifiedAds.IdentityServer.Models.UserModels; + +public class ChangePasswordModel { - public class ChangePasswordModel - { - public Guid Id { get; set; } - public string UserName { get; set; } - public string Password { get; set; } + public Guid Id { get; set; } + public string UserName { get; set; } + public string Password { get; set; } - [Compare(nameof(Password))] - public string ConfirmPassword { get; set; } + [Compare(nameof(Password))] + public string ConfirmPassword { get; set; } - public static ChangePasswordModel FromEntity(User user) + public static ChangePasswordModel FromEntity(User user) + { + return new ChangePasswordModel { - return new ChangePasswordModel - { - Id = user.Id, - UserName = user.UserName, - }; - } + Id = user.Id, + UserName = user.UserName, + }; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/UserModels/ClaimModel.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/UserModels/ClaimModel.cs index 811594c6b..1d460e2d9 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/UserModels/ClaimModel.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/UserModels/ClaimModel.cs @@ -1,24 +1,23 @@ using ClassifiedAds.Domain.Entities; using System; -namespace ClassifiedAds.IdentityServer.Models.UserModels +namespace ClassifiedAds.IdentityServer.Models.UserModels; + +public class ClaimModel { - public class ClaimModel - { - public Guid Id { get; set; } - public string Type { get; set; } - public string Value { get; set; } - public User User { get; set; } + public Guid Id { get; set; } + public string Type { get; set; } + public string Value { get; set; } + public User User { get; set; } - public static ClaimModel FromEntity(UserClaim claim) + public static ClaimModel FromEntity(UserClaim claim) + { + return new ClaimModel { - return new ClaimModel - { - Id = claim.Id, - Type = claim.Type, - Value = claim.Value, - User = claim.User, - }; - } + Id = claim.Id, + Type = claim.Type, + Value = claim.Value, + User = claim.User, + }; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/UserModels/ClaimsModel.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/UserModels/ClaimsModel.cs index d4e5e8e66..e9ddbae12 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/UserModels/ClaimsModel.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/UserModels/ClaimsModel.cs @@ -2,19 +2,18 @@ using System.Collections.Generic; using System.Linq; -namespace ClassifiedAds.IdentityServer.Models.UserModels +namespace ClassifiedAds.IdentityServer.Models.UserModels; + +public class ClaimsModel : ClaimModel { - public class ClaimsModel : ClaimModel - { - public List Claims { get; set; } + public List Claims { get; set; } - public static ClaimsModel FromEntity(User user) + public static ClaimsModel FromEntity(User user) + { + return new ClaimsModel { - return new ClaimsModel - { - User = user, - Claims = user.Claims?.Select(x => FromEntity(x))?.ToList(), - }; - } + User = user, + Claims = user.Claims?.Select(x => FromEntity(x))?.ToList(), + }; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/UserModels/RoleModel.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/UserModels/RoleModel.cs index 3036e8eee..d4c68c3a4 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/UserModels/RoleModel.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/UserModels/RoleModel.cs @@ -1,16 +1,15 @@ using ClassifiedAds.Domain.Entities; using System; -namespace ClassifiedAds.IdentityServer.Models.UserModels +namespace ClassifiedAds.IdentityServer.Models.UserModels; + +public class RoleModel { - public class RoleModel - { - public Guid RoleId { get; set; } + public Guid RoleId { get; set; } - public Guid UserId { get; set; } + public Guid UserId { get; set; } - public User User { get; set; } + public User User { get; set; } - public Role Role { get; set; } - } + public Role Role { get; set; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/UserModels/RolesModel.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/UserModels/RolesModel.cs index afb9c716c..152f40e50 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/UserModels/RolesModel.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/UserModels/RolesModel.cs @@ -1,16 +1,15 @@ using ClassifiedAds.Domain.Entities; using System.Collections.Generic; -namespace ClassifiedAds.IdentityServer.Models.UserModels +namespace ClassifiedAds.IdentityServer.Models.UserModels; + +public class RolesModel { - public class RolesModel - { - public User User { get; set; } + public User User { get; set; } - public RoleModel Role { get; set; } + public RoleModel Role { get; set; } - public List Roles { get; set; } + public List Roles { get; set; } - public List UserRoles { get; set; } - } + public List UserRoles { get; set; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/UserModels/UserModel.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/UserModels/UserModel.cs index 4bd3ba2cf..8759dfe08 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/UserModels/UserModel.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Models/UserModels/UserModel.cs @@ -3,9 +3,8 @@ using System.Linq; using System.Threading.Tasks; -namespace ClassifiedAds.IdentityServer.Models.UserModels +namespace ClassifiedAds.IdentityServer.Models.UserModels; + +public class UserModel { - public class UserModel - { - } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Program.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Program.cs index 699ac5441..62f4752bc 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Program.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Program.cs @@ -4,23 +4,22 @@ using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; -namespace ClassifiedAds.IdentityServer +namespace ClassifiedAds.IdentityServer; + +public class Program { - public class Program + public static void Main(string[] args) { - public static void Main(string[] args) - { - CreateWebHostBuilder(args).Build().Run(); - } - - public static IWebHostBuilder CreateWebHostBuilder(string[] args) => - WebHost.CreateDefaultBuilder(args) - .UseStartup() - .UseClassifiedAdsLogger(configuration => - { - var appSettings = new AppSettings(); - configuration.Bind(appSettings); - return appSettings.Logging; - }); + CreateWebHostBuilder(args).Build().Run(); } + + public static IWebHostBuilder CreateWebHostBuilder(string[] args) => + WebHost.CreateDefaultBuilder(args) + .UseStartup() + .UseClassifiedAdsLogger(configuration => + { + var appSettings = new AppSettings(); + configuration.Bind(appSettings); + return appSettings.Logging; + }); } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Account/AccountController.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Account/AccountController.cs index 0ce155c71..7fd98e57c 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Account/AccountController.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Account/AccountController.cs @@ -25,316 +25,147 @@ using System.Linq; using System.Threading.Tasks; -namespace IdentityServerHost.Quickstart.UI +namespace IdentityServerHost.Quickstart.UI; + +/// +/// This sample controller implements a typical login/logout/provision workflow for local and external accounts. +/// The login service encapsulates the interactions with the user data store. This data store is in-memory only and cannot be used for production! +/// The interaction service provides a way for the UI to communicate with identityserver for validation and context retrieval +/// +[SecurityHeaders] +[AllowAnonymous] +public class AccountController : Controller { + private readonly IIdentityServerInteractionService _interaction; + private readonly IClientStore _clientStore; + private readonly IAuthenticationSchemeProvider _schemeProvider; + private readonly IEventService _events; + + private readonly ILogger _logger; + private readonly UserManager _userManager; + private readonly SignInManager _signInManager; + private readonly Dispatcher _dispatcher; + + public AccountController( + ILogger logger, + UserManager userManager, + SignInManager signInManager, + Dispatcher dispatcher, + IIdentityServerInteractionService interaction, + IClientStore clientStore, + IAuthenticationSchemeProvider schemeProvider, + IEventService events) + { + _logger = logger; + _userManager = userManager; + _signInManager = signInManager; + _dispatcher = dispatcher; + _interaction = interaction; + _clientStore = clientStore; + _schemeProvider = schemeProvider; + _events = events; + } + /// - /// This sample controller implements a typical login/logout/provision workflow for local and external accounts. - /// The login service encapsulates the interactions with the user data store. This data store is in-memory only and cannot be used for production! - /// The interaction service provides a way for the UI to communicate with identityserver for validation and context retrieval + /// Entry point into the login workflow /// - [SecurityHeaders] - [AllowAnonymous] - public class AccountController : Controller + [HttpGet] + public async Task Login(string returnUrl) { - private readonly IIdentityServerInteractionService _interaction; - private readonly IClientStore _clientStore; - private readonly IAuthenticationSchemeProvider _schemeProvider; - private readonly IEventService _events; - - private readonly ILogger _logger; - private readonly UserManager _userManager; - private readonly SignInManager _signInManager; - private readonly Dispatcher _dispatcher; - - public AccountController( - ILogger logger, - UserManager userManager, - SignInManager signInManager, - Dispatcher dispatcher, - IIdentityServerInteractionService interaction, - IClientStore clientStore, - IAuthenticationSchemeProvider schemeProvider, - IEventService events) - { - _logger = logger; - _userManager = userManager; - _signInManager = signInManager; - _dispatcher = dispatcher; - _interaction = interaction; - _clientStore = clientStore; - _schemeProvider = schemeProvider; - _events = events; - } - - /// - /// Entry point into the login workflow - /// - [HttpGet] - public async Task Login(string returnUrl) - { - // build a model so we know what to show on the login page - var vm = await BuildLoginViewModelAsync(returnUrl); - - if (vm.IsExternalLoginOnly) - { - // we only have one option for logging in and it's an external provider - return RedirectToAction("Challenge", "External", new { scheme = vm.ExternalLoginScheme, returnUrl }); - } + // build a model so we know what to show on the login page + var vm = await BuildLoginViewModelAsync(returnUrl); - return View(vm); - } - - /// - /// Handle postback from username/password login - /// - [HttpPost] - [ValidateAntiForgeryToken] - public async Task Login(LoginInputModel model, string button) + if (vm.IsExternalLoginOnly) { - // check if we are in the context of an authorization request - var context = await _interaction.GetAuthorizationContextAsync(model.ReturnUrl); - - // the user clicked the "cancel" button - if (button != "login") - { - if (context != null) - { - // if the user cancels, send a result back into IdentityServer as if they - // denied the consent (even if this client does not require consent). - // this will send back an access denied OIDC error response to the client. - await _interaction.DenyAuthorizationAsync(context, AuthorizationError.AccessDenied); + // we only have one option for logging in and it's an external provider + return RedirectToAction("Challenge", "External", new { scheme = vm.ExternalLoginScheme, returnUrl }); + } - // we can trust model.ReturnUrl since GetAuthorizationContextAsync returned non-null - if (context.IsNativeClient()) - { - // The client is native, so this change in how to - // return the response is for better UX for the end user. - return this.LoadingPage("Redirect", model.ReturnUrl); - } + return View(vm); + } - return Redirect(model.ReturnUrl); - } - else - { - // since we don't have a valid context, then we just go back to the home page - return Redirect("~/"); - } - } + /// + /// Handle postback from username/password login + /// + [HttpPost] + [ValidateAntiForgeryToken] + public async Task Login(LoginInputModel model, string button) + { + // check if we are in the context of an authorization request + var context = await _interaction.GetAuthorizationContextAsync(model.ReturnUrl); - if (ModelState.IsValid) + // the user clicked the "cancel" button + if (button != "login") + { + if (context != null) { - var user = await _userManager.FindByNameAsync(model.Username); - - if (user != null && user.TwoFactorEnabled) - { - var result = await _signInManager.PasswordSignInAsync(model.Username, model.Password, model.RememberLogin, lockoutOnFailure: false); - if (result.Succeeded) - { - _logger.LogInformation(1, "User logged in."); - return RedirectToLocal(model.ReturnUrl); - } - - if (result.RequiresTwoFactor) - { - return RedirectToAction(nameof(SendCode), new { ReturnUrl = model.ReturnUrl, RememberMe = model.RememberLogin }); - } - - if (result.IsLockedOut) - { - _logger.LogWarning(2, "User account locked out."); - return View("Lockout"); - } - else - { - ModelState.AddModelError(string.Empty, "Invalid login attempt."); - return View(await BuildLoginViewModelAsync(model)); - } - } + // if the user cancels, send a result back into IdentityServer as if they + // denied the consent (even if this client does not require consent). + // this will send back an access denied OIDC error response to the client. + await _interaction.DenyAuthorizationAsync(context, AuthorizationError.AccessDenied); - if (user != null && await _userManager.CheckPasswordAsync(user, model.Password)) + // we can trust model.ReturnUrl since GetAuthorizationContextAsync returned non-null + if (context.IsNativeClient()) { - await _events.RaiseAsync(new UserLoginSuccessEvent(user.UserName, user.Id.ToString(), user.UserName, clientId: context?.Client.ClientId)); - - // only set explicit expiration here if user chooses "remember me". - // otherwise we rely upon expiration configured in cookie middleware. - AuthenticationProperties props = null; - if (AccountOptions.AllowRememberLogin && model.RememberLogin) - { - props = new AuthenticationProperties - { - IsPersistent = true, - ExpiresUtc = DateTimeOffset.UtcNow.Add(AccountOptions.RememberMeLoginDuration) - }; - }; - - // issue authentication cookie with subject ID and username - var isuser = new IdentityServerUser(user.Id.ToString()) - { - DisplayName = user.UserName, - }; - - await HttpContext.SignInAsync(isuser, props); - - if (context != null) - { - if (context.IsNativeClient()) - { - // The client is native, so this change in how to - // return the response is for better UX for the end user. - return this.LoadingPage("Redirect", model.ReturnUrl); - } - - // we can trust model.ReturnUrl since GetAuthorizationContextAsync returned non-null - return Redirect(model.ReturnUrl); - } - - // request for a local page - if (Url.IsLocalUrl(model.ReturnUrl)) - { - return Redirect(model.ReturnUrl); - } - else if (string.IsNullOrEmpty(model.ReturnUrl)) - { - return Redirect("~/"); - } - else - { - // user might have clicked on a malicious link - should be logged - throw new Exception("invalid return URL"); - } + // The client is native, so this change in how to + // return the response is for better UX for the end user. + return this.LoadingPage("Redirect", model.ReturnUrl); } - await _events.RaiseAsync(new UserLoginFailureEvent(model.Username, "invalid credentials", clientId: context?.Client.ClientId)); - ModelState.AddModelError(string.Empty, AccountOptions.InvalidCredentialsErrorMessage); + return Redirect(model.ReturnUrl); } - - // something went wrong, show form with error - var vm = await BuildLoginViewModelAsync(model); - return View(vm); - } - - // - // GET: /Account/SendCode - [HttpGet] - [AllowAnonymous] - public async Task SendCode(string returnUrl = null, bool rememberMe = false) - { - var user = await _signInManager.GetTwoFactorAuthenticationUserAsync(); - if (user == null) + else { - return View("Error"); + // since we don't have a valid context, then we just go back to the home page + return Redirect("~/"); } - - var userFactors = await _userManager.GetValidTwoFactorProvidersAsync(user); - var factorOptions = userFactors.Select(purpose => new SelectListItem { Text = purpose, Value = purpose }).ToList(); - return View(new SendCodeViewModel { Providers = factorOptions, ReturnUrl = returnUrl, RememberMe = rememberMe }); } - // - // POST: /Account/SendCode - [HttpPost] - [AllowAnonymous] - [ValidateAntiForgeryToken] - public async Task SendCode(SendCodeViewModel model) + if (ModelState.IsValid) { - if (!ModelState.IsValid) - { - return View(); - } - - var user = await _signInManager.GetTwoFactorAuthenticationUserAsync(); - if (user == null) - { - return View("Error"); - } - - if (model.SelectedProvider == "Authenticator") - { - return RedirectToAction(nameof(VerifyCode), new { Provider = model.SelectedProvider, ReturnUrl = model.ReturnUrl, RememberMe = model.RememberMe }); - } - - // Generate the token and send it - var code = await _userManager.GenerateTwoFactorTokenAsync(user, model.SelectedProvider); - if (string.IsNullOrWhiteSpace(code)) - { - return View("Error"); - } - - var message = "Your security code is: " + code; - if (model.SelectedProvider == "Email") - { - //await _dispatcher.DispatchAsync(new AddOrUpdateEntityCommand(new EmailMessage - //{ - // From = "phong@gmail.com", - // Tos = user.Email, - // Subject = "Security Code", - // Body = message, - //})); - } - else if (model.SelectedProvider == "Phone") - { - //await _dispatcher.DispatchAsync(new AddOrUpdateEntityCommand(new SmsMessage - //{ - // PhoneNumber = user.PhoneNumber, - // Message = message, - //})); - } + var user = await _userManager.FindByNameAsync(model.Username); - return RedirectToAction(nameof(VerifyCode), new { Provider = model.SelectedProvider, ReturnUrl = model.ReturnUrl, RememberMe = model.RememberMe }); - } - - // - // GET: /Account/VerifyCode - [HttpGet] - [AllowAnonymous] - public async Task VerifyCode(string provider, bool rememberMe, string returnUrl = null) - { - // Require that the user has already logged in via username/password or external login - var user = await _signInManager.GetTwoFactorAuthenticationUserAsync(); - if (user == null) + if (user != null && user.TwoFactorEnabled) { - return View("Error"); - } + var result = await _signInManager.PasswordSignInAsync(model.Username, model.Password, model.RememberLogin, lockoutOnFailure: false); + if (result.Succeeded) + { + _logger.LogInformation(1, "User logged in."); + return RedirectToLocal(model.ReturnUrl); + } - return View(new VerifyCodeViewModel { Provider = provider, ReturnUrl = returnUrl, RememberMe = rememberMe }); - } + if (result.RequiresTwoFactor) + { + return RedirectToAction(nameof(SendCode), new { ReturnUrl = model.ReturnUrl, RememberMe = model.RememberLogin }); + } - // - // POST: /Account/VerifyCode - [HttpPost] - [AllowAnonymous] - [ValidateAntiForgeryToken] - public async Task VerifyCode(VerifyCodeViewModel model) - { - if (!ModelState.IsValid) - { - return View(model); + if (result.IsLockedOut) + { + _logger.LogWarning(2, "User account locked out."); + return View("Lockout"); + } + else + { + ModelState.AddModelError(string.Empty, "Invalid login attempt."); + return View(await BuildLoginViewModelAsync(model)); + } } - var user = await _signInManager.GetTwoFactorAuthenticationUserAsync(); - - // The following code protects for brute force attacks against the two factor codes. - // If a user enters incorrect codes for a specified amount of time then the user account - // will be locked out for a specified amount of time. - var result = await _signInManager.TwoFactorSignInAsync(model.Provider, model.Code, model.RememberMe, model.RememberBrowser); - if (result.Succeeded) + if (user != null && await _userManager.CheckPasswordAsync(user, model.Password)) { - // check if we are in the context of an authorization request - var context = await _interaction.GetAuthorizationContextAsync(model.ReturnUrl); - await _events.RaiseAsync(new UserLoginSuccessEvent(user.UserName, user.Id.ToString(), user.UserName, clientId: context?.Client.ClientId)); // only set explicit expiration here if user chooses "remember me". // otherwise we rely upon expiration configured in cookie middleware. AuthenticationProperties props = null; - if (AccountOptions.AllowRememberLogin && model.RememberMe) + if (AccountOptions.AllowRememberLogin && model.RememberLogin) { props = new AuthenticationProperties { IsPersistent = true, ExpiresUtc = DateTimeOffset.UtcNow.Add(AccountOptions.RememberMeLoginDuration) }; - } + }; // issue authentication cookie with subject ID and username var isuser = new IdentityServerUser(user.Id.ToString()) @@ -371,374 +202,542 @@ public async Task VerifyCode(VerifyCodeViewModel model) // user might have clicked on a malicious link - should be logged throw new Exception("invalid return URL"); } - - return RedirectToLocal(model.ReturnUrl); } - if (result.IsLockedOut) - { - _logger.LogWarning(7, "User account locked out."); - return View("Lockout"); - } - else - { - ModelState.AddModelError(string.Empty, "Invalid code."); - return View(model); - } + await _events.RaiseAsync(new UserLoginFailureEvent(model.Username, "invalid credentials", clientId: context?.Client.ClientId)); + ModelState.AddModelError(string.Empty, AccountOptions.InvalidCredentialsErrorMessage); } + // something went wrong, show form with error + var vm = await BuildLoginViewModelAsync(model); + return View(vm); + } - /// - /// Show logout page - /// - [HttpGet] - public async Task Logout(string logoutId) + // + // GET: /Account/SendCode + [HttpGet] + [AllowAnonymous] + public async Task SendCode(string returnUrl = null, bool rememberMe = false) + { + var user = await _signInManager.GetTwoFactorAuthenticationUserAsync(); + if (user == null) { - // build a model so the logout page knows what to display - var vm = await BuildLogoutViewModelAsync(logoutId); + return View("Error"); + } - if (vm.ShowLogoutPrompt == false) - { - // if the request for logout was properly authenticated from IdentityServer, then - // we don't need to show the prompt and can just log the user out directly. - return await Logout(vm); - } + var userFactors = await _userManager.GetValidTwoFactorProvidersAsync(user); + var factorOptions = userFactors.Select(purpose => new SelectListItem { Text = purpose, Value = purpose }).ToList(); + return View(new SendCodeViewModel { Providers = factorOptions, ReturnUrl = returnUrl, RememberMe = rememberMe }); + } - return View(vm); + // + // POST: /Account/SendCode + [HttpPost] + [AllowAnonymous] + [ValidateAntiForgeryToken] + public async Task SendCode(SendCodeViewModel model) + { + if (!ModelState.IsValid) + { + return View(); } - /// - /// Handle logout page postback - /// - [HttpPost] - [ValidateAntiForgeryToken] - public async Task Logout(LogoutInputModel model) + var user = await _signInManager.GetTwoFactorAuthenticationUserAsync(); + if (user == null) { - // build a model so the logged out page knows what to display - var vm = await BuildLoggedOutViewModelAsync(model.LogoutId); + return View("Error"); + } - if (User?.Identity.IsAuthenticated == true) - { - // delete local authentication cookie - await HttpContext.SignOutAsync(IdentityConstants.ApplicationScheme); + if (model.SelectedProvider == "Authenticator") + { + return RedirectToAction(nameof(VerifyCode), new { Provider = model.SelectedProvider, ReturnUrl = model.ReturnUrl, RememberMe = model.RememberMe }); + } - // raise the logout event - await _events.RaiseAsync(new UserLogoutSuccessEvent(User.GetSubjectId(), User.GetDisplayName())); - } + // Generate the token and send it + var code = await _userManager.GenerateTwoFactorTokenAsync(user, model.SelectedProvider); + if (string.IsNullOrWhiteSpace(code)) + { + return View("Error"); + } - // check if we need to trigger sign-out at an upstream identity provider - if (vm.TriggerExternalSignout) - { - // build a return URL so the upstream provider will redirect back - // to us after the user has logged out. this allows us to then - // complete our single sign-out processing. - string url = Url.Action("Logout", new { logoutId = vm.LogoutId }); + var message = "Your security code is: " + code; + if (model.SelectedProvider == "Email") + { + //await _dispatcher.DispatchAsync(new AddOrUpdateEntityCommand(new EmailMessage + //{ + // From = "phong@gmail.com", + // Tos = user.Email, + // Subject = "Security Code", + // Body = message, + //})); + } + else if (model.SelectedProvider == "Phone") + { + //await _dispatcher.DispatchAsync(new AddOrUpdateEntityCommand(new SmsMessage + //{ + // PhoneNumber = user.PhoneNumber, + // Message = message, + //})); + } - // this triggers a redirect to the external provider for sign-out - return SignOut(new AuthenticationProperties { RedirectUri = url }, vm.ExternalAuthenticationScheme); - } + return RedirectToAction(nameof(VerifyCode), new { Provider = model.SelectedProvider, ReturnUrl = model.ReturnUrl, RememberMe = model.RememberMe }); + } - return View("LoggedOut", vm); + // + // GET: /Account/VerifyCode + [HttpGet] + [AllowAnonymous] + public async Task VerifyCode(string provider, bool rememberMe, string returnUrl = null) + { + // Require that the user has already logged in via username/password or external login + var user = await _signInManager.GetTwoFactorAuthenticationUserAsync(); + if (user == null) + { + return View("Error"); } - [HttpGet] - public IActionResult AccessDenied() + return View(new VerifyCodeViewModel { Provider = provider, ReturnUrl = returnUrl, RememberMe = rememberMe }); + } + + // + // POST: /Account/VerifyCode + [HttpPost] + [AllowAnonymous] + [ValidateAntiForgeryToken] + public async Task VerifyCode(VerifyCodeViewModel model) + { + if (!ModelState.IsValid) { - return View(); + return View(model); } + var user = await _signInManager.GetTwoFactorAuthenticationUserAsync(); - /*****************************************/ - /* helper APIs for the AccountController */ - /*****************************************/ - private async Task BuildLoginViewModelAsync(string returnUrl) + // The following code protects for brute force attacks against the two factor codes. + // If a user enters incorrect codes for a specified amount of time then the user account + // will be locked out for a specified amount of time. + var result = await _signInManager.TwoFactorSignInAsync(model.Provider, model.Code, model.RememberMe, model.RememberBrowser); + if (result.Succeeded) { - var context = await _interaction.GetAuthorizationContextAsync(returnUrl); - if (context?.IdP != null && await _schemeProvider.GetSchemeAsync(context.IdP) != null) - { - var local = context.IdP == IdentityServer4.IdentityServerConstants.LocalIdentityProvider; + // check if we are in the context of an authorization request + var context = await _interaction.GetAuthorizationContextAsync(model.ReturnUrl); - // this is meant to short circuit the UI and only trigger the one external IdP - var vm = new LoginViewModel - { - EnableLocalLogin = local, - ReturnUrl = returnUrl, - Username = context?.LoginHint, - }; + await _events.RaiseAsync(new UserLoginSuccessEvent(user.UserName, user.Id.ToString(), user.UserName, clientId: context?.Client.ClientId)); - if (!local) + // only set explicit expiration here if user chooses "remember me". + // otherwise we rely upon expiration configured in cookie middleware. + AuthenticationProperties props = null; + if (AccountOptions.AllowRememberLogin && model.RememberMe) + { + props = new AuthenticationProperties { - vm.ExternalProviders = new[] { new ExternalProvider { AuthenticationScheme = context.IdP } }; - } - - return vm; + IsPersistent = true, + ExpiresUtc = DateTimeOffset.UtcNow.Add(AccountOptions.RememberMeLoginDuration) + }; } - var schemes = await _schemeProvider.GetAllSchemesAsync(); + // issue authentication cookie with subject ID and username + var isuser = new IdentityServerUser(user.Id.ToString()) + { + DisplayName = user.UserName, + }; - var providers = schemes - .Where(x => x.DisplayName != null) - .Select(x => new ExternalProvider - { - DisplayName = x.DisplayName ?? x.Name, - AuthenticationScheme = x.Name, - }).ToList(); + await HttpContext.SignInAsync(isuser, props); - var allowLocal = true; - if (context?.Client.ClientId != null) + if (context != null) { - var client = await _clientStore.FindEnabledClientByIdAsync(context.Client.ClientId); - if (client != null) + if (context.IsNativeClient()) { - allowLocal = client.EnableLocalLogin; - - if (client.IdentityProviderRestrictions != null && client.IdentityProviderRestrictions.Any()) - { - providers = providers.Where(provider => client.IdentityProviderRestrictions.Contains(provider.AuthenticationScheme)).ToList(); - } + // The client is native, so this change in how to + // return the response is for better UX for the end user. + return this.LoadingPage("Redirect", model.ReturnUrl); } + + // we can trust model.ReturnUrl since GetAuthorizationContextAsync returned non-null + return Redirect(model.ReturnUrl); } - return new LoginViewModel + // request for a local page + if (Url.IsLocalUrl(model.ReturnUrl)) { - AllowRememberLogin = AccountOptions.AllowRememberLogin, - EnableLocalLogin = allowLocal && AccountOptions.AllowLocalLogin, - ReturnUrl = returnUrl, - Username = context?.LoginHint, - ExternalProviders = providers.ToArray(), - }; + return Redirect(model.ReturnUrl); + } + else if (string.IsNullOrEmpty(model.ReturnUrl)) + { + return Redirect("~/"); + } + else + { + // user might have clicked on a malicious link - should be logged + throw new Exception("invalid return URL"); + } + + return RedirectToLocal(model.ReturnUrl); } - private async Task BuildLoginViewModelAsync(LoginInputModel model) + if (result.IsLockedOut) { - var vm = await BuildLoginViewModelAsync(model.ReturnUrl); - vm.Username = model.Username; - vm.RememberLogin = model.RememberLogin; - return vm; + _logger.LogWarning(7, "User account locked out."); + return View("Lockout"); + } + else + { + ModelState.AddModelError(string.Empty, "Invalid code."); + return View(model); } + } + - private async Task BuildLogoutViewModelAsync(string logoutId) + /// + /// Show logout page + /// + [HttpGet] + public async Task Logout(string logoutId) + { + // build a model so the logout page knows what to display + var vm = await BuildLogoutViewModelAsync(logoutId); + + if (vm.ShowLogoutPrompt == false) { - var vm = new LogoutViewModel { LogoutId = logoutId, ShowLogoutPrompt = AccountOptions.ShowLogoutPrompt }; + // if the request for logout was properly authenticated from IdentityServer, then + // we don't need to show the prompt and can just log the user out directly. + return await Logout(vm); + } - if (User?.Identity.IsAuthenticated != true) - { - // if the user is not authenticated, then just show logged out page - vm.ShowLogoutPrompt = false; - return vm; - } + return View(vm); + } - var context = await _interaction.GetLogoutContextAsync(logoutId); - if (context?.ShowSignoutPrompt == false) - { - // it's safe to automatically sign-out - vm.ShowLogoutPrompt = false; - return vm; - } + /// + /// Handle logout page postback + /// + [HttpPost] + [ValidateAntiForgeryToken] + public async Task Logout(LogoutInputModel model) + { + // build a model so the logged out page knows what to display + var vm = await BuildLoggedOutViewModelAsync(model.LogoutId); - // show the logout prompt. this prevents attacks where the user - // is automatically signed out by another malicious web page. - return vm; + if (User?.Identity.IsAuthenticated == true) + { + // delete local authentication cookie + await HttpContext.SignOutAsync(IdentityConstants.ApplicationScheme); + + // raise the logout event + await _events.RaiseAsync(new UserLogoutSuccessEvent(User.GetSubjectId(), User.GetDisplayName())); } - private async Task BuildLoggedOutViewModelAsync(string logoutId) + // check if we need to trigger sign-out at an upstream identity provider + if (vm.TriggerExternalSignout) + { + // build a return URL so the upstream provider will redirect back + // to us after the user has logged out. this allows us to then + // complete our single sign-out processing. + string url = Url.Action("Logout", new { logoutId = vm.LogoutId }); + + // this triggers a redirect to the external provider for sign-out + return SignOut(new AuthenticationProperties { RedirectUri = url }, vm.ExternalAuthenticationScheme); + } + + return View("LoggedOut", vm); + } + + [HttpGet] + public IActionResult AccessDenied() + { + return View(); + } + + + /*****************************************/ + /* helper APIs for the AccountController */ + /*****************************************/ + private async Task BuildLoginViewModelAsync(string returnUrl) + { + var context = await _interaction.GetAuthorizationContextAsync(returnUrl); + if (context?.IdP != null && await _schemeProvider.GetSchemeAsync(context.IdP) != null) { - // get context information (client name, post logout redirect URI and iframe for federated signout) - var logout = await _interaction.GetLogoutContextAsync(logoutId); + var local = context.IdP == IdentityServer4.IdentityServerConstants.LocalIdentityProvider; - var vm = new LoggedOutViewModel + // this is meant to short circuit the UI and only trigger the one external IdP + var vm = new LoginViewModel { - AutomaticRedirectAfterSignOut = AccountOptions.AutomaticRedirectAfterSignOut, - PostLogoutRedirectUri = logout?.PostLogoutRedirectUri, - ClientName = string.IsNullOrEmpty(logout?.ClientName) ? logout?.ClientId : logout?.ClientName, - SignOutIframeUrl = logout?.SignOutIFrameUrl, - LogoutId = logoutId, + EnableLocalLogin = local, + ReturnUrl = returnUrl, + Username = context?.LoginHint, }; - if (User?.Identity.IsAuthenticated == true) + if (!local) { - var idp = User.FindFirst(JwtClaimTypes.IdentityProvider)?.Value; - if (idp != null && idp != IdentityServer4.IdentityServerConstants.LocalIdentityProvider) - { - var providerSupportsSignout = await HttpContext.GetSchemeSupportsSignOutAsync(idp); - if (providerSupportsSignout) - { - if (vm.LogoutId == null) - { - // if there's no current logout context, we need to create one - // this captures necessary info from the current logged in user - // before we signout and redirect away to the external IdP for signout - vm.LogoutId = await _interaction.CreateLogoutContextAsync(); - } - - vm.ExternalAuthenticationScheme = idp; - } - } + vm.ExternalProviders = new[] { new ExternalProvider { AuthenticationScheme = context.IdP } }; } return vm; } - [HttpGet] - public IActionResult Register() - { - return View(); - } + var schemes = await _schemeProvider.GetAllSchemesAsync(); + + var providers = schemes + .Where(x => x.DisplayName != null) + .Select(x => new ExternalProvider + { + DisplayName = x.DisplayName ?? x.Name, + AuthenticationScheme = x.Name, + }).ToList(); - [HttpPost] - [ValidateAntiForgeryToken] - public async Task Register(RegisterModel model) + var allowLocal = true; + if (context?.Client.ClientId != null) { - if (!ModelState.IsValid) + var client = await _clientStore.FindEnabledClientByIdAsync(context.Client.ClientId); + if (client != null) { - return View(); + allowLocal = client.EnableLocalLogin; + + if (client.IdentityProviderRestrictions != null && client.IdentityProviderRestrictions.Any()) + { + providers = providers.Where(provider => client.IdentityProviderRestrictions.Contains(provider.AuthenticationScheme)).ToList(); + } } + } - var user = await _userManager.FindByNameAsync(model.UserName); + return new LoginViewModel + { + AllowRememberLogin = AccountOptions.AllowRememberLogin, + EnableLocalLogin = allowLocal && AccountOptions.AllowLocalLogin, + ReturnUrl = returnUrl, + Username = context?.LoginHint, + ExternalProviders = providers.ToArray(), + }; + } - if (user != null) - { - return View("Success"); - } + private async Task BuildLoginViewModelAsync(LoginInputModel model) + { + var vm = await BuildLoginViewModelAsync(model.ReturnUrl); + vm.Username = model.Username; + vm.RememberLogin = model.RememberLogin; + return vm; + } - user = new User - { - UserName = model.UserName, - Email = model.UserName, - }; + private async Task BuildLogoutViewModelAsync(string logoutId) + { + var vm = new LogoutViewModel { LogoutId = logoutId, ShowLogoutPrompt = AccountOptions.ShowLogoutPrompt }; - var result = await _userManager.CreateAsync(user, model.Password); + if (User?.Identity.IsAuthenticated != true) + { + // if the user is not authenticated, then just show logged out page + vm.ShowLogoutPrompt = false; + return vm; + } + + var context = await _interaction.GetLogoutContextAsync(logoutId); + if (context?.ShowSignoutPrompt == false) + { + // it's safe to automatically sign-out + vm.ShowLogoutPrompt = false; + return vm; + } + + // show the logout prompt. this prevents attacks where the user + // is automatically signed out by another malicious web page. + return vm; + } + + private async Task BuildLoggedOutViewModelAsync(string logoutId) + { + // get context information (client name, post logout redirect URI and iframe for federated signout) + var logout = await _interaction.GetLogoutContextAsync(logoutId); - if (!result.Succeeded) + var vm = new LoggedOutViewModel + { + AutomaticRedirectAfterSignOut = AccountOptions.AutomaticRedirectAfterSignOut, + PostLogoutRedirectUri = logout?.PostLogoutRedirectUri, + ClientName = string.IsNullOrEmpty(logout?.ClientName) ? logout?.ClientId : logout?.ClientName, + SignOutIframeUrl = logout?.SignOutIFrameUrl, + LogoutId = logoutId, + }; + + if (User?.Identity.IsAuthenticated == true) + { + var idp = User.FindFirst(JwtClaimTypes.IdentityProvider)?.Value; + if (idp != null && idp != IdentityServer4.IdentityServerConstants.LocalIdentityProvider) { - foreach (var error in result.Errors) + var providerSupportsSignout = await HttpContext.GetSchemeSupportsSignOutAsync(idp); + if (providerSupportsSignout) { - ModelState.AddModelError(string.Empty, error.Description); - } + if (vm.LogoutId == null) + { + // if there's no current logout context, we need to create one + // this captures necessary info from the current logged in user + // before we signout and redirect away to the external IdP for signout + vm.LogoutId = await _interaction.CreateLogoutContextAsync(); + } - return View(); + vm.ExternalAuthenticationScheme = idp; + } } + } - var token = await _userManager.GenerateEmailConfirmationTokenAsync(user); - var confirmationEmail = Url.Action("ConfirmEmailAddress", "Account", - new { token = token, email = user.Email }, Request.Scheme); + return vm; + } - //await _dispatcher.DispatchAsync(new AddOrUpdateEntityCommand(new EmailMessage - //{ - // From = "phong@gmail.com", - // Tos = user.Email, - // Subject = "Confirmation Email", - // Body = string.Format("Confirmation Email: {0}", confirmationEmail), - //} - //)); + [HttpGet] + public IActionResult Register() + { + return View(); + } + [HttpPost] + [ValidateAntiForgeryToken] + public async Task Register(RegisterModel model) + { + if (!ModelState.IsValid) + { + return View(); + } + + var user = await _userManager.FindByNameAsync(model.UserName); + + if (user != null) + { return View("Success"); } - [HttpGet] - public async Task ConfirmEmailAddress(string token, string email) + user = new User { - var user = await _userManager.FindByEmailAsync(email); + UserName = model.UserName, + Email = model.UserName, + }; + + var result = await _userManager.CreateAsync(user, model.Password); - if (user == null) + if (!result.Succeeded) + { + foreach (var error in result.Errors) { - return View("Error"); + ModelState.AddModelError(string.Empty, error.Description); } - var result = await _userManager.ConfirmEmailAsync(user, token); + return View(); + } - if (result.Succeeded) - { - return View("Success"); - } + var token = await _userManager.GenerateEmailConfirmationTokenAsync(user); + var confirmationEmail = Url.Action("ConfirmEmailAddress", "Account", + new { token = token, email = user.Email }, Request.Scheme); + + //await _dispatcher.DispatchAsync(new AddOrUpdateEntityCommand(new EmailMessage + //{ + // From = "phong@gmail.com", + // Tos = user.Email, + // Subject = "Confirmation Email", + // Body = string.Format("Confirmation Email: {0}", confirmationEmail), + //} + //)); + + return View("Success"); + } + + [HttpGet] + public async Task ConfirmEmailAddress(string token, string email) + { + var user = await _userManager.FindByEmailAsync(email); + if (user == null) + { return View("Error"); } - [HttpGet] - public IActionResult ForgotPassword() + var result = await _userManager.ConfirmEmailAsync(user, token); + + if (result.Succeeded) { - return View(); + return View("Success"); } - [HttpPost] - public async Task ForgotPassword(ForgotPasswordModel model) + return View("Error"); + } + + [HttpGet] + public IActionResult ForgotPassword() + { + return View(); + } + + [HttpPost] + public async Task ForgotPassword(ForgotPasswordModel model) + { + if (ModelState.IsValid) { - if (ModelState.IsValid) - { - var user = await _userManager.FindByEmailAsync(model.Email); + var user = await _userManager.FindByEmailAsync(model.Email); - if (user != null) - { - var token = await _userManager.GeneratePasswordResetTokenAsync(user); - var resetUrl = Url.Action("ResetPassword", "Account", - new { token = token, email = user.Email }, Request.Scheme); - - //await _dispatcher.DispatchAsync(new AddOrUpdateEntityCommand(new EmailMessage - //{ - // From = "phong@gmail.com", - // Tos = user.Email, - // Subject = "Forgot Password", - // Body = string.Format("Reset Url: {0}", resetUrl), - //})); - } - else - { - // email user and inform them that they do not have an account - } + if (user != null) + { + var token = await _userManager.GeneratePasswordResetTokenAsync(user); + var resetUrl = Url.Action("ResetPassword", "Account", + new { token = token, email = user.Email }, Request.Scheme); - return View("Success"); + //await _dispatcher.DispatchAsync(new AddOrUpdateEntityCommand(new EmailMessage + //{ + // From = "phong@gmail.com", + // Tos = user.Email, + // Subject = "Forgot Password", + // Body = string.Format("Reset Url: {0}", resetUrl), + //})); + } + else + { + // email user and inform them that they do not have an account } - return View(); + return View("Success"); } - [HttpGet] - public IActionResult ResetPassword(string token, string email) - { - return View(new ResetPasswordModel { Token = token, Email = email }); - } + return View(); + } + + [HttpGet] + public IActionResult ResetPassword(string token, string email) + { + return View(new ResetPasswordModel { Token = token, Email = email }); + } - [HttpPost] - public async Task ResetPassword(ResetPasswordModel model) + [HttpPost] + public async Task ResetPassword(ResetPasswordModel model) + { + if (ModelState.IsValid) { - if (ModelState.IsValid) + var user = await _userManager.FindByEmailAsync(model.Email); + + if (user != null) { - var user = await _userManager.FindByEmailAsync(model.Email); + var result = await _userManager.ResetPasswordAsync(user, model.Token, model.Password); - if (user != null) + if (!result.Succeeded) { - var result = await _userManager.ResetPasswordAsync(user, model.Token, model.Password); - - if (!result.Succeeded) + foreach (var error in result.Errors) { - foreach (var error in result.Errors) - { - ModelState.AddModelError(string.Empty, error.Description); - } - - return View(); + ModelState.AddModelError(string.Empty, error.Description); } - return View("Success"); + return View(); } - ModelState.AddModelError(string.Empty, "Invalid Request"); + return View("Success"); } - return View(); + ModelState.AddModelError(string.Empty, "Invalid Request"); } - private IActionResult RedirectToLocal(string returnUrl) + return View(); + } + + private IActionResult RedirectToLocal(string returnUrl) + { + if (Url.IsLocalUrl(returnUrl)) { - if (Url.IsLocalUrl(returnUrl)) - { - return Redirect(returnUrl); - } - else - { - return RedirectToAction(nameof(HomeController.Index), "Home"); - } + return Redirect(returnUrl); + } + else + { + return RedirectToAction(nameof(HomeController.Index), "Home"); } } } \ No newline at end of file diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Account/AccountOptions.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Account/AccountOptions.cs index 5a8cafff8..ebce57f62 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Account/AccountOptions.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Account/AccountOptions.cs @@ -4,17 +4,16 @@ using System; -namespace IdentityServerHost.Quickstart.UI +namespace IdentityServerHost.Quickstart.UI; + +public class AccountOptions { - public class AccountOptions - { - public static bool AllowLocalLogin = true; - public static bool AllowRememberLogin = true; - public static TimeSpan RememberMeLoginDuration = TimeSpan.FromDays(30); + public static bool AllowLocalLogin = true; + public static bool AllowRememberLogin = true; + public static TimeSpan RememberMeLoginDuration = TimeSpan.FromDays(30); - public static bool ShowLogoutPrompt = true; - public static bool AutomaticRedirectAfterSignOut = true; + public static bool ShowLogoutPrompt = true; + public static bool AutomaticRedirectAfterSignOut = true; - public static string InvalidCredentialsErrorMessage = "Invalid username or password"; - } + public static string InvalidCredentialsErrorMessage = "Invalid username or password"; } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Account/ExternalController.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Account/ExternalController.cs index 481a96939..e84584d27 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Account/ExternalController.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Account/ExternalController.cs @@ -17,202 +17,201 @@ using System.Security.Claims; using System.Threading.Tasks; -namespace IdentityServerHost.Quickstart.UI +namespace IdentityServerHost.Quickstart.UI; + +[SecurityHeaders] +[AllowAnonymous] +public class ExternalController : Controller { - [SecurityHeaders] - [AllowAnonymous] - public class ExternalController : Controller + private readonly UserManager _userManager; + private readonly IIdentityServerInteractionService _interaction; + private readonly IClientStore _clientStore; + private readonly ILogger _logger; + private readonly IEventService _events; + + public ExternalController( + UserManager userManager, + IIdentityServerInteractionService interaction, + IClientStore clientStore, + IEventService events, + ILogger logger) + { + _userManager = userManager; + _interaction = interaction; + _clientStore = clientStore; + _logger = logger; + _events = events; + } + + /// + /// initiate roundtrip to external authentication provider + /// + [HttpGet] + public IActionResult Challenge(string scheme, string returnUrl) { - private readonly UserManager _userManager; - private readonly IIdentityServerInteractionService _interaction; - private readonly IClientStore _clientStore; - private readonly ILogger _logger; - private readonly IEventService _events; - - public ExternalController( - UserManager userManager, - IIdentityServerInteractionService interaction, - IClientStore clientStore, - IEventService events, - ILogger logger) + if (string.IsNullOrEmpty(returnUrl)) returnUrl = "~/"; + + // validate returnUrl - either it is a valid OIDC URL or back to a local page + if (Url.IsLocalUrl(returnUrl) == false && _interaction.IsValidReturnUrl(returnUrl) == false) { - _userManager = userManager; - _interaction = interaction; - _clientStore = clientStore; - _logger = logger; - _events = events; + // user might have clicked on a malicious link - should be logged + throw new Exception("invalid return URL"); } - - /// - /// initiate roundtrip to external authentication provider - /// - [HttpGet] - public IActionResult Challenge(string scheme, string returnUrl) + + // start challenge and roundtrip the return URL and scheme + var props = new AuthenticationProperties { - if (string.IsNullOrEmpty(returnUrl)) returnUrl = "~/"; - - // validate returnUrl - either it is a valid OIDC URL or back to a local page - if (Url.IsLocalUrl(returnUrl) == false && _interaction.IsValidReturnUrl(returnUrl) == false) + RedirectUri = Url.Action(nameof(Callback)), + Items = { - // user might have clicked on a malicious link - should be logged - throw new Exception("invalid return URL"); + { "returnUrl", returnUrl }, + { "scheme", scheme }, } - - // start challenge and roundtrip the return URL and scheme - var props = new AuthenticationProperties - { - RedirectUri = Url.Action(nameof(Callback)), - Items = - { - { "returnUrl", returnUrl }, - { "scheme", scheme }, - } - }; - - return Challenge(props, scheme); - - } + }; + + return Challenge(props, scheme); + + } - /// - /// Post processing of external authentication - /// - [HttpGet] - public async Task Callback() + /// + /// Post processing of external authentication + /// + [HttpGet] + public async Task Callback() + { + // read external identity from the temporary cookie + var result = await HttpContext.AuthenticateAsync(IdentityServerConstants.ExternalCookieAuthenticationScheme); + if (result?.Succeeded != true) { - // read external identity from the temporary cookie - var result = await HttpContext.AuthenticateAsync(IdentityServerConstants.ExternalCookieAuthenticationScheme); - if (result?.Succeeded != true) - { - throw new Exception("External authentication error"); - } + throw new Exception("External authentication error"); + } - if (_logger.IsEnabled(LogLevel.Debug)) - { - var externalClaims = result.Principal.Claims.Select(c => $"{c.Type}: {c.Value}"); - _logger.LogDebug("External claims: {@claims}", externalClaims); - } + if (_logger.IsEnabled(LogLevel.Debug)) + { + var externalClaims = result.Principal.Claims.Select(c => $"{c.Type}: {c.Value}"); + _logger.LogDebug("External claims: {@claims}", externalClaims); + } - // lookup our user and external provider info - var (user, provider, providerUserId, claims) = FindUserFromExternalProvider(result); - if (user == null) - { - // this might be where you might initiate a custom workflow for user registration - // in this sample we don't show how that would be done, as our sample implementation - // simply auto-provisions new external user - user = AutoProvisionUser(provider, providerUserId, claims); - } + // lookup our user and external provider info + var (user, provider, providerUserId, claims) = FindUserFromExternalProvider(result); + if (user == null) + { + // this might be where you might initiate a custom workflow for user registration + // in this sample we don't show how that would be done, as our sample implementation + // simply auto-provisions new external user + user = AutoProvisionUser(provider, providerUserId, claims); + } - // this allows us to collect any additional claims or properties - // for the specific protocols used and store them in the local auth cookie. - // this is typically used to store data needed for signout from those protocols. - var additionalLocalClaims = new List(); - var localSignInProps = new AuthenticationProperties(); - ProcessLoginCallback(result, additionalLocalClaims, localSignInProps); - - // issue authentication cookie for user - var isuser = new IdentityServerUser(user.Id.ToString()) - { - DisplayName = user.UserName, - IdentityProvider = provider, - AdditionalClaims = additionalLocalClaims, - }; + // this allows us to collect any additional claims or properties + // for the specific protocols used and store them in the local auth cookie. + // this is typically used to store data needed for signout from those protocols. + var additionalLocalClaims = new List(); + var localSignInProps = new AuthenticationProperties(); + ProcessLoginCallback(result, additionalLocalClaims, localSignInProps); + + // issue authentication cookie for user + var isuser = new IdentityServerUser(user.Id.ToString()) + { + DisplayName = user.UserName, + IdentityProvider = provider, + AdditionalClaims = additionalLocalClaims, + }; - await HttpContext.SignInAsync(isuser, localSignInProps); + await HttpContext.SignInAsync(isuser, localSignInProps); - // delete temporary cookie used during external authentication - await HttpContext.SignOutAsync(IdentityServerConstants.ExternalCookieAuthenticationScheme); + // delete temporary cookie used during external authentication + await HttpContext.SignOutAsync(IdentityServerConstants.ExternalCookieAuthenticationScheme); - // retrieve return URL - var returnUrl = result.Properties.Items["returnUrl"] ?? "~/"; + // retrieve return URL + var returnUrl = result.Properties.Items["returnUrl"] ?? "~/"; - // check if external login is in the context of an OIDC request - var context = await _interaction.GetAuthorizationContextAsync(returnUrl); - await _events.RaiseAsync(new UserLoginSuccessEvent(provider, providerUserId, user.Id.ToString(), user.UserName, true, context?.Client.ClientId)); + // check if external login is in the context of an OIDC request + var context = await _interaction.GetAuthorizationContextAsync(returnUrl); + await _events.RaiseAsync(new UserLoginSuccessEvent(provider, providerUserId, user.Id.ToString(), user.UserName, true, context?.Client.ClientId)); - if (context != null) + if (context != null) + { + if (context.IsNativeClient()) { - if (context.IsNativeClient()) - { - // The client is native, so this change in how to - // return the response is for better UX for the end user. - return this.LoadingPage("Redirect", returnUrl); - } + // The client is native, so this change in how to + // return the response is for better UX for the end user. + return this.LoadingPage("Redirect", returnUrl); } - - return Redirect(returnUrl); } - private (User user, string provider, string providerUserId, IEnumerable claims) FindUserFromExternalProvider(AuthenticateResult result) + return Redirect(returnUrl); + } + + private (User user, string provider, string providerUserId, IEnumerable claims) FindUserFromExternalProvider(AuthenticateResult result) + { + var externalUser = result.Principal; + var provider = result.Properties.Items["scheme"]; + + // try to determine the unique id of the external user (issued by the provider) + // the most common claim type for that are the sub claim and the NameIdentifier + // depending on the external provider, some other claim type might be used + var emailClaim = externalUser.FindFirst(ClaimTypes.Email) ?? + externalUser.FindFirst(JwtClaimTypes.Subject) ?? + externalUser.FindFirst(ClaimTypes.NameIdentifier) ?? + throw new Exception("Unknown userid"); + + if (provider == "AAD") { - var externalUser = result.Principal; - var provider = result.Properties.Items["scheme"]; - - // try to determine the unique id of the external user (issued by the provider) - // the most common claim type for that are the sub claim and the NameIdentifier - // depending on the external provider, some other claim type might be used - var emailClaim = externalUser.FindFirst(ClaimTypes.Email) ?? - externalUser.FindFirst(JwtClaimTypes.Subject) ?? - externalUser.FindFirst(ClaimTypes.NameIdentifier) ?? - throw new Exception("Unknown userid"); - - if (provider == "AAD") - { - emailClaim = externalUser.FindFirst(ClaimTypes.Upn); - } - else if (provider == "Microsoft") - { - emailClaim = externalUser.FindFirst(ClaimTypes.Email); - } - else if (provider == "Google") - { - emailClaim = externalUser.FindFirst(ClaimTypes.Email); - } - else if (provider == "Facebook") - { - emailClaim = externalUser.FindFirst(ClaimTypes.Email); - } + emailClaim = externalUser.FindFirst(ClaimTypes.Upn); + } + else if (provider == "Microsoft") + { + emailClaim = externalUser.FindFirst(ClaimTypes.Email); + } + else if (provider == "Google") + { + emailClaim = externalUser.FindFirst(ClaimTypes.Email); + } + else if (provider == "Facebook") + { + emailClaim = externalUser.FindFirst(ClaimTypes.Email); + } - // remove the user id claim so we don't include it as an extra claim if/when we provision the user - var claims = externalUser.Claims.ToList(); - claims.Remove(emailClaim); + // remove the user id claim so we don't include it as an extra claim if/when we provision the user + var claims = externalUser.Claims.ToList(); + claims.Remove(emailClaim); - var providerUserEmail = emailClaim.Value; + var providerUserEmail = emailClaim.Value; - // find external user - var user = _userManager.FindByEmailAsync(providerUserEmail).GetAwaiter().GetResult(); + // find external user + var user = _userManager.FindByEmailAsync(providerUserEmail).GetAwaiter().GetResult(); - return (user, provider, providerUserEmail, claims); - } + return (user, provider, providerUserEmail, claims); + } - private User AutoProvisionUser(string provider, string providerUserId, IEnumerable claims) + private User AutoProvisionUser(string provider, string providerUserId, IEnumerable claims) + { + var user = new User { - var user = new User - { - UserName = providerUserId, - Email = providerUserId, - }; - var rs = _userManager.CreateAsync(user, "4SBbS]#Nc3*Dca").GetAwaiter().GetResult(); - return user; - } + UserName = providerUserId, + Email = providerUserId, + }; + var rs = _userManager.CreateAsync(user, "4SBbS]#Nc3*Dca").GetAwaiter().GetResult(); + return user; + } - // if the external login is OIDC-based, there are certain things we need to preserve to make logout work - // this will be different for WS-Fed, SAML2p or other protocols - private void ProcessLoginCallback(AuthenticateResult externalResult, List localClaims, AuthenticationProperties localSignInProps) + // if the external login is OIDC-based, there are certain things we need to preserve to make logout work + // this will be different for WS-Fed, SAML2p or other protocols + private void ProcessLoginCallback(AuthenticateResult externalResult, List localClaims, AuthenticationProperties localSignInProps) + { + // if the external system sent a session id claim, copy it over + // so we can use it for single sign-out + var sid = externalResult.Principal.Claims.FirstOrDefault(x => x.Type == JwtClaimTypes.SessionId); + if (sid != null) { - // if the external system sent a session id claim, copy it over - // so we can use it for single sign-out - var sid = externalResult.Principal.Claims.FirstOrDefault(x => x.Type == JwtClaimTypes.SessionId); - if (sid != null) - { - localClaims.Add(new Claim(JwtClaimTypes.SessionId, sid.Value)); - } + localClaims.Add(new Claim(JwtClaimTypes.SessionId, sid.Value)); + } - // if the external provider issued an id_token, we'll keep it for signout - var idToken = externalResult.Properties.GetTokenValue("id_token"); - if (idToken != null) - { - localSignInProps.StoreTokens(new[] { new AuthenticationToken { Name = "id_token", Value = idToken } }); - } + // if the external provider issued an id_token, we'll keep it for signout + var idToken = externalResult.Properties.GetTokenValue("id_token"); + if (idToken != null) + { + localSignInProps.StoreTokens(new[] { new AuthenticationToken { Name = "id_token", Value = idToken } }); } } } \ No newline at end of file diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Account/ExternalProvider.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Account/ExternalProvider.cs index a18311372..5d50f82ab 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Account/ExternalProvider.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Account/ExternalProvider.cs @@ -2,11 +2,10 @@ // Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. -namespace IdentityServerHost.Quickstart.UI +namespace IdentityServerHost.Quickstart.UI; + +public class ExternalProvider { - public class ExternalProvider - { - public string DisplayName { get; set; } - public string AuthenticationScheme { get; set; } - } + public string DisplayName { get; set; } + public string AuthenticationScheme { get; set; } } \ No newline at end of file diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Account/LoggedOutViewModel.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Account/LoggedOutViewModel.cs index 63688328c..68c23622e 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Account/LoggedOutViewModel.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Account/LoggedOutViewModel.cs @@ -2,18 +2,17 @@ // Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. -namespace IdentityServerHost.Quickstart.UI +namespace IdentityServerHost.Quickstart.UI; + +public class LoggedOutViewModel { - public class LoggedOutViewModel - { - public string PostLogoutRedirectUri { get; set; } - public string ClientName { get; set; } - public string SignOutIframeUrl { get; set; } + public string PostLogoutRedirectUri { get; set; } + public string ClientName { get; set; } + public string SignOutIframeUrl { get; set; } - public bool AutomaticRedirectAfterSignOut { get; set; } + public bool AutomaticRedirectAfterSignOut { get; set; } - public string LogoutId { get; set; } - public bool TriggerExternalSignout => ExternalAuthenticationScheme != null; - public string ExternalAuthenticationScheme { get; set; } - } + public string LogoutId { get; set; } + public bool TriggerExternalSignout => ExternalAuthenticationScheme != null; + public string ExternalAuthenticationScheme { get; set; } } \ No newline at end of file diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Account/LoginInputModel.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Account/LoginInputModel.cs index bcb7853a1..a5581fd34 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Account/LoginInputModel.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Account/LoginInputModel.cs @@ -4,15 +4,14 @@ using System.ComponentModel.DataAnnotations; -namespace IdentityServerHost.Quickstart.UI +namespace IdentityServerHost.Quickstart.UI; + +public class LoginInputModel { - public class LoginInputModel - { - [Required] - public string Username { get; set; } - [Required] - public string Password { get; set; } - public bool RememberLogin { get; set; } - public string ReturnUrl { get; set; } - } + [Required] + public string Username { get; set; } + [Required] + public string Password { get; set; } + public bool RememberLogin { get; set; } + public string ReturnUrl { get; set; } } \ No newline at end of file diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Account/LoginViewModel.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Account/LoginViewModel.cs index 9bf6c8f3f..afd4576cd 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Account/LoginViewModel.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Account/LoginViewModel.cs @@ -6,17 +6,16 @@ using System.Collections.Generic; using System.Linq; -namespace IdentityServerHost.Quickstart.UI +namespace IdentityServerHost.Quickstart.UI; + +public class LoginViewModel : LoginInputModel { - public class LoginViewModel : LoginInputModel - { - public bool AllowRememberLogin { get; set; } = true; - public bool EnableLocalLogin { get; set; } = true; + public bool AllowRememberLogin { get; set; } = true; + public bool EnableLocalLogin { get; set; } = true; - public IEnumerable ExternalProviders { get; set; } = Enumerable.Empty(); - public IEnumerable VisibleExternalProviders => ExternalProviders.Where(x => !String.IsNullOrWhiteSpace(x.DisplayName)); + public IEnumerable ExternalProviders { get; set; } = Enumerable.Empty(); + public IEnumerable VisibleExternalProviders => ExternalProviders.Where(x => !String.IsNullOrWhiteSpace(x.DisplayName)); - public bool IsExternalLoginOnly => EnableLocalLogin == false && ExternalProviders?.Count() == 1; - public string ExternalLoginScheme => IsExternalLoginOnly ? ExternalProviders?.SingleOrDefault()?.AuthenticationScheme : null; - } + public bool IsExternalLoginOnly => EnableLocalLogin == false && ExternalProviders?.Count() == 1; + public string ExternalLoginScheme => IsExternalLoginOnly ? ExternalProviders?.SingleOrDefault()?.AuthenticationScheme : null; } \ No newline at end of file diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Account/LogoutInputModel.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Account/LogoutInputModel.cs index bb74202e2..512b36fa5 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Account/LogoutInputModel.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Account/LogoutInputModel.cs @@ -2,10 +2,9 @@ // Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. -namespace IdentityServerHost.Quickstart.UI +namespace IdentityServerHost.Quickstart.UI; + +public class LogoutInputModel { - public class LogoutInputModel - { - public string LogoutId { get; set; } - } + public string LogoutId { get; set; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Account/LogoutViewModel.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Account/LogoutViewModel.cs index 236cd6c88..841289b70 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Account/LogoutViewModel.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Account/LogoutViewModel.cs @@ -2,10 +2,9 @@ // Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. -namespace IdentityServerHost.Quickstart.UI +namespace IdentityServerHost.Quickstart.UI; + +public class LogoutViewModel : LogoutInputModel { - public class LogoutViewModel : LogoutInputModel - { - public bool ShowLogoutPrompt { get; set; } = true; - } + public bool ShowLogoutPrompt { get; set; } = true; } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Account/RedirectViewModel.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Account/RedirectViewModel.cs index 904ae2060..101830f48 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Account/RedirectViewModel.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Account/RedirectViewModel.cs @@ -1,12 +1,11 @@ -// Copyright (c) Brock Allen & Dominick Baier. All rights reserved. +// Copyright (c) Brock Allen & Dominick Baier. All rights reserved. // Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. -namespace IdentityServerHost.Quickstart.UI +namespace IdentityServerHost.Quickstart.UI; + +public class RedirectViewModel { - public class RedirectViewModel - { - public string RedirectUrl { get; set; } - } + public string RedirectUrl { get; set; } } \ No newline at end of file diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Account/SendCodeViewModel.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Account/SendCodeViewModel.cs index ad162c695..6dfb7ab4d 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Account/SendCodeViewModel.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Account/SendCodeViewModel.cs @@ -4,16 +4,15 @@ using System.Linq; using System.Threading.Tasks; -namespace ClassifiedAds.IdentityServer.Quickstart.Account +namespace ClassifiedAds.IdentityServer.Quickstart.Account; + +public class SendCodeViewModel { - public class SendCodeViewModel - { - public string SelectedProvider { get; set; } + public string SelectedProvider { get; set; } - public ICollection Providers { get; set; } + public ICollection Providers { get; set; } - public string ReturnUrl { get; set; } + public string ReturnUrl { get; set; } - public bool RememberMe { get; set; } - } + public bool RememberMe { get; set; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Account/VerifyCodeViewModel.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Account/VerifyCodeViewModel.cs index 945feda63..067f68dac 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Account/VerifyCodeViewModel.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Account/VerifyCodeViewModel.cs @@ -4,22 +4,21 @@ using System.Linq; using System.Threading.Tasks; -namespace ClassifiedAds.IdentityServer.Quickstart.Account +namespace ClassifiedAds.IdentityServer.Quickstart.Account; + +public class VerifyCodeViewModel { - public class VerifyCodeViewModel - { - [Required] - public string Provider { get; set; } + [Required] + public string Provider { get; set; } - [Required] - public string Code { get; set; } + [Required] + public string Code { get; set; } - public string ReturnUrl { get; set; } + public string ReturnUrl { get; set; } - [Display(Name = "Remember this browser?")] - public bool RememberBrowser { get; set; } + [Display(Name = "Remember this browser?")] + public bool RememberBrowser { get; set; } - [Display(Name = "Remember me?")] - public bool RememberMe { get; set; } - } + [Display(Name = "Remember me?")] + public bool RememberMe { get; set; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Consent/ConsentController.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Consent/ConsentController.cs index d14c2f1f3..2d4f7a825 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Consent/ConsentController.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Consent/ConsentController.cs @@ -15,248 +15,247 @@ using System.Collections.Generic; using System; -namespace IdentityServerHost.Quickstart.UI +namespace IdentityServerHost.Quickstart.UI; + +/// +/// This controller processes the consent UI +/// +[SecurityHeaders] +[Authorize] +public class ConsentController : Controller { + private readonly IIdentityServerInteractionService _interaction; + private readonly IEventService _events; + private readonly ILogger _logger; + + public ConsentController( + IIdentityServerInteractionService interaction, + IEventService events, + ILogger logger) + { + _interaction = interaction; + _events = events; + _logger = logger; + } + /// - /// This controller processes the consent UI + /// Shows the consent screen /// - [SecurityHeaders] - [Authorize] - public class ConsentController : Controller + /// + /// + [HttpGet] + public async Task Index(string returnUrl) { - private readonly IIdentityServerInteractionService _interaction; - private readonly IEventService _events; - private readonly ILogger _logger; - - public ConsentController( - IIdentityServerInteractionService interaction, - IEventService events, - ILogger logger) + var vm = await BuildViewModelAsync(returnUrl); + if (vm != null) { - _interaction = interaction; - _events = events; - _logger = logger; + return View("Index", vm); } - /// - /// Shows the consent screen - /// - /// - /// - [HttpGet] - public async Task Index(string returnUrl) + return View("Error"); + } + + /// + /// Handles the consent screen postback + /// + [HttpPost] + [ValidateAntiForgeryToken] + public async Task Index(ConsentInputModel model) + { + var result = await ProcessConsent(model); + + if (result.IsRedirect) { - var vm = await BuildViewModelAsync(returnUrl); - if (vm != null) + var context = await _interaction.GetAuthorizationContextAsync(model.ReturnUrl); + if (context?.IsNativeClient() == true) { - return View("Index", vm); + // The client is native, so this change in how to + // return the response is for better UX for the end user. + return this.LoadingPage("Redirect", result.RedirectUri); } - return View("Error"); + return Redirect(result.RedirectUri); } - /// - /// Handles the consent screen postback - /// - [HttpPost] - [ValidateAntiForgeryToken] - public async Task Index(ConsentInputModel model) + if (result.HasValidationError) { - var result = await ProcessConsent(model); + ModelState.AddModelError(string.Empty, result.ValidationError); + } - if (result.IsRedirect) - { - var context = await _interaction.GetAuthorizationContextAsync(model.ReturnUrl); - if (context?.IsNativeClient() == true) - { - // The client is native, so this change in how to - // return the response is for better UX for the end user. - return this.LoadingPage("Redirect", result.RedirectUri); - } + if (result.ShowView) + { + return View("Index", result.ViewModel); + } - return Redirect(result.RedirectUri); - } + return View("Error"); + } - if (result.HasValidationError) - { - ModelState.AddModelError(string.Empty, result.ValidationError); - } + /*****************************************/ + /* helper APIs for the ConsentController */ + /*****************************************/ + private async Task ProcessConsent(ConsentInputModel model) + { + var result = new ProcessConsentResult(); - if (result.ShowView) - { - return View("Index", result.ViewModel); - } + // validate return url is still valid + var request = await _interaction.GetAuthorizationContextAsync(model.ReturnUrl); + if (request == null) return result; - return View("Error"); - } + ConsentResponse grantedConsent = null; - /*****************************************/ - /* helper APIs for the ConsentController */ - /*****************************************/ - private async Task ProcessConsent(ConsentInputModel model) + // user clicked 'no' - send back the standard 'access_denied' response + if (model?.Button == "no") { - var result = new ProcessConsentResult(); - - // validate return url is still valid - var request = await _interaction.GetAuthorizationContextAsync(model.ReturnUrl); - if (request == null) return result; - - ConsentResponse grantedConsent = null; + grantedConsent = new ConsentResponse { Error = AuthorizationError.AccessDenied }; - // user clicked 'no' - send back the standard 'access_denied' response - if (model?.Button == "no") - { - grantedConsent = new ConsentResponse { Error = AuthorizationError.AccessDenied }; - - // emit event - await _events.RaiseAsync(new ConsentDeniedEvent(User.GetSubjectId(), request.Client.ClientId, request.ValidatedResources.RawScopeValues)); - } - // user clicked 'yes' - validate the data - else if (model?.Button == "yes") + // emit event + await _events.RaiseAsync(new ConsentDeniedEvent(User.GetSubjectId(), request.Client.ClientId, request.ValidatedResources.RawScopeValues)); + } + // user clicked 'yes' - validate the data + else if (model?.Button == "yes") + { + // if the user consented to some scope, build the response model + if (model.ScopesConsented != null && model.ScopesConsented.Any()) { - // if the user consented to some scope, build the response model - if (model.ScopesConsented != null && model.ScopesConsented.Any()) - { - var scopes = model.ScopesConsented; - if (ConsentOptions.EnableOfflineAccess == false) - { - scopes = scopes.Where(x => x != IdentityServer4.IdentityServerConstants.StandardScopes.OfflineAccess); - } - - grantedConsent = new ConsentResponse - { - RememberConsent = model.RememberConsent, - ScopesValuesConsented = scopes.ToArray(), - Description = model.Description, - }; - - // emit event - await _events.RaiseAsync(new ConsentGrantedEvent(User.GetSubjectId(), request.Client.ClientId, request.ValidatedResources.RawScopeValues, grantedConsent.ScopesValuesConsented, grantedConsent.RememberConsent)); - } - else + var scopes = model.ScopesConsented; + if (ConsentOptions.EnableOfflineAccess == false) { - result.ValidationError = ConsentOptions.MustChooseOneErrorMessage; + scopes = scopes.Where(x => x != IdentityServer4.IdentityServerConstants.StandardScopes.OfflineAccess); } - } - else - { - result.ValidationError = ConsentOptions.InvalidSelectionErrorMessage; - } - if (grantedConsent != null) - { - // communicate outcome of consent back to identityserver - await _interaction.GrantConsentAsync(request, grantedConsent); + grantedConsent = new ConsentResponse + { + RememberConsent = model.RememberConsent, + ScopesValuesConsented = scopes.ToArray(), + Description = model.Description, + }; - // indicate that's it ok to redirect back to authorization endpoint - result.RedirectUri = model.ReturnUrl; - result.Client = request.Client; + // emit event + await _events.RaiseAsync(new ConsentGrantedEvent(User.GetSubjectId(), request.Client.ClientId, request.ValidatedResources.RawScopeValues, grantedConsent.ScopesValuesConsented, grantedConsent.RememberConsent)); } else { - // we need to redisplay the consent UI - result.ViewModel = await BuildViewModelAsync(model.ReturnUrl, model); + result.ValidationError = ConsentOptions.MustChooseOneErrorMessage; } - - return result; + } + else + { + result.ValidationError = ConsentOptions.InvalidSelectionErrorMessage; } - private async Task BuildViewModelAsync(string returnUrl, ConsentInputModel model = null) + if (grantedConsent != null) { - var request = await _interaction.GetAuthorizationContextAsync(returnUrl); - if (request != null) - { - return CreateConsentViewModel(model, returnUrl, request); - } - else - { - _logger.LogError("No consent request matching request: {0}", returnUrl); - } + // communicate outcome of consent back to identityserver + await _interaction.GrantConsentAsync(request, grantedConsent); - return null; + // indicate that's it ok to redirect back to authorization endpoint + result.RedirectUri = model.ReturnUrl; + result.Client = request.Client; } + else + { + // we need to redisplay the consent UI + result.ViewModel = await BuildViewModelAsync(model.ReturnUrl, model); + } + + return result; + } - private ConsentViewModel CreateConsentViewModel( - ConsentInputModel model, string returnUrl, - AuthorizationRequest request) + private async Task BuildViewModelAsync(string returnUrl, ConsentInputModel model = null) + { + var request = await _interaction.GetAuthorizationContextAsync(returnUrl); + if (request != null) { - var vm = new ConsentViewModel - { - RememberConsent = model?.RememberConsent ?? true, - ScopesConsented = model?.ScopesConsented ?? Enumerable.Empty(), - Description = model?.Description, + return CreateConsentViewModel(model, returnUrl, request); + } + else + { + _logger.LogError("No consent request matching request: {0}", returnUrl); + } - ReturnUrl = returnUrl, + return null; + } - ClientName = request.Client.ClientName ?? request.Client.ClientId, - ClientUrl = request.Client.ClientUri, - ClientLogoUrl = request.Client.LogoUri, - AllowRememberConsent = request.Client.AllowRememberConsent - }; + private ConsentViewModel CreateConsentViewModel( + ConsentInputModel model, string returnUrl, + AuthorizationRequest request) + { + var vm = new ConsentViewModel + { + RememberConsent = model?.RememberConsent ?? true, + ScopesConsented = model?.ScopesConsented ?? Enumerable.Empty(), + Description = model?.Description, - vm.IdentityScopes = request.ValidatedResources.Resources.IdentityResources.Select(x => CreateScopeViewModel(x, vm.ScopesConsented.Contains(x.Name) || model == null)).ToArray(); + ReturnUrl = returnUrl, - var apiScopes = new List(); - foreach(var parsedScope in request.ValidatedResources.ParsedScopes) - { - var apiScope = request.ValidatedResources.Resources.FindApiScope(parsedScope.ParsedName); - if (apiScope != null) - { - var scopeVm = CreateScopeViewModel(parsedScope, apiScope, vm.ScopesConsented.Contains(parsedScope.RawValue) || model == null); - apiScopes.Add(scopeVm); - } - } - if (ConsentOptions.EnableOfflineAccess && request.ValidatedResources.Resources.OfflineAccess) - { - apiScopes.Add(GetOfflineAccessScope(vm.ScopesConsented.Contains(IdentityServer4.IdentityServerConstants.StandardScopes.OfflineAccess) || model == null)); - } - vm.ApiScopes = apiScopes; + ClientName = request.Client.ClientName ?? request.Client.ClientId, + ClientUrl = request.Client.ClientUri, + ClientLogoUrl = request.Client.LogoUri, + AllowRememberConsent = request.Client.AllowRememberConsent + }; - return vm; - } + vm.IdentityScopes = request.ValidatedResources.Resources.IdentityResources.Select(x => CreateScopeViewModel(x, vm.ScopesConsented.Contains(x.Name) || model == null)).ToArray(); - private ScopeViewModel CreateScopeViewModel(IdentityResource identity, bool check) + var apiScopes = new List(); + foreach(var parsedScope in request.ValidatedResources.ParsedScopes) { - return new ScopeViewModel + var apiScope = request.ValidatedResources.Resources.FindApiScope(parsedScope.ParsedName); + if (apiScope != null) { - Value = identity.Name, - DisplayName = identity.DisplayName ?? identity.Name, - Description = identity.Description, - Emphasize = identity.Emphasize, - Required = identity.Required, - Checked = check || identity.Required - }; + var scopeVm = CreateScopeViewModel(parsedScope, apiScope, vm.ScopesConsented.Contains(parsedScope.RawValue) || model == null); + apiScopes.Add(scopeVm); + } + } + if (ConsentOptions.EnableOfflineAccess && request.ValidatedResources.Resources.OfflineAccess) + { + apiScopes.Add(GetOfflineAccessScope(vm.ScopesConsented.Contains(IdentityServer4.IdentityServerConstants.StandardScopes.OfflineAccess) || model == null)); } + vm.ApiScopes = apiScopes; - public ScopeViewModel CreateScopeViewModel(ParsedScopeValue parsedScopeValue, ApiScope apiScope, bool check) + return vm; + } + + private ScopeViewModel CreateScopeViewModel(IdentityResource identity, bool check) + { + return new ScopeViewModel { - var displayName = apiScope.DisplayName ?? apiScope.Name; - if (!String.IsNullOrWhiteSpace(parsedScopeValue.ParsedParameter)) - { - displayName += ":" + parsedScopeValue.ParsedParameter; - } + Value = identity.Name, + DisplayName = identity.DisplayName ?? identity.Name, + Description = identity.Description, + Emphasize = identity.Emphasize, + Required = identity.Required, + Checked = check || identity.Required + }; + } - return new ScopeViewModel - { - Value = parsedScopeValue.RawValue, - DisplayName = displayName, - Description = apiScope.Description, - Emphasize = apiScope.Emphasize, - Required = apiScope.Required, - Checked = check || apiScope.Required - }; + public ScopeViewModel CreateScopeViewModel(ParsedScopeValue parsedScopeValue, ApiScope apiScope, bool check) + { + var displayName = apiScope.DisplayName ?? apiScope.Name; + if (!String.IsNullOrWhiteSpace(parsedScopeValue.ParsedParameter)) + { + displayName += ":" + parsedScopeValue.ParsedParameter; } - private ScopeViewModel GetOfflineAccessScope(bool check) + return new ScopeViewModel { - return new ScopeViewModel - { - Value = IdentityServer4.IdentityServerConstants.StandardScopes.OfflineAccess, - DisplayName = ConsentOptions.OfflineAccessDisplayName, - Description = ConsentOptions.OfflineAccessDescription, - Emphasize = true, - Checked = check - }; - } + Value = parsedScopeValue.RawValue, + DisplayName = displayName, + Description = apiScope.Description, + Emphasize = apiScope.Emphasize, + Required = apiScope.Required, + Checked = check || apiScope.Required + }; + } + + private ScopeViewModel GetOfflineAccessScope(bool check) + { + return new ScopeViewModel + { + Value = IdentityServer4.IdentityServerConstants.StandardScopes.OfflineAccess, + DisplayName = ConsentOptions.OfflineAccessDisplayName, + Description = ConsentOptions.OfflineAccessDescription, + Emphasize = true, + Checked = check + }; } } \ No newline at end of file diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Consent/ConsentInputModel.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Consent/ConsentInputModel.cs index f608fe3bb..71d6da943 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Consent/ConsentInputModel.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Consent/ConsentInputModel.cs @@ -4,14 +4,13 @@ using System.Collections.Generic; -namespace IdentityServerHost.Quickstart.UI +namespace IdentityServerHost.Quickstart.UI; + +public class ConsentInputModel { - public class ConsentInputModel - { - public string Button { get; set; } - public IEnumerable ScopesConsented { get; set; } - public bool RememberConsent { get; set; } - public string ReturnUrl { get; set; } - public string Description { get; set; } - } + public string Button { get; set; } + public IEnumerable ScopesConsented { get; set; } + public bool RememberConsent { get; set; } + public string ReturnUrl { get; set; } + public string Description { get; set; } } \ No newline at end of file diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Consent/ConsentOptions.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Consent/ConsentOptions.cs index 998c51dca..3d330628f 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Consent/ConsentOptions.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Consent/ConsentOptions.cs @@ -2,15 +2,14 @@ // Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. -namespace IdentityServerHost.Quickstart.UI +namespace IdentityServerHost.Quickstart.UI; + +public class ConsentOptions { - public class ConsentOptions - { - public static bool EnableOfflineAccess = true; - public static string OfflineAccessDisplayName = "Offline Access"; - public static string OfflineAccessDescription = "Access to your applications and resources, even when you are offline"; + public static bool EnableOfflineAccess = true; + public static string OfflineAccessDisplayName = "Offline Access"; + public static string OfflineAccessDescription = "Access to your applications and resources, even when you are offline"; - public static readonly string MustChooseOneErrorMessage = "You must pick at least one permission"; - public static readonly string InvalidSelectionErrorMessage = "Invalid selection"; - } + public static readonly string MustChooseOneErrorMessage = "You must pick at least one permission"; + public static readonly string InvalidSelectionErrorMessage = "Invalid selection"; } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Consent/ConsentViewModel.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Consent/ConsentViewModel.cs index af4b9c5c9..3e5c0dce0 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Consent/ConsentViewModel.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Consent/ConsentViewModel.cs @@ -4,16 +4,15 @@ using System.Collections.Generic; -namespace IdentityServerHost.Quickstart.UI +namespace IdentityServerHost.Quickstart.UI; + +public class ConsentViewModel : ConsentInputModel { - public class ConsentViewModel : ConsentInputModel - { - public string ClientName { get; set; } - public string ClientUrl { get; set; } - public string ClientLogoUrl { get; set; } - public bool AllowRememberConsent { get; set; } + public string ClientName { get; set; } + public string ClientUrl { get; set; } + public string ClientLogoUrl { get; set; } + public bool AllowRememberConsent { get; set; } - public IEnumerable IdentityScopes { get; set; } - public IEnumerable ApiScopes { get; set; } - } + public IEnumerable IdentityScopes { get; set; } + public IEnumerable ApiScopes { get; set; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Consent/ProcessConsentResult.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Consent/ProcessConsentResult.cs index 1d331df04..931835600 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Consent/ProcessConsentResult.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Consent/ProcessConsentResult.cs @@ -4,18 +4,17 @@ using IdentityServer4.Models; -namespace IdentityServerHost.Quickstart.UI +namespace IdentityServerHost.Quickstart.UI; + +public class ProcessConsentResult { - public class ProcessConsentResult - { - public bool IsRedirect => RedirectUri != null; - public string RedirectUri { get; set; } - public Client Client { get; set; } + public bool IsRedirect => RedirectUri != null; + public string RedirectUri { get; set; } + public Client Client { get; set; } - public bool ShowView => ViewModel != null; - public ConsentViewModel ViewModel { get; set; } + public bool ShowView => ViewModel != null; + public ConsentViewModel ViewModel { get; set; } - public bool HasValidationError => ValidationError != null; - public string ValidationError { get; set; } - } + public bool HasValidationError => ValidationError != null; + public string ValidationError { get; set; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Consent/ScopeViewModel.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Consent/ScopeViewModel.cs index 532d1b1a8..6d242f456 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Consent/ScopeViewModel.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Consent/ScopeViewModel.cs @@ -2,15 +2,14 @@ // Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. -namespace IdentityServerHost.Quickstart.UI +namespace IdentityServerHost.Quickstart.UI; + +public class ScopeViewModel { - public class ScopeViewModel - { - public string Value { get; set; } - public string DisplayName { get; set; } - public string Description { get; set; } - public bool Emphasize { get; set; } - public bool Required { get; set; } - public bool Checked { get; set; } - } + public string Value { get; set; } + public string DisplayName { get; set; } + public string Description { get; set; } + public bool Emphasize { get; set; } + public bool Required { get; set; } + public bool Checked { get; set; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Device/DeviceAuthorizationInputModel.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Device/DeviceAuthorizationInputModel.cs index a221181e8..e47f22c0a 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Device/DeviceAuthorizationInputModel.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Device/DeviceAuthorizationInputModel.cs @@ -2,10 +2,9 @@ // Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. -namespace IdentityServerHost.Quickstart.UI +namespace IdentityServerHost.Quickstart.UI; + +public class DeviceAuthorizationInputModel : ConsentInputModel { - public class DeviceAuthorizationInputModel : ConsentInputModel - { - public string UserCode { get; set; } - } + public string UserCode { get; set; } } \ No newline at end of file diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Device/DeviceAuthorizationViewModel.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Device/DeviceAuthorizationViewModel.cs index 3e8857f65..a8aad3e69 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Device/DeviceAuthorizationViewModel.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Device/DeviceAuthorizationViewModel.cs @@ -2,11 +2,10 @@ // Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. -namespace IdentityServerHost.Quickstart.UI +namespace IdentityServerHost.Quickstart.UI; + +public class DeviceAuthorizationViewModel : ConsentViewModel { - public class DeviceAuthorizationViewModel : ConsentViewModel - { - public string UserCode { get; set; } - public bool ConfirmUserCode { get; set; } - } + public string UserCode { get; set; } + public bool ConfirmUserCode { get; set; } } \ No newline at end of file diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Device/DeviceController.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Device/DeviceController.cs index d7d07aeb9..1ba1e0ba1 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Device/DeviceController.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Device/DeviceController.cs @@ -17,216 +17,215 @@ using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; -namespace IdentityServerHost.Quickstart.UI +namespace IdentityServerHost.Quickstart.UI; + +[Authorize] +[SecurityHeaders] +public class DeviceController : Controller { - [Authorize] - [SecurityHeaders] - public class DeviceController : Controller + private readonly IDeviceFlowInteractionService _interaction; + private readonly IEventService _events; + private readonly IOptions _options; + private readonly ILogger _logger; + + public DeviceController( + IDeviceFlowInteractionService interaction, + IEventService eventService, + IOptions options, + ILogger logger) { - private readonly IDeviceFlowInteractionService _interaction; - private readonly IEventService _events; - private readonly IOptions _options; - private readonly ILogger _logger; - - public DeviceController( - IDeviceFlowInteractionService interaction, - IEventService eventService, - IOptions options, - ILogger logger) - { - _interaction = interaction; - _events = eventService; - _options = options; - _logger = logger; - } + _interaction = interaction; + _events = eventService; + _options = options; + _logger = logger; + } - [HttpGet] - public async Task Index() - { - string userCodeParamName = _options.Value.UserInteraction.DeviceVerificationUserCodeParameter; - string userCode = Request.Query[userCodeParamName]; - if (string.IsNullOrWhiteSpace(userCode)) return View("UserCodeCapture"); + [HttpGet] + public async Task Index() + { + string userCodeParamName = _options.Value.UserInteraction.DeviceVerificationUserCodeParameter; + string userCode = Request.Query[userCodeParamName]; + if (string.IsNullOrWhiteSpace(userCode)) return View("UserCodeCapture"); - var vm = await BuildViewModelAsync(userCode); - if (vm == null) return View("Error"); + var vm = await BuildViewModelAsync(userCode); + if (vm == null) return View("Error"); - vm.ConfirmUserCode = true; - return View("UserCodeConfirmation", vm); - } + vm.ConfirmUserCode = true; + return View("UserCodeConfirmation", vm); + } - [HttpPost] - [ValidateAntiForgeryToken] - public async Task UserCodeCapture(string userCode) - { - var vm = await BuildViewModelAsync(userCode); - if (vm == null) return View("Error"); + [HttpPost] + [ValidateAntiForgeryToken] + public async Task UserCodeCapture(string userCode) + { + var vm = await BuildViewModelAsync(userCode); + if (vm == null) return View("Error"); - return View("UserCodeConfirmation", vm); - } + return View("UserCodeConfirmation", vm); + } - [HttpPost] - [ValidateAntiForgeryToken] - public async Task Callback(DeviceAuthorizationInputModel model) - { - if (model == null) throw new ArgumentNullException(nameof(model)); + [HttpPost] + [ValidateAntiForgeryToken] + public async Task Callback(DeviceAuthorizationInputModel model) + { + if (model == null) throw new ArgumentNullException(nameof(model)); - var result = await ProcessConsent(model); - if (result.HasValidationError) return View("Error"); + var result = await ProcessConsent(model); + if (result.HasValidationError) return View("Error"); - return View("Success"); - } + return View("Success"); + } - private async Task ProcessConsent(DeviceAuthorizationInputModel model) - { - var result = new ProcessConsentResult(); + private async Task ProcessConsent(DeviceAuthorizationInputModel model) + { + var result = new ProcessConsentResult(); - var request = await _interaction.GetAuthorizationContextAsync(model.UserCode); - if (request == null) return result; + var request = await _interaction.GetAuthorizationContextAsync(model.UserCode); + if (request == null) return result; - ConsentResponse grantedConsent = null; + ConsentResponse grantedConsent = null; - // user clicked 'no' - send back the standard 'access_denied' response - if (model.Button == "no") - { - grantedConsent = new ConsentResponse { Error = AuthorizationError.AccessDenied }; + // user clicked 'no' - send back the standard 'access_denied' response + if (model.Button == "no") + { + grantedConsent = new ConsentResponse { Error = AuthorizationError.AccessDenied }; - // emit event - await _events.RaiseAsync(new ConsentDeniedEvent(User.GetSubjectId(), request.Client.ClientId, request.ValidatedResources.RawScopeValues)); - } - // user clicked 'yes' - validate the data - else if (model.Button == "yes") + // emit event + await _events.RaiseAsync(new ConsentDeniedEvent(User.GetSubjectId(), request.Client.ClientId, request.ValidatedResources.RawScopeValues)); + } + // user clicked 'yes' - validate the data + else if (model.Button == "yes") + { + // if the user consented to some scope, build the response model + if (model.ScopesConsented != null && model.ScopesConsented.Any()) { - // if the user consented to some scope, build the response model - if (model.ScopesConsented != null && model.ScopesConsented.Any()) - { - var scopes = model.ScopesConsented; - if (ConsentOptions.EnableOfflineAccess == false) - { - scopes = scopes.Where(x => x != IdentityServer4.IdentityServerConstants.StandardScopes.OfflineAccess); - } - - grantedConsent = new ConsentResponse - { - RememberConsent = model.RememberConsent, - ScopesValuesConsented = scopes.ToArray(), - Description = model.Description - }; - - // emit event - await _events.RaiseAsync(new ConsentGrantedEvent(User.GetSubjectId(), request.Client.ClientId, request.ValidatedResources.RawScopeValues, grantedConsent.ScopesValuesConsented, grantedConsent.RememberConsent)); - } - else + var scopes = model.ScopesConsented; + if (ConsentOptions.EnableOfflineAccess == false) { - result.ValidationError = ConsentOptions.MustChooseOneErrorMessage; + scopes = scopes.Where(x => x != IdentityServer4.IdentityServerConstants.StandardScopes.OfflineAccess); } - } - else - { - result.ValidationError = ConsentOptions.InvalidSelectionErrorMessage; - } - if (grantedConsent != null) - { - // communicate outcome of consent back to identityserver - await _interaction.HandleRequestAsync(model.UserCode, grantedConsent); + grantedConsent = new ConsentResponse + { + RememberConsent = model.RememberConsent, + ScopesValuesConsented = scopes.ToArray(), + Description = model.Description + }; - // indicate that's it ok to redirect back to authorization endpoint - result.RedirectUri = model.ReturnUrl; - result.Client = request.Client; + // emit event + await _events.RaiseAsync(new ConsentGrantedEvent(User.GetSubjectId(), request.Client.ClientId, request.ValidatedResources.RawScopeValues, grantedConsent.ScopesValuesConsented, grantedConsent.RememberConsent)); } else { - // we need to redisplay the consent UI - result.ViewModel = await BuildViewModelAsync(model.UserCode, model); + result.ValidationError = ConsentOptions.MustChooseOneErrorMessage; } - - return result; + } + else + { + result.ValidationError = ConsentOptions.InvalidSelectionErrorMessage; } - private async Task BuildViewModelAsync(string userCode, DeviceAuthorizationInputModel model = null) + if (grantedConsent != null) { - var request = await _interaction.GetAuthorizationContextAsync(userCode); - if (request != null) - { - return CreateConsentViewModel(userCode, model, request); - } + // communicate outcome of consent back to identityserver + await _interaction.HandleRequestAsync(model.UserCode, grantedConsent); - return null; + // indicate that's it ok to redirect back to authorization endpoint + result.RedirectUri = model.ReturnUrl; + result.Client = request.Client; + } + else + { + // we need to redisplay the consent UI + result.ViewModel = await BuildViewModelAsync(model.UserCode, model); } - private DeviceAuthorizationViewModel CreateConsentViewModel(string userCode, DeviceAuthorizationInputModel model, DeviceFlowAuthorizationRequest request) + return result; + } + + private async Task BuildViewModelAsync(string userCode, DeviceAuthorizationInputModel model = null) + { + var request = await _interaction.GetAuthorizationContextAsync(userCode); + if (request != null) { - var vm = new DeviceAuthorizationViewModel - { - UserCode = userCode, - Description = model?.Description, + return CreateConsentViewModel(userCode, model, request); + } - RememberConsent = model?.RememberConsent ?? true, - ScopesConsented = model?.ScopesConsented ?? Enumerable.Empty(), + return null; + } - ClientName = request.Client.ClientName ?? request.Client.ClientId, - ClientUrl = request.Client.ClientUri, - ClientLogoUrl = request.Client.LogoUri, - AllowRememberConsent = request.Client.AllowRememberConsent - }; + private DeviceAuthorizationViewModel CreateConsentViewModel(string userCode, DeviceAuthorizationInputModel model, DeviceFlowAuthorizationRequest request) + { + var vm = new DeviceAuthorizationViewModel + { + UserCode = userCode, + Description = model?.Description, - vm.IdentityScopes = request.ValidatedResources.Resources.IdentityResources.Select(x => CreateScopeViewModel(x, vm.ScopesConsented.Contains(x.Name) || model == null)).ToArray(); + RememberConsent = model?.RememberConsent ?? true, + ScopesConsented = model?.ScopesConsented ?? Enumerable.Empty(), - var apiScopes = new List(); - foreach (var parsedScope in request.ValidatedResources.ParsedScopes) - { - var apiScope = request.ValidatedResources.Resources.FindApiScope(parsedScope.ParsedName); - if (apiScope != null) - { - var scopeVm = CreateScopeViewModel(parsedScope, apiScope, vm.ScopesConsented.Contains(parsedScope.RawValue) || model == null); - apiScopes.Add(scopeVm); - } - } - if (ConsentOptions.EnableOfflineAccess && request.ValidatedResources.Resources.OfflineAccess) - { - apiScopes.Add(GetOfflineAccessScope(vm.ScopesConsented.Contains(IdentityServer4.IdentityServerConstants.StandardScopes.OfflineAccess) || model == null)); - } - vm.ApiScopes = apiScopes; + ClientName = request.Client.ClientName ?? request.Client.ClientId, + ClientUrl = request.Client.ClientUri, + ClientLogoUrl = request.Client.LogoUri, + AllowRememberConsent = request.Client.AllowRememberConsent + }; - return vm; - } + vm.IdentityScopes = request.ValidatedResources.Resources.IdentityResources.Select(x => CreateScopeViewModel(x, vm.ScopesConsented.Contains(x.Name) || model == null)).ToArray(); - private ScopeViewModel CreateScopeViewModel(IdentityResource identity, bool check) + var apiScopes = new List(); + foreach (var parsedScope in request.ValidatedResources.ParsedScopes) { - return new ScopeViewModel + var apiScope = request.ValidatedResources.Resources.FindApiScope(parsedScope.ParsedName); + if (apiScope != null) { - Value = identity.Name, - DisplayName = identity.DisplayName ?? identity.Name, - Description = identity.Description, - Emphasize = identity.Emphasize, - Required = identity.Required, - Checked = check || identity.Required - }; + var scopeVm = CreateScopeViewModel(parsedScope, apiScope, vm.ScopesConsented.Contains(parsedScope.RawValue) || model == null); + apiScopes.Add(scopeVm); + } } - - public ScopeViewModel CreateScopeViewModel(ParsedScopeValue parsedScopeValue, ApiScope apiScope, bool check) + if (ConsentOptions.EnableOfflineAccess && request.ValidatedResources.Resources.OfflineAccess) { - return new ScopeViewModel - { - Value = parsedScopeValue.RawValue, - // todo: use the parsed scope value in the display? - DisplayName = apiScope.DisplayName ?? apiScope.Name, - Description = apiScope.Description, - Emphasize = apiScope.Emphasize, - Required = apiScope.Required, - Checked = check || apiScope.Required - }; + apiScopes.Add(GetOfflineAccessScope(vm.ScopesConsented.Contains(IdentityServer4.IdentityServerConstants.StandardScopes.OfflineAccess) || model == null)); } - private ScopeViewModel GetOfflineAccessScope(bool check) + vm.ApiScopes = apiScopes; + + return vm; + } + + private ScopeViewModel CreateScopeViewModel(IdentityResource identity, bool check) + { + return new ScopeViewModel { - return new ScopeViewModel - { - Value = IdentityServer4.IdentityServerConstants.StandardScopes.OfflineAccess, - DisplayName = ConsentOptions.OfflineAccessDisplayName, - Description = ConsentOptions.OfflineAccessDescription, - Emphasize = true, - Checked = check - }; - } + Value = identity.Name, + DisplayName = identity.DisplayName ?? identity.Name, + Description = identity.Description, + Emphasize = identity.Emphasize, + Required = identity.Required, + Checked = check || identity.Required + }; + } + + public ScopeViewModel CreateScopeViewModel(ParsedScopeValue parsedScopeValue, ApiScope apiScope, bool check) + { + return new ScopeViewModel + { + Value = parsedScopeValue.RawValue, + // todo: use the parsed scope value in the display? + DisplayName = apiScope.DisplayName ?? apiScope.Name, + Description = apiScope.Description, + Emphasize = apiScope.Emphasize, + Required = apiScope.Required, + Checked = check || apiScope.Required + }; + } + private ScopeViewModel GetOfflineAccessScope(bool check) + { + return new ScopeViewModel + { + Value = IdentityServer4.IdentityServerConstants.StandardScopes.OfflineAccess, + DisplayName = ConsentOptions.OfflineAccessDisplayName, + Description = ConsentOptions.OfflineAccessDescription, + Emphasize = true, + Checked = check + }; } } \ No newline at end of file diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Diagnostics/DiagnosticsController.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Diagnostics/DiagnosticsController.cs index 57c2f55f9..120b12351 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Diagnostics/DiagnosticsController.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Diagnostics/DiagnosticsController.cs @@ -8,22 +8,21 @@ using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; -namespace IdentityServerHost.Quickstart.UI +namespace IdentityServerHost.Quickstart.UI; + +[SecurityHeaders] +[Authorize] +public class DiagnosticsController : Controller { - [SecurityHeaders] - [Authorize] - public class DiagnosticsController : Controller + public async Task Index() { - public async Task Index() + var localAddresses = new string[] { "127.0.0.1", "::1", HttpContext.Connection.LocalIpAddress.ToString() }; + if (!localAddresses.Contains(HttpContext.Connection.RemoteIpAddress.ToString())) { - var localAddresses = new string[] { "127.0.0.1", "::1", HttpContext.Connection.LocalIpAddress.ToString() }; - if (!localAddresses.Contains(HttpContext.Connection.RemoteIpAddress.ToString())) - { - return NotFound(); - } - - var model = new DiagnosticsViewModel(await HttpContext.AuthenticateAsync()); - return View(model); + return NotFound(); } + + var model = new DiagnosticsViewModel(await HttpContext.AuthenticateAsync()); + return View(model); } } \ No newline at end of file diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Diagnostics/DiagnosticsViewModel.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Diagnostics/DiagnosticsViewModel.cs index 70b5c0578..2a25b6dab 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Diagnostics/DiagnosticsViewModel.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Diagnostics/DiagnosticsViewModel.cs @@ -8,25 +8,24 @@ using System.Text; using System.Text.Json; -namespace IdentityServerHost.Quickstart.UI +namespace IdentityServerHost.Quickstart.UI; + +public class DiagnosticsViewModel { - public class DiagnosticsViewModel + public DiagnosticsViewModel(AuthenticateResult result) { - public DiagnosticsViewModel(AuthenticateResult result) - { - AuthenticateResult = result; + AuthenticateResult = result; - if (result.Properties.Items.ContainsKey("client_list")) - { - var encoded = result.Properties.Items["client_list"]; - var bytes = Base64Url.Decode(encoded); - var value = Encoding.UTF8.GetString(bytes); + if (result.Properties.Items.ContainsKey("client_list")) + { + var encoded = result.Properties.Items["client_list"]; + var bytes = Base64Url.Decode(encoded); + var value = Encoding.UTF8.GetString(bytes); - Clients = JsonSerializer.Deserialize(value); - } + Clients = JsonSerializer.Deserialize(value); } - - public AuthenticateResult AuthenticateResult { get; } - public IEnumerable Clients { get; } = new List(); } + + public AuthenticateResult AuthenticateResult { get; } + public IEnumerable Clients { get; } = new List(); } \ No newline at end of file diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Extensions.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Extensions.cs index 6c720b707..fe72077d4 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Extensions.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Extensions.cs @@ -2,26 +2,25 @@ using IdentityServer4.Models; using Microsoft.AspNetCore.Mvc; -namespace IdentityServerHost.Quickstart.UI +namespace IdentityServerHost.Quickstart.UI; + +public static class Extensions { - public static class Extensions + /// + /// Checks if the redirect URI is for a native client. + /// + /// + public static bool IsNativeClient(this AuthorizationRequest context) { - /// - /// Checks if the redirect URI is for a native client. - /// - /// - public static bool IsNativeClient(this AuthorizationRequest context) - { - return !context.RedirectUri.StartsWith("https", StringComparison.Ordinal) - && !context.RedirectUri.StartsWith("http", StringComparison.Ordinal); - } + return !context.RedirectUri.StartsWith("https", StringComparison.Ordinal) + && !context.RedirectUri.StartsWith("http", StringComparison.Ordinal); + } - public static IActionResult LoadingPage(this Controller controller, string viewName, string redirectUri) - { - controller.HttpContext.Response.StatusCode = 200; - controller.HttpContext.Response.Headers["Location"] = ""; - - return controller.View(viewName, new RedirectViewModel { RedirectUrl = redirectUri }); - } + public static IActionResult LoadingPage(this Controller controller, string viewName, string redirectUri) + { + controller.HttpContext.Response.StatusCode = 200; + controller.HttpContext.Response.Headers["Location"] = ""; + + return controller.View(viewName, new RedirectViewModel { RedirectUrl = redirectUri }); } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Grants/GrantsController.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Grants/GrantsController.cs index 128ce5921..df5c6c239 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Grants/GrantsController.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Grants/GrantsController.cs @@ -12,86 +12,85 @@ using IdentityServer4.Events; using IdentityServer4.Extensions; -namespace IdentityServerHost.Quickstart.UI +namespace IdentityServerHost.Quickstart.UI; + +/// +/// This sample controller allows a user to revoke grants given to clients +/// +[SecurityHeaders] +[Authorize] +public class GrantsController : Controller { + private readonly IIdentityServerInteractionService _interaction; + private readonly IClientStore _clients; + private readonly IResourceStore _resources; + private readonly IEventService _events; + + public GrantsController(IIdentityServerInteractionService interaction, + IClientStore clients, + IResourceStore resources, + IEventService events) + { + _interaction = interaction; + _clients = clients; + _resources = resources; + _events = events; + } + /// - /// This sample controller allows a user to revoke grants given to clients + /// Show list of grants /// - [SecurityHeaders] - [Authorize] - public class GrantsController : Controller + [HttpGet] + public async Task Index() { - private readonly IIdentityServerInteractionService _interaction; - private readonly IClientStore _clients; - private readonly IResourceStore _resources; - private readonly IEventService _events; - - public GrantsController(IIdentityServerInteractionService interaction, - IClientStore clients, - IResourceStore resources, - IEventService events) - { - _interaction = interaction; - _clients = clients; - _resources = resources; - _events = events; - } + return View("Index", await BuildViewModelAsync()); + } - /// - /// Show list of grants - /// - [HttpGet] - public async Task Index() - { - return View("Index", await BuildViewModelAsync()); - } + /// + /// Handle postback to revoke a client + /// + [HttpPost] + [ValidateAntiForgeryToken] + public async Task Revoke(string clientId) + { + await _interaction.RevokeUserConsentAsync(clientId); + await _events.RaiseAsync(new GrantsRevokedEvent(User.GetSubjectId(), clientId)); - /// - /// Handle postback to revoke a client - /// - [HttpPost] - [ValidateAntiForgeryToken] - public async Task Revoke(string clientId) - { - await _interaction.RevokeUserConsentAsync(clientId); - await _events.RaiseAsync(new GrantsRevokedEvent(User.GetSubjectId(), clientId)); + return RedirectToAction("Index"); + } - return RedirectToAction("Index"); - } + private async Task BuildViewModelAsync() + { + var grants = await _interaction.GetAllUserGrantsAsync(); - private async Task BuildViewModelAsync() + var list = new List(); + foreach(var grant in grants) { - var grants = await _interaction.GetAllUserGrantsAsync(); - - var list = new List(); - foreach(var grant in grants) + var client = await _clients.FindClientByIdAsync(grant.ClientId); + if (client != null) { - var client = await _clients.FindClientByIdAsync(grant.ClientId); - if (client != null) - { - var resources = await _resources.FindResourcesByScopeAsync(grant.Scopes); + var resources = await _resources.FindResourcesByScopeAsync(grant.Scopes); - var item = new GrantViewModel() - { - ClientId = client.ClientId, - ClientName = client.ClientName ?? client.ClientId, - ClientLogoUrl = client.LogoUri, - ClientUrl = client.ClientUri, - Description = grant.Description, - Created = grant.CreationTime, - Expires = grant.Expiration, - IdentityGrantNames = resources.IdentityResources.Select(x => x.DisplayName ?? x.Name).ToArray(), - ApiGrantNames = resources.ApiScopes.Select(x => x.DisplayName ?? x.Name).ToArray() - }; + var item = new GrantViewModel() + { + ClientId = client.ClientId, + ClientName = client.ClientName ?? client.ClientId, + ClientLogoUrl = client.LogoUri, + ClientUrl = client.ClientUri, + Description = grant.Description, + Created = grant.CreationTime, + Expires = grant.Expiration, + IdentityGrantNames = resources.IdentityResources.Select(x => x.DisplayName ?? x.Name).ToArray(), + ApiGrantNames = resources.ApiScopes.Select(x => x.DisplayName ?? x.Name).ToArray() + }; - list.Add(item); - } + list.Add(item); } - - return new GrantsViewModel - { - Grants = list - }; } + + return new GrantsViewModel + { + Grants = list + }; } } \ No newline at end of file diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Grants/GrantsViewModel.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Grants/GrantsViewModel.cs index 2114deebf..7cd90116b 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Grants/GrantsViewModel.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Grants/GrantsViewModel.cs @@ -5,23 +5,22 @@ using System; using System.Collections.Generic; -namespace IdentityServerHost.Quickstart.UI +namespace IdentityServerHost.Quickstart.UI; + +public class GrantsViewModel { - public class GrantsViewModel - { - public IEnumerable Grants { get; set; } - } + public IEnumerable Grants { get; set; } +} - public class GrantViewModel - { - public string ClientId { get; set; } - public string ClientName { get; set; } - public string ClientUrl { get; set; } - public string ClientLogoUrl { get; set; } - public string Description { get; set; } - public DateTime Created { get; set; } - public DateTime? Expires { get; set; } - public IEnumerable IdentityGrantNames { get; set; } - public IEnumerable ApiGrantNames { get; set; } - } +public class GrantViewModel +{ + public string ClientId { get; set; } + public string ClientName { get; set; } + public string ClientUrl { get; set; } + public string ClientLogoUrl { get; set; } + public string Description { get; set; } + public DateTime Created { get; set; } + public DateTime? Expires { get; set; } + public IEnumerable IdentityGrantNames { get; set; } + public IEnumerable ApiGrantNames { get; set; } } \ No newline at end of file diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Home/ErrorViewModel.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Home/ErrorViewModel.cs index c1a27b8e6..5137e150c 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Home/ErrorViewModel.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Home/ErrorViewModel.cs @@ -4,10 +4,9 @@ using IdentityServer4.Models; -namespace IdentityServer4.Quickstart.UI +namespace IdentityServer4.Quickstart.UI; + +public class ErrorViewModel { - public class ErrorViewModel - { - public ErrorMessage Error { get; set; } - } + public ErrorMessage Error { get; set; } } \ No newline at end of file diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Home/HomeController.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Home/HomeController.cs index e14648bac..bfa02ac63 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Home/HomeController.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Home/HomeController.cs @@ -1,4 +1,4 @@ -// Copyright (c) Brock Allen & Dominick Baier. All rights reserved. +// Copyright (c) Brock Allen & Dominick Baier. All rights reserved. // Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. @@ -10,49 +10,48 @@ using Microsoft.Extensions.Logging; using System.Threading.Tasks; -namespace IdentityServer4.Quickstart.UI +namespace IdentityServer4.Quickstart.UI; + +[SecurityHeaders] +[AllowAnonymous] +public class HomeController : Controller { - [SecurityHeaders] - [AllowAnonymous] - public class HomeController : Controller + private readonly IIdentityServerInteractionService _interaction; + private readonly IHostingEnvironment _environment; + private readonly ILogger _logger; + + public HomeController(IIdentityServerInteractionService interaction, IHostingEnvironment environment, ILogger logger) { - private readonly IIdentityServerInteractionService _interaction; - private readonly IHostingEnvironment _environment; - private readonly ILogger _logger; + _interaction = interaction; + _environment = environment; + _logger = logger; + } - public HomeController(IIdentityServerInteractionService interaction, IHostingEnvironment environment, ILogger logger) - { - _interaction = interaction; - _environment = environment; - _logger = logger; - } + public IActionResult Index() + { + return View(); + } - public IActionResult Index() - { - return View(); - } + /// + /// Shows the error page + /// + public async Task Error(string errorId) + { + var vm = new ErrorViewModel(); - /// - /// Shows the error page - /// - public async Task Error(string errorId) + // retrieve error details from identityserver + var message = await _interaction.GetErrorContextAsync(errorId); + if (message != null) { - var vm = new ErrorViewModel(); + vm.Error = message; - // retrieve error details from identityserver - var message = await _interaction.GetErrorContextAsync(errorId); - if (message != null) + if (!_environment.IsDevelopment()) { - vm.Error = message; - - if (!_environment.IsDevelopment()) - { - // only show in development - message.ErrorDescription = null; - } + // only show in development + message.ErrorDescription = null; } - - return View("Error", vm); } + + return View("Error", vm); } } \ No newline at end of file diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Manage/AddPhoneNumberViewModel.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Manage/AddPhoneNumberViewModel.cs index e863df704..11a955014 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Manage/AddPhoneNumberViewModel.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Manage/AddPhoneNumberViewModel.cs @@ -4,13 +4,12 @@ using System.Linq; using System.Threading.Tasks; -namespace ClassifiedAds.IdentityServer.Manage.Models +namespace ClassifiedAds.IdentityServer.Manage.Models; + +public class AddPhoneNumberViewModel { - public class AddPhoneNumberViewModel - { - [Required] - [Phone] - [Display(Name = "Phone number")] - public string PhoneNumber { get; set; } - } + [Required] + [Phone] + [Display(Name = "Phone number")] + public string PhoneNumber { get; set; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Manage/ChangePasswordViewModel.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Manage/ChangePasswordViewModel.cs index 67df14cfa..2f60cda75 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Manage/ChangePasswordViewModel.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Manage/ChangePasswordViewModel.cs @@ -4,24 +4,23 @@ using System.Linq; using System.Threading.Tasks; -namespace ClassifiedAds.IdentityServer.Manage.Models +namespace ClassifiedAds.IdentityServer.Manage.Models; + +public class ChangePasswordViewModel { - public class ChangePasswordViewModel - { - [Required] - [DataType(DataType.Password)] - [Display(Name = "Current password")] - public string OldPassword { get; set; } + [Required] + [DataType(DataType.Password)] + [Display(Name = "Current password")] + public string OldPassword { get; set; } - [Required] - [StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)] - [DataType(DataType.Password)] - [Display(Name = "New password")] - public string NewPassword { get; set; } + [Required] + [StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)] + [DataType(DataType.Password)] + [Display(Name = "New password")] + public string NewPassword { get; set; } - [DataType(DataType.Password)] - [Display(Name = "Confirm new password")] - [Compare("NewPassword", ErrorMessage = "The new password and confirmation password do not match.")] - public string ConfirmPassword { get; set; } - } + [DataType(DataType.Password)] + [Display(Name = "Confirm new password")] + [Compare("NewPassword", ErrorMessage = "The new password and confirmation password do not match.")] + public string ConfirmPassword { get; set; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Manage/ConfigureTwoFactorViewModel.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Manage/ConfigureTwoFactorViewModel.cs index be7ca0d8c..c3fb81345 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Manage/ConfigureTwoFactorViewModel.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Manage/ConfigureTwoFactorViewModel.cs @@ -4,12 +4,11 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc.Rendering; -namespace ClassifiedAds.IdentityServer.Manage.Models +namespace ClassifiedAds.IdentityServer.Manage.Models; + +public class ConfigureTwoFactorViewModel { - public class ConfigureTwoFactorViewModel - { - public string SelectedProvider { get; set; } + public string SelectedProvider { get; set; } - public ICollection Providers { get; set; } - } + public ICollection Providers { get; set; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Manage/DisplayRecoveryCodesViewModel.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Manage/DisplayRecoveryCodesViewModel.cs index a6b23ce1e..931286a67 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Manage/DisplayRecoveryCodesViewModel.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Manage/DisplayRecoveryCodesViewModel.cs @@ -1,12 +1,11 @@ using System.Collections.Generic; using System.ComponentModel.DataAnnotations; -namespace ClassifiedAds.IdentityServer.Manage.Models +namespace ClassifiedAds.IdentityServer.Manage.Models; + +public class DisplayRecoveryCodesViewModel { - public class DisplayRecoveryCodesViewModel - { - [Required] - public IEnumerable Codes { get; set; } + [Required] + public IEnumerable Codes { get; set; } - } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Manage/FactorViewModel.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Manage/FactorViewModel.cs index f5fb884a8..d8e6214cc 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Manage/FactorViewModel.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Manage/FactorViewModel.cs @@ -3,10 +3,9 @@ using System.Linq; using System.Threading.Tasks; -namespace ClassifiedAds.IdentityServer.Manage.Models +namespace ClassifiedAds.IdentityServer.Manage.Models; + +public class FactorViewModel { - public class FactorViewModel - { - public string Purpose { get; set; } - } + public string Purpose { get; set; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Manage/IndexViewModel.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Manage/IndexViewModel.cs index 231d202df..1d131e0ea 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Manage/IndexViewModel.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Manage/IndexViewModel.cs @@ -1,20 +1,19 @@ using System.Collections.Generic; using Microsoft.AspNetCore.Identity; -namespace ClassifiedAds.IdentityServer.Manage.Models +namespace ClassifiedAds.IdentityServer.Manage.Models; + +public class IndexViewModel { - public class IndexViewModel - { - public bool HasPassword { get; set; } + public bool HasPassword { get; set; } - public IList Logins { get; set; } + public IList Logins { get; set; } - public string PhoneNumber { get; set; } + public string PhoneNumber { get; set; } - public bool TwoFactor { get; set; } + public bool TwoFactor { get; set; } - public bool BrowserRemembered { get; set; } + public bool BrowserRemembered { get; set; } - public string AuthenticatorKey { get; set; } - } + public string AuthenticatorKey { get; set; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Manage/ManageController.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Manage/ManageController.cs index 45dc235af..790687316 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Manage/ManageController.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Manage/ManageController.cs @@ -9,373 +9,372 @@ using System.Linq; using System.Threading.Tasks; -namespace ClassifiedAds.IdentityServer.Quickstart.Manage +namespace ClassifiedAds.IdentityServer.Quickstart.Manage; + +[Authorize] +public class ManageController : Controller { - [Authorize] - public class ManageController : Controller + private readonly UserManager _userManager; + private readonly SignInManager _signInManager; + private readonly Dispatcher _dispatcher; + private readonly ILogger _logger; + + public ManageController( + UserManager userManager, + SignInManager signInManager, + ILoggerFactory loggerFactory, + Dispatcher dispatcher) { - private readonly UserManager _userManager; - private readonly SignInManager _signInManager; - private readonly Dispatcher _dispatcher; - private readonly ILogger _logger; + _userManager = userManager; + _signInManager = signInManager; + _dispatcher = dispatcher; + _logger = loggerFactory.CreateLogger(); + } - public ManageController( - UserManager userManager, - SignInManager signInManager, - ILoggerFactory loggerFactory, - Dispatcher dispatcher) - { - _userManager = userManager; - _signInManager = signInManager; - _dispatcher = dispatcher; - _logger = loggerFactory.CreateLogger(); - } + // + // GET: /Manage/Index + [HttpGet] + public async Task Index(ManageMessageId? message = null) + { + ViewData["StatusMessage"] = + message == ManageMessageId.ChangePasswordSuccess ? "Your password has been changed." + : message == ManageMessageId.SetPasswordSuccess ? "Your password has been set." + : message == ManageMessageId.SetTwoFactorSuccess ? "Your two-factor authentication provider has been set." + : message == ManageMessageId.Error ? "An error has occurred." + : message == ManageMessageId.AddPhoneSuccess ? "Your phone number was added." + : message == ManageMessageId.RemovePhoneSuccess ? "Your phone number was removed." + : ""; - // - // GET: /Manage/Index - [HttpGet] - public async Task Index(ManageMessageId? message = null) + var user = await GetCurrentUserAsync(); + var model = new IndexViewModel { - ViewData["StatusMessage"] = - message == ManageMessageId.ChangePasswordSuccess ? "Your password has been changed." - : message == ManageMessageId.SetPasswordSuccess ? "Your password has been set." - : message == ManageMessageId.SetTwoFactorSuccess ? "Your two-factor authentication provider has been set." - : message == ManageMessageId.Error ? "An error has occurred." - : message == ManageMessageId.AddPhoneSuccess ? "Your phone number was added." - : message == ManageMessageId.RemovePhoneSuccess ? "Your phone number was removed." - : ""; - - var user = await GetCurrentUserAsync(); - var model = new IndexViewModel - { - HasPassword = await _userManager.HasPasswordAsync(user), - PhoneNumber = await _userManager.GetPhoneNumberAsync(user), - TwoFactor = await _userManager.GetTwoFactorEnabledAsync(user), - //Logins = await _userManager.GetLoginsAsync(user), - Logins = new List(), - BrowserRemembered = await _signInManager.IsTwoFactorClientRememberedAsync(user), - AuthenticatorKey = await _userManager.GetAuthenticatorKeyAsync(user) - }; - return View(model); - } + HasPassword = await _userManager.HasPasswordAsync(user), + PhoneNumber = await _userManager.GetPhoneNumberAsync(user), + TwoFactor = await _userManager.GetTwoFactorEnabledAsync(user), + //Logins = await _userManager.GetLoginsAsync(user), + Logins = new List(), + BrowserRemembered = await _signInManager.IsTwoFactorClientRememberedAsync(user), + AuthenticatorKey = await _userManager.GetAuthenticatorKeyAsync(user) + }; + return View(model); + } - // - // POST: /Manage/RemoveLogin - [HttpPost] - [ValidateAntiForgeryToken] - public async Task RemoveLogin(RemoveLoginViewModel account) + // + // POST: /Manage/RemoveLogin + [HttpPost] + [ValidateAntiForgeryToken] + public async Task RemoveLogin(RemoveLoginViewModel account) + { + ManageMessageId? message = ManageMessageId.Error; + var user = await GetCurrentUserAsync(); + if (user != null) { - ManageMessageId? message = ManageMessageId.Error; - var user = await GetCurrentUserAsync(); - if (user != null) + var result = await _userManager.RemoveLoginAsync(user, account.LoginProvider, account.ProviderKey); + if (result.Succeeded) { - var result = await _userManager.RemoveLoginAsync(user, account.LoginProvider, account.ProviderKey); - if (result.Succeeded) - { - await _signInManager.SignInAsync(user, isPersistent: false); - message = ManageMessageId.RemoveLoginSuccess; - } + await _signInManager.SignInAsync(user, isPersistent: false); + message = ManageMessageId.RemoveLoginSuccess; } - return RedirectToAction(nameof(ManageLogins), new { Message = message }); } + return RedirectToAction(nameof(ManageLogins), new { Message = message }); + } - // - // GET: /Manage/AddPhoneNumber - public IActionResult AddPhoneNumber() - { - return View(); - } + // + // GET: /Manage/AddPhoneNumber + public IActionResult AddPhoneNumber() + { + return View(); + } - // - // POST: /Manage/AddPhoneNumber - [HttpPost] - [ValidateAntiForgeryToken] - public async Task AddPhoneNumber(AddPhoneNumberViewModel model) + // + // POST: /Manage/AddPhoneNumber + [HttpPost] + [ValidateAntiForgeryToken] + public async Task AddPhoneNumber(AddPhoneNumberViewModel model) + { + if (!ModelState.IsValid) { - if (!ModelState.IsValid) - { - return View(model); - } - // Generate the token and send it - var user = await GetCurrentUserAsync(); - var code = await _userManager.GenerateChangePhoneNumberTokenAsync(user, model.PhoneNumber); - //await _dispatcher.DispatchAsync(new AddOrUpdateEntityCommand(new SmsMessage - //{ - // PhoneNumber = model.PhoneNumber, - // Message = "Your security code is: " + code, - //})); - return RedirectToAction(nameof(VerifyPhoneNumber), new { PhoneNumber = model.PhoneNumber }); + return View(model); } + // Generate the token and send it + var user = await GetCurrentUserAsync(); + var code = await _userManager.GenerateChangePhoneNumberTokenAsync(user, model.PhoneNumber); + //await _dispatcher.DispatchAsync(new AddOrUpdateEntityCommand(new SmsMessage + //{ + // PhoneNumber = model.PhoneNumber, + // Message = "Your security code is: " + code, + //})); + return RedirectToAction(nameof(VerifyPhoneNumber), new { PhoneNumber = model.PhoneNumber }); + } - // - // POST: /Manage/ResetAuthenticatorKey - [HttpPost] - [ValidateAntiForgeryToken] - public async Task ResetAuthenticatorKey() + // + // POST: /Manage/ResetAuthenticatorKey + [HttpPost] + [ValidateAntiForgeryToken] + public async Task ResetAuthenticatorKey() + { + var user = await GetCurrentUserAsync(); + if (user != null) { - var user = await GetCurrentUserAsync(); - if (user != null) - { - await _userManager.ResetAuthenticatorKeyAsync(user); - _logger.LogInformation(1, "User reset authenticator key."); - } - return RedirectToAction(nameof(Index), "Manage"); + await _userManager.ResetAuthenticatorKeyAsync(user); + _logger.LogInformation(1, "User reset authenticator key."); } + return RedirectToAction(nameof(Index), "Manage"); + } - // - // POST: /Manage/GenerateRecoveryCode - [HttpPost] - [ValidateAntiForgeryToken] - public async Task GenerateRecoveryCode() + // + // POST: /Manage/GenerateRecoveryCode + [HttpPost] + [ValidateAntiForgeryToken] + public async Task GenerateRecoveryCode() + { + var user = await GetCurrentUserAsync(); + if (user != null) { - var user = await GetCurrentUserAsync(); - if (user != null) - { - var codes = await _userManager.GenerateNewTwoFactorRecoveryCodesAsync(user, 5); - _logger.LogInformation(1, "User generated new recovery code."); - return View("DisplayRecoveryCodes", new DisplayRecoveryCodesViewModel { Codes = codes }); - } - return View("Error"); + var codes = await _userManager.GenerateNewTwoFactorRecoveryCodesAsync(user, 5); + _logger.LogInformation(1, "User generated new recovery code."); + return View("DisplayRecoveryCodes", new DisplayRecoveryCodesViewModel { Codes = codes }); } + return View("Error"); + } - // - // POST: /Manage/EnableTwoFactorAuthentication - [HttpPost] - [ValidateAntiForgeryToken] - public async Task EnableTwoFactorAuthentication() + // + // POST: /Manage/EnableTwoFactorAuthentication + [HttpPost] + [ValidateAntiForgeryToken] + public async Task EnableTwoFactorAuthentication() + { + var user = await GetCurrentUserAsync(); + if (user != null) { - var user = await GetCurrentUserAsync(); - if (user != null) - { - await _userManager.SetTwoFactorEnabledAsync(user, true); - await _signInManager.SignInAsync(user, isPersistent: false); - _logger.LogInformation(1, "User enabled two-factor authentication."); - } - return RedirectToAction(nameof(Index), "Manage"); + await _userManager.SetTwoFactorEnabledAsync(user, true); + await _signInManager.SignInAsync(user, isPersistent: false); + _logger.LogInformation(1, "User enabled two-factor authentication."); } + return RedirectToAction(nameof(Index), "Manage"); + } - // - // POST: /Manage/DisableTwoFactorAuthentication - [HttpPost] - [ValidateAntiForgeryToken] - public async Task DisableTwoFactorAuthentication() + // + // POST: /Manage/DisableTwoFactorAuthentication + [HttpPost] + [ValidateAntiForgeryToken] + public async Task DisableTwoFactorAuthentication() + { + var user = await GetCurrentUserAsync(); + if (user != null) { - var user = await GetCurrentUserAsync(); - if (user != null) - { - await _userManager.SetTwoFactorEnabledAsync(user, false); - await _signInManager.SignInAsync(user, isPersistent: false); - _logger.LogInformation(2, "User disabled two-factor authentication."); - } - return RedirectToAction(nameof(Index), "Manage"); + await _userManager.SetTwoFactorEnabledAsync(user, false); + await _signInManager.SignInAsync(user, isPersistent: false); + _logger.LogInformation(2, "User disabled two-factor authentication."); } + return RedirectToAction(nameof(Index), "Manage"); + } + + // + // GET: /Manage/VerifyPhoneNumber + [HttpGet] + public async Task VerifyPhoneNumber(string phoneNumber) + { + var code = await _userManager.GenerateChangePhoneNumberTokenAsync(await GetCurrentUserAsync(), phoneNumber); + // Send an SMS to verify the phone number + return phoneNumber == null ? View("Error") : View(new VerifyPhoneNumberViewModel { PhoneNumber = phoneNumber }); + } - // - // GET: /Manage/VerifyPhoneNumber - [HttpGet] - public async Task VerifyPhoneNumber(string phoneNumber) + // + // POST: /Manage/VerifyPhoneNumber + [HttpPost] + [ValidateAntiForgeryToken] + public async Task VerifyPhoneNumber(VerifyPhoneNumberViewModel model) + { + if (!ModelState.IsValid) { - var code = await _userManager.GenerateChangePhoneNumberTokenAsync(await GetCurrentUserAsync(), phoneNumber); - // Send an SMS to verify the phone number - return phoneNumber == null ? View("Error") : View(new VerifyPhoneNumberViewModel { PhoneNumber = phoneNumber }); + return View(model); } - - // - // POST: /Manage/VerifyPhoneNumber - [HttpPost] - [ValidateAntiForgeryToken] - public async Task VerifyPhoneNumber(VerifyPhoneNumberViewModel model) + var user = await GetCurrentUserAsync(); + if (user != null) { - if (!ModelState.IsValid) + var result = await _userManager.ChangePhoneNumberAsync(user, model.PhoneNumber, model.Code); + if (result.Succeeded) { - return View(model); - } - var user = await GetCurrentUserAsync(); - if (user != null) - { - var result = await _userManager.ChangePhoneNumberAsync(user, model.PhoneNumber, model.Code); - if (result.Succeeded) - { - await _signInManager.SignInAsync(user, isPersistent: false); - return RedirectToAction(nameof(Index), new { Message = ManageMessageId.AddPhoneSuccess }); - } + await _signInManager.SignInAsync(user, isPersistent: false); + return RedirectToAction(nameof(Index), new { Message = ManageMessageId.AddPhoneSuccess }); } - // If we got this far, something failed, redisplay the form - ModelState.AddModelError(string.Empty, "Failed to verify phone number"); - return View(model); } + // If we got this far, something failed, redisplay the form + ModelState.AddModelError(string.Empty, "Failed to verify phone number"); + return View(model); + } - // - // GET: /Manage/RemovePhoneNumber - [HttpPost] - [ValidateAntiForgeryToken] - public async Task RemovePhoneNumber() + // + // GET: /Manage/RemovePhoneNumber + [HttpPost] + [ValidateAntiForgeryToken] + public async Task RemovePhoneNumber() + { + var user = await GetCurrentUserAsync(); + if (user != null) { - var user = await GetCurrentUserAsync(); - if (user != null) + var result = await _userManager.SetPhoneNumberAsync(user, null); + if (result.Succeeded) { - var result = await _userManager.SetPhoneNumberAsync(user, null); - if (result.Succeeded) - { - await _signInManager.SignInAsync(user, isPersistent: false); - return RedirectToAction(nameof(Index), new { Message = ManageMessageId.RemovePhoneSuccess }); - } + await _signInManager.SignInAsync(user, isPersistent: false); + return RedirectToAction(nameof(Index), new { Message = ManageMessageId.RemovePhoneSuccess }); } - return RedirectToAction(nameof(Index), new { Message = ManageMessageId.Error }); } + return RedirectToAction(nameof(Index), new { Message = ManageMessageId.Error }); + } - // - // GET: /Manage/ChangePassword - [HttpGet] - public IActionResult ChangePassword() + // + // GET: /Manage/ChangePassword + [HttpGet] + public IActionResult ChangePassword() + { + return View(); + } + + // + // POST: /Manage/ChangePassword + [HttpPost] + [ValidateAntiForgeryToken] + public async Task ChangePassword(ChangePasswordViewModel model) + { + if (!ModelState.IsValid) { - return View(); + return View(model); } - - // - // POST: /Manage/ChangePassword - [HttpPost] - [ValidateAntiForgeryToken] - public async Task ChangePassword(ChangePasswordViewModel model) + var user = await GetCurrentUserAsync(); + if (user != null) { - if (!ModelState.IsValid) - { - return View(model); - } - var user = await GetCurrentUserAsync(); - if (user != null) + var result = await _userManager.ChangePasswordAsync(user, model.OldPassword, model.NewPassword); + if (result.Succeeded) { - var result = await _userManager.ChangePasswordAsync(user, model.OldPassword, model.NewPassword); - if (result.Succeeded) - { - await _signInManager.SignInAsync(user, isPersistent: false); - _logger.LogInformation(3, "User changed their password successfully."); - return RedirectToAction(nameof(Index), new { Message = ManageMessageId.ChangePasswordSuccess }); - } - AddErrors(result); - return View(model); + await _signInManager.SignInAsync(user, isPersistent: false); + _logger.LogInformation(3, "User changed their password successfully."); + return RedirectToAction(nameof(Index), new { Message = ManageMessageId.ChangePasswordSuccess }); } - return RedirectToAction(nameof(Index), new { Message = ManageMessageId.Error }); + AddErrors(result); + return View(model); } + return RedirectToAction(nameof(Index), new { Message = ManageMessageId.Error }); + } - // - // GET: /Manage/SetPassword - [HttpGet] - public IActionResult SetPassword() - { - return View(); - } + // + // GET: /Manage/SetPassword + [HttpGet] + public IActionResult SetPassword() + { + return View(); + } - // - // POST: /Manage/SetPassword - [HttpPost] - [ValidateAntiForgeryToken] - public async Task SetPassword(SetPasswordViewModel model) + // + // POST: /Manage/SetPassword + [HttpPost] + [ValidateAntiForgeryToken] + public async Task SetPassword(SetPasswordViewModel model) + { + if (!ModelState.IsValid) { - if (!ModelState.IsValid) - { - return View(model); - } - - var user = await GetCurrentUserAsync(); - if (user != null) - { - var result = await _userManager.AddPasswordAsync(user, model.NewPassword); - if (result.Succeeded) - { - await _signInManager.SignInAsync(user, isPersistent: false); - return RedirectToAction(nameof(Index), new { Message = ManageMessageId.SetPasswordSuccess }); - } - AddErrors(result); - return View(model); - } - return RedirectToAction(nameof(Index), new { Message = ManageMessageId.Error }); + return View(model); } - //GET: /Manage/ManageLogins - [HttpGet] - public async Task ManageLogins(ManageMessageId? message = null) + var user = await GetCurrentUserAsync(); + if (user != null) { - ViewData["StatusMessage"] = - message == ManageMessageId.RemoveLoginSuccess ? "The external login was removed." - : message == ManageMessageId.AddLoginSuccess ? "The external login was added." - : message == ManageMessageId.Error ? "An error has occurred." - : ""; - var user = await GetCurrentUserAsync(); - if (user == null) + var result = await _userManager.AddPasswordAsync(user, model.NewPassword); + if (result.Succeeded) { - return View("Error"); + await _signInManager.SignInAsync(user, isPersistent: false); + return RedirectToAction(nameof(Index), new { Message = ManageMessageId.SetPasswordSuccess }); } - var userLogins = await _userManager.GetLoginsAsync(user); - var schemes = await _signInManager.GetExternalAuthenticationSchemesAsync(); - var otherLogins = schemes.Where(auth => userLogins.All(ul => auth.Name != ul.LoginProvider)).ToList(); - ViewData["ShowRemoveButton"] = user.PasswordHash != null || userLogins.Count > 1; - return View(new ManageLoginsViewModel - { - CurrentLogins = userLogins, - OtherLogins = otherLogins - }); + AddErrors(result); + return View(model); } + return RedirectToAction(nameof(Index), new { Message = ManageMessageId.Error }); + } - // - // POST: /Manage/LinkLogin - [HttpPost] - [ValidateAntiForgeryToken] - public IActionResult LinkLogin(string provider) + //GET: /Manage/ManageLogins + [HttpGet] + public async Task ManageLogins(ManageMessageId? message = null) + { + ViewData["StatusMessage"] = + message == ManageMessageId.RemoveLoginSuccess ? "The external login was removed." + : message == ManageMessageId.AddLoginSuccess ? "The external login was added." + : message == ManageMessageId.Error ? "An error has occurred." + : ""; + var user = await GetCurrentUserAsync(); + if (user == null) { - // Request a redirect to the external login provider to link a login for the current user - var redirectUrl = Url.Action("LinkLoginCallback", "Manage"); - var properties = _signInManager.ConfigureExternalAuthenticationProperties(provider, redirectUrl, _userManager.GetUserId(User)); - return Challenge(properties, provider); + return View("Error"); } - - // - // GET: /Manage/LinkLoginCallback - [HttpGet] - public async Task LinkLoginCallback() + var userLogins = await _userManager.GetLoginsAsync(user); + var schemes = await _signInManager.GetExternalAuthenticationSchemesAsync(); + var otherLogins = schemes.Where(auth => userLogins.All(ul => auth.Name != ul.LoginProvider)).ToList(); + ViewData["ShowRemoveButton"] = user.PasswordHash != null || userLogins.Count > 1; + return View(new ManageLoginsViewModel { - var user = await GetCurrentUserAsync(); - if (user == null) - { - return View("Error"); - } - var info = await _signInManager.GetExternalLoginInfoAsync(await _userManager.GetUserIdAsync(user)); - if (info == null) - { - return RedirectToAction(nameof(ManageLogins), new { Message = ManageMessageId.Error }); - } - var result = await _userManager.AddLoginAsync(user, info); - var message = result.Succeeded ? ManageMessageId.AddLoginSuccess : ManageMessageId.Error; - return RedirectToAction(nameof(ManageLogins), new { Message = message }); - } + CurrentLogins = userLogins, + OtherLogins = otherLogins + }); + } - #region Helpers + // + // POST: /Manage/LinkLogin + [HttpPost] + [ValidateAntiForgeryToken] + public IActionResult LinkLogin(string provider) + { + // Request a redirect to the external login provider to link a login for the current user + var redirectUrl = Url.Action("LinkLoginCallback", "Manage"); + var properties = _signInManager.ConfigureExternalAuthenticationProperties(provider, redirectUrl, _userManager.GetUserId(User)); + return Challenge(properties, provider); + } - private void AddErrors(IdentityResult result) + // + // GET: /Manage/LinkLoginCallback + [HttpGet] + public async Task LinkLoginCallback() + { + var user = await GetCurrentUserAsync(); + if (user == null) { - foreach (var error in result.Errors) - { - ModelState.AddModelError(string.Empty, error.Description); - } + return View("Error"); } - - public enum ManageMessageId + var info = await _signInManager.GetExternalLoginInfoAsync(await _userManager.GetUserIdAsync(user)); + if (info == null) { - AddPhoneSuccess, - AddLoginSuccess, - ChangePasswordSuccess, - SetTwoFactorSuccess, - SetPasswordSuccess, - RemoveLoginSuccess, - RemovePhoneSuccess, - Error + return RedirectToAction(nameof(ManageLogins), new { Message = ManageMessageId.Error }); } + var result = await _userManager.AddLoginAsync(user, info); + var message = result.Succeeded ? ManageMessageId.AddLoginSuccess : ManageMessageId.Error; + return RedirectToAction(nameof(ManageLogins), new { Message = message }); + } + + #region Helpers - private Task GetCurrentUserAsync() + private void AddErrors(IdentityResult result) + { + foreach (var error in result.Errors) { - return _userManager.GetUserAsync(HttpContext.User); + ModelState.AddModelError(string.Empty, error.Description); } + } + + public enum ManageMessageId + { + AddPhoneSuccess, + AddLoginSuccess, + ChangePasswordSuccess, + SetTwoFactorSuccess, + SetPasswordSuccess, + RemoveLoginSuccess, + RemovePhoneSuccess, + Error + } - #endregion + private Task GetCurrentUserAsync() + { + return _userManager.GetUserAsync(HttpContext.User); } + + #endregion } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Manage/ManageLoginsViewModel.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Manage/ManageLoginsViewModel.cs index ad361a6f9..f6552a5e8 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Manage/ManageLoginsViewModel.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Manage/ManageLoginsViewModel.cs @@ -2,12 +2,11 @@ using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Identity; -namespace ClassifiedAds.IdentityServer.Manage.Models +namespace ClassifiedAds.IdentityServer.Manage.Models; + +public class ManageLoginsViewModel { - public class ManageLoginsViewModel - { - public IList CurrentLogins { get; set; } + public IList CurrentLogins { get; set; } - public IList OtherLogins { get; set; } - } + public IList OtherLogins { get; set; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Manage/RemoveLoginViewModel.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Manage/RemoveLoginViewModel.cs index 7e7cd720a..c913f3d9f 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Manage/RemoveLoginViewModel.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Manage/RemoveLoginViewModel.cs @@ -4,11 +4,10 @@ using System.Linq; using System.Threading.Tasks; -namespace ClassifiedAds.IdentityServer.Manage.Models +namespace ClassifiedAds.IdentityServer.Manage.Models; + +public class RemoveLoginViewModel { - public class RemoveLoginViewModel - { - public string LoginProvider { get; set; } - public string ProviderKey { get; set; } - } + public string LoginProvider { get; set; } + public string ProviderKey { get; set; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Manage/SetPasswordViewModel.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Manage/SetPasswordViewModel.cs index f551e7175..9d47e7258 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Manage/SetPasswordViewModel.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Manage/SetPasswordViewModel.cs @@ -4,19 +4,18 @@ using System.Linq; using System.Threading.Tasks; -namespace ClassifiedAds.IdentityServer.Manage.Models +namespace ClassifiedAds.IdentityServer.Manage.Models; + +public class SetPasswordViewModel { - public class SetPasswordViewModel - { - [Required] - [StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)] - [DataType(DataType.Password)] - [Display(Name = "New password")] - public string NewPassword { get; set; } + [Required] + [StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)] + [DataType(DataType.Password)] + [Display(Name = "New password")] + public string NewPassword { get; set; } - [DataType(DataType.Password)] - [Display(Name = "Confirm new password")] - [Compare("NewPassword", ErrorMessage = "The new password and confirmation password do not match.")] - public string ConfirmPassword { get; set; } - } + [DataType(DataType.Password)] + [Display(Name = "Confirm new password")] + [Compare("NewPassword", ErrorMessage = "The new password and confirmation password do not match.")] + public string ConfirmPassword { get; set; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Manage/VerifyPhoneNumberViewModel.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Manage/VerifyPhoneNumberViewModel.cs index ea46ef04e..9e336ef6b 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Manage/VerifyPhoneNumberViewModel.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/Manage/VerifyPhoneNumberViewModel.cs @@ -4,16 +4,15 @@ using System.Linq; using System.Threading.Tasks; -namespace ClassifiedAds.IdentityServer.Manage.Models +namespace ClassifiedAds.IdentityServer.Manage.Models; + +public class VerifyPhoneNumberViewModel { - public class VerifyPhoneNumberViewModel - { - [Required] - public string Code { get; set; } + [Required] + public string Code { get; set; } - [Required] - [Phone] - [Display(Name = "Phone number")] - public string PhoneNumber { get; set; } - } + [Required] + [Phone] + [Display(Name = "Phone number")] + public string PhoneNumber { get; set; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/SecurityHeadersAttribute.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/SecurityHeadersAttribute.cs index 93ca67ffc..f3c75c097 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/SecurityHeadersAttribute.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/SecurityHeadersAttribute.cs @@ -5,51 +5,50 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Filters; -namespace IdentityServerHost.Quickstart.UI +namespace IdentityServerHost.Quickstart.UI; + +public class SecurityHeadersAttribute : ActionFilterAttribute { - public class SecurityHeadersAttribute : ActionFilterAttribute + public override void OnResultExecuting(ResultExecutingContext context) { - public override void OnResultExecuting(ResultExecutingContext context) + var result = context.Result; + if (result is ViewResult) { - var result = context.Result; - if (result is ViewResult) + // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Content-Type-Options + if (!context.HttpContext.Response.Headers.ContainsKey("X-Content-Type-Options")) + { + context.HttpContext.Response.Headers.Add("X-Content-Type-Options", "nosniff"); + } + + // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options + if (!context.HttpContext.Response.Headers.ContainsKey("X-Frame-Options")) + { + context.HttpContext.Response.Headers.Add("X-Frame-Options", "SAMEORIGIN"); + } + + // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy + var csp = "default-src 'self'; object-src 'none'; frame-ancestors 'none'; sandbox allow-forms allow-same-origin allow-scripts; base-uri 'self';"; + // also consider adding upgrade-insecure-requests once you have HTTPS in place for production + //csp += "upgrade-insecure-requests;"; + // also an example if you need client images to be displayed from twitter + // csp += "img-src 'self' https://pbs.twimg.com;"; + + // once for standards compliant browsers + if (!context.HttpContext.Response.Headers.ContainsKey("Content-Security-Policy")) + { + context.HttpContext.Response.Headers.Add("Content-Security-Policy", csp); + } + // and once again for IE + if (!context.HttpContext.Response.Headers.ContainsKey("X-Content-Security-Policy")) + { + context.HttpContext.Response.Headers.Add("X-Content-Security-Policy", csp); + } + + // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referrer-Policy + var referrer_policy = "no-referrer"; + if (!context.HttpContext.Response.Headers.ContainsKey("Referrer-Policy")) { - // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Content-Type-Options - if (!context.HttpContext.Response.Headers.ContainsKey("X-Content-Type-Options")) - { - context.HttpContext.Response.Headers.Add("X-Content-Type-Options", "nosniff"); - } - - // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options - if (!context.HttpContext.Response.Headers.ContainsKey("X-Frame-Options")) - { - context.HttpContext.Response.Headers.Add("X-Frame-Options", "SAMEORIGIN"); - } - - // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy - var csp = "default-src 'self'; object-src 'none'; frame-ancestors 'none'; sandbox allow-forms allow-same-origin allow-scripts; base-uri 'self';"; - // also consider adding upgrade-insecure-requests once you have HTTPS in place for production - //csp += "upgrade-insecure-requests;"; - // also an example if you need client images to be displayed from twitter - // csp += "img-src 'self' https://pbs.twimg.com;"; - - // once for standards compliant browsers - if (!context.HttpContext.Response.Headers.ContainsKey("Content-Security-Policy")) - { - context.HttpContext.Response.Headers.Add("Content-Security-Policy", csp); - } - // and once again for IE - if (!context.HttpContext.Response.Headers.ContainsKey("X-Content-Security-Policy")) - { - context.HttpContext.Response.Headers.Add("X-Content-Security-Policy", csp); - } - - // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referrer-Policy - var referrer_policy = "no-referrer"; - if (!context.HttpContext.Response.Headers.ContainsKey("Referrer-Policy")) - { - context.HttpContext.Response.Headers.Add("Referrer-Policy", referrer_policy); - } + context.HttpContext.Response.Headers.Add("Referrer-Policy", referrer_policy); } } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/TestUsers.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/TestUsers.cs deleted file mode 100644 index ba81fa537..000000000 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Quickstart/TestUsers.cs +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright (c) Brock Allen & Dominick Baier. All rights reserved. -// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. - - -using IdentityModel; -using IdentityServer4.Test; -using System.Collections.Generic; -using System.Security.Claims; - -namespace IdentityServer4.Quickstart.UI -{ - public class TestUsers - { - public static List Users = new List - { - new TestUser{SubjectId = "818727", Username = "alice", Password = "alice", - Claims = - { - new Claim(JwtClaimTypes.Name, "Alice Smith"), - new Claim(JwtClaimTypes.GivenName, "Alice"), - new Claim(JwtClaimTypes.FamilyName, "Smith"), - new Claim(JwtClaimTypes.Email, "AliceSmith@email.com"), - new Claim(JwtClaimTypes.EmailVerified, "true", ClaimValueTypes.Boolean), - new Claim(JwtClaimTypes.WebSite, "http://alice.com"), - new Claim(JwtClaimTypes.Address, @"{ 'street_address': 'One Hacker Way', 'locality': 'Heidelberg', 'postal_code': 69118, 'country': 'Germany' }", IdentityServer4.IdentityServerConstants.ClaimValueTypes.Json) - } - }, - new TestUser{SubjectId = "88421113", Username = "bob", Password = "bob", - Claims = - { - new Claim(JwtClaimTypes.Name, "Bob Smith"), - new Claim(JwtClaimTypes.GivenName, "Bob"), - new Claim(JwtClaimTypes.FamilyName, "Smith"), - new Claim(JwtClaimTypes.Email, "BobSmith@email.com"), - new Claim(JwtClaimTypes.EmailVerified, "true", ClaimValueTypes.Boolean), - new Claim(JwtClaimTypes.WebSite, "http://bob.com"), - new Claim(JwtClaimTypes.Address, @"{ 'street_address': 'One Hacker Way', 'locality': 'Heidelberg', 'postal_code': 69118, 'country': 'Germany' }", IdentityServer4.IdentityServerConstants.ClaimValueTypes.Json), - new Claim("location", "somewhere") - } - } - }; - } -} \ No newline at end of file diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Startup.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Startup.cs index e53841413..3ea3bb712 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Startup.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/Startup.cs @@ -13,191 +13,190 @@ using System; using System.Threading.Tasks; -namespace ClassifiedAds.IdentityServer +namespace ClassifiedAds.IdentityServer; + +public class Startup { - public class Startup + public Startup(IConfiguration configuration, IWebHostEnvironment env) { - public Startup(IConfiguration configuration, IWebHostEnvironment env) - { - Configuration = configuration; + Configuration = configuration; - AppSettings = new AppSettings(); - Configuration.Bind(AppSettings); - } + AppSettings = new AppSettings(); + Configuration.Bind(AppSettings); + } - public IConfiguration Configuration { get; } + public IConfiguration Configuration { get; } - private AppSettings AppSettings { get; set; } + private AppSettings AppSettings { get; set; } - // This method gets called by the runtime. Use this method to add services to the container. - // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 - public void ConfigureServices(IServiceCollection services) + // This method gets called by the runtime. Use this method to add services to the container. + // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 + public void ConfigureServices(IServiceCollection services) + { + services.Configure(options => { - services.Configure(options => - { - options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto; - options.KnownNetworks.Clear(); - options.KnownProxies.Clear(); - }); + options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto; + options.KnownNetworks.Clear(); + options.KnownProxies.Clear(); + }); - services.Configure(Configuration); + services.Configure(Configuration); - if (AppSettings.CookiePolicyOptions?.IsEnabled ?? false) + if (AppSettings.CookiePolicyOptions?.IsEnabled ?? false) + { + services.Configure(options => { - services.Configure(options => - { - // This lambda determines whether user consent for non-essential cookies is needed for a given request. - options.CheckConsentNeeded = context => true; - options.MinimumSameSitePolicy = AppSettings.CookiePolicyOptions.MinimumSameSitePolicy; - options.Secure = AppSettings.CookiePolicyOptions.Secure; - }); - } + // This lambda determines whether user consent for non-essential cookies is needed for a given request. + options.CheckConsentNeeded = context => true; + options.MinimumSameSitePolicy = AppSettings.CookiePolicyOptions.MinimumSameSitePolicy; + options.Secure = AppSettings.CookiePolicyOptions.Secure; + }); + } - services.AddMonitoringServices(AppSettings.Monitoring); + services.AddMonitoringServices(AppSettings.Monitoring); - services.AddControllersWithViews(); - services.AddRazorPages(); + services.AddControllersWithViews(); + services.AddRazorPages(); - services.AddCors(); + services.AddCors(); - services.AddDateTimeProvider(); + services.AddDateTimeProvider(); - services.AddPersistence(AppSettings.ConnectionStrings.ClassifiedAds) - .AddDomainServices() - .AddApplicationServices((Type serviceType, Type implementationType, ServiceLifetime serviceLifetime) => - { - services.AddInterceptors(serviceType, implementationType, serviceLifetime, AppSettings.Interceptors); - }) - .AddMessageHandlers() - .ConfigureInterceptors() - .AddIdentity(); + services.AddPersistence(AppSettings.ConnectionStrings.ClassifiedAds) + .AddDomainServices() + .AddApplicationServices((Type serviceType, Type implementationType, ServiceLifetime serviceLifetime) => + { + services.AddInterceptors(serviceType, implementationType, serviceLifetime, AppSettings.Interceptors); + }) + .AddMessageHandlers() + .ConfigureInterceptors() + .AddIdentity(); - services.AddIdentityServer(options => + services.AddIdentityServer(options => + { + if (!string.IsNullOrWhiteSpace(AppSettings.IdentityServer.IssuerUri)) { - if (!string.IsNullOrWhiteSpace(AppSettings.IdentityServer.IssuerUri)) - { - options.IssuerUri = AppSettings.IdentityServer.IssuerUri; - } + options.IssuerUri = AppSettings.IdentityServer.IssuerUri; + } - options.InputLengthRestrictions.Password = int.MaxValue; - options.InputLengthRestrictions.UserName = int.MaxValue; - }) - .AddSigningCredential(AppSettings.IdentityServer.Certificate.FindCertificate()) - .AddAspNetIdentity() - .AddIdServerPersistence(AppSettings.ConnectionStrings.IdentityServer); + options.InputLengthRestrictions.Password = int.MaxValue; + options.InputLengthRestrictions.UserName = int.MaxValue; + }) + .AddSigningCredential(AppSettings.IdentityServer.Certificate.FindCertificate()) + .AddAspNetIdentity() + .AddIdServerPersistence(AppSettings.ConnectionStrings.IdentityServer); - services.AddDataProtection() - .PersistKeysToDbContext() - .SetApplicationName("ClassifiedAds"); + services.AddDataProtection() + .PersistKeysToDbContext() + .SetApplicationName("ClassifiedAds"); - services.AddCaches(AppSettings.Caching); + services.AddCaches(AppSettings.Caching); - var authenBuilder = services.AddAuthentication(); + var authenBuilder = services.AddAuthentication(); - if (AppSettings?.ExternalLogin?.AzureActiveDirectory?.IsEnabled ?? false) + if (AppSettings?.ExternalLogin?.AzureActiveDirectory?.IsEnabled ?? false) + { + authenBuilder.AddOpenIdConnect("AAD", "Azure Active Directory", options => { - authenBuilder.AddOpenIdConnect("AAD", "Azure Active Directory", options => + options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme; + options.SignOutScheme = IdentityServerConstants.SignoutScheme; + options.Authority = AppSettings.ExternalLogin.AzureActiveDirectory.Authority; + options.ClientId = AppSettings.ExternalLogin.AzureActiveDirectory.ClientId; + options.ClientSecret = AppSettings.ExternalLogin.AzureActiveDirectory.ClientSecret; + options.ResponseType = "code id_token"; + options.Scope.Add("openid"); + options.Scope.Add("profile"); + options.Scope.Add("email"); + options.Scope.Add("offline_access"); + options.SaveTokens = true; + options.GetClaimsFromUserInfoEndpoint = true; + options.Events.OnTicketReceived = (ct) => { - options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme; - options.SignOutScheme = IdentityServerConstants.SignoutScheme; - options.Authority = AppSettings.ExternalLogin.AzureActiveDirectory.Authority; - options.ClientId = AppSettings.ExternalLogin.AzureActiveDirectory.ClientId; - options.ClientSecret = AppSettings.ExternalLogin.AzureActiveDirectory.ClientSecret; - options.ResponseType = "code id_token"; - options.Scope.Add("openid"); - options.Scope.Add("profile"); - options.Scope.Add("email"); - options.Scope.Add("offline_access"); - options.SaveTokens = true; - options.GetClaimsFromUserInfoEndpoint = true; - options.Events.OnTicketReceived = (ct) => - { - return Task.CompletedTask; - }; - options.Events.OnTokenResponseReceived = (ct) => - { - return Task.CompletedTask; - }; - options.Events.OnTokenValidated = (ct) => - { - return Task.CompletedTask; - }; - options.Events.OnUserInformationReceived = (ct) => - { - return Task.CompletedTask; - }; - }); - } - - if (AppSettings?.ExternalLogin?.Microsoft?.IsEnabled ?? false) - { - authenBuilder.AddMicrosoftAccount(options => + return Task.CompletedTask; + }; + options.Events.OnTokenResponseReceived = (ct) => { - options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme; - options.ClientId = AppSettings.ExternalLogin.Microsoft.ClientId; - options.ClientSecret = AppSettings.ExternalLogin.Microsoft.ClientSecret; - }); - } - - if (AppSettings?.ExternalLogin?.Google?.IsEnabled ?? false) - { - authenBuilder.AddGoogle(options => + return Task.CompletedTask; + }; + options.Events.OnTokenValidated = (ct) => + { + return Task.CompletedTask; + }; + options.Events.OnUserInformationReceived = (ct) => { - options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme; - options.ClientId = AppSettings.ExternalLogin.Google.ClientId; - options.ClientSecret = AppSettings.ExternalLogin.Google.ClientSecret; - }); - } + return Task.CompletedTask; + }; + }); + } - if (AppSettings?.ExternalLogin?.Facebook?.IsEnabled ?? false) + if (AppSettings?.ExternalLogin?.Microsoft?.IsEnabled ?? false) + { + authenBuilder.AddMicrosoftAccount(options => { - authenBuilder.AddFacebook(options => - { - options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme; - options.AppId = AppSettings.ExternalLogin.Facebook.AppId; - options.AppSecret = AppSettings.ExternalLogin.Facebook.AppSecret; - }); - } + options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme; + options.ClientId = AppSettings.ExternalLogin.Microsoft.ClientId; + options.ClientSecret = AppSettings.ExternalLogin.Microsoft.ClientSecret; + }); } - // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. - public void Configure(IApplicationBuilder app, IWebHostEnvironment env) + if (AppSettings?.ExternalLogin?.Google?.IsEnabled ?? false) { - app.UseForwardedHeaders(); + authenBuilder.AddGoogle(options => + { + options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme; + options.ClientId = AppSettings.ExternalLogin.Google.ClientId; + options.ClientSecret = AppSettings.ExternalLogin.Google.ClientSecret; + }); + } - if (env.IsDevelopment()) + if (AppSettings?.ExternalLogin?.Facebook?.IsEnabled ?? false) + { + authenBuilder.AddFacebook(options => { - app.UseDeveloperExceptionPage(); - } + options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme; + options.AppId = AppSettings.ExternalLogin.Facebook.AppId; + options.AppSecret = AppSettings.ExternalLogin.Facebook.AppSecret; + }); + } + } - app.UseStaticFiles(); + // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. + public void Configure(IApplicationBuilder app, IWebHostEnvironment env) + { + app.UseForwardedHeaders(); - if (AppSettings.CookiePolicyOptions?.IsEnabled ?? false) - { - app.UseCookiePolicy(); - } + if (env.IsDevelopment()) + { + app.UseDeveloperExceptionPage(); + } + + app.UseStaticFiles(); + + if (AppSettings.CookiePolicyOptions?.IsEnabled ?? false) + { + app.UseCookiePolicy(); + } - app.UseRouting(); + app.UseRouting(); - app.UseCors( - builder => builder - .AllowAnyOrigin() - .AllowAnyHeader() - .AllowAnyMethod() - ); + app.UseCors( + builder => builder + .AllowAnyOrigin() + .AllowAnyHeader() + .AllowAnyMethod() + ); - app.UseSecurityHeaders(AppSettings.SecurityHeaders); + app.UseSecurityHeaders(AppSettings.SecurityHeaders); - app.UseIdentityServer(); - app.UseAuthorization(); + app.UseIdentityServer(); + app.UseAuthorization(); - app.UseMonitoringServices(AppSettings.Monitoring); + app.UseMonitoringServices(AppSettings.Monitoring); - app.UseEndpoints(endpoints => - { - endpoints.MapDefaultControllerRoute(); - endpoints.MapRazorPages(); - }); - } + app.UseEndpoints(endpoints => + { + endpoints.MapDefaultControllerRoute(); + endpoints.MapRazorPages(); + }); } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/TagHelpers/PickerTagHelper.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/TagHelpers/PickerTagHelper.cs index 79a0147c1..10956b0ce 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/TagHelpers/PickerTagHelper.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/TagHelpers/PickerTagHelper.cs @@ -5,147 +5,146 @@ using System.ComponentModel.DataAnnotations; using System.Text.Json; -namespace ClassifiedAds.IdentityServer.TagHelpers -{ - [HtmlTargetElement("picker")] - public class PickerTagHelper : TagHelper - { - public string Url { get; set; } - - [Required] - public string Id { get; set; } +namespace ClassifiedAds.IdentityServer.TagHelpers; - public string SelectedItemsTitle { get; set; } +[HtmlTargetElement("picker")] +public class PickerTagHelper : TagHelper +{ + public string Url { get; set; } - public string SearchInputPlaceholder { get; set; } + [Required] + public string Id { get; set; } - public string SearchResultTitle { get; set; } + public string SelectedItemsTitle { get; set; } - public string SuggestedItemsTitle { get; set; } + public string SearchInputPlaceholder { get; set; } - public string NoItemSelectedTitle { get; set; } + public string SearchResultTitle { get; set; } - public List SelectedItems { get; set; } + public string SuggestedItemsTitle { get; set; } - public string SelectedItem { get; set; } + public string NoItemSelectedTitle { get; set; } - public string ShowAllItemsTitle { get; set; } + public List SelectedItems { get; set; } - public int MinSearchText { get; set; } + public string SelectedItem { get; set; } - public bool MultipleSelect { get; set; } + public string ShowAllItemsTitle { get; set; } - public bool AllowItemAlreadySelectedNotification { get; set; } = true; + public int MinSearchText { get; set; } - public string ItemAlreadySelectedTitle { get; set; } + public bool MultipleSelect { get; set; } - public bool AllowSuggestedItems { get; set; } = true; + public bool AllowItemAlreadySelectedNotification { get; set; } = true; - public int TopSuggestedItems { get; set; } = 5; + public string ItemAlreadySelectedTitle { get; set; } - public bool Required { get; set; } + public bool AllowSuggestedItems { get; set; } = true; - public string RequiredMessage { get; set; } + public int TopSuggestedItems { get; set; } = 5; - public override void Process(TagHelperContext context, TagHelperOutput output) - { - AddWrapper(output); - AddComponent(output); - AddHiddenField(output); - } + public bool Required { get; set; } - private void AddWrapper(TagHelperOutput output) - { - output.TagMode = TagMode.StartTagAndEndTag; - output.TagName = "div"; - output.Attributes.Add("class", "hidden picker"); - output.Attributes.Add(new TagHelperAttribute("data-bind", new HtmlString("css: { hidden: false }"))); - } + public string RequiredMessage { get; set; } - private void AddComponent(TagHelperOutput output) - { - var selectedItems = GetSelectedItems(); + public override void Process(TagHelperContext context, TagHelperOutput output) + { + AddWrapper(output); + AddComponent(output); + AddHiddenField(output); + } - var component = new - { - name = "picker", - @params = new - { - search = "", - hiddenId = Id, - url = Url, - selectedItemsTitle = SelectedItemsTitle, - allowSuggestedItems = AllowSuggestedItems, - searchResultTitle = SearchResultTitle, - suggestedItemsTitle = SuggestedItemsTitle, - noItemSelectedTitle = NoItemSelectedTitle, - searchInputPlaceholder = SearchInputPlaceholder, - showAllItemsTitle = ShowAllItemsTitle, - selectedItems, - minSearchText = MinSearchText, - topSuggestedItems = TopSuggestedItems, - multipleSelect = MultipleSelect, - allowItemAlreadySelectedNotification = AllowItemAlreadySelectedNotification, - itemAlreadySelectedTitle = ItemAlreadySelectedTitle - } - }; - - var rawPickerHtml = new HtmlString($"
"); - - output.Content.AppendHtml(rawPickerHtml); - } + private void AddWrapper(TagHelperOutput output) + { + output.TagMode = TagMode.StartTagAndEndTag; + output.TagName = "div"; + output.Attributes.Add("class", "hidden picker"); + output.Attributes.Add(new TagHelperAttribute("data-bind", new HtmlString("css: { hidden: false }"))); + } - /// - /// Get Selected Items - /// - /// - private List GetSelectedItems() - { - return MultipleSelect ? GetSelectedItemsWithRemovedQuotes() : GetSelectedItemWithRemovedQuotes(); - } + private void AddComponent(TagHelperOutput output) + { + var selectedItems = GetSelectedItems(); - /// - /// Get Selected Items - with removed quotes - /// - /// - private List GetSelectedItemsWithRemovedQuotes() + var component = new { - for (var i = 0; i < SelectedItems?.Count; i++) + name = "picker", + @params = new { - SelectedItems[i] = SelectedItems[i].Replace("'", "").Replace("\"", ""); + search = "", + hiddenId = Id, + url = Url, + selectedItemsTitle = SelectedItemsTitle, + allowSuggestedItems = AllowSuggestedItems, + searchResultTitle = SearchResultTitle, + suggestedItemsTitle = SuggestedItemsTitle, + noItemSelectedTitle = NoItemSelectedTitle, + searchInputPlaceholder = SearchInputPlaceholder, + showAllItemsTitle = ShowAllItemsTitle, + selectedItems, + minSearchText = MinSearchText, + topSuggestedItems = TopSuggestedItems, + multipleSelect = MultipleSelect, + allowItemAlreadySelectedNotification = AllowItemAlreadySelectedNotification, + itemAlreadySelectedTitle = ItemAlreadySelectedTitle } + }; - return SelectedItems; - } + var rawPickerHtml = new HtmlString($"
"); - /// - /// Get Selected Item - with removed quotes, the picker component expect the collection of items, therefore it is used the list for single value as well - /// - /// - private List GetSelectedItemWithRemovedQuotes() - { - SelectedItem = SelectedItem.Replace("'", "").Replace("\"", ""); + output.Content.AppendHtml(rawPickerHtml); + } - return string.IsNullOrWhiteSpace(SelectedItem) ? new List() : new List { SelectedItem }; - } + /// + /// Get Selected Items + /// + /// + private List GetSelectedItems() + { + return MultipleSelect ? GetSelectedItemsWithRemovedQuotes() : GetSelectedItemWithRemovedQuotes(); + } - private void AddHiddenField(TagHelperOutput output) + /// + /// Get Selected Items - with removed quotes + /// + /// + private List GetSelectedItemsWithRemovedQuotes() + { + for (var i = 0; i < SelectedItems?.Count; i++) { - var hiddenField = new TagBuilder("input"); - hiddenField.Attributes.Add("type", "hidden"); - hiddenField.Attributes.Add("id", Id); - hiddenField.Attributes.Add("name", Id); - hiddenField.Attributes.Add("value", string.Empty); + SelectedItems[i] = SelectedItems[i].Replace("'", "").Replace("\"", ""); + } - if (Required) - { - hiddenField.Attributes.Add("required", string.Empty); - hiddenField.Attributes.Add("data-val", "true"); - hiddenField.Attributes.Add("data-val-required", RequiredMessage ?? $"The {Id} field is required."); - hiddenField.Attributes.Add("aria-required", "true"); - } + return SelectedItems; + } + + /// + /// Get Selected Item - with removed quotes, the picker component expect the collection of items, therefore it is used the list for single value as well + /// + /// + private List GetSelectedItemWithRemovedQuotes() + { + SelectedItem = SelectedItem.Replace("'", "").Replace("\"", ""); + + return string.IsNullOrWhiteSpace(SelectedItem) ? new List() : new List { SelectedItem }; + } - output.Content.AppendHtml(hiddenField); + private void AddHiddenField(TagHelperOutput output) + { + var hiddenField = new TagBuilder("input"); + hiddenField.Attributes.Add("type", "hidden"); + hiddenField.Attributes.Add("id", Id); + hiddenField.Attributes.Add("name", Id); + hiddenField.Attributes.Add("value", string.Empty); + + if (Required) + { + hiddenField.Attributes.Add("required", string.Empty); + hiddenField.Attributes.Add("data-val", "true"); + hiddenField.Attributes.Add("data-val-required", RequiredMessage ?? $"The {Id} field is required."); + hiddenField.Attributes.Add("aria-required", "true"); } + + output.Content.AppendHtml(hiddenField); } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/TagHelpers/SwitchTagHelper.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/TagHelpers/SwitchTagHelper.cs index e1dc65e2b..cf062629a 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/TagHelpers/SwitchTagHelper.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.IdentityServer/TagHelpers/SwitchTagHelper.cs @@ -2,23 +2,22 @@ using Microsoft.AspNetCore.Mvc.Rendering; using Microsoft.AspNetCore.Razor.TagHelpers; -namespace ClassifiedAds.IdentityServer.TagHelpers +namespace ClassifiedAds.IdentityServer.TagHelpers; + +[HtmlTargetElement("toggle-button")] +public class SwitchTagHelper : TagHelper { - [HtmlTargetElement("toggle-button")] - public class SwitchTagHelper : TagHelper + public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output) { - public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output) - { - var childContent = await output.GetChildContentAsync(); + var childContent = await output.GetChildContentAsync(); - var divSlider = new TagBuilder("div"); - divSlider.AddCssClass("slider round"); + var divSlider = new TagBuilder("div"); + divSlider.AddCssClass("slider round"); - output.TagName = "label"; - output.Attributes.Add("class", "switch"); - output.Content.AppendHtml(childContent); - output.Content.AppendHtml(divSlider); - output.TagMode = TagMode.StartTagAndEndTag; - } + output.TagName = "label"; + output.Attributes.Add("class", "switch"); + output.Content.AppendHtml(childContent); + output.Content.AppendHtml(divSlider); + output.TagMode = TagMode.StartTagAndEndTag; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Caching/CachingOptions.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Caching/CachingOptions.cs index 67ef160ec..1c2c1a04d 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Caching/CachingOptions.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Caching/CachingOptions.cs @@ -1,41 +1,40 @@ -namespace ClassifiedAds.Infrastructure.Caching +namespace ClassifiedAds.Infrastructure.Caching; + +public class CachingOptions { - public class CachingOptions - { - public InMemoryCacheOptions InMemory { get; set; } + public InMemoryCacheOptions InMemory { get; set; } - public DistributedCacheOptions Distributed { get; set; } - } + public DistributedCacheOptions Distributed { get; set; } +} - public class InMemoryCacheOptions - { - public long? SizeLimit { get; set; } - } +public class InMemoryCacheOptions +{ + public long? SizeLimit { get; set; } +} - public class DistributedCacheOptions - { - public string Provider { get; set; } +public class DistributedCacheOptions +{ + public string Provider { get; set; } - public InMemoryCacheOptions InMemory { get; set; } + public InMemoryCacheOptions InMemory { get; set; } - public RedisOptions Redis { get; set; } + public RedisOptions Redis { get; set; } - public SqlServerOptions SqlServer { get; set; } - } + public SqlServerOptions SqlServer { get; set; } +} - public class RedisOptions - { - public string Configuration { get; set; } +public class RedisOptions +{ + public string Configuration { get; set; } - public string InstanceName { get; set; } - } + public string InstanceName { get; set; } +} - public class SqlServerOptions - { - public string ConnectionString { get; set; } +public class SqlServerOptions +{ + public string ConnectionString { get; set; } - public string SchemaName { get; set; } + public string SchemaName { get; set; } - public string TableName { get; set; } - } + public string TableName { get; set; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Caching/CachingServiceCollectionExtensions.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Caching/CachingServiceCollectionExtensions.cs index 3805a42a7..a1f22cb05 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Caching/CachingServiceCollectionExtensions.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Caching/CachingServiceCollectionExtensions.cs @@ -1,44 +1,43 @@ using ClassifiedAds.Infrastructure.Caching; -namespace Microsoft.Extensions.DependencyInjection +namespace Microsoft.Extensions.DependencyInjection; + +public static class CachingServiceCollectionExtensions { - public static class CachingServiceCollectionExtensions + public static IServiceCollection AddCaches(this IServiceCollection services, CachingOptions options = null) { - public static IServiceCollection AddCaches(this IServiceCollection services, CachingOptions options = null) + services.AddMemoryCache(opt => { - services.AddMemoryCache(opt => - { - opt.SizeLimit = options?.InMemory?.SizeLimit; - }); + opt.SizeLimit = options?.InMemory?.SizeLimit; + }); - var distributedProvider = options?.Distributed?.Provider; + var distributedProvider = options?.Distributed?.Provider; - if (distributedProvider == "InMemory") + if (distributedProvider == "InMemory") + { + services.AddDistributedMemoryCache(opt => { - services.AddDistributedMemoryCache(opt => - { - opt.SizeLimit = options?.Distributed?.InMemory?.SizeLimit; - }); - } - else if (distributedProvider == "Redis") + opt.SizeLimit = options?.Distributed?.InMemory?.SizeLimit; + }); + } + else if (distributedProvider == "Redis") + { + services.AddDistributedRedisCache(opt => { - services.AddDistributedRedisCache(opt => - { - opt.Configuration = options.Distributed.Redis.Configuration; - opt.InstanceName = options.Distributed.Redis.InstanceName; - }); - } - else if (distributedProvider == "SqlServer") + opt.Configuration = options.Distributed.Redis.Configuration; + opt.InstanceName = options.Distributed.Redis.InstanceName; + }); + } + else if (distributedProvider == "SqlServer") + { + services.AddDistributedSqlServerCache(opt => { - services.AddDistributedSqlServerCache(opt => - { - opt.ConnectionString = options.Distributed.SqlServer.ConnectionString; - opt.SchemaName = options.Distributed.SqlServer.SchemaName; - opt.TableName = options.Distributed.SqlServer.TableName; - }); - } - - return services; + opt.ConnectionString = options.Distributed.SqlServer.ConnectionString; + opt.SchemaName = options.Distributed.SqlServer.SchemaName; + opt.TableName = options.Distributed.SqlServer.TableName; + }); } + + return services; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/DateTimes/DateTimeProvider.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/DateTimes/DateTimeProvider.cs index 19e07631d..a0ae894c7 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/DateTimes/DateTimeProvider.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/DateTimes/DateTimeProvider.cs @@ -1,16 +1,15 @@ using ClassifiedAds.CrossCuttingConcerns.DateTimes; using System; -namespace ClassifiedAds.Infrastructure.DateTimes +namespace ClassifiedAds.Infrastructure.DateTimes; + +public class DateTimeProvider : IDateTimeProvider { - public class DateTimeProvider : IDateTimeProvider - { - public DateTime Now => DateTime.Now; + public DateTime Now => DateTime.Now; - public DateTime UtcNow => DateTime.UtcNow; + public DateTime UtcNow => DateTime.UtcNow; - public DateTimeOffset OffsetNow => DateTimeOffset.Now; + public DateTimeOffset OffsetNow => DateTimeOffset.Now; - public DateTimeOffset OffsetUtcNow => DateTimeOffset.UtcNow; - } + public DateTimeOffset OffsetUtcNow => DateTimeOffset.UtcNow; } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/DateTimes/DateTimeProviderExtensions.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/DateTimes/DateTimeProviderExtensions.cs index 29277a890..4994f38f1 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/DateTimes/DateTimeProviderExtensions.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/DateTimes/DateTimeProviderExtensions.cs @@ -1,14 +1,13 @@ using ClassifiedAds.CrossCuttingConcerns.DateTimes; using ClassifiedAds.Infrastructure.DateTimes; -namespace Microsoft.Extensions.DependencyInjection +namespace Microsoft.Extensions.DependencyInjection; + +public static class DateTimeProviderExtensions { - public static class DateTimeProviderExtensions + public static IServiceCollection AddDateTimeProvider(this IServiceCollection services) { - public static IServiceCollection AddDateTimeProvider(this IServiceCollection services) - { - _ = services.AddSingleton(); - return services; - } + _ = services.AddSingleton(); + return services; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/HealthChecks/HttpHealthCheck.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/HealthChecks/HttpHealthCheck.cs index 0245bb2fa..3488b1d2d 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/HealthChecks/HttpHealthCheck.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/HealthChecks/HttpHealthCheck.cs @@ -4,36 +4,35 @@ using System.Threading; using System.Threading.Tasks; -namespace ClassifiedAds.Infrastructure.HealthChecks +namespace ClassifiedAds.Infrastructure.HealthChecks; + +public class HttpHealthCheck : IHealthCheck { - public class HttpHealthCheck : IHealthCheck - { - private static HttpClient _httpClient = new HttpClient(); - private readonly string _uri; + private static HttpClient _httpClient = new HttpClient(); + private readonly string _uri; - public HttpHealthCheck(string uri) - { - _uri = uri; - } + public HttpHealthCheck(string uri) + { + _uri = uri; + } - public async Task CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default) + public async Task CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default) + { + try { - try + var response = await _httpClient.GetAsync(_uri); + if (response.IsSuccessStatusCode) { - var response = await _httpClient.GetAsync(_uri); - if (response.IsSuccessStatusCode) - { - return HealthCheckResult.Healthy($"Uri: '{_uri}', StatusCode: '{response.StatusCode}'"); - } - else - { - return new HealthCheckResult(context.Registration.FailureStatus, $"Uri: '{_uri}', StatusCode: '{response.StatusCode}'"); - } + return HealthCheckResult.Healthy($"Uri: '{_uri}', StatusCode: '{response.StatusCode}'"); } - catch (Exception exception) + else { - return new HealthCheckResult(context.Registration.FailureStatus, $"Uri: '{_uri}', Exception: '{exception.Message}'", exception); + return new HealthCheckResult(context.Registration.FailureStatus, $"Uri: '{_uri}', StatusCode: '{response.StatusCode}'"); } } + catch (Exception exception) + { + return new HealthCheckResult(context.Registration.FailureStatus, $"Uri: '{_uri}', Exception: '{exception.Message}'", exception); + } } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/HealthChecks/NetworkPortCheck.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/HealthChecks/NetworkPortCheck.cs index 08e6eefb6..e587dcf7c 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/HealthChecks/NetworkPortCheck.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/HealthChecks/NetworkPortCheck.cs @@ -2,43 +2,42 @@ using System.Net.Sockets; using System.Threading; -namespace ClassifiedAds.Infrastructure.HealthChecks +namespace ClassifiedAds.Infrastructure.HealthChecks; + +public class NetworkPortCheck { - public class NetworkPortCheck + public static bool IsReady(string address) { - public static bool IsReady(string address) - { - var parts = address.Split(':'); - string host = parts[0]; - int port = int.Parse(parts[1]); + var parts = address.Split(':'); + string host = parts[0]; + int port = int.Parse(parts[1]); - try - { - TcpClient client = new TcpClient(host, port); - return client.Connected; - } - catch (Exception ex) - { - Console.WriteLine($"Failed to connect to {address} :" + ex.Message); - return false; - } + try + { + TcpClient client = new TcpClient(host, port); + return client.Connected; } + catch (Exception ex) + { + Console.WriteLine($"Failed to connect to {address} :" + ex.Message); + return false; + } + } - public static void Wait(string address, int retries = 0, int timeOut = 30000) + public static void Wait(string address, int retries = 0, int timeOut = 30000) + { + int count = 0; + do { - int count = 0; - do + var isReady = IsReady(address); + if (isReady) { - var isReady = IsReady(address); - if (isReady) - { - return; - } - - count++; - Thread.Sleep(timeOut); + return; } - while (count <= retries); + + count++; + Thread.Sleep(timeOut); } + while (count <= retries); } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/HealthChecks/SqlServerHealthCheck.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/HealthChecks/SqlServerHealthCheck.cs index 507e45aaa..f1366967d 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/HealthChecks/SqlServerHealthCheck.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/HealthChecks/SqlServerHealthCheck.cs @@ -4,38 +4,37 @@ using System.Threading; using System.Threading.Tasks; -namespace ClassifiedAds.Infrastructure.HealthChecks +namespace ClassifiedAds.Infrastructure.HealthChecks; + +public class SqlServerHealthCheck : IHealthCheck { - public class SqlServerHealthCheck : IHealthCheck - { - private readonly string _connectionString; + private readonly string _connectionString; - private readonly string _sql; + private readonly string _sql; - public SqlServerHealthCheck(string connectionString, string sql) - { - _connectionString = connectionString ?? throw new ArgumentNullException("connectionString"); - _sql = sql ?? throw new ArgumentNullException("sql"); - } + public SqlServerHealthCheck(string connectionString, string sql) + { + _connectionString = connectionString ?? throw new ArgumentNullException("connectionString"); + _sql = sql ?? throw new ArgumentNullException("sql"); + } - public async Task CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default(CancellationToken)) + public async Task CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default(CancellationToken)) + { + try { - try + using SqlConnection connection = new SqlConnection(_connectionString); + await connection.OpenAsync(cancellationToken); + using (SqlCommand command = connection.CreateCommand()) { - using SqlConnection connection = new SqlConnection(_connectionString); - await connection.OpenAsync(cancellationToken); - using (SqlCommand command = connection.CreateCommand()) - { - command.CommandText = _sql; - await command.ExecuteScalarAsync(cancellationToken); - } - - return HealthCheckResult.Healthy(); - } - catch (Exception exception) - { - return new HealthCheckResult(context.Registration.FailureStatus, null, exception); + command.CommandText = _sql; + await command.ExecuteScalarAsync(cancellationToken); } + + return HealthCheckResult.Healthy(); + } + catch (Exception exception) + { + return new HealthCheckResult(context.Registration.FailureStatus, null, exception); } } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/HostedServices/CronJobBackgroundService.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/HostedServices/CronJobBackgroundService.cs index 9277100a6..8a26403b9 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/HostedServices/CronJobBackgroundService.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/HostedServices/CronJobBackgroundService.cs @@ -4,30 +4,29 @@ using System.Threading; using System.Threading.Tasks; -namespace ClassifiedAds.Infrastructure.HostedServices +namespace ClassifiedAds.Infrastructure.HostedServices; + +public abstract class CronJobBackgroundService : BackgroundService { - public abstract class CronJobBackgroundService : BackgroundService + protected string Cron { get; set; } + + protected override async Task ExecuteAsync(CancellationToken stoppingToken) { - protected string Cron { get; set; } + var cron = new CronExpression(Cron); + var next = cron.GetNextValidTimeAfter(DateTimeOffset.Now); - protected override async Task ExecuteAsync(CancellationToken stoppingToken) + while (!stoppingToken.IsCancellationRequested) { - var cron = new CronExpression(Cron); - var next = cron.GetNextValidTimeAfter(DateTimeOffset.Now); - - while (!stoppingToken.IsCancellationRequested) + if (DateTimeOffset.Now > next) { - if (DateTimeOffset.Now > next) - { - await DoWork(stoppingToken); - - next = cron.GetNextValidTimeAfter(DateTimeOffset.Now); - } + await DoWork(stoppingToken); - await Task.Delay(1000, stoppingToken); + next = cron.GetNextValidTimeAfter(DateTimeOffset.Now); } - } - protected abstract Task DoWork(CancellationToken stoppingToken); + await Task.Delay(1000, stoppingToken); + } } + + protected abstract Task DoWork(CancellationToken stoppingToken); } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/HttpMessageHandlers/DebuggingHandler.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/HttpMessageHandlers/DebuggingHandler.cs index 43c2956b0..a260b7efb 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/HttpMessageHandlers/DebuggingHandler.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/HttpMessageHandlers/DebuggingHandler.cs @@ -2,18 +2,17 @@ using System.Threading; using System.Threading.Tasks; -namespace ClassifiedAds.Infrastructure.HttpMessageHandlers +namespace ClassifiedAds.Infrastructure.HttpMessageHandlers; + +public class DebuggingHandler : DelegatingHandler { - public class DebuggingHandler : DelegatingHandler + public DebuggingHandler() { - public DebuggingHandler() - { - } + } - protected override async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) - { - var response = await base.SendAsync(request, cancellationToken); - return response; - } + protected override async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) + { + var response = await base.SendAsync(request, cancellationToken); + return response; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Identity/AnonymousUser.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Identity/AnonymousUser.cs index bd7d47240..d99bc3327 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Identity/AnonymousUser.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Identity/AnonymousUser.cs @@ -1,12 +1,11 @@ using ClassifiedAds.Domain.Identity; using System; -namespace ClassifiedAds.Infrastructure.Identity +namespace ClassifiedAds.Infrastructure.Identity; + +public class AnonymousUser : ICurrentUser { - public class AnonymousUser : ICurrentUser - { - public bool IsAuthenticated => false; + public bool IsAuthenticated => false; - public Guid UserId => Guid.Empty; - } + public Guid UserId => Guid.Empty; } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Identity/CurrentWebUser.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Identity/CurrentWebUser.cs index 15a8ccde5..6aacd87e1 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Identity/CurrentWebUser.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Identity/CurrentWebUser.cs @@ -3,34 +3,33 @@ using System; using System.Security.Claims; -namespace ClassifiedAds.Infrastructure.Identity +namespace ClassifiedAds.Infrastructure.Identity; + +public class CurrentWebUser : ICurrentUser { - public class CurrentWebUser : ICurrentUser - { - private readonly IHttpContextAccessor _context; + private readonly IHttpContextAccessor _context; - public CurrentWebUser(IHttpContextAccessor context) - { - _context = context; - } + public CurrentWebUser(IHttpContextAccessor context) + { + _context = context; + } - public bool IsAuthenticated + public bool IsAuthenticated + { + get { - get - { - return _context.HttpContext.User.Identity.IsAuthenticated; - } + return _context.HttpContext.User.Identity.IsAuthenticated; } + } - public Guid UserId + public Guid UserId + { + get { - get - { - var userId = _context.HttpContext.User.FindFirst(ClaimTypes.NameIdentifier)?.Value - ?? _context.HttpContext.User.FindFirst("sub")?.Value; + var userId = _context.HttpContext.User.FindFirst(ClaimTypes.NameIdentifier)?.Value + ?? _context.HttpContext.User.FindFirst("sub")?.Value; - return Guid.Parse(userId); - } + return Guid.Parse(userId); } } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Identity/EmailConfirmationTokenProvider.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Identity/EmailConfirmationTokenProvider.cs index 46d402a98..e0cd57384 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Identity/EmailConfirmationTokenProvider.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Identity/EmailConfirmationTokenProvider.cs @@ -3,19 +3,18 @@ using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; -namespace ClassifiedAds.Infrastructure.Identity +namespace ClassifiedAds.Infrastructure.Identity; + +public class EmailConfirmationTokenProvider : DataProtectorTokenProvider + where TUser : class { - public class EmailConfirmationTokenProvider : DataProtectorTokenProvider - where TUser : class + public EmailConfirmationTokenProvider(IDataProtectionProvider dataProtectionProvider, + IOptions options, ILogger> logger) + : base(dataProtectionProvider, options, logger) { - public EmailConfirmationTokenProvider(IDataProtectionProvider dataProtectionProvider, - IOptions options, ILogger> logger) - : base(dataProtectionProvider, options, logger) - { - } } +} - public class EmailConfirmationTokenProviderOptions : DataProtectionTokenProviderOptions - { - } +public class EmailConfirmationTokenProviderOptions : DataProtectionTokenProviderOptions +{ } \ No newline at end of file diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Identity/HistoricalPasswordValidator.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Identity/HistoricalPasswordValidator.cs index 1ea6dfe25..7a96926f4 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Identity/HistoricalPasswordValidator.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Identity/HistoricalPasswordValidator.cs @@ -2,23 +2,22 @@ using Microsoft.AspNetCore.Identity; using System.Threading.Tasks; -namespace ClassifiedAds.Infrastructure.Identity +namespace ClassifiedAds.Infrastructure.Identity; + +public class HistoricalPasswordValidator : IPasswordValidator { - public class HistoricalPasswordValidator : IPasswordValidator + public Task ValidateAsync(UserManager manager, User user, string password) { - public Task ValidateAsync(UserManager manager, User user, string password) + if (password.Contains("testhistoricalpassword")) { - if (password.Contains("testhistoricalpassword")) + return Task.FromResult(IdentityResult.Failed(new IdentityError { - return Task.FromResult(IdentityResult.Failed(new IdentityError - { - Code = "HistoricalPassword", - Description = "HistoricalPasswordValidator testing.", - })); - } - - // TODO: check password histories, etc. - return Task.FromResult(IdentityResult.Success); + Code = "HistoricalPassword", + Description = "HistoricalPasswordValidator testing.", + })); } + + // TODO: check password histories, etc. + return Task.FromResult(IdentityResult.Success); } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Identity/IdentityServiceCollectionExtensions.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Identity/IdentityServiceCollectionExtensions.cs index 825118c2f..29f14d4dc 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Identity/IdentityServiceCollectionExtensions.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Identity/IdentityServiceCollectionExtensions.cs @@ -4,90 +4,89 @@ using Microsoft.AspNetCore.Identity; using System; -namespace Microsoft.Extensions.DependencyInjection +namespace Microsoft.Extensions.DependencyInjection; + +public static class IdentityServiceCollectionExtensions { - public static class IdentityServiceCollectionExtensions + public static IServiceCollection AddIdentity(this IServiceCollection services) { - public static IServiceCollection AddIdentity(this IServiceCollection services) + services.AddIdentity() + .AddTokenProviders() + .AddPasswordValidators(); + + services.AddTransient, UserStore>(); + services.AddTransient, RoleStore>(); + services.AddScoped(); + + ConfigureOptions(services); + + services.ConfigureApplicationCookie(options => { - services.AddIdentity() - .AddTokenProviders() - .AddPasswordValidators(); + options.LoginPath = "/Account/Login"; + }); - services.AddTransient, UserStore>(); - services.AddTransient, RoleStore>(); - services.AddScoped(); + return services; + } - ConfigureOptions(services); + public static IServiceCollection AddIdentityCore(this IServiceCollection services) + { + services.AddIdentityCore() + .AddTokenProviders() + .AddPasswordValidators(); - services.ConfigureApplicationCookie(options => - { - options.LoginPath = "/Account/Login"; - }); + services.AddTransient, UserStore>(); + services.AddTransient, RoleStore>(); + services.AddScoped(); - return services; - } + ConfigureOptions(services); - public static IServiceCollection AddIdentityCore(this IServiceCollection services) - { - services.AddIdentityCore() - .AddTokenProviders() - .AddPasswordValidators(); + return services; + } - services.AddTransient, UserStore>(); - services.AddTransient, RoleStore>(); - services.AddScoped(); + private static IdentityBuilder AddTokenProviders(this IdentityBuilder identityBuilder) + { + identityBuilder + .AddDefaultTokenProviders() + .AddTokenProvider>("EmailConfirmation"); - ConfigureOptions(services); + return identityBuilder; + } - return services; - } + private static IdentityBuilder AddPasswordValidators(this IdentityBuilder identityBuilder) + { + identityBuilder + .AddPasswordValidator() + .AddPasswordValidator(); - private static IdentityBuilder AddTokenProviders(this IdentityBuilder identityBuilder) + return identityBuilder; + } + + private static void ConfigureOptions(IServiceCollection services) + { + services.Configure(options => { - identityBuilder - .AddDefaultTokenProviders() - .AddTokenProvider>("EmailConfirmation"); + options.TokenLifespan = TimeSpan.FromHours(3); + }); - return identityBuilder; - } + services.Configure(options => + { + options.TokenLifespan = TimeSpan.FromDays(2); + }); - private static IdentityBuilder AddPasswordValidators(this IdentityBuilder identityBuilder) + services.Configure(options => { - identityBuilder - .AddPasswordValidator() - .AddPasswordValidator(); + options.Tokens.EmailConfirmationTokenProvider = "EmailConfirmation"; - return identityBuilder; - } + // Default Lockout settings. + options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(5); + options.Lockout.MaxFailedAccessAttempts = 5; + options.Lockout.AllowedForNewUsers = true; + }); - private static void ConfigureOptions(IServiceCollection services) + services.Configure(option => { - services.Configure(options => - { - options.TokenLifespan = TimeSpan.FromHours(3); - }); - - services.Configure(options => - { - options.TokenLifespan = TimeSpan.FromDays(2); - }); - - services.Configure(options => - { - options.Tokens.EmailConfirmationTokenProvider = "EmailConfirmation"; - - // Default Lockout settings. - options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(5); - options.Lockout.MaxFailedAccessAttempts = 5; - options.Lockout.AllowedForNewUsers = true; - }); - - services.Configure(option => - { - // option.IterationCount = 10000; - // option.CompatibilityMode = PasswordHasherCompatibilityMode.IdentityV2; - }); - } + // option.IterationCount = 10000; + // option.CompatibilityMode = PasswordHasherCompatibilityMode.IdentityV2; + }); } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Identity/PasswordHasher.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Identity/PasswordHasher.cs index 8eef788d1..75eea8424 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Identity/PasswordHasher.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Identity/PasswordHasher.cs @@ -2,13 +2,12 @@ using ClassifiedAds.Domain.Identity; using Microsoft.AspNetCore.Identity; -namespace ClassifiedAds.Infrastructure.Identity +namespace ClassifiedAds.Infrastructure.Identity; + +public class PasswordHasher : IPasswordHasher { - public class PasswordHasher : IPasswordHasher + public bool VerifyHashedPassword(User user, string hashedPassword, string providedPassword) { - public bool VerifyHashedPassword(User user, string hashedPassword, string providedPassword) - { - return new PasswordHasher().VerifyHashedPassword(user, hashedPassword, providedPassword) != PasswordVerificationResult.Failed; - } + return new PasswordHasher().VerifyHashedPassword(user, hashedPassword, providedPassword) != PasswordVerificationResult.Failed; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Identity/RoleStore.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Identity/RoleStore.cs index 5695ec569..2b207d7cd 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Identity/RoleStore.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Identity/RoleStore.cs @@ -5,69 +5,68 @@ using System.Threading; using System.Threading.Tasks; -namespace ClassifiedAds.Infrastructure.Identity +namespace ClassifiedAds.Infrastructure.Identity; + +public class RoleStore : IRoleStore { - public class RoleStore : IRoleStore - { - private readonly IRepository _roleRepository; + private readonly IRepository _roleRepository; - public RoleStore(IRepository roleRepository) - { - _roleRepository = roleRepository; - } + public RoleStore(IRepository roleRepository) + { + _roleRepository = roleRepository; + } - public void Dispose() - { - } + public void Dispose() + { + } - public Task CreateAsync(Role role, CancellationToken cancellationToken) - { - throw new NotImplementedException(); - } + public Task CreateAsync(Role role, CancellationToken cancellationToken) + { + throw new NotImplementedException(); + } - public Task DeleteAsync(Role role, CancellationToken cancellationToken) - { - throw new NotImplementedException(); - } + public Task DeleteAsync(Role role, CancellationToken cancellationToken) + { + throw new NotImplementedException(); + } - public Task FindByIdAsync(string roleId, CancellationToken cancellationToken) - { - throw new NotImplementedException(); - } + public Task FindByIdAsync(string roleId, CancellationToken cancellationToken) + { + throw new NotImplementedException(); + } - public Task FindByNameAsync(string normalizedRoleName, CancellationToken cancellationToken) - { - throw new NotImplementedException(); - } + public Task FindByNameAsync(string normalizedRoleName, CancellationToken cancellationToken) + { + throw new NotImplementedException(); + } - public Task GetNormalizedRoleNameAsync(Role role, CancellationToken cancellationToken) - { - throw new NotImplementedException(); - } + public Task GetNormalizedRoleNameAsync(Role role, CancellationToken cancellationToken) + { + throw new NotImplementedException(); + } - public Task GetRoleIdAsync(Role role, CancellationToken cancellationToken) - { - throw new NotImplementedException(); - } + public Task GetRoleIdAsync(Role role, CancellationToken cancellationToken) + { + throw new NotImplementedException(); + } - public Task GetRoleNameAsync(Role role, CancellationToken cancellationToken) - { - throw new NotImplementedException(); - } + public Task GetRoleNameAsync(Role role, CancellationToken cancellationToken) + { + throw new NotImplementedException(); + } - public Task SetNormalizedRoleNameAsync(Role role, string normalizedName, CancellationToken cancellationToken) - { - throw new NotImplementedException(); - } + public Task SetNormalizedRoleNameAsync(Role role, string normalizedName, CancellationToken cancellationToken) + { + throw new NotImplementedException(); + } - public Task SetRoleNameAsync(Role role, string roleName, CancellationToken cancellationToken) - { - throw new NotImplementedException(); - } + public Task SetRoleNameAsync(Role role, string roleName, CancellationToken cancellationToken) + { + throw new NotImplementedException(); + } - public Task UpdateAsync(Role role, CancellationToken cancellationToken) - { - throw new NotImplementedException(); - } + public Task UpdateAsync(Role role, CancellationToken cancellationToken) + { + throw new NotImplementedException(); } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Identity/UserStore.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Identity/UserStore.cs index 035762ebf..0db23c77b 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Identity/UserStore.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Identity/UserStore.cs @@ -8,317 +8,316 @@ using System.Threading; using System.Threading.Tasks; -namespace ClassifiedAds.Infrastructure.Identity +namespace ClassifiedAds.Infrastructure.Identity; + +public class UserStore : IUserStore, + IUserPasswordStore, + IUserSecurityStampStore, + IUserEmailStore, + IUserPhoneNumberStore, + IUserTwoFactorStore, + IUserLockoutStore, + IUserAuthenticationTokenStore, + IUserAuthenticatorKeyStore, + IUserTwoFactorRecoveryCodeStore { - public class UserStore : IUserStore, - IUserPasswordStore, - IUserSecurityStampStore, - IUserEmailStore, - IUserPhoneNumberStore, - IUserTwoFactorStore, - IUserLockoutStore, - IUserAuthenticationTokenStore, - IUserAuthenticatorKeyStore, - IUserTwoFactorRecoveryCodeStore - { - private readonly IUnitOfWork _unitOfWork; - private readonly IUserRepository _userRepository; - - public UserStore(IUserRepository userRepository) - { - _unitOfWork = userRepository.UnitOfWork; - _userRepository = userRepository; - } + private readonly IUnitOfWork _unitOfWork; + private readonly IUserRepository _userRepository; - public void Dispose() - { - } + public UserStore(IUserRepository userRepository) + { + _unitOfWork = userRepository.UnitOfWork; + _userRepository = userRepository; + } - public async Task CreateAsync(User user, CancellationToken cancellationToken) + public void Dispose() + { + } + + public async Task CreateAsync(User user, CancellationToken cancellationToken) + { + user.PasswordHistories = new List() { - user.PasswordHistories = new List() + new PasswordHistory { - new PasswordHistory - { - PasswordHash = user.PasswordHash, - CreatedDateTime = DateTimeOffset.Now, - }, - }; - await _userRepository.AddOrUpdateAsync(user); - await _unitOfWork.SaveChangesAsync(); - return IdentityResult.Success; - } + PasswordHash = user.PasswordHash, + CreatedDateTime = DateTimeOffset.Now, + }, + }; + await _userRepository.AddOrUpdateAsync(user); + await _unitOfWork.SaveChangesAsync(); + return IdentityResult.Success; + } - public Task DeleteAsync(User user, CancellationToken cancellationToken) - { - _userRepository.Delete(user); - return Task.FromResult(IdentityResult.Success); - } + public Task DeleteAsync(User user, CancellationToken cancellationToken) + { + _userRepository.Delete(user); + return Task.FromResult(IdentityResult.Success); + } - public Task FindByEmailAsync(string normalizedEmail, CancellationToken cancellationToken) - { - return _userRepository.Get(new UserQueryOptions { IncludeTokens = true }).FirstOrDefaultAsync(x => x.NormalizedEmail == normalizedEmail); - } + public Task FindByEmailAsync(string normalizedEmail, CancellationToken cancellationToken) + { + return _userRepository.Get(new UserQueryOptions { IncludeTokens = true }).FirstOrDefaultAsync(x => x.NormalizedEmail == normalizedEmail); + } - public Task FindByIdAsync(string userId, CancellationToken cancellationToken) - { - return _userRepository.Get(new UserQueryOptions { IncludeTokens = true }).FirstOrDefaultAsync(x => x.Id == Guid.Parse(userId)); - } + public Task FindByIdAsync(string userId, CancellationToken cancellationToken) + { + return _userRepository.Get(new UserQueryOptions { IncludeTokens = true }).FirstOrDefaultAsync(x => x.Id == Guid.Parse(userId)); + } - public Task FindByNameAsync(string normalizedUserName, CancellationToken cancellationToken) - { - return _userRepository.Get(new UserQueryOptions { IncludeTokens = true }).FirstOrDefaultAsync(x => x.NormalizedUserName == normalizedUserName); - } + public Task FindByNameAsync(string normalizedUserName, CancellationToken cancellationToken) + { + return _userRepository.Get(new UserQueryOptions { IncludeTokens = true }).FirstOrDefaultAsync(x => x.NormalizedUserName == normalizedUserName); + } - public Task GetAccessFailedCountAsync(User user, CancellationToken cancellationToken) - { - return Task.FromResult(user.AccessFailedCount); - } + public Task GetAccessFailedCountAsync(User user, CancellationToken cancellationToken) + { + return Task.FromResult(user.AccessFailedCount); + } - public Task GetEmailAsync(User user, CancellationToken cancellationToken) - { - return Task.FromResult(user.Email); - } + public Task GetEmailAsync(User user, CancellationToken cancellationToken) + { + return Task.FromResult(user.Email); + } - public Task GetEmailConfirmedAsync(User user, CancellationToken cancellationToken) - { - return Task.FromResult(user.EmailConfirmed); - } + public Task GetEmailConfirmedAsync(User user, CancellationToken cancellationToken) + { + return Task.FromResult(user.EmailConfirmed); + } - public Task GetLockoutEnabledAsync(User user, CancellationToken cancellationToken) - { - return Task.FromResult(user.LockoutEnabled); - } + public Task GetLockoutEnabledAsync(User user, CancellationToken cancellationToken) + { + return Task.FromResult(user.LockoutEnabled); + } - public Task GetLockoutEndDateAsync(User user, CancellationToken cancellationToken) - { - return Task.FromResult(user.LockoutEnd); - } + public Task GetLockoutEndDateAsync(User user, CancellationToken cancellationToken) + { + return Task.FromResult(user.LockoutEnd); + } - public Task GetNormalizedEmailAsync(User user, CancellationToken cancellationToken) - { - return Task.FromResult(user.NormalizedEmail); - } + public Task GetNormalizedEmailAsync(User user, CancellationToken cancellationToken) + { + return Task.FromResult(user.NormalizedEmail); + } - public Task GetNormalizedUserNameAsync(User user, CancellationToken cancellationToken) - { - return Task.FromResult(user.NormalizedUserName); - } + public Task GetNormalizedUserNameAsync(User user, CancellationToken cancellationToken) + { + return Task.FromResult(user.NormalizedUserName); + } - public Task GetPasswordHashAsync(User user, CancellationToken cancellationToken) - { - return Task.FromResult(user.PasswordHash); - } + public Task GetPasswordHashAsync(User user, CancellationToken cancellationToken) + { + return Task.FromResult(user.PasswordHash); + } - public Task GetPhoneNumberAsync(User user, CancellationToken cancellationToken) - { - return Task.FromResult(user.PhoneNumber); - } + public Task GetPhoneNumberAsync(User user, CancellationToken cancellationToken) + { + return Task.FromResult(user.PhoneNumber); + } - public Task GetPhoneNumberConfirmedAsync(User user, CancellationToken cancellationToken) - { - return Task.FromResult(user.PhoneNumberConfirmed); - } + public Task GetPhoneNumberConfirmedAsync(User user, CancellationToken cancellationToken) + { + return Task.FromResult(user.PhoneNumberConfirmed); + } - public Task GetSecurityStampAsync(User user, CancellationToken cancellationToken) - { - return Task.FromResult(user.SecurityStamp ?? string.Empty); - } + public Task GetSecurityStampAsync(User user, CancellationToken cancellationToken) + { + return Task.FromResult(user.SecurityStamp ?? string.Empty); + } - public Task GetTwoFactorEnabledAsync(User user, CancellationToken cancellationToken) - { - return Task.FromResult(user.TwoFactorEnabled); - } + public Task GetTwoFactorEnabledAsync(User user, CancellationToken cancellationToken) + { + return Task.FromResult(user.TwoFactorEnabled); + } - public Task GetUserIdAsync(User user, CancellationToken cancellationToken) - { - return Task.FromResult(user.Id.ToString()); - } + public Task GetUserIdAsync(User user, CancellationToken cancellationToken) + { + return Task.FromResult(user.Id.ToString()); + } - public Task GetUserNameAsync(User user, CancellationToken cancellationToken) - { - return Task.FromResult(user.UserName); - } + public Task GetUserNameAsync(User user, CancellationToken cancellationToken) + { + return Task.FromResult(user.UserName); + } - public Task HasPasswordAsync(User user, CancellationToken cancellationToken) - { - return Task.FromResult(user.PasswordHash != null); - } + public Task HasPasswordAsync(User user, CancellationToken cancellationToken) + { + return Task.FromResult(user.PasswordHash != null); + } - public Task IncrementAccessFailedCountAsync(User user, CancellationToken cancellationToken) - { - user.AccessFailedCount++; - return Task.FromResult(user.AccessFailedCount); - } + public Task IncrementAccessFailedCountAsync(User user, CancellationToken cancellationToken) + { + user.AccessFailedCount++; + return Task.FromResult(user.AccessFailedCount); + } - public Task ResetAccessFailedCountAsync(User user, CancellationToken cancellationToken) - { - user.AccessFailedCount = 0; - return Task.CompletedTask; - } + public Task ResetAccessFailedCountAsync(User user, CancellationToken cancellationToken) + { + user.AccessFailedCount = 0; + return Task.CompletedTask; + } - public Task SetEmailAsync(User user, string email, CancellationToken cancellationToken) - { - user.Email = email; - return Task.CompletedTask; - } + public Task SetEmailAsync(User user, string email, CancellationToken cancellationToken) + { + user.Email = email; + return Task.CompletedTask; + } - public Task SetEmailConfirmedAsync(User user, bool confirmed, CancellationToken cancellationToken) - { - user.EmailConfirmed = confirmed; - return Task.CompletedTask; - } + public Task SetEmailConfirmedAsync(User user, bool confirmed, CancellationToken cancellationToken) + { + user.EmailConfirmed = confirmed; + return Task.CompletedTask; + } - public Task SetLockoutEnabledAsync(User user, bool enabled, CancellationToken cancellationToken) - { - user.LockoutEnabled = enabled; - return Task.CompletedTask; - } + public Task SetLockoutEnabledAsync(User user, bool enabled, CancellationToken cancellationToken) + { + user.LockoutEnabled = enabled; + return Task.CompletedTask; + } - public Task SetLockoutEndDateAsync(User user, DateTimeOffset? lockoutEnd, CancellationToken cancellationToken) - { - user.LockoutEnd = lockoutEnd; - return Task.CompletedTask; - } + public Task SetLockoutEndDateAsync(User user, DateTimeOffset? lockoutEnd, CancellationToken cancellationToken) + { + user.LockoutEnd = lockoutEnd; + return Task.CompletedTask; + } - public Task SetNormalizedEmailAsync(User user, string normalizedEmail, CancellationToken cancellationToken) - { - user.NormalizedEmail = normalizedEmail; - return Task.CompletedTask; - } + public Task SetNormalizedEmailAsync(User user, string normalizedEmail, CancellationToken cancellationToken) + { + user.NormalizedEmail = normalizedEmail; + return Task.CompletedTask; + } - public Task SetNormalizedUserNameAsync(User user, string normalizedName, CancellationToken cancellationToken) - { - user.NormalizedUserName = normalizedName; - return Task.CompletedTask; - } + public Task SetNormalizedUserNameAsync(User user, string normalizedName, CancellationToken cancellationToken) + { + user.NormalizedUserName = normalizedName; + return Task.CompletedTask; + } - public Task SetPasswordHashAsync(User user, string passwordHash, CancellationToken cancellationToken) - { - user.PasswordHash = passwordHash; - return Task.CompletedTask; - } + public Task SetPasswordHashAsync(User user, string passwordHash, CancellationToken cancellationToken) + { + user.PasswordHash = passwordHash; + return Task.CompletedTask; + } - public Task SetPhoneNumberAsync(User user, string phoneNumber, CancellationToken cancellationToken) - { - user.PhoneNumber = phoneNumber; - return Task.CompletedTask; - } + public Task SetPhoneNumberAsync(User user, string phoneNumber, CancellationToken cancellationToken) + { + user.PhoneNumber = phoneNumber; + return Task.CompletedTask; + } - public Task SetPhoneNumberConfirmedAsync(User user, bool confirmed, CancellationToken cancellationToken) - { - user.PhoneNumberConfirmed = confirmed; - return Task.CompletedTask; - } + public Task SetPhoneNumberConfirmedAsync(User user, bool confirmed, CancellationToken cancellationToken) + { + user.PhoneNumberConfirmed = confirmed; + return Task.CompletedTask; + } - public Task SetSecurityStampAsync(User user, string stamp, CancellationToken cancellationToken) - { - user.SecurityStamp = stamp; - return Task.CompletedTask; - } + public Task SetSecurityStampAsync(User user, string stamp, CancellationToken cancellationToken) + { + user.SecurityStamp = stamp; + return Task.CompletedTask; + } - public Task SetTwoFactorEnabledAsync(User user, bool enabled, CancellationToken cancellationToken) - { - user.TwoFactorEnabled = enabled; - return Task.CompletedTask; - } + public Task SetTwoFactorEnabledAsync(User user, bool enabled, CancellationToken cancellationToken) + { + user.TwoFactorEnabled = enabled; + return Task.CompletedTask; + } - public Task SetUserNameAsync(User user, string userName, CancellationToken cancellationToken) - { - user.UserName = userName; - return Task.CompletedTask; - } + public Task SetUserNameAsync(User user, string userName, CancellationToken cancellationToken) + { + user.UserName = userName; + return Task.CompletedTask; + } - public async Task UpdateAsync(User user, CancellationToken cancellationToken) - { - await _userRepository.AddOrUpdateAsync(user); - await _unitOfWork.SaveChangesAsync(); - return IdentityResult.Success; - } + public async Task UpdateAsync(User user, CancellationToken cancellationToken) + { + await _userRepository.AddOrUpdateAsync(user); + await _unitOfWork.SaveChangesAsync(); + return IdentityResult.Success; + } - private const string AuthenticatorStoreLoginProvider = "[AuthenticatorStore]"; - private const string AuthenticatorKeyTokenName = "AuthenticatorKey"; - private const string RecoveryCodeTokenName = "RecoveryCodes"; + private const string AuthenticatorStoreLoginProvider = "[AuthenticatorStore]"; + private const string AuthenticatorKeyTokenName = "AuthenticatorKey"; + private const string RecoveryCodeTokenName = "RecoveryCodes"; - public Task GetTokenAsync(User user, string loginProvider, string name, CancellationToken cancellationToken) - { - var tokenEntity = user.Tokens.SingleOrDefault( - l => l.TokenName == name && l.LoginProvider == loginProvider); - return Task.FromResult(tokenEntity?.TokenValue); - } + public Task GetTokenAsync(User user, string loginProvider, string name, CancellationToken cancellationToken) + { + var tokenEntity = user.Tokens.SingleOrDefault( + l => l.TokenName == name && l.LoginProvider == loginProvider); + return Task.FromResult(tokenEntity?.TokenValue); + } - public async Task SetTokenAsync(User user, string loginProvider, string name, string value, CancellationToken cancellationToken) + public async Task SetTokenAsync(User user, string loginProvider, string name, string value, CancellationToken cancellationToken) + { + var tokenEntity = user.Tokens.SingleOrDefault( + l => l.TokenName == name && l.LoginProvider == loginProvider); + if (tokenEntity != null) { - var tokenEntity = user.Tokens.SingleOrDefault( - l => l.TokenName == name && l.LoginProvider == loginProvider); - if (tokenEntity != null) - { - tokenEntity.TokenValue = value; - } - else - { - user.Tokens.Add(new UserToken - { - UserId = user.Id, - LoginProvider = loginProvider, - TokenName = name, - TokenValue = value, - }); - } - - await _unitOfWork.SaveChangesAsync(); + tokenEntity.TokenValue = value; } - - public async Task RemoveTokenAsync(User user, string loginProvider, string name, CancellationToken cancellationToken) + else { - var tokenEntity = user.Tokens.SingleOrDefault( - l => l.TokenName == name && l.LoginProvider == loginProvider); - if (tokenEntity != null) + user.Tokens.Add(new UserToken { - user.Tokens.Remove(tokenEntity); - await _unitOfWork.SaveChangesAsync(); - } + UserId = user.Id, + LoginProvider = loginProvider, + TokenName = name, + TokenValue = value, + }); } - public Task SetAuthenticatorKeyAsync(User user, string key, CancellationToken cancellationToken) - { - return SetTokenAsync(user, AuthenticatorStoreLoginProvider, AuthenticatorKeyTokenName, key, cancellationToken); - } + await _unitOfWork.SaveChangesAsync(); + } - public Task GetAuthenticatorKeyAsync(User user, CancellationToken cancellationToken) + public async Task RemoveTokenAsync(User user, string loginProvider, string name, CancellationToken cancellationToken) + { + var tokenEntity = user.Tokens.SingleOrDefault( + l => l.TokenName == name && l.LoginProvider == loginProvider); + if (tokenEntity != null) { - return GetTokenAsync(user, AuthenticatorStoreLoginProvider, AuthenticatorKeyTokenName, cancellationToken); + user.Tokens.Remove(tokenEntity); + await _unitOfWork.SaveChangesAsync(); } + } - public Task ReplaceCodesAsync(User user, IEnumerable recoveryCodes, CancellationToken cancellationToken) - { - var mergedCodes = string.Join(";", recoveryCodes); - return SetTokenAsync(user, AuthenticatorStoreLoginProvider, RecoveryCodeTokenName, mergedCodes, cancellationToken); - } + public Task SetAuthenticatorKeyAsync(User user, string key, CancellationToken cancellationToken) + { + return SetTokenAsync(user, AuthenticatorStoreLoginProvider, AuthenticatorKeyTokenName, key, cancellationToken); + } - public async Task RedeemCodeAsync(User user, string code, CancellationToken cancellationToken) - { - var mergedCodes = await GetTokenAsync(user, AuthenticatorStoreLoginProvider, RecoveryCodeTokenName, cancellationToken) ?? string.Empty; - var splitCodes = mergedCodes.Split(';'); - if (splitCodes.Contains(code)) - { - var updatedCodes = new List(splitCodes.Where(s => s != code)); - await ReplaceCodesAsync(user, updatedCodes, cancellationToken); - return true; - } + public Task GetAuthenticatorKeyAsync(User user, CancellationToken cancellationToken) + { + return GetTokenAsync(user, AuthenticatorStoreLoginProvider, AuthenticatorKeyTokenName, cancellationToken); + } - return false; - } + public Task ReplaceCodesAsync(User user, IEnumerable recoveryCodes, CancellationToken cancellationToken) + { + var mergedCodes = string.Join(";", recoveryCodes); + return SetTokenAsync(user, AuthenticatorStoreLoginProvider, RecoveryCodeTokenName, mergedCodes, cancellationToken); + } - public async Task CountCodesAsync(User user, CancellationToken cancellationToken) + public async Task RedeemCodeAsync(User user, string code, CancellationToken cancellationToken) + { + var mergedCodes = await GetTokenAsync(user, AuthenticatorStoreLoginProvider, RecoveryCodeTokenName, cancellationToken) ?? string.Empty; + var splitCodes = mergedCodes.Split(';'); + if (splitCodes.Contains(code)) { - var mergedCodes = await GetTokenAsync(user, AuthenticatorStoreLoginProvider, RecoveryCodeTokenName, cancellationToken) ?? string.Empty; - if (mergedCodes.Length > 0) - { - return mergedCodes.Split(';').Length; - } + var updatedCodes = new List(splitCodes.Where(s => s != code)); + await ReplaceCodesAsync(user, updatedCodes, cancellationToken); + return true; + } - return 0; + return false; + } + + public async Task CountCodesAsync(User user, CancellationToken cancellationToken) + { + var mergedCodes = await GetTokenAsync(user, AuthenticatorStoreLoginProvider, RecoveryCodeTokenName, cancellationToken) ?? string.Empty; + if (mergedCodes.Length > 0) + { + return mergedCodes.Split(';').Length; } + + return 0; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Identity/WeakPasswordValidator.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Identity/WeakPasswordValidator.cs index 586fc5718..8053261f8 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Identity/WeakPasswordValidator.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Identity/WeakPasswordValidator.cs @@ -3,23 +3,22 @@ using System; using System.Threading.Tasks; -namespace ClassifiedAds.Infrastructure.Identity +namespace ClassifiedAds.Infrastructure.Identity; + +public class WeakPasswordValidator : IPasswordValidator { - public class WeakPasswordValidator : IPasswordValidator + public Task ValidateAsync(UserManager manager, User user, string password) { - public Task ValidateAsync(UserManager manager, User user, string password) + if (password.Contains("testweakpassword")) { - if (password.Contains("testweakpassword")) + return Task.FromResult(IdentityResult.Failed(new IdentityError { - return Task.FromResult(IdentityResult.Failed(new IdentityError - { - Code = "WeakPassword", - Description = "WeakPasswordValidator testing.", - })); - } - - // TODO: check weak password, leaked password, password histories, etc. - return Task.FromResult(IdentityResult.Success); + Code = "WeakPassword", + Description = "WeakPasswordValidator testing.", + })); } + + // TODO: check weak password, leaked password, password histories, etc. + return Task.FromResult(IdentityResult.Success); } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Interceptors/ErrorCatchingInterceptor.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Interceptors/ErrorCatchingInterceptor.cs index 405f04fb7..4fc85b872 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Interceptors/ErrorCatchingInterceptor.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Interceptors/ErrorCatchingInterceptor.cs @@ -7,86 +7,85 @@ using System.Threading; using System.Threading.Tasks; -namespace ClassifiedAds.Infrastructure.Interceptors +namespace ClassifiedAds.Infrastructure.Interceptors; + +public class ErrorCatchingInterceptor : IInterceptor { - public class ErrorCatchingInterceptor : IInterceptor - { - private readonly ILogger _logger; + private readonly ILogger _logger; - public ErrorCatchingInterceptor(ILogger logger) - { - _logger = logger; - } + public ErrorCatchingInterceptor(ILogger logger) + { + _logger = logger; + } - public void Intercept(IInvocation invocation) + public void Intercept(IInvocation invocation) + { + try { - try + var returnType = invocation.Method.ReturnType; + if (returnType == typeof(Task)) { - var returnType = invocation.Method.ReturnType; - if (returnType == typeof(Task)) - { - invocation.Proceed(); - invocation.ReturnValue = InterceptResultAsync((dynamic)invocation.ReturnValue, invocation); - } - else if (returnType.IsGenericType && returnType.GetGenericTypeDefinition() == typeof(Task<>)) - { - invocation.Proceed(); - invocation.ReturnValue = InterceptResultAsync((dynamic)invocation.ReturnValue, invocation); - } - else - { - invocation.Proceed(); - } + invocation.Proceed(); + invocation.ReturnValue = InterceptResultAsync((dynamic)invocation.ReturnValue, invocation); } - catch (Exception ex) + else if (returnType.IsGenericType && returnType.GetGenericTypeDefinition() == typeof(Task<>)) { - LogException(invocation, ex); - throw; + invocation.Proceed(); + invocation.ReturnValue = InterceptResultAsync((dynamic)invocation.ReturnValue, invocation); } - } - - private async Task InterceptResultAsync(Task task, IInvocation invocation) - { - try - { - await task.ConfigureAwait(false); - } - catch (Exception ex) + else { - LogException(invocation, ex); - throw; + invocation.Proceed(); } } + catch (Exception ex) + { + LogException(invocation, ex); + throw; + } + } - private async Task InterceptResultAsync(Task task, IInvocation invocation) + private async Task InterceptResultAsync(Task task, IInvocation invocation) + { + try { - try - { - T result = await task.ConfigureAwait(false); - return result; - } - catch (Exception ex) - { - LogException(invocation, ex); - throw; - } + await task.ConfigureAwait(false); + } + catch (Exception ex) + { + LogException(invocation, ex); + throw; } + } - private void LogException(IInvocation invocation, Exception ex) + private async Task InterceptResultAsync(Task task, IInvocation invocation) + { + try + { + T result = await task.ConfigureAwait(false); + return result; + } + catch (Exception ex) { - var method = invocation.Method; - var className = method.DeclaringType.Name; - var methodName = method.Name; + LogException(invocation, ex); + throw; + } + } - // TODO: Ignore serialize large argument object. - var arguments = JsonSerializer.Serialize(invocation.Arguments.Where(x => x.GetType() != typeof(CancellationToken)), new JsonSerializerOptions() - { - WriteIndented = false, - DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull, - ReferenceHandler = ReferenceHandler.IgnoreCycles, - }); + private void LogException(IInvocation invocation, Exception ex) + { + var method = invocation.Method; + var className = method.DeclaringType.Name; + var methodName = method.Name; - _logger.LogError($"An unhandled exception has occurred while executing the method: {className}.{methodName} with ({arguments}). {Environment.NewLine}{ex}"); - } + // TODO: Ignore serialize large argument object. + var arguments = JsonSerializer.Serialize(invocation.Arguments.Where(x => x.GetType() != typeof(CancellationToken)), new JsonSerializerOptions() + { + WriteIndented = false, + DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull, + ReferenceHandler = ReferenceHandler.IgnoreCycles, + }); + + _logger.LogError($"An unhandled exception has occurred while executing the method: {className}.{methodName} with ({arguments}). {Environment.NewLine}{ex}"); } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Interceptors/InterceptorsOptions.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Interceptors/InterceptorsOptions.cs index 1e01bab51..b933e731c 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Interceptors/InterceptorsOptions.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Interceptors/InterceptorsOptions.cs @@ -1,28 +1,27 @@ using System; using System.Collections.Generic; -namespace ClassifiedAds.Infrastructure.Interceptors +namespace ClassifiedAds.Infrastructure.Interceptors; + +public class InterceptorsOptions { - public class InterceptorsOptions - { - public bool LoggingInterceptor { get; set; } + public bool LoggingInterceptor { get; set; } - public bool ErrorCatchingInterceptor { get; set; } + public bool ErrorCatchingInterceptor { get; set; } - public Type[] GetInterceptors() + public Type[] GetInterceptors() + { + var interceptors = new List(); + if (LoggingInterceptor) { - var interceptors = new List(); - if (LoggingInterceptor) - { - interceptors.Add(typeof(LoggingInterceptor)); - } - - if (ErrorCatchingInterceptor) - { - interceptors.Add(typeof(ErrorCatchingInterceptor)); - } + interceptors.Add(typeof(LoggingInterceptor)); + } - return interceptors.ToArray(); + if (ErrorCatchingInterceptor) + { + interceptors.Add(typeof(ErrorCatchingInterceptor)); } + + return interceptors.ToArray(); } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Interceptors/LoggingInterceptor.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Interceptors/LoggingInterceptor.cs index 22ef312c7..d7af933d7 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Interceptors/LoggingInterceptor.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Interceptors/LoggingInterceptor.cs @@ -7,78 +7,77 @@ using System.Threading; using System.Threading.Tasks; -namespace ClassifiedAds.Infrastructure.Interceptors +namespace ClassifiedAds.Infrastructure.Interceptors; + +public class LoggingInterceptor : IInterceptor { - public class LoggingInterceptor : IInterceptor + private readonly ILogger _logger; + + public LoggingInterceptor(ILogger logger) + { + _logger = logger; + } + + public void Intercept(IInvocation invocation) { - private readonly ILogger _logger; + var method = invocation.Method; + var className = method.DeclaringType.Name; + var methodName = method.Name; - public LoggingInterceptor(ILogger logger) + var arguments = JsonSerializer.Serialize(invocation.Arguments.Where(x => x.GetType() != typeof(CancellationToken)), new JsonSerializerOptions() { - _logger = logger; - } + WriteIndented = false, + DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull, + ReferenceHandler = ReferenceHandler.IgnoreCycles, + }); - public void Intercept(IInvocation invocation) + _logger.LogDebug($"Start calling method: {className}.{methodName} with ({arguments})."); + + var watch = new Stopwatch(); + watch.Start(); + + var returnType = invocation.Method.ReturnType; + if (returnType == typeof(Task)) { - var method = invocation.Method; - var className = method.DeclaringType.Name; - var methodName = method.Name; - - var arguments = JsonSerializer.Serialize(invocation.Arguments.Where(x => x.GetType() != typeof(CancellationToken)), new JsonSerializerOptions() - { - WriteIndented = false, - DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull, - ReferenceHandler = ReferenceHandler.IgnoreCycles, - }); - - _logger.LogDebug($"Start calling method: {className}.{methodName} with ({arguments})."); - - var watch = new Stopwatch(); - watch.Start(); - - var returnType = invocation.Method.ReturnType; - if (returnType == typeof(Task)) - { - invocation.Proceed(); - invocation.ReturnValue = InterceptResultAsync((dynamic)invocation.ReturnValue, watch, className, methodName); - } - else if (returnType.IsGenericType && returnType.GetGenericTypeDefinition() == typeof(Task<>)) - { - invocation.Proceed(); - invocation.ReturnValue = InterceptResultAsync((dynamic)invocation.ReturnValue, watch, className, methodName); - } - else - { - invocation.Proceed(); - InterceptResult(invocation.ReturnValue, watch, className, methodName); - } + invocation.Proceed(); + invocation.ReturnValue = InterceptResultAsync((dynamic)invocation.ReturnValue, watch, className, methodName); } - - private void InterceptResult(object returnValue, Stopwatch watch, string className, string methodName) + else if (returnType.IsGenericType && returnType.GetGenericTypeDefinition() == typeof(Task<>)) { - watch.Stop(); - - _logger.LogDebug($"Finished calling method: {className}.{methodName}. Took: {watch.ElapsedMilliseconds} milliseconds"); + invocation.Proceed(); + invocation.ReturnValue = InterceptResultAsync((dynamic)invocation.ReturnValue, watch, className, methodName); } - - private async Task InterceptResultAsync(Task task, Stopwatch watch, string className, string methodName) + else { - await task.ConfigureAwait(false); + invocation.Proceed(); + InterceptResult(invocation.ReturnValue, watch, className, methodName); + } + } - watch.Stop(); + private void InterceptResult(object returnValue, Stopwatch watch, string className, string methodName) + { + watch.Stop(); - _logger.LogDebug($"Finished calling method: {className}.{methodName}. Took: {watch.ElapsedMilliseconds} milliseconds"); - } + _logger.LogDebug($"Finished calling method: {className}.{methodName}. Took: {watch.ElapsedMilliseconds} milliseconds"); + } - private async Task InterceptResultAsync(Task task, Stopwatch watch, string className, string methodName) - { - T result = await task.ConfigureAwait(false); + private async Task InterceptResultAsync(Task task, Stopwatch watch, string className, string methodName) + { + await task.ConfigureAwait(false); - watch.Stop(); + watch.Stop(); - _logger.LogDebug($"Finished calling method: {className}.{methodName}. Took: {watch.ElapsedMilliseconds} milliseconds"); + _logger.LogDebug($"Finished calling method: {className}.{methodName}. Took: {watch.ElapsedMilliseconds} milliseconds"); + } - return result; - } + private async Task InterceptResultAsync(Task task, Stopwatch watch, string className, string methodName) + { + T result = await task.ConfigureAwait(false); + + watch.Stop(); + + _logger.LogDebug($"Finished calling method: {className}.{methodName}. Took: {watch.ElapsedMilliseconds} milliseconds"); + + return result; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Interceptors/ServiceCollectionServiceExtensions.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Interceptors/ServiceCollectionServiceExtensions.cs index 980128819..4b3f44ccf 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Interceptors/ServiceCollectionServiceExtensions.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Interceptors/ServiceCollectionServiceExtensions.cs @@ -3,45 +3,44 @@ using System; using System.Linq; -namespace Microsoft.Extensions.DependencyInjection +namespace Microsoft.Extensions.DependencyInjection; + +public static class ServiceCollectionServiceExtensions { - public static class ServiceCollectionServiceExtensions + public static IServiceCollection ConfigureInterceptors(this IServiceCollection services) + { + services.AddSingleton(new ProxyGenerator()); + services.AddTransient(); + services.AddTransient(); + return services; + } + + public static IServiceCollection AddInterceptors(this IServiceCollection services, Type serviceType, Type implementationType, ServiceLifetime serviceLifetime, Type[] interceptorTypes) { - public static IServiceCollection ConfigureInterceptors(this IServiceCollection services) + if (interceptorTypes == null || !interceptorTypes.Any()) { - services.AddSingleton(new ProxyGenerator()); - services.AddTransient(); - services.AddTransient(); return services; } - public static IServiceCollection AddInterceptors(this IServiceCollection services, Type serviceType, Type implementationType, ServiceLifetime serviceLifetime, Type[] interceptorTypes) - { - if (interceptorTypes == null || !interceptorTypes.Any()) - { - return services; - } - - services.Add(new ServiceDescriptor(implementationType, implementationType, serviceLifetime)); + services.Add(new ServiceDescriptor(implementationType, implementationType, serviceLifetime)); - var serviceDescriptor = new ServiceDescriptor(serviceType, provider => - { - var target = provider.GetService(implementationType); + var serviceDescriptor = new ServiceDescriptor(serviceType, provider => + { + var target = provider.GetService(implementationType); - var interceptors = interceptorTypes.Select(x => (IInterceptor)provider.GetService(x)).ToArray(); + var interceptors = interceptorTypes.Select(x => (IInterceptor)provider.GetService(x)).ToArray(); - var proxy = provider.GetService().CreateInterfaceProxyWithTarget(serviceType, target, interceptors); - return proxy; - }, serviceLifetime); + var proxy = provider.GetService().CreateInterfaceProxyWithTarget(serviceType, target, interceptors); + return proxy; + }, serviceLifetime); - services.Add(serviceDescriptor); + services.Add(serviceDescriptor); - return services; - } + return services; + } - public static IServiceCollection AddInterceptors(this IServiceCollection services, Type serviceType, Type implementationType, ServiceLifetime serviceLifetime, InterceptorsOptions interceptorsOptions) - { - return services.AddInterceptors(serviceType, implementationType, serviceLifetime, interceptorsOptions?.GetInterceptors()); - } + public static IServiceCollection AddInterceptors(this IServiceCollection services, Type serviceType, Type implementationType, ServiceLifetime serviceLifetime, InterceptorsOptions interceptorsOptions) + { + return services.AddInterceptors(serviceType, implementationType, serviceLifetime, interceptorsOptions?.GetInterceptors()); } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Localization/DefaultStringLocalizer.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Localization/DefaultStringLocalizer.cs index 25b0fa0d1..3e2b8df1b 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Localization/DefaultStringLocalizer.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Localization/DefaultStringLocalizer.cs @@ -2,30 +2,29 @@ using System; using System.Collections.Generic; -namespace ClassifiedAds.Infrastructure.Localization +namespace ClassifiedAds.Infrastructure.Localization; + +public class DefaultStringLocalizer : IStringLocalizer { - public class DefaultStringLocalizer : IStringLocalizer + public LocalizedString this[string name] { - public LocalizedString this[string name] + get { - get - { - return new LocalizedString(name, name); - } + return new LocalizedString(name, name); } + } - public LocalizedString this[string name, params object[] arguments] + public LocalizedString this[string name, params object[] arguments] + { + get { - get - { - var value = string.Format(name, arguments); - return new LocalizedString(name, value); - } + var value = string.Format(name, arguments); + return new LocalizedString(name, value); } + } - public IEnumerable GetAllStrings(bool includeParentCultures) - { - throw new NotImplementedException(); - } + public IEnumerable GetAllStrings(bool includeParentCultures) + { + throw new NotImplementedException(); } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Localization/LocalizationProviders.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Localization/LocalizationProviders.cs index dde7fead5..cfb19a726 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Localization/LocalizationProviders.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Localization/LocalizationProviders.cs @@ -1,7 +1,6 @@ -namespace ClassifiedAds.Infrastructure.Localization +namespace ClassifiedAds.Infrastructure.Localization; + +public class LocalizationProviders { - public class LocalizationProviders - { - public SqlServerOptions SqlServer { get; set; } - } + public SqlServerOptions SqlServer { get; set; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Localization/LocalizationServiceCollectionExtensions.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Localization/LocalizationServiceCollectionExtensions.cs index 4c20aef14..5d4cb61b1 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Localization/LocalizationServiceCollectionExtensions.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Localization/LocalizationServiceCollectionExtensions.cs @@ -4,52 +4,51 @@ using Microsoft.Extensions.Localization; using System.Globalization; -namespace ClassifiedAds.Infrastructure.Localization +namespace ClassifiedAds.Infrastructure.Localization; + +public static class LocalizationServiceCollectionExtensions { - public static class LocalizationServiceCollectionExtensions + public static IServiceCollection AddClassifiedAdsLocalization(this IServiceCollection services, LocalizationProviders providers = null) { - public static IServiceCollection AddClassifiedAdsLocalization(this IServiceCollection services, LocalizationProviders providers = null) + if (providers?.SqlServer?.IsEnabled ?? false) { - if (providers?.SqlServer?.IsEnabled ?? false) + services.Configure(op => { - services.Configure(op => - { - op.ConnectionString = providers.SqlServer.ConnectionString; - op.SqlQuery = providers.SqlServer.SqlQuery; - op.CacheMinutes = providers.SqlServer.CacheMinutes; - }); - - services.AddSingleton(); - services.AddScoped(provider => provider.GetRequiredService().Create(null)); - } - else + op.ConnectionString = providers.SqlServer.ConnectionString; + op.SqlQuery = providers.SqlServer.SqlQuery; + op.CacheMinutes = providers.SqlServer.CacheMinutes; + }); + + services.AddSingleton(); + services.AddScoped(provider => provider.GetRequiredService().Create(null)); + } + else + { + services.AddScoped(); + } + + services.AddLocalization(); + + services.Configure(options => + { + var supportedCultures = new[] { - services.AddScoped(); - } + new CultureInfo("en-US"), + new CultureInfo("vi-VN"), + }; - services.AddLocalization(); + options.DefaultRequestCulture = new RequestCulture(culture: "en-US", uiCulture: "en-US"); + options.SupportedCultures = supportedCultures; + options.SupportedUICultures = supportedCultures; - services.Configure(options => + options.AddInitialRequestCultureProvider(new CustomRequestCultureProvider(async context => { - var supportedCultures = new[] - { - new CultureInfo("en-US"), - new CultureInfo("vi-VN"), - }; - - options.DefaultRequestCulture = new RequestCulture(culture: "en-US", uiCulture: "en-US"); - options.SupportedCultures = supportedCultures; - options.SupportedUICultures = supportedCultures; - - options.AddInitialRequestCultureProvider(new CustomRequestCultureProvider(async context => - { - // My custom request culture logic - // return new ProviderCultureResult("vi-VN"); - return new ProviderCultureResult("en-US"); - })); - }); + // My custom request culture logic + // return new ProviderCultureResult("vi-VN"); + return new ProviderCultureResult("en-US"); + })); + }); - return services; - } + return services; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Localization/SqlServerOptions.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Localization/SqlServerOptions.cs index 874c653a1..b86459144 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Localization/SqlServerOptions.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Localization/SqlServerOptions.cs @@ -1,13 +1,12 @@ -namespace ClassifiedAds.Infrastructure.Localization +namespace ClassifiedAds.Infrastructure.Localization; + +public class SqlServerOptions { - public class SqlServerOptions - { - public bool IsEnabled { get; set; } + public bool IsEnabled { get; set; } - public string ConnectionString { get; set; } + public string ConnectionString { get; set; } - public string SqlQuery { get; set; } + public string SqlQuery { get; set; } - public int CacheMinutes { get; set; } - } + public int CacheMinutes { get; set; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Localization/SqlServerStringLocalizer.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Localization/SqlServerStringLocalizer.cs index c6f895026..e1e8a97ee 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Localization/SqlServerStringLocalizer.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Localization/SqlServerStringLocalizer.cs @@ -3,51 +3,50 @@ using System.Collections.Generic; using System.Globalization; -namespace ClassifiedAds.Infrastructure.Localization +namespace ClassifiedAds.Infrastructure.Localization; + +public class SqlServerStringLocalizer : IStringLocalizer { - public class SqlServerStringLocalizer : IStringLocalizer + private readonly Dictionary> _data; + + public SqlServerStringLocalizer(Dictionary> data) { - private readonly Dictionary> _data; + _data = data; + } - public SqlServerStringLocalizer(Dictionary> data) + public LocalizedString this[string name] + { + get { - _data = data; + var value = GetString(name); + return new LocalizedString(name, value); } + } - public LocalizedString this[string name] + public LocalizedString this[string name, params object[] arguments] + { + get { - get - { - var value = GetString(name); - return new LocalizedString(name, value); - } + var format = GetString(name); + var value = string.Format(format ?? name, arguments); + return new LocalizedString(name, value); } + } - public LocalizedString this[string name, params object[] arguments] - { - get - { - var format = GetString(name); - var value = string.Format(format ?? name, arguments); - return new LocalizedString(name, value); - } - } + public IEnumerable GetAllStrings(bool includeParentCultures) + { + throw new NotImplementedException(); + } - public IEnumerable GetAllStrings(bool includeParentCultures) - { - throw new NotImplementedException(); - } + private string GetString(string name) + { + var culture = CultureInfo.CurrentCulture.ToString(); - private string GetString(string name) + if (_data.ContainsKey(name) && _data[name].ContainsKey(culture)) { - var culture = CultureInfo.CurrentCulture.ToString(); - - if (_data.ContainsKey(name) && _data[name].ContainsKey(culture)) - { - return _data[name][culture]; - } - - return name; + return _data[name][culture]; } + + return name; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Localization/SqlServerStringLocalizerFactory.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Localization/SqlServerStringLocalizerFactory.cs index e615b7c0c..6e62a6f0a 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Localization/SqlServerStringLocalizerFactory.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Localization/SqlServerStringLocalizerFactory.cs @@ -7,56 +7,55 @@ using System.Collections.Generic; using System.Linq; -namespace ClassifiedAds.Infrastructure.Localization +namespace ClassifiedAds.Infrastructure.Localization; + +public class SqlServerStringLocalizerFactory : IStringLocalizerFactory { - public class SqlServerStringLocalizerFactory : IStringLocalizerFactory + private readonly SqlServerOptions _options; + private readonly IMemoryCache _memoryCache; + + public SqlServerStringLocalizerFactory(IOptions options, IMemoryCache memoryCache) { - private readonly SqlServerOptions _options; - private readonly IMemoryCache _memoryCache; + _options = options.Value; + _memoryCache = memoryCache; + } - public SqlServerStringLocalizerFactory(IOptions options, IMemoryCache memoryCache) - { - _options = options.Value; - _memoryCache = memoryCache; - } + public IStringLocalizer Create(Type resourceSource) + { + return new SqlServerStringLocalizer(LoadData()); + } - public IStringLocalizer Create(Type resourceSource) - { - return new SqlServerStringLocalizer(LoadData()); - } + public IStringLocalizer Create(string baseName, string location) + { + return new SqlServerStringLocalizer(LoadData()); + } - public IStringLocalizer Create(string baseName, string location) - { - return new SqlServerStringLocalizer(LoadData()); - } + private Dictionary> LoadData() + { + var data = _memoryCache.Get>>(typeof(SqlServerStringLocalizerFactory).FullName); - private Dictionary> LoadData() + if (data == null) { - var data = _memoryCache.Get>>(typeof(SqlServerStringLocalizerFactory).FullName); - - if (data == null) + using var conn = new SqlConnection(_options.ConnectionString); { - using var conn = new SqlConnection(_options.ConnectionString); - { - conn.Open(); - data = conn.Query(_options.SqlQuery) - .GroupBy(x => x.Name) - .ToDictionary(x => x.Key, x => x.ToDictionary(y => y.Culture, y => y.Value)); - } - - _memoryCache.Set(typeof(SqlServerStringLocalizerFactory).FullName, data, DateTimeOffset.Now.AddMinutes(_options.CacheMinutes)); + conn.Open(); + data = conn.Query(_options.SqlQuery) + .GroupBy(x => x.Name) + .ToDictionary(x => x.Key, x => x.ToDictionary(y => y.Culture, y => y.Value)); } - return data; + _memoryCache.Set(typeof(SqlServerStringLocalizerFactory).FullName, data, DateTimeOffset.Now.AddMinutes(_options.CacheMinutes)); } + + return data; } +} - public class LocalizationEntry - { - public string Name { get; set; } +public class LocalizationEntry +{ + public string Name { get; set; } - public string Value { get; set; } + public string Value { get; set; } - public string Culture { get; set; } - } + public string Culture { get; set; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Logging/ActivityEnricher.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Logging/ActivityEnricher.cs index 3fb3b9a47..cc2decab4 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Logging/ActivityEnricher.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Logging/ActivityEnricher.cs @@ -7,55 +7,54 @@ using Serilog.Events; using System.Diagnostics; -namespace ClassifiedAds.Infrastructure.Logging +namespace ClassifiedAds.Infrastructure.Logging; + +public class ActivityEnricher : ILogEventEnricher { - public class ActivityEnricher : ILogEventEnricher + public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory) { - public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory) - { - var activity = Activity.Current; + var activity = Activity.Current; - if (activity == null) - { - return; - } - - logEvent.AddPropertyIfAbsent(new LogEventProperty("SpanId", new ScalarValue(activity.GetSpanId()))); - logEvent.AddPropertyIfAbsent(new LogEventProperty("TraceId", new ScalarValue(activity.GetTraceId()))); - logEvent.AddPropertyIfAbsent(new LogEventProperty("ParentId", new ScalarValue(activity.GetParentId()))); + if (activity == null) + { + return; } + + logEvent.AddPropertyIfAbsent(new LogEventProperty("SpanId", new ScalarValue(activity.GetSpanId()))); + logEvent.AddPropertyIfAbsent(new LogEventProperty("TraceId", new ScalarValue(activity.GetTraceId()))); + logEvent.AddPropertyIfAbsent(new LogEventProperty("ParentId", new ScalarValue(activity.GetParentId()))); } +} - internal static class ActivityExtensions +internal static class ActivityExtensions +{ + public static string GetSpanId(this Activity activity) { - public static string GetSpanId(this Activity activity) + return activity.IdFormat switch { - return activity.IdFormat switch - { - ActivityIdFormat.Hierarchical => activity.Id, - ActivityIdFormat.W3C => activity.SpanId.ToHexString(), - _ => null, - } ?? string.Empty; - } + ActivityIdFormat.Hierarchical => activity.Id, + ActivityIdFormat.W3C => activity.SpanId.ToHexString(), + _ => null, + } ?? string.Empty; + } - public static string GetTraceId(this Activity activity) + public static string GetTraceId(this Activity activity) + { + return activity.IdFormat switch { - return activity.IdFormat switch - { - ActivityIdFormat.Hierarchical => activity.RootId, - ActivityIdFormat.W3C => activity.TraceId.ToHexString(), - _ => null, - } ?? string.Empty; - } + ActivityIdFormat.Hierarchical => activity.RootId, + ActivityIdFormat.W3C => activity.TraceId.ToHexString(), + _ => null, + } ?? string.Empty; + } - public static string GetParentId(this Activity activity) + public static string GetParentId(this Activity activity) + { + return activity.IdFormat switch { - return activity.IdFormat switch - { - ActivityIdFormat.Hierarchical => activity.ParentId, - ActivityIdFormat.W3C => activity.ParentSpanId.ToHexString(), - _ => null, - } ?? string.Empty; - } + ActivityIdFormat.Hierarchical => activity.ParentId, + ActivityIdFormat.W3C => activity.ParentSpanId.ToHexString(), + _ => null, + } ?? string.Empty; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Logging/ApplicationInsightsOptions.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Logging/ApplicationInsightsOptions.cs index 47f9524ea..ea2bf37aa 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Logging/ApplicationInsightsOptions.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Logging/ApplicationInsightsOptions.cs @@ -1,9 +1,8 @@ -namespace ClassifiedAds.Infrastructure.Logging +namespace ClassifiedAds.Infrastructure.Logging; + +public class ApplicationInsightsOptions { - public class ApplicationInsightsOptions - { - public bool IsEnabled { get; set; } + public bool IsEnabled { get; set; } - public string InstrumentationKey { get; set; } - } + public string InstrumentationKey { get; set; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Logging/EventLogOptions.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Logging/EventLogOptions.cs index b36f1d9ba..5e11b9008 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Logging/EventLogOptions.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Logging/EventLogOptions.cs @@ -1,11 +1,10 @@ -namespace ClassifiedAds.Infrastructure.Logging +namespace ClassifiedAds.Infrastructure.Logging; + +public class EventLogOptions { - public class EventLogOptions - { - public bool IsEnabled { get; set; } + public bool IsEnabled { get; set; } - public string LogName { get; set; } + public string LogName { get; set; } - public string SourceName { get; set; } - } + public string SourceName { get; set; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Logging/FileOptions.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Logging/FileOptions.cs index 4fa1eb91a..f279c8b44 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Logging/FileOptions.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Logging/FileOptions.cs @@ -1,9 +1,8 @@ using Serilog.Events; -namespace ClassifiedAds.Infrastructure.Logging +namespace ClassifiedAds.Infrastructure.Logging; + +public class FileOptions { - public class FileOptions - { - public LogEventLevel MinimumLogEventLevel { get; set; } - } + public LogEventLevel MinimumLogEventLevel { get; set; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Logging/LoggingExtensions.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Logging/LoggingExtensions.cs index eb127fc60..563a4b94f 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Logging/LoggingExtensions.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Logging/LoggingExtensions.cs @@ -11,208 +11,207 @@ using System.Linq; using System.Reflection; -namespace ClassifiedAds.Infrastructure.Logging +namespace ClassifiedAds.Infrastructure.Logging; + +public static class LoggingExtensions { - public static class LoggingExtensions + private static void UseClassifiedAdsLogger(this IWebHostEnvironment env, LoggingOptions options) { - private static void UseClassifiedAdsLogger(this IWebHostEnvironment env, LoggingOptions options) - { - var assemblyName = Assembly.GetEntryAssembly()?.GetName().Name; - - var logsPath = Path.Combine(env.ContentRootPath, "logs"); - Directory.CreateDirectory(logsPath); - var loggerConfiguration = new LoggerConfiguration(); - - loggerConfiguration = loggerConfiguration - .MinimumLevel.Debug() - .Enrich.FromLogContext() - .Enrich.With() - .Enrich.WithMachineName() - .Enrich.WithEnvironmentUserName() - .Enrich.WithProperty("Assembly", assemblyName) - .Enrich.WithProperty("Application", env.ApplicationName) - .Enrich.WithProperty("EnvironmentName", env.EnvironmentName) - .Enrich.WithProperty("ContentRootPath", env.ContentRootPath) - .Enrich.WithProperty("WebRootPath", env.WebRootPath) - .Enrich.WithExceptionDetails() - .Filter.ByIncludingOnly((logEvent) => + var assemblyName = Assembly.GetEntryAssembly()?.GetName().Name; + + var logsPath = Path.Combine(env.ContentRootPath, "logs"); + Directory.CreateDirectory(logsPath); + var loggerConfiguration = new LoggerConfiguration(); + + loggerConfiguration = loggerConfiguration + .MinimumLevel.Debug() + .Enrich.FromLogContext() + .Enrich.With() + .Enrich.WithMachineName() + .Enrich.WithEnvironmentUserName() + .Enrich.WithProperty("Assembly", assemblyName) + .Enrich.WithProperty("Application", env.ApplicationName) + .Enrich.WithProperty("EnvironmentName", env.EnvironmentName) + .Enrich.WithProperty("ContentRootPath", env.ContentRootPath) + .Enrich.WithProperty("WebRootPath", env.WebRootPath) + .Enrich.WithExceptionDetails() + .Filter.ByIncludingOnly((logEvent) => + { + if (logEvent.Level >= options.File.MinimumLogEventLevel) { - if (logEvent.Level >= options.File.MinimumLogEventLevel) - { - var sourceContext = logEvent.Properties.ContainsKey("SourceContext") - ? logEvent.Properties["SourceContext"].ToString() - : null; - - var logLevel = GetLogLevel(sourceContext, options); - - return logEvent.Level >= logLevel; - } - - return false; - }) - .WriteTo.File(Path.Combine(logsPath, "log.txt"), - fileSizeLimitBytes: 10 * 1024 * 1024, - rollOnFileSizeLimit: true, - shared: true, - flushToDiskInterval: TimeSpan.FromSeconds(1), - outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] [{SourceContext}] [TraceId: {TraceId}] {Message:lj}{NewLine}{Exception}", - restrictedToMinimumLevel: options.File.MinimumLogEventLevel); - - Log.Logger = loggerConfiguration.CreateLogger(); - } + var sourceContext = logEvent.Properties.ContainsKey("SourceContext") + ? logEvent.Properties["SourceContext"].ToString() + : null; - private static LoggingOptions SetDefault(LoggingOptions options) - { - options ??= new LoggingOptions - { - }; + var logLevel = GetLogLevel(sourceContext, options); - options.LogLevel ??= new Dictionary(); + return logEvent.Level >= logLevel; + } - if (!options.LogLevel.ContainsKey("Default")) - { - options.LogLevel["Default"] = "Warning"; - } + return false; + }) + .WriteTo.File(Path.Combine(logsPath, "log.txt"), + fileSizeLimitBytes: 10 * 1024 * 1024, + rollOnFileSizeLimit: true, + shared: true, + flushToDiskInterval: TimeSpan.FromSeconds(1), + outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] [{SourceContext}] [TraceId: {TraceId}] {Message:lj}{NewLine}{Exception}", + restrictedToMinimumLevel: options.File.MinimumLogEventLevel); + + Log.Logger = loggerConfiguration.CreateLogger(); + } - options.File ??= new FileOptions - { - MinimumLogEventLevel = Serilog.Events.LogEventLevel.Warning, - }; + private static LoggingOptions SetDefault(LoggingOptions options) + { + options ??= new LoggingOptions + { + }; - options.EventLog ??= new EventLogOptions - { - IsEnabled = false, - }; - return options; + options.LogLevel ??= new Dictionary(); + + if (!options.LogLevel.ContainsKey("Default")) + { + options.LogLevel["Default"] = "Warning"; } - private static Serilog.Events.LogEventLevel GetLogLevel(string context, LoggingOptions options) + options.File ??= new FileOptions { - context = context.Replace("\"", string.Empty); - string level = "Default"; - var matches = options.LogLevel.Keys.Where(k => context.StartsWith(k, StringComparison.OrdinalIgnoreCase)); + MinimumLogEventLevel = Serilog.Events.LogEventLevel.Warning, + }; - if (matches.Any()) - { - level = matches.Max(); - } + options.EventLog ??= new EventLogOptions + { + IsEnabled = false, + }; + return options; + } - return (Serilog.Events.LogEventLevel)Enum.Parse(typeof(Serilog.Events.LogEventLevel), options.LogLevel[level], true); + private static Serilog.Events.LogEventLevel GetLogLevel(string context, LoggingOptions options) + { + context = context.Replace("\"", string.Empty); + string level = "Default"; + var matches = options.LogLevel.Keys.Where(k => context.StartsWith(k, StringComparison.OrdinalIgnoreCase)); + + if (matches.Any()) + { + level = matches.Max(); } - public static IWebHostBuilder UseClassifiedAdsLogger(this IWebHostBuilder builder, Func logOptions) + return (Serilog.Events.LogEventLevel)Enum.Parse(typeof(Serilog.Events.LogEventLevel), options.LogLevel[level], true); + } + + public static IWebHostBuilder UseClassifiedAdsLogger(this IWebHostBuilder builder, Func logOptions) + { + builder.ConfigureLogging((context, logging) => { - builder.ConfigureLogging((context, logging) => + logging.Configure(options => { - logging.Configure(options => - { - // options.ActivityTrackingOptions = ActivityTrackingOptions.SpanId | ActivityTrackingOptions.TraceId | ActivityTrackingOptions.ParentId; - }); + // options.ActivityTrackingOptions = ActivityTrackingOptions.SpanId | ActivityTrackingOptions.TraceId | ActivityTrackingOptions.ParentId; + }); - logging.AddAzureWebAppDiagnostics(); + logging.AddAzureWebAppDiagnostics(); - logging.AddSerilog(); + logging.AddSerilog(); - LoggingOptions options = SetDefault(logOptions(context.Configuration)); + LoggingOptions options = SetDefault(logOptions(context.Configuration)); - if (options.EventLog != null && options.EventLog.IsEnabled) + if (options.EventLog != null && options.EventLog.IsEnabled) + { + logging.AddEventLog(new EventLogSettings { - logging.AddEventLog(new EventLogSettings - { - LogName = options.EventLog.LogName, - SourceName = options.EventLog.SourceName, - }); - } + LogName = options.EventLog.LogName, + SourceName = options.EventLog.SourceName, + }); + } - if (options?.ApplicationInsights?.IsEnabled ?? false) - { - logging.AddApplicationInsights(options.ApplicationInsights.InstrumentationKey); - } + if (options?.ApplicationInsights?.IsEnabled ?? false) + { + logging.AddApplicationInsights(options.ApplicationInsights.InstrumentationKey); + } - context.HostingEnvironment.UseClassifiedAdsLogger(options); - }); + context.HostingEnvironment.UseClassifiedAdsLogger(options); + }); - return builder; - } + return builder; + } - public static IHostBuilder UseClassifiedAdsLogger(this IHostBuilder builder, Func logOptions) + public static IHostBuilder UseClassifiedAdsLogger(this IHostBuilder builder, Func logOptions) + { + builder.ConfigureLogging((context, logging) => { - builder.ConfigureLogging((context, logging) => + logging.Configure(options => { - logging.Configure(options => - { - // options.ActivityTrackingOptions = ActivityTrackingOptions.SpanId | ActivityTrackingOptions.TraceId | ActivityTrackingOptions.ParentId; - }); + // options.ActivityTrackingOptions = ActivityTrackingOptions.SpanId | ActivityTrackingOptions.TraceId | ActivityTrackingOptions.ParentId; + }); - logging.AddAzureWebAppDiagnostics(); + logging.AddAzureWebAppDiagnostics(); - logging.AddSerilog(); + logging.AddSerilog(); - LoggingOptions options = SetDefault(logOptions(context.Configuration)); + LoggingOptions options = SetDefault(logOptions(context.Configuration)); - if (options.EventLog != null && options.EventLog.IsEnabled) + if (options.EventLog != null && options.EventLog.IsEnabled) + { + logging.AddEventLog(new EventLogSettings { - logging.AddEventLog(new EventLogSettings - { - LogName = options.EventLog.LogName, - SourceName = options.EventLog.SourceName, - }); - } + LogName = options.EventLog.LogName, + SourceName = options.EventLog.SourceName, + }); + } - if (options?.ApplicationInsights?.IsEnabled ?? false) - { - logging.AddApplicationInsights(options.ApplicationInsights.InstrumentationKey); - } + if (options?.ApplicationInsights?.IsEnabled ?? false) + { + logging.AddApplicationInsights(options.ApplicationInsights.InstrumentationKey); + } - context.HostingEnvironment.UseClassifiedAdsLogger(options); - }); + context.HostingEnvironment.UseClassifiedAdsLogger(options); + }); - return builder; - } + return builder; + } - private static void UseClassifiedAdsLogger(this IHostEnvironment env, LoggingOptions options) - { - var assemblyName = Assembly.GetEntryAssembly()?.GetName().Name; - - var logsPath = Path.Combine(env.ContentRootPath, "logs"); - Directory.CreateDirectory(logsPath); - var loggerConfiguration = new LoggerConfiguration(); - - loggerConfiguration = loggerConfiguration - .MinimumLevel.Debug() - .Enrich.FromLogContext() - .Enrich.With() - .Enrich.WithMachineName() - .Enrich.WithEnvironmentUserName() - .Enrich.WithProperty("Assembly", assemblyName) - .Enrich.WithProperty("Application", env.ApplicationName) - .Enrich.WithProperty("EnvironmentName", env.EnvironmentName) - .Enrich.WithProperty("ContentRootPath", env.ContentRootPath) - .Enrich.WithExceptionDetails() - .Filter.ByIncludingOnly((logEvent) => + private static void UseClassifiedAdsLogger(this IHostEnvironment env, LoggingOptions options) + { + var assemblyName = Assembly.GetEntryAssembly()?.GetName().Name; + + var logsPath = Path.Combine(env.ContentRootPath, "logs"); + Directory.CreateDirectory(logsPath); + var loggerConfiguration = new LoggerConfiguration(); + + loggerConfiguration = loggerConfiguration + .MinimumLevel.Debug() + .Enrich.FromLogContext() + .Enrich.With() + .Enrich.WithMachineName() + .Enrich.WithEnvironmentUserName() + .Enrich.WithProperty("Assembly", assemblyName) + .Enrich.WithProperty("Application", env.ApplicationName) + .Enrich.WithProperty("EnvironmentName", env.EnvironmentName) + .Enrich.WithProperty("ContentRootPath", env.ContentRootPath) + .Enrich.WithExceptionDetails() + .Filter.ByIncludingOnly((logEvent) => + { + if (logEvent.Level >= options.File.MinimumLogEventLevel) { - if (logEvent.Level >= options.File.MinimumLogEventLevel) - { - var sourceContext = logEvent.Properties.ContainsKey("SourceContext") - ? logEvent.Properties["SourceContext"].ToString() - : null; - - var logLevel = GetLogLevel(sourceContext, options); - - return logEvent.Level >= logLevel; - } - - return false; - }) - .WriteTo.File(Path.Combine(logsPath, "log.txt"), - fileSizeLimitBytes: 10 * 1024 * 1024, - rollOnFileSizeLimit: true, - shared: true, - flushToDiskInterval: TimeSpan.FromSeconds(1), - outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] [{SourceContext}] [TraceId: {TraceId}] {Message:lj}{NewLine}{Exception}", - restrictedToMinimumLevel: options.File.MinimumLogEventLevel); - - Log.Logger = loggerConfiguration.CreateLogger(); - } + var sourceContext = logEvent.Properties.ContainsKey("SourceContext") + ? logEvent.Properties["SourceContext"].ToString() + : null; + + var logLevel = GetLogLevel(sourceContext, options); + + return logEvent.Level >= logLevel; + } + + return false; + }) + .WriteTo.File(Path.Combine(logsPath, "log.txt"), + fileSizeLimitBytes: 10 * 1024 * 1024, + rollOnFileSizeLimit: true, + shared: true, + flushToDiskInterval: TimeSpan.FromSeconds(1), + outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] [{SourceContext}] [TraceId: {TraceId}] {Message:lj}{NewLine}{Exception}", + restrictedToMinimumLevel: options.File.MinimumLogEventLevel); + + Log.Logger = loggerConfiguration.CreateLogger(); } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Logging/LoggingOptions.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Logging/LoggingOptions.cs index e5e8ae23d..7ba3d7e22 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Logging/LoggingOptions.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Logging/LoggingOptions.cs @@ -1,15 +1,14 @@ using System.Collections.Generic; -namespace ClassifiedAds.Infrastructure.Logging +namespace ClassifiedAds.Infrastructure.Logging; + +public class LoggingOptions { - public class LoggingOptions - { - public Dictionary LogLevel { get; set; } + public Dictionary LogLevel { get; set; } - public FileOptions File { get; set; } + public FileOptions File { get; set; } - public EventLogOptions EventLog { get; set; } + public EventLogOptions EventLog { get; set; } - public ApplicationInsightsOptions ApplicationInsights { get; set; } - } + public ApplicationInsightsOptions ApplicationInsights { get; set; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Monitoring/AzureApplicationInsights/AzureApplicationInsightsOptions.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Monitoring/AzureApplicationInsights/AzureApplicationInsightsOptions.cs index 8a1ae1702..a19471f61 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Monitoring/AzureApplicationInsights/AzureApplicationInsightsOptions.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Monitoring/AzureApplicationInsights/AzureApplicationInsightsOptions.cs @@ -1,11 +1,10 @@ -namespace ClassifiedAds.Infrastructure.Monitoring.AzureApplicationInsights +namespace ClassifiedAds.Infrastructure.Monitoring.AzureApplicationInsights; + +public class AzureApplicationInsightsOptions { - public class AzureApplicationInsightsOptions - { - public bool IsEnabled { get; set; } + public bool IsEnabled { get; set; } - public string InstrumentationKey { get; set; } + public string InstrumentationKey { get; set; } - public bool EnableSqlCommandTextInstrumentation { get; set; } - } + public bool EnableSqlCommandTextInstrumentation { get; set; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Monitoring/AzureApplicationInsights/AzureApplicationInsightsServiceCollectionExtensions.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Monitoring/AzureApplicationInsights/AzureApplicationInsightsServiceCollectionExtensions.cs index 3c9696dcd..6ab72a52f 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Monitoring/AzureApplicationInsights/AzureApplicationInsightsServiceCollectionExtensions.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Monitoring/AzureApplicationInsights/AzureApplicationInsightsServiceCollectionExtensions.cs @@ -2,29 +2,28 @@ using Microsoft.ApplicationInsights.Extensibility; using Microsoft.Extensions.DependencyInjection; -namespace ClassifiedAds.Infrastructure.Monitoring.AzureApplicationInsights +namespace ClassifiedAds.Infrastructure.Monitoring.AzureApplicationInsights; + +public static class AzureApplicationInsightsServiceCollectionExtensions { - public static class AzureApplicationInsightsServiceCollectionExtensions + public static IServiceCollection AddAzureApplicationInsights(this IServiceCollection services, AzureApplicationInsightsOptions azureApplicationInsightsOptions = null) { - public static IServiceCollection AddAzureApplicationInsights(this IServiceCollection services, AzureApplicationInsightsOptions azureApplicationInsightsOptions = null) + if (azureApplicationInsightsOptions?.IsEnabled ?? false) { - if (azureApplicationInsightsOptions?.IsEnabled ?? false) + services.AddApplicationInsightsTelemetry(opt => { - services.AddApplicationInsightsTelemetry(opt => - { - opt.InstrumentationKey = azureApplicationInsightsOptions.InstrumentationKey; - }); - - services.ConfigureTelemetryModule((module, o) => - { - module.EnableSqlCommandTextInstrumentation = azureApplicationInsightsOptions.EnableSqlCommandTextInstrumentation; - }); + opt.InstrumentationKey = azureApplicationInsightsOptions.InstrumentationKey; + }); - services.AddApplicationInsightsTelemetryProcessor(); - services.AddSingleton(); - } + services.ConfigureTelemetryModule((module, o) => + { + module.EnableSqlCommandTextInstrumentation = azureApplicationInsightsOptions.EnableSqlCommandTextInstrumentation; + }); - return services; + services.AddApplicationInsightsTelemetryProcessor(); + services.AddSingleton(); } + + return services; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Monitoring/AzureApplicationInsights/CustomTelemetryInitializer.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Monitoring/AzureApplicationInsights/CustomTelemetryInitializer.cs index 90ffc02f3..6fff851f7 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Monitoring/AzureApplicationInsights/CustomTelemetryInitializer.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Monitoring/AzureApplicationInsights/CustomTelemetryInitializer.cs @@ -2,27 +2,26 @@ using Microsoft.ApplicationInsights.DataContracts; using Microsoft.ApplicationInsights.Extensibility; -namespace ClassifiedAds.Infrastructure.Monitoring.AzureApplicationInsights +namespace ClassifiedAds.Infrastructure.Monitoring.AzureApplicationInsights; + +public class CustomTelemetryInitializer : ITelemetryInitializer { - public class CustomTelemetryInitializer : ITelemetryInitializer + public void Initialize(ITelemetry telemetry) { - public void Initialize(ITelemetry telemetry) + if (!(telemetry is RequestTelemetry requestTelemetry)) { - if (!(telemetry is RequestTelemetry requestTelemetry)) - { - return; - } + return; + } - if (int.TryParse(requestTelemetry.ResponseCode, out int code)) + if (int.TryParse(requestTelemetry.ResponseCode, out int code)) + { + if (code >= 400 && code < 500) { - if (code >= 400 && code < 500) - { - // If we set the Success property, the SDK won't change it: - requestTelemetry.Success = true; + // If we set the Success property, the SDK won't change it: + requestTelemetry.Success = true; - // Allow us to filter these requests in the portal: - requestTelemetry.Properties["Overridden400s"] = "true"; - } + // Allow us to filter these requests in the portal: + requestTelemetry.Properties["Overridden400s"] = "true"; } } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Monitoring/AzureApplicationInsights/CustomTelemetryProcessor.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Monitoring/AzureApplicationInsights/CustomTelemetryProcessor.cs index 6babba2e8..433d9d5e2 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Monitoring/AzureApplicationInsights/CustomTelemetryProcessor.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Monitoring/AzureApplicationInsights/CustomTelemetryProcessor.cs @@ -2,38 +2,37 @@ using Microsoft.ApplicationInsights.DataContracts; using Microsoft.ApplicationInsights.Extensibility; -namespace ClassifiedAds.Infrastructure.Monitoring.AzureApplicationInsights +namespace ClassifiedAds.Infrastructure.Monitoring.AzureApplicationInsights; + +public class CustomTelemetryProcessor : ITelemetryProcessor { - public class CustomTelemetryProcessor : ITelemetryProcessor + private ITelemetryProcessor Next { get; set; } + + public CustomTelemetryProcessor(ITelemetryProcessor next) { - private ITelemetryProcessor Next { get; set; } + Next = next; + } - public CustomTelemetryProcessor(ITelemetryProcessor next) + public void Process(ITelemetry item) + { + if (!OKtoSend(item)) { - Next = next; + return; } - public void Process(ITelemetry item) - { - if (!OKtoSend(item)) - { - return; - } + Next.Process(item); + } - Next.Process(item); + private bool OKtoSend(ITelemetry item) + { + if (item is RequestTelemetry request) + { } - private bool OKtoSend(ITelemetry item) + if (item is DependencyTelemetry dependency) { - if (item is RequestTelemetry request) - { - } - - if (item is DependencyTelemetry dependency) - { - } - - return true; } + + return true; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Monitoring/MiniProfiler/MiniProfilerOptions.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Monitoring/MiniProfiler/MiniProfilerOptions.cs index cf6f4995e..85e48fce1 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Monitoring/MiniProfiler/MiniProfilerOptions.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Monitoring/MiniProfiler/MiniProfilerOptions.cs @@ -1,20 +1,19 @@ -namespace ClassifiedAds.Infrastructure.Monitoring.MiniProfiler +namespace ClassifiedAds.Infrastructure.Monitoring.MiniProfiler; + +public class MiniProfilerOptions { - public class MiniProfilerOptions - { - public bool IsEnabled { get; set; } + public bool IsEnabled { get; set; } - public SqlServerStorageOptions SqlServerStorage { get; set; } + public SqlServerStorageOptions SqlServerStorage { get; set; } - public class SqlServerStorageOptions - { - public string ConectionString { get; set; } + public class SqlServerStorageOptions + { + public string ConectionString { get; set; } - public string ProfilersTable { get; set; } + public string ProfilersTable { get; set; } - public string TimingsTable { get; set; } + public string TimingsTable { get; set; } - public string ClientTimingsTable { get; set; } - } + public string ClientTimingsTable { get; set; } } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Monitoring/MiniProfiler/MiniProfilerServiceCollectionExtensions.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Monitoring/MiniProfiler/MiniProfilerServiceCollectionExtensions.cs index 7c05b9b0a..3b63fd56d 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Monitoring/MiniProfiler/MiniProfilerServiceCollectionExtensions.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Monitoring/MiniProfiler/MiniProfilerServiceCollectionExtensions.cs @@ -2,49 +2,48 @@ using StackExchange.Profiling.Storage; using System.Security.Claims; -namespace ClassifiedAds.Infrastructure.Monitoring.MiniProfiler +namespace ClassifiedAds.Infrastructure.Monitoring.MiniProfiler; + +public static class MiniProfilerServiceCollectionExtensions { - public static class MiniProfilerServiceCollectionExtensions + public static IServiceCollection AddMiniProfiler(this IServiceCollection services, MiniProfilerOptions miniProfilerOptions = null) { - public static IServiceCollection AddMiniProfiler(this IServiceCollection services, MiniProfilerOptions miniProfilerOptions = null) + if (miniProfilerOptions?.IsEnabled ?? false) { - if (miniProfilerOptions?.IsEnabled ?? false) + services.AddMiniProfiler(options => { - services.AddMiniProfiler(options => + options.UserIdProvider = (request) => { - options.UserIdProvider = (request) => - { - var id = request.HttpContext.User.FindFirst(ClaimTypes.NameIdentifier)?.Value - ?? request.HttpContext.User.FindFirst("sub")?.Value; - return id; - }; + var id = request.HttpContext.User.FindFirst(ClaimTypes.NameIdentifier)?.Value + ?? request.HttpContext.User.FindFirst("sub")?.Value; + return id; + }; - options.RouteBasePath = "/profiler"; // access /profiler/results to see last profile check - options.PopupRenderPosition = StackExchange.Profiling.RenderPosition.BottomLeft; - options.PopupShowTimeWithChildren = true; - if (!string.IsNullOrEmpty(miniProfilerOptions?.SqlServerStorage?.ConectionString)) - { - var storageOpt = miniProfilerOptions.SqlServerStorage; - var storage = new SqlServerStorage(storageOpt.ConectionString, storageOpt.ProfilersTable, storageOpt.TimingsTable, storageOpt.ClientTimingsTable); - _ = storage.TableCreationScripts; + options.RouteBasePath = "/profiler"; // access /profiler/results to see last profile check + options.PopupRenderPosition = StackExchange.Profiling.RenderPosition.BottomLeft; + options.PopupShowTimeWithChildren = true; + if (!string.IsNullOrEmpty(miniProfilerOptions?.SqlServerStorage?.ConectionString)) + { + var storageOpt = miniProfilerOptions.SqlServerStorage; + var storage = new SqlServerStorage(storageOpt.ConectionString, storageOpt.ProfilersTable, storageOpt.TimingsTable, storageOpt.ClientTimingsTable); + _ = storage.TableCreationScripts; - options.Storage = storage; - } + options.Storage = storage; + } - options.ShouldProfile = (request) => + options.ShouldProfile = (request) => + { + if (request.Path.StartsWithSegments("/healthcheck")) { - if (request.Path.StartsWithSegments("/healthcheck")) - { - return false; - } - - return true; - }; - }) - .AddEntityFramework(); - } + return false; + } - return services; + return true; + }; + }) + .AddEntityFramework(); } + + return services; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Monitoring/MonitoringExtensions.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Monitoring/MonitoringExtensions.cs index a1924df05..65dd9bacc 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Monitoring/MonitoringExtensions.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Monitoring/MonitoringExtensions.cs @@ -3,33 +3,32 @@ using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.DependencyInjection; -namespace ClassifiedAds.Infrastructure.Monitoring +namespace ClassifiedAds.Infrastructure.Monitoring; + +public static class MonitoringExtensions { - public static class MonitoringExtensions + public static IServiceCollection AddMonitoringServices(this IServiceCollection services, MonitoringOptions monitoringOptions = null) { - public static IServiceCollection AddMonitoringServices(this IServiceCollection services, MonitoringOptions monitoringOptions = null) + if (monitoringOptions?.MiniProfiler?.IsEnabled ?? false) { - if (monitoringOptions?.MiniProfiler?.IsEnabled ?? false) - { - services.AddMiniProfiler(monitoringOptions.MiniProfiler); - } - - if (monitoringOptions?.AzureApplicationInsights?.IsEnabled ?? false) - { - services.AddAzureApplicationInsights(monitoringOptions.AzureApplicationInsights); - } - - return services; + services.AddMiniProfiler(monitoringOptions.MiniProfiler); } - public static IApplicationBuilder UseMonitoringServices(this IApplicationBuilder builder, MonitoringOptions monitoringOptions) + if (monitoringOptions?.AzureApplicationInsights?.IsEnabled ?? false) { - if (monitoringOptions?.MiniProfiler?.IsEnabled ?? false) - { - builder.UseMiniProfiler(); - } + services.AddAzureApplicationInsights(monitoringOptions.AzureApplicationInsights); + } - return builder; + return services; + } + + public static IApplicationBuilder UseMonitoringServices(this IApplicationBuilder builder, MonitoringOptions monitoringOptions) + { + if (monitoringOptions?.MiniProfiler?.IsEnabled ?? false) + { + builder.UseMiniProfiler(); } + + return builder; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Monitoring/MonitoringOptions.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Monitoring/MonitoringOptions.cs index f5f9f47b2..2672e8e11 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Monitoring/MonitoringOptions.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Monitoring/MonitoringOptions.cs @@ -1,12 +1,11 @@ using ClassifiedAds.Infrastructure.Monitoring.AzureApplicationInsights; using ClassifiedAds.Infrastructure.Monitoring.MiniProfiler; -namespace ClassifiedAds.Infrastructure.Monitoring +namespace ClassifiedAds.Infrastructure.Monitoring; + +public class MonitoringOptions { - public class MonitoringOptions - { - public MiniProfilerOptions MiniProfiler { get; set; } + public MiniProfilerOptions MiniProfiler { get; set; } - public AzureApplicationInsightsOptions AzureApplicationInsights { get; set; } - } + public AzureApplicationInsightsOptions AzureApplicationInsights { get; set; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Notification/Email/EmailNotificationServiceCollectionExtensions.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Notification/Email/EmailNotificationServiceCollectionExtensions.cs index 594313341..6fec5233c 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Notification/Email/EmailNotificationServiceCollectionExtensions.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Notification/Email/EmailNotificationServiceCollectionExtensions.cs @@ -3,44 +3,43 @@ using ClassifiedAds.Infrastructure.Notification.Email.SendGrid; using ClassifiedAds.Infrastructure.Notification.Email.SmtpClient; -namespace Microsoft.Extensions.DependencyInjection +namespace Microsoft.Extensions.DependencyInjection; + +public static class EmailNotificationServiceCollectionExtensions { - public static class EmailNotificationServiceCollectionExtensions + public static IServiceCollection AddSmtpClientEmailNotification(this IServiceCollection services, SmtpClientOptions options) { - public static IServiceCollection AddSmtpClientEmailNotification(this IServiceCollection services, SmtpClientOptions options) - { - services.AddSingleton(new SmtpClientEmailNotification(options)); - return services; - } + services.AddSingleton(new SmtpClientEmailNotification(options)); + return services; + } - public static IServiceCollection AddFakeEmailNotification(this IServiceCollection services) + public static IServiceCollection AddFakeEmailNotification(this IServiceCollection services) + { + services.AddSingleton(new FakeEmailNotification()); + return services; + } + + public static IServiceCollection AddSendGridEmailNotification(this IServiceCollection services, SendGridOptions options) + { + services.AddSingleton(new SendGridEmailNotification(options)); + return services; + } + + public static IServiceCollection AddEmailNotification(this IServiceCollection services, EmailOptions options) + { + if (options.UsedFake()) { - services.AddSingleton(new FakeEmailNotification()); - return services; + services.AddFakeEmailNotification(); } - - public static IServiceCollection AddSendGridEmailNotification(this IServiceCollection services, SendGridOptions options) + else if (options.UsedSmtpClient()) { - services.AddSingleton(new SendGridEmailNotification(options)); - return services; + services.AddSmtpClientEmailNotification(options.SmtpClient); } - - public static IServiceCollection AddEmailNotification(this IServiceCollection services, EmailOptions options) + else if (options.UsedSendGrid()) { - if (options.UsedFake()) - { - services.AddFakeEmailNotification(); - } - else if (options.UsedSmtpClient()) - { - services.AddSmtpClientEmailNotification(options.SmtpClient); - } - else if (options.UsedSendGrid()) - { - services.AddSendGridEmailNotification(options.SendGrid); - } - - return services; + services.AddSendGridEmailNotification(options.SendGrid); } + + return services; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Notification/Email/EmailOptions.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Notification/Email/EmailOptions.cs index c24fda9c3..b9362fb3b 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Notification/Email/EmailOptions.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Notification/Email/EmailOptions.cs @@ -1,29 +1,28 @@ using ClassifiedAds.Infrastructure.Notification.Email.SendGrid; using ClassifiedAds.Infrastructure.Notification.Email.SmtpClient; -namespace ClassifiedAds.Infrastructure.Notification.Email +namespace ClassifiedAds.Infrastructure.Notification.Email; + +public class EmailOptions { - public class EmailOptions - { - public string Provider { get; set; } + public string Provider { get; set; } - public SmtpClientOptions SmtpClient { get; set; } + public SmtpClientOptions SmtpClient { get; set; } - public SendGridOptions SendGrid { get; set; } + public SendGridOptions SendGrid { get; set; } - public bool UsedFake() - { - return Provider == "Fake"; - } + public bool UsedFake() + { + return Provider == "Fake"; + } - public bool UsedSmtpClient() - { - return Provider == "SmtpClient"; - } + public bool UsedSmtpClient() + { + return Provider == "SmtpClient"; + } - public bool UsedSendGrid() - { - return Provider == "SendGrid"; - } + public bool UsedSendGrid() + { + return Provider == "SendGrid"; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Notification/Email/Fake/FakeEmailNotification.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Notification/Email/Fake/FakeEmailNotification.cs index ad2c0486d..d6987defa 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Notification/Email/Fake/FakeEmailNotification.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Notification/Email/Fake/FakeEmailNotification.cs @@ -2,13 +2,12 @@ using System.Threading; using System.Threading.Tasks; -namespace ClassifiedAds.Infrastructure.Notification.Email.SmtpClient +namespace ClassifiedAds.Infrastructure.Notification.Email.SmtpClient; + +public class FakeEmailNotification : IEmailNotification { - public class FakeEmailNotification : IEmailNotification + public Task SendAsync(IEmailMessage emailMessage, CancellationToken cancellationToken = default) { - public Task SendAsync(IEmailMessage emailMessage, CancellationToken cancellationToken = default) - { - return Task.CompletedTask; - } + return Task.CompletedTask; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Notification/Email/SendGrid/SendGridEmailNotification.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Notification/Email/SendGrid/SendGridEmailNotification.cs index 0d1aaff0d..a5958eb65 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Notification/Email/SendGrid/SendGridEmailNotification.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Notification/Email/SendGrid/SendGridEmailNotification.cs @@ -5,29 +5,28 @@ using System.Threading; using System.Threading.Tasks; -namespace ClassifiedAds.Infrastructure.Notification.Email.SendGrid +namespace ClassifiedAds.Infrastructure.Notification.Email.SendGrid; + +public class SendGridEmailNotification : IEmailNotification { - public class SendGridEmailNotification : IEmailNotification - { - private readonly SendGridOptions _options; + private readonly SendGridOptions _options; - public SendGridEmailNotification(SendGridOptions options) - { - _options = options; - } + public SendGridEmailNotification(SendGridOptions options) + { + _options = options; + } - public async Task SendAsync(IEmailMessage emailMessage, CancellationToken cancellationToken = default) - { - var client = new SendGridClient(_options.ApiKey); - var from = new EmailAddress(!string.IsNullOrWhiteSpace(_options.OverrideFrom) ? _options.OverrideFrom : emailMessage.From); + public async Task SendAsync(IEmailMessage emailMessage, CancellationToken cancellationToken = default) + { + var client = new SendGridClient(_options.ApiKey); + var from = new EmailAddress(!string.IsNullOrWhiteSpace(_options.OverrideFrom) ? _options.OverrideFrom : emailMessage.From); - var tos = (!string.IsNullOrWhiteSpace(_options.OverrideTos) ? _options.OverrideTos : emailMessage.Tos)?.Split(';') - .Where(x => !string.IsNullOrWhiteSpace(x)) - .Select(x => new EmailAddress(x)) - .ToList(); + var tos = (!string.IsNullOrWhiteSpace(_options.OverrideTos) ? _options.OverrideTos : emailMessage.Tos)?.Split(';') + .Where(x => !string.IsNullOrWhiteSpace(x)) + .Select(x => new EmailAddress(x)) + .ToList(); - var msg = MailHelper.CreateSingleEmailToMultipleRecipients(from, tos, emailMessage.Subject, string.Empty, emailMessage.Body, showAllRecipients: true); - var response = await client.SendEmailAsync(msg, cancellationToken); - } + var msg = MailHelper.CreateSingleEmailToMultipleRecipients(from, tos, emailMessage.Subject, string.Empty, emailMessage.Body, showAllRecipients: true); + var response = await client.SendEmailAsync(msg, cancellationToken); } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Notification/Email/SendGrid/SendGridOptions.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Notification/Email/SendGrid/SendGridOptions.cs index ded9c2e35..021cb0783 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Notification/Email/SendGrid/SendGridOptions.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Notification/Email/SendGrid/SendGridOptions.cs @@ -1,11 +1,10 @@ -namespace ClassifiedAds.Infrastructure.Notification.Email.SendGrid +namespace ClassifiedAds.Infrastructure.Notification.Email.SendGrid; + +public class SendGridOptions { - public class SendGridOptions - { - public string ApiKey { get; set; } + public string ApiKey { get; set; } - public string OverrideFrom { get; set; } + public string OverrideFrom { get; set; } - public string OverrideTos { get; set; } - } + public string OverrideTos { get; set; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Notification/Email/SmtpClient/SmtpClientEmailNotification.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Notification/Email/SmtpClient/SmtpClientEmailNotification.cs index 607697be1..ac249bb3f 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Notification/Email/SmtpClient/SmtpClientEmailNotification.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Notification/Email/SmtpClient/SmtpClientEmailNotification.cs @@ -4,62 +4,61 @@ using System.Threading; using System.Threading.Tasks; -namespace ClassifiedAds.Infrastructure.Notification.Email.SmtpClient -{ - public class SmtpClientEmailNotification : IEmailNotification - { - private readonly SmtpClientOptions _options; +namespace ClassifiedAds.Infrastructure.Notification.Email.SmtpClient; - public SmtpClientEmailNotification(SmtpClientOptions options) - { - _options = options; - } +public class SmtpClientEmailNotification : IEmailNotification +{ + private readonly SmtpClientOptions _options; - public async Task SendAsync(IEmailMessage emailMessage, CancellationToken cancellationToken = default) - { - var mail = new MailMessage(); + public SmtpClientEmailNotification(SmtpClientOptions options) + { + _options = options; + } - mail.From = new MailAddress(emailMessage.From); + public async Task SendAsync(IEmailMessage emailMessage, CancellationToken cancellationToken = default) + { + var mail = new MailMessage(); - emailMessage.Tos?.Split(';') - .Where(x => !string.IsNullOrWhiteSpace(x)) - .ToList() - .ForEach(x => mail.To.Add(x)); + mail.From = new MailAddress(emailMessage.From); - emailMessage.CCs?.Split(';') - .Where(x => !string.IsNullOrWhiteSpace(x)) - .ToList() - .ForEach(x => mail.CC.Add(x)); + emailMessage.Tos?.Split(';') + .Where(x => !string.IsNullOrWhiteSpace(x)) + .ToList() + .ForEach(x => mail.To.Add(x)); - emailMessage.BCCs?.Split(';') - .Where(x => !string.IsNullOrWhiteSpace(x)) - .ToList() - .ForEach(x => mail.Bcc.Add(x)); + emailMessage.CCs?.Split(';') + .Where(x => !string.IsNullOrWhiteSpace(x)) + .ToList() + .ForEach(x => mail.CC.Add(x)); - mail.Subject = emailMessage.Subject; + emailMessage.BCCs?.Split(';') + .Where(x => !string.IsNullOrWhiteSpace(x)) + .ToList() + .ForEach(x => mail.Bcc.Add(x)); - mail.Body = emailMessage.Body; + mail.Subject = emailMessage.Subject; - mail.IsBodyHtml = true; + mail.Body = emailMessage.Body; - var smtpClient = new System.Net.Mail.SmtpClient(_options.Host); + mail.IsBodyHtml = true; - if (_options.Port.HasValue) - { - smtpClient.Port = _options.Port.Value; - } + var smtpClient = new System.Net.Mail.SmtpClient(_options.Host); - if (!string.IsNullOrWhiteSpace(_options.UserName) && !string.IsNullOrWhiteSpace(_options.Password)) - { - smtpClient.Credentials = new System.Net.NetworkCredential(_options.UserName, _options.Password); - } + if (_options.Port.HasValue) + { + smtpClient.Port = _options.Port.Value; + } - if (_options.EnableSsl.HasValue) - { - smtpClient.EnableSsl = _options.EnableSsl.Value; - } + if (!string.IsNullOrWhiteSpace(_options.UserName) && !string.IsNullOrWhiteSpace(_options.Password)) + { + smtpClient.Credentials = new System.Net.NetworkCredential(_options.UserName, _options.Password); + } - await smtpClient.SendMailAsync(mail, cancellationToken); + if (_options.EnableSsl.HasValue) + { + smtpClient.EnableSsl = _options.EnableSsl.Value; } + + await smtpClient.SendMailAsync(mail, cancellationToken); } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Notification/Email/SmtpClient/SmtpClientOptions.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Notification/Email/SmtpClient/SmtpClientOptions.cs index e7484d8f3..41e448767 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Notification/Email/SmtpClient/SmtpClientOptions.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Notification/Email/SmtpClient/SmtpClientOptions.cs @@ -1,15 +1,14 @@ -namespace ClassifiedAds.Infrastructure.Notification.Email.SmtpClient +namespace ClassifiedAds.Infrastructure.Notification.Email.SmtpClient; + +public class SmtpClientOptions { - public class SmtpClientOptions - { - public string Host { get; set; } + public string Host { get; set; } - public int? Port { get; set; } + public int? Port { get; set; } - public string UserName { get; set; } + public string UserName { get; set; } - public string Password { get; set; } + public string Password { get; set; } - public bool? EnableSsl { get; set; } - } + public bool? EnableSsl { get; set; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Notification/NotificationOptions.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Notification/NotificationOptions.cs index dc66fcca6..2c8de44a6 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Notification/NotificationOptions.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Notification/NotificationOptions.cs @@ -2,14 +2,13 @@ using ClassifiedAds.Infrastructure.Notification.Sms; using ClassifiedAds.Infrastructure.Notification.Web; -namespace ClassifiedAds.Infrastructure.Notification +namespace ClassifiedAds.Infrastructure.Notification; + +public class NotificationOptions { - public class NotificationOptions - { - public EmailOptions Email { get; set; } + public EmailOptions Email { get; set; } - public SmsOptions Sms { get; set; } + public SmsOptions Sms { get; set; } - public WebOptions Web { get; set; } - } + public WebOptions Web { get; set; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Notification/NotificationServiceCollectionExtensions.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Notification/NotificationServiceCollectionExtensions.cs index 63c4fdf2e..9d8b657a3 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Notification/NotificationServiceCollectionExtensions.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Notification/NotificationServiceCollectionExtensions.cs @@ -1,16 +1,15 @@ using ClassifiedAds.Infrastructure.Notification; -namespace Microsoft.Extensions.DependencyInjection +namespace Microsoft.Extensions.DependencyInjection; + +public static class NotificationServiceCollectionExtensions { - public static class NotificationServiceCollectionExtensions + public static IServiceCollection AddNotificationServices(this IServiceCollection services, NotificationOptions options) { - public static IServiceCollection AddNotificationServices(this IServiceCollection services, NotificationOptions options) - { - services.AddEmailNotification(options.Email); + services.AddEmailNotification(options.Email); - services.AddSmsNotification(options.Sms); + services.AddSmsNotification(options.Sms); - return services; - } + return services; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Notification/Sms/Azure/AzureOptions.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Notification/Sms/Azure/AzureOptions.cs index 407f4bdb5..6a5ff89f6 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Notification/Sms/Azure/AzureOptions.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Notification/Sms/Azure/AzureOptions.cs @@ -1,8 +1,7 @@ -namespace ClassifiedAds.Infrastructure.Notification.Sms.Azure +namespace ClassifiedAds.Infrastructure.Notification.Sms.Azure; + +public class AzureOptions { - public class AzureOptions - { - public string ConnectionString { get; set; } - public string FromNumber { get; set; } - } + public string ConnectionString { get; set; } + public string FromNumber { get; set; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Notification/Sms/Azure/AzureSmsNotification.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Notification/Sms/Azure/AzureSmsNotification.cs index 79c7ec2f8..5cd0de3a0 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Notification/Sms/Azure/AzureSmsNotification.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Notification/Sms/Azure/AzureSmsNotification.cs @@ -3,29 +3,28 @@ using System.Threading; using System.Threading.Tasks; -namespace ClassifiedAds.Infrastructure.Notification.Sms.Azure +namespace ClassifiedAds.Infrastructure.Notification.Sms.Azure; + +public class AzureSmsNotification : ISmsNotification { - public class AzureSmsNotification : ISmsNotification + private readonly AzureOptions _options; + + public AzureSmsNotification(AzureOptions options) { - private readonly AzureOptions _options; + _options = options; + } - public AzureSmsNotification(AzureOptions options) - { - _options = options; - } + public async Task SendAsync(ISmsMessage smsMessage, CancellationToken cancellationToken = default) + { + var smsClient = new SmsClient(_options.ConnectionString); + var response = await smsClient.SendAsync( + from: _options.FromNumber, + to: smsMessage.PhoneNumber, + message: smsMessage.Message, + cancellationToken: cancellationToken); - public async Task SendAsync(ISmsMessage smsMessage, CancellationToken cancellationToken = default) + if (!string.IsNullOrWhiteSpace(response?.Value?.MessageId)) { - var smsClient = new SmsClient(_options.ConnectionString); - var response = await smsClient.SendAsync( - from: _options.FromNumber, - to: smsMessage.PhoneNumber, - message: smsMessage.Message, - cancellationToken: cancellationToken); - - if (!string.IsNullOrWhiteSpace(response?.Value?.MessageId)) - { - } } } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Notification/Sms/Fake/FakeSmsNotification.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Notification/Sms/Fake/FakeSmsNotification.cs index fa982b793..4bbc5fa52 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Notification/Sms/Fake/FakeSmsNotification.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Notification/Sms/Fake/FakeSmsNotification.cs @@ -2,13 +2,12 @@ using System.Threading; using System.Threading.Tasks; -namespace ClassifiedAds.Infrastructure.Notification.Sms.Fake +namespace ClassifiedAds.Infrastructure.Notification.Sms.Fake; + +public class FakeSmsNotification : ISmsNotification { - public class FakeSmsNotification : ISmsNotification + public Task SendAsync(ISmsMessage smsMessage, CancellationToken cancellationToken = default) { - public Task SendAsync(ISmsMessage smsMessage, CancellationToken cancellationToken = default) - { - return Task.CompletedTask; - } + return Task.CompletedTask; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Notification/Sms/SmsNotificationServiceCollectionExtensions.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Notification/Sms/SmsNotificationServiceCollectionExtensions.cs index 9b86df612..f266cc88d 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Notification/Sms/SmsNotificationServiceCollectionExtensions.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Notification/Sms/SmsNotificationServiceCollectionExtensions.cs @@ -4,44 +4,43 @@ using ClassifiedAds.Infrastructure.Notification.Sms.Fake; using ClassifiedAds.Infrastructure.Notification.Sms.Twilio; -namespace Microsoft.Extensions.DependencyInjection +namespace Microsoft.Extensions.DependencyInjection; + +public static class SmsNotificationServiceCollectionExtensions { - public static class SmsNotificationServiceCollectionExtensions + public static IServiceCollection AddTwilioSmsNotification(this IServiceCollection services, TwilioOptions options) { - public static IServiceCollection AddTwilioSmsNotification(this IServiceCollection services, TwilioOptions options) - { - services.AddSingleton(new TwilioSmsNotification(options)); - return services; - } + services.AddSingleton(new TwilioSmsNotification(options)); + return services; + } - public static IServiceCollection AddAzureSmsNotification(this IServiceCollection services, AzureOptions options) + public static IServiceCollection AddAzureSmsNotification(this IServiceCollection services, AzureOptions options) + { + services.AddSingleton(new AzureSmsNotification(options)); + return services; + } + + public static IServiceCollection AddFakeSmsNotification(this IServiceCollection services) + { + services.AddSingleton(new FakeSmsNotification()); + return services; + } + + public static IServiceCollection AddSmsNotification(this IServiceCollection services, SmsOptions options) + { + if (options.UsedFake()) { - services.AddSingleton(new AzureSmsNotification(options)); - return services; + services.AddFakeSmsNotification(); } - - public static IServiceCollection AddFakeSmsNotification(this IServiceCollection services) + else if (options.UsedTwilio()) { - services.AddSingleton(new FakeSmsNotification()); - return services; + services.AddTwilioSmsNotification(options.Twilio); } - - public static IServiceCollection AddSmsNotification(this IServiceCollection services, SmsOptions options) + else if (options.UsedAzure()) { - if (options.UsedFake()) - { - services.AddFakeSmsNotification(); - } - else if (options.UsedTwilio()) - { - services.AddTwilioSmsNotification(options.Twilio); - } - else if (options.UsedAzure()) - { - services.AddAzureSmsNotification(options.Azure); - } - - return services; + services.AddAzureSmsNotification(options.Azure); } + + return services; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Notification/Sms/SmsOptions.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Notification/Sms/SmsOptions.cs index db7cab1d2..7abdb05a0 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Notification/Sms/SmsOptions.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Notification/Sms/SmsOptions.cs @@ -1,29 +1,28 @@ using ClassifiedAds.Infrastructure.Notification.Sms.Azure; using ClassifiedAds.Infrastructure.Notification.Sms.Twilio; -namespace ClassifiedAds.Infrastructure.Notification.Sms +namespace ClassifiedAds.Infrastructure.Notification.Sms; + +public class SmsOptions { - public class SmsOptions - { - public string Provider { get; set; } + public string Provider { get; set; } - public TwilioOptions Twilio { get; set; } + public TwilioOptions Twilio { get; set; } - public AzureOptions Azure { get; set; } + public AzureOptions Azure { get; set; } - public bool UsedFake() - { - return Provider == "Fake"; - } + public bool UsedFake() + { + return Provider == "Fake"; + } - public bool UsedTwilio() - { - return Provider == "Twilio"; - } + public bool UsedTwilio() + { + return Provider == "Twilio"; + } - public bool UsedAzure() - { - return Provider == "Azure"; - } + public bool UsedAzure() + { + return Provider == "Azure"; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Notification/Sms/Twilio/TwilioOptions.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Notification/Sms/Twilio/TwilioOptions.cs index 74abf0de2..2a16f640e 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Notification/Sms/Twilio/TwilioOptions.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Notification/Sms/Twilio/TwilioOptions.cs @@ -1,11 +1,10 @@ -namespace ClassifiedAds.Infrastructure.Notification.Sms.Twilio +namespace ClassifiedAds.Infrastructure.Notification.Sms.Twilio; + +public class TwilioOptions { - public class TwilioOptions - { - public string AccountSId { get; set; } + public string AccountSId { get; set; } - public string AuthToken { get; set; } + public string AuthToken { get; set; } - public string FromNumber { get; set; } - } + public string FromNumber { get; set; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Notification/Sms/Twilio/TwilioSmsNotification.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Notification/Sms/Twilio/TwilioSmsNotification.cs index 9893beca8..dabaca91f 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Notification/Sms/Twilio/TwilioSmsNotification.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Notification/Sms/Twilio/TwilioSmsNotification.cs @@ -5,29 +5,28 @@ using Twilio.Rest.Api.V2010.Account; using Twilio.Types; -namespace ClassifiedAds.Infrastructure.Notification.Sms.Twilio +namespace ClassifiedAds.Infrastructure.Notification.Sms.Twilio; + +public class TwilioSmsNotification : ISmsNotification { - public class TwilioSmsNotification : ISmsNotification - { - private readonly TwilioOptions _options; + private readonly TwilioOptions _options; - public TwilioSmsNotification(TwilioOptions options) - { - _options = options; - } + public TwilioSmsNotification(TwilioOptions options) + { + _options = options; + } - public async Task SendAsync(ISmsMessage smsMessage, CancellationToken cancellationToken = default) - { - TwilioClient.Init(_options.AccountSId, _options.AuthToken); + public async Task SendAsync(ISmsMessage smsMessage, CancellationToken cancellationToken = default) + { + TwilioClient.Init(_options.AccountSId, _options.AuthToken); - var message = await MessageResource.CreateAsync( - body: smsMessage.Message, - from: new PhoneNumber(_options.FromNumber), - to: new PhoneNumber(smsMessage.PhoneNumber)); + var message = await MessageResource.CreateAsync( + body: smsMessage.Message, + from: new PhoneNumber(_options.FromNumber), + to: new PhoneNumber(smsMessage.PhoneNumber)); - if (!string.IsNullOrWhiteSpace(message.Sid)) - { - } + if (!string.IsNullOrWhiteSpace(message.Sid)) + { } } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Notification/Web/Fake/FakeWebNotification.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Notification/Web/Fake/FakeWebNotification.cs index 629065ba6..5ca77f598 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Notification/Web/Fake/FakeWebNotification.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Notification/Web/Fake/FakeWebNotification.cs @@ -2,13 +2,12 @@ using System.Threading; using System.Threading.Tasks; -namespace ClassifiedAds.Infrastructure.Notification.Web.Fake +namespace ClassifiedAds.Infrastructure.Notification.Web.Fake; + +public class FakeWebNotification : IWebNotification { - public class FakeWebNotification : IWebNotification + public Task SendAsync(T message, CancellationToken cancellationToken = default) { - public Task SendAsync(T message, CancellationToken cancellationToken = default) - { - return Task.CompletedTask; - } + return Task.CompletedTask; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Notification/Web/SignalR/SignalRNotification.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Notification/Web/SignalR/SignalRNotification.cs index 30e3da630..f6c7326a9 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Notification/Web/SignalR/SignalRNotification.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Notification/Web/SignalR/SignalRNotification.cs @@ -4,33 +4,32 @@ using System.Threading; using System.Threading.Tasks; -namespace ClassifiedAds.Infrastructure.Notification.Web.SignalR +namespace ClassifiedAds.Infrastructure.Notification.Web.SignalR; + +public class SignalRNotification : IWebNotification { - public class SignalRNotification : IWebNotification - { - private readonly HubConnection _connection; - private readonly string _endpoint; - private readonly string _eventName; + private readonly HubConnection _connection; + private readonly string _endpoint; + private readonly string _eventName; - public SignalRNotification(string endpoint, string hubName, string eventName) - { - _endpoint = endpoint + "/" + hubName; - _eventName = eventName; + public SignalRNotification(string endpoint, string hubName, string eventName) + { + _endpoint = endpoint + "/" + hubName; + _eventName = eventName; - _connection = new HubConnectionBuilder() - .WithUrl(_endpoint) - .AddMessagePackProtocol() - .Build(); - } + _connection = new HubConnectionBuilder() + .WithUrl(_endpoint) + .AddMessagePackProtocol() + .Build(); + } - public async Task SendAsync(T message, CancellationToken cancellationToken = default) + public async Task SendAsync(T message, CancellationToken cancellationToken = default) + { + if (_connection.State != HubConnectionState.Connected) { - if (_connection.State != HubConnectionState.Connected) - { - _connection.StartAsync(cancellationToken).GetAwaiter().GetResult(); - } - - await _connection.InvokeAsync(_eventName, message, cancellationToken); + _connection.StartAsync(cancellationToken).GetAwaiter().GetResult(); } + + await _connection.InvokeAsync(_eventName, message, cancellationToken); } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Notification/Web/SignalR/SignalROptions.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Notification/Web/SignalR/SignalROptions.cs index c062ee75c..a24bc0852 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Notification/Web/SignalR/SignalROptions.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Notification/Web/SignalR/SignalROptions.cs @@ -1,13 +1,12 @@ using System.Collections.Generic; -namespace ClassifiedAds.Infrastructure.Notification.Web.SignalR +namespace ClassifiedAds.Infrastructure.Notification.Web.SignalR; + +public class SignalROptions { - public class SignalROptions - { - public string Endpoint { get; set; } + public string Endpoint { get; set; } - public Dictionary Hubs { get; set; } + public Dictionary Hubs { get; set; } - public Dictionary MethodNames { get; set; } - } + public Dictionary MethodNames { get; set; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Notification/Web/WebNotificationServiceCollectionExtensions.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Notification/Web/WebNotificationServiceCollectionExtensions.cs index b772556f1..459157d95 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Notification/Web/WebNotificationServiceCollectionExtensions.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Notification/Web/WebNotificationServiceCollectionExtensions.cs @@ -3,34 +3,33 @@ using ClassifiedAds.Infrastructure.Notification.Web.Fake; using ClassifiedAds.Infrastructure.Notification.Web.SignalR; -namespace Microsoft.Extensions.DependencyInjection +namespace Microsoft.Extensions.DependencyInjection; + +public static class WebNotificationServiceCollectionExtensions { - public static class WebNotificationServiceCollectionExtensions + public static IServiceCollection AddSignalRWebNotification(this IServiceCollection services, SignalROptions options) { - public static IServiceCollection AddSignalRWebNotification(this IServiceCollection services, SignalROptions options) - { - services.AddSingleton>(new SignalRNotification(options.Endpoint, options.Hubs[typeof(T).Name], options.MethodNames[typeof(T).Name])); - return services; - } + services.AddSingleton>(new SignalRNotification(options.Endpoint, options.Hubs[typeof(T).Name], options.MethodNames[typeof(T).Name])); + return services; + } - public static IServiceCollection AddFakeWebNotification(this IServiceCollection services) + public static IServiceCollection AddFakeWebNotification(this IServiceCollection services) + { + services.AddSingleton>(new FakeWebNotification()); + return services; + } + + public static IServiceCollection AddWebNotification(this IServiceCollection services, WebOptions options) + { + if (options.UsedFake()) { - services.AddSingleton>(new FakeWebNotification()); - return services; + services.AddFakeWebNotification(); } - - public static IServiceCollection AddWebNotification(this IServiceCollection services, WebOptions options) + else if (options.UsedSignalR()) { - if (options.UsedFake()) - { - services.AddFakeWebNotification(); - } - else if (options.UsedSignalR()) - { - services.AddSignalRWebNotification(options.SignalR); - } - - return services; + services.AddSignalRWebNotification(options.SignalR); } + + return services; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Notification/Web/WebOptions.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Notification/Web/WebOptions.cs index 6798cebf0..ef24241fe 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Notification/Web/WebOptions.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Notification/Web/WebOptions.cs @@ -1,21 +1,20 @@ using ClassifiedAds.Infrastructure.Notification.Web.SignalR; -namespace ClassifiedAds.Infrastructure.Notification.Web +namespace ClassifiedAds.Infrastructure.Notification.Web; + +public class WebOptions { - public class WebOptions - { - public string Provider { get; set; } + public string Provider { get; set; } - public SignalROptions SignalR { get; set; } + public SignalROptions SignalR { get; set; } - public bool UsedFake() - { - return Provider == "Fake"; - } + public bool UsedFake() + { + return Provider == "Fake"; + } - public bool UsedSignalR() - { - return Provider == "SignalR"; - } + public bool UsedSignalR() + { + return Provider == "SignalR"; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Web/Authentication/TokenManager.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Web/Authentication/TokenManager.cs index a186e6af9..fb8724a2b 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Web/Authentication/TokenManager.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Web/Authentication/TokenManager.cs @@ -4,52 +4,51 @@ using System.Net.Http; using System.Threading.Tasks; -namespace ClassifiedAds.Infrastructure.Web.Authentication +namespace ClassifiedAds.Infrastructure.Web.Authentication; + +public class TokenManager { - public class TokenManager + private readonly IHttpClientFactory _httpClientFactory; + private readonly OpenIdConnectOptions _options; + + public TokenManager(IHttpClientFactory httpClientFactory, OpenIdConnectOptions options) { - private readonly IHttpClientFactory _httpClientFactory; - private readonly OpenIdConnectOptions _options; + _httpClientFactory = httpClientFactory; + _options = options; + } - public TokenManager(IHttpClientFactory httpClientFactory, OpenIdConnectOptions options) + public async Task RefreshToken(string refreshToken) + { + var httpClient = _httpClientFactory.CreateClient(); + var metaDataResponse = await httpClient.GetDiscoveryDocumentAsync(new DiscoveryDocumentRequest { - _httpClientFactory = httpClientFactory; - _options = options; - } + Address = _options.Authority, + Policy = { RequireHttps = _options.RequireHttpsMetadata }, + }); - public async Task RefreshToken(string refreshToken) + var response = await httpClient.RequestRefreshTokenAsync(new RefreshTokenRequest { - var httpClient = _httpClientFactory.CreateClient(); - var metaDataResponse = await httpClient.GetDiscoveryDocumentAsync(new DiscoveryDocumentRequest - { - Address = _options.Authority, - Policy = { RequireHttps = _options.RequireHttpsMetadata }, - }); + Address = metaDataResponse.TokenEndpoint, + ClientId = _options.ClientId, + ClientSecret = _options.ClientSecret, + RefreshToken = refreshToken, + }); - var response = await httpClient.RequestRefreshTokenAsync(new RefreshTokenRequest - { - Address = metaDataResponse.TokenEndpoint, - ClientId = _options.ClientId, - ClientSecret = _options.ClientSecret, - RefreshToken = refreshToken, - }); - - if (response.IsError) + if (response.IsError) + { + if (response.HttpStatusCode == System.Net.HttpStatusCode.BadRequest) { - if (response.HttpStatusCode == System.Net.HttpStatusCode.BadRequest) - { - return null; - } - - throw new Exception(response.Raw); + return null; } - return new TokenModel - { - AccessToken = response.AccessToken, - RefreshToken = response.RefreshToken, - ExpiresAt = DateTime.UtcNow + TimeSpan.FromSeconds(response.ExpiresIn), - }; + throw new Exception(response.Raw); } + + return new TokenModel + { + AccessToken = response.AccessToken, + RefreshToken = response.RefreshToken, + ExpiresAt = DateTime.UtcNow + TimeSpan.FromSeconds(response.ExpiresIn), + }; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Web/Authentication/TokenModel.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Web/Authentication/TokenModel.cs index c7982bfe0..67407aff8 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Web/Authentication/TokenModel.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Web/Authentication/TokenModel.cs @@ -1,21 +1,20 @@ using System; -namespace ClassifiedAds.Infrastructure.Web.Authentication +namespace ClassifiedAds.Infrastructure.Web.Authentication; + +public class TokenModel { - public class TokenModel - { - public string AccessToken { get; set; } + public string AccessToken { get; set; } - public string RefreshToken { get; set; } + public string RefreshToken { get; set; } - public DateTimeOffset ExpiresAt { get; set; } + public DateTimeOffset ExpiresAt { get; set; } - public bool TokenExpired + public bool TokenExpired + { + get { - get - { - return ExpiresAt.AddSeconds(-60).ToUniversalTime() <= DateTime.UtcNow; - } + return ExpiresAt.AddSeconds(-60).ToUniversalTime() <= DateTime.UtcNow; } } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Web/Authorization/Policies/AuthorizePolicyAttribute.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Web/Authorization/Policies/AuthorizePolicyAttribute.cs index 39b3876e2..1b1403b11 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Web/Authorization/Policies/AuthorizePolicyAttribute.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Web/Authorization/Policies/AuthorizePolicyAttribute.cs @@ -1,13 +1,12 @@ using Microsoft.AspNetCore.Authorization; using System; -namespace ClassifiedAds.Infrastructure.Web.Authorization.Policies +namespace ClassifiedAds.Infrastructure.Web.Authorization.Policies; + +public class AuthorizePolicyAttribute : AuthorizeAttribute { - public class AuthorizePolicyAttribute : AuthorizeAttribute + public AuthorizePolicyAttribute(Type policy) + : base(policy.FullName) { - public AuthorizePolicyAttribute(Type policy) - : base(policy.FullName) - { - } } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Web/Authorization/Policies/IPolicy.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Web/Authorization/Policies/IPolicy.cs index 9d08a6c06..2845ea8f7 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Web/Authorization/Policies/IPolicy.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Web/Authorization/Policies/IPolicy.cs @@ -1,9 +1,8 @@ using Microsoft.AspNetCore.Authorization; -namespace ClassifiedAds.Infrastructure.Web.Authorization.Policies +namespace ClassifiedAds.Infrastructure.Web.Authorization.Policies; + +public interface IPolicy { - public interface IPolicy - { - void Configure(AuthorizationPolicyBuilder policy); - } + void Configure(AuthorizationPolicyBuilder policy); } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Web/Authorization/Policies/PolicyServiceCollectionExtensions.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Web/Authorization/Policies/PolicyServiceCollectionExtensions.cs index ce83efcee..6c9acf73b 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Web/Authorization/Policies/PolicyServiceCollectionExtensions.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Web/Authorization/Policies/PolicyServiceCollectionExtensions.cs @@ -4,39 +4,38 @@ using System.Linq; using System.Reflection; -namespace Microsoft.Extensions.DependencyInjection +namespace Microsoft.Extensions.DependencyInjection; + +public static class PolicyServiceCollectionExtensions { - public static class PolicyServiceCollectionExtensions + public static IServiceCollection AddAuthorizationPolicies(this IServiceCollection services, Assembly assembly) { - public static IServiceCollection AddAuthorizationPolicies(this IServiceCollection services, Assembly assembly) + services.Configure(options => { - services.Configure(options => - { - var policyTypes = assembly.GetTypes().Where(t => t.GetInterfaces().Any(i => i == typeof(IPolicy))).ToList(); - - foreach (var type in policyTypes) - { - var obj = (IPolicy)Activator.CreateInstance(type); - - var policyName = type.FullName; + var policyTypes = assembly.GetTypes().Where(t => t.GetInterfaces().Any(i => i == typeof(IPolicy))).ToList(); - options.AddPolicy(policyName, policy => - { - obj.Configure(policy); - }); - } - }); + foreach (var type in policyTypes) + { + var obj = (IPolicy)Activator.CreateInstance(type); - var requirementHandlerTypes = assembly.GetTypes() - .Where(t => t.BaseType != null && t.BaseType.IsGenericType && t.BaseType.GetGenericTypeDefinition() == typeof(AuthorizationHandler<>)) - .ToList(); + var policyName = type.FullName; - foreach (var type in requirementHandlerTypes) - { - services.AddSingleton(typeof(IAuthorizationHandler), type); + options.AddPolicy(policyName, policy => + { + obj.Configure(policy); + }); } + }); + + var requirementHandlerTypes = assembly.GetTypes() + .Where(t => t.BaseType != null && t.BaseType.IsGenericType && t.BaseType.GetGenericTypeDefinition() == typeof(AuthorizationHandler<>)) + .ToList(); - return services; + foreach (var type in requirementHandlerTypes) + { + services.AddSingleton(typeof(IAuthorizationHandler), type); } + + return services; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Web/Filters/GlobalExceptionFilter.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Web/Filters/GlobalExceptionFilter.cs index d373d1aa3..3d4d2f13f 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Web/Filters/GlobalExceptionFilter.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Web/Filters/GlobalExceptionFilter.cs @@ -6,70 +6,69 @@ using System; using System.Net; -namespace ClassifiedAds.Infrastructure.Web.Filters +namespace ClassifiedAds.Infrastructure.Web.Filters; + +public class GlobalExceptionFilter : IExceptionFilter { - public class GlobalExceptionFilter : IExceptionFilter + private readonly ILogger _logger; + private readonly GlobalExceptionFilterOptions _options; + + public GlobalExceptionFilter(ILogger logger, + IOptionsSnapshot options) { - private readonly ILogger _logger; - private readonly GlobalExceptionFilterOptions _options; + _logger = logger; + _options = options.Value; + } - public GlobalExceptionFilter(ILogger logger, - IOptionsSnapshot options) + public void OnException(ExceptionContext context) + { + if (context.Exception is NotFoundException) { - _logger = logger; - _options = options.Value; + context.Result = new NotFoundResult(); } - - public void OnException(ExceptionContext context) + else if (context.Exception is ValidationException) { - if (context.Exception is NotFoundException) - { - context.Result = new NotFoundResult(); - } - else if (context.Exception is ValidationException) - { - context.Result = new BadRequestObjectResult(context.Exception.Message); - } - else - { - _logger.LogError(context.Exception, $"[{DateTime.UtcNow.Ticks}-{Environment.CurrentManagedThreadId}]"); - - if (_options.DetailLevel == GlobalExceptionDetailLevel.Throw) - { - return; - } + context.Result = new BadRequestObjectResult(context.Exception.Message); + } + else + { + _logger.LogError(context.Exception, $"[{DateTime.UtcNow.Ticks}-{Environment.CurrentManagedThreadId}]"); - context.Result = new ObjectResult(new { Message = GetErrorMessage(context.Exception) }) - { - StatusCode = (int)HttpStatusCode.InternalServerError, - }; + if (_options.DetailLevel == GlobalExceptionDetailLevel.Throw) + { + return; } - } - private string GetErrorMessage(Exception ex) - { - return _options.DetailLevel switch + context.Result = new ObjectResult(new { Message = GetErrorMessage(context.Exception) }) { - GlobalExceptionDetailLevel.None => "An internal exception has occurred.", - GlobalExceptionDetailLevel.Message => ex.Message, - GlobalExceptionDetailLevel.StackTrace => ex.StackTrace, - GlobalExceptionDetailLevel.ToString => ex.ToString(), - _ => "An internal exception has occurred.", + StatusCode = (int)HttpStatusCode.InternalServerError, }; } } - public class GlobalExceptionFilterOptions + private string GetErrorMessage(Exception ex) { - public GlobalExceptionDetailLevel DetailLevel { get; set; } + return _options.DetailLevel switch + { + GlobalExceptionDetailLevel.None => "An internal exception has occurred.", + GlobalExceptionDetailLevel.Message => ex.Message, + GlobalExceptionDetailLevel.StackTrace => ex.StackTrace, + GlobalExceptionDetailLevel.ToString => ex.ToString(), + _ => "An internal exception has occurred.", + }; } +} - public enum GlobalExceptionDetailLevel - { - None, - Message, - StackTrace, - ToString, - Throw, - } +public class GlobalExceptionFilterOptions +{ + public GlobalExceptionDetailLevel DetailLevel { get; set; } +} + +public enum GlobalExceptionDetailLevel +{ + None, + Message, + StackTrace, + ToString, + Throw, } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Web/Middleware/AccessTokenFromFormMiddleware.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Web/Middleware/AccessTokenFromFormMiddleware.cs index 2f64f881d..2a856e2f2 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Web/Middleware/AccessTokenFromFormMiddleware.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Web/Middleware/AccessTokenFromFormMiddleware.cs @@ -2,33 +2,32 @@ using Microsoft.Extensions.Logging; using System.Threading.Tasks; -namespace ClassifiedAds.Infrastructure.Web.Middleware +namespace ClassifiedAds.Infrastructure.Web.Middleware; + +internal class AccessTokenFromFormMiddleware { - internal class AccessTokenFromFormMiddleware - { - private readonly RequestDelegate _next; - private readonly ILogger _logger; + private readonly RequestDelegate _next; + private readonly ILogger _logger; - public AccessTokenFromFormMiddleware(RequestDelegate next, ILogger logger) - { - _next = next; - _logger = logger; - } + public AccessTokenFromFormMiddleware(RequestDelegate next, ILogger logger) + { + _next = next; + _logger = logger; + } - public async Task InvokeAsync(HttpContext context) + public async Task InvokeAsync(HttpContext context) + { + if (context.Request.Method == "POST" + && context.Request.ContentType == "application/x-www-form-urlencoded" + && string.IsNullOrEmpty(context.Request.Headers["Authorization"])) { - if (context.Request.Method == "POST" - && context.Request.ContentType == "application/x-www-form-urlencoded" - && string.IsNullOrEmpty(context.Request.Headers["Authorization"])) + var token = context.Request.Form["access_token"]; + if (!string.IsNullOrEmpty(token)) { - var token = context.Request.Form["access_token"]; - if (!string.IsNullOrEmpty(token)) - { - context.Request.Headers.Add("Authorization", "Bearer " + token); - } + context.Request.Headers.Add("Authorization", "Bearer " + token); } - - await _next(context); } + + await _next(context); } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Web/Middleware/DebuggingMiddleware.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Web/Middleware/DebuggingMiddleware.cs index 5819a1b6a..974b6233c 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Web/Middleware/DebuggingMiddleware.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Web/Middleware/DebuggingMiddleware.cs @@ -3,29 +3,28 @@ using System.Diagnostics; using System.Threading.Tasks; -namespace ClassifiedAds.Infrastructure.Web.Middleware +namespace ClassifiedAds.Infrastructure.Web.Middleware; + +public class DebuggingMiddleware { - public class DebuggingMiddleware - { - private readonly RequestDelegate _next; - private readonly ILogger _logger; + private readonly RequestDelegate _next; + private readonly ILogger _logger; - public DebuggingMiddleware(RequestDelegate next, ILogger logger) - { - _next = next; - _logger = logger; - } + public DebuggingMiddleware(RequestDelegate next, ILogger logger) + { + _next = next; + _logger = logger; + } - public async Task InvokeAsync(HttpContext context) - { - var stopwatch = Stopwatch.StartNew(); - await _next(context); - var elapsedTime = stopwatch.Elapsed; + public async Task InvokeAsync(HttpContext context) + { + var stopwatch = Stopwatch.StartNew(); + await _next(context); + var elapsedTime = stopwatch.Elapsed; - // inspect the context here - // if (context.Request.Path.HasValue && context.Request.Path.Value.Contains("oidc")) - // { - // } - } + // inspect the context here + // if (context.Request.Path.HasValue && context.Request.Path.Value.Contains("oidc")) + // { + // } } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Web/Middleware/GlobalExceptionHandlerMiddleware.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Web/Middleware/GlobalExceptionHandlerMiddleware.cs index 37f1a25de..03518177d 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Web/Middleware/GlobalExceptionHandlerMiddleware.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Web/Middleware/GlobalExceptionHandlerMiddleware.cs @@ -6,82 +6,81 @@ using System.Text.Json; using System.Threading.Tasks; -namespace ClassifiedAds.Infrastructure.Web.Middleware +namespace ClassifiedAds.Infrastructure.Web.Middleware; + +public class GlobalExceptionHandlerMiddleware { - public class GlobalExceptionHandlerMiddleware + private readonly RequestDelegate _next; + private readonly ILogger _logger; + private readonly GlobalExceptionHandlerMiddlewareOptions _options; + + public GlobalExceptionHandlerMiddleware(RequestDelegate next, + ILogger logger, + GlobalExceptionHandlerMiddlewareOptions options) { - private readonly RequestDelegate _next; - private readonly ILogger _logger; - private readonly GlobalExceptionHandlerMiddlewareOptions _options; + _next = next; + _logger = logger; + _options = options; + } - public GlobalExceptionHandlerMiddleware(RequestDelegate next, - ILogger logger, - GlobalExceptionHandlerMiddlewareOptions options) + public async Task InvokeAsync(HttpContext context) + { + try { - _next = next; - _logger = logger; - _options = options; + await _next(context); } - - public async Task InvokeAsync(HttpContext context) + catch (Exception ex) { - try - { - await _next(context); - } - catch (Exception ex) - { - var response = context.Response; - response.ContentType = "application/json"; - - switch (ex) - { - case ValidationException: - response.StatusCode = (int)HttpStatusCode.BadRequest; - break; - case NotFoundException: - response.StatusCode = (int)HttpStatusCode.NotFound; - break; - default: - _logger.LogError(ex, $"[{DateTime.UtcNow.Ticks}-{Environment.CurrentManagedThreadId}]"); - response.StatusCode = (int)HttpStatusCode.InternalServerError; - break; - } - - var result = JsonSerializer.Serialize(new { message = GetErrorMessage(ex) }); - await response.WriteAsync(result); - } - } + var response = context.Response; + response.ContentType = "application/json"; - private string GetErrorMessage(Exception ex) - { - if (ex is ValidationException) + switch (ex) { - return ex.Message; + case ValidationException: + response.StatusCode = (int)HttpStatusCode.BadRequest; + break; + case NotFoundException: + response.StatusCode = (int)HttpStatusCode.NotFound; + break; + default: + _logger.LogError(ex, $"[{DateTime.UtcNow.Ticks}-{Environment.CurrentManagedThreadId}]"); + response.StatusCode = (int)HttpStatusCode.InternalServerError; + break; } - return _options.DetailLevel switch - { - GlobalExceptionDetailLevel.None => "An internal exception has occurred.", - GlobalExceptionDetailLevel.Message => ex.Message, - GlobalExceptionDetailLevel.StackTrace => ex.StackTrace, - GlobalExceptionDetailLevel.ToString => ex.ToString(), - _ => "An internal exception has occurred.", - }; + var result = JsonSerializer.Serialize(new { message = GetErrorMessage(ex) }); + await response.WriteAsync(result); } } - public class GlobalExceptionHandlerMiddlewareOptions + private string GetErrorMessage(Exception ex) { - public GlobalExceptionDetailLevel DetailLevel { get; set; } - } + if (ex is ValidationException) + { + return ex.Message; + } - public enum GlobalExceptionDetailLevel - { - None, - Message, - StackTrace, - ToString, - Throw, + return _options.DetailLevel switch + { + GlobalExceptionDetailLevel.None => "An internal exception has occurred.", + GlobalExceptionDetailLevel.Message => ex.Message, + GlobalExceptionDetailLevel.StackTrace => ex.StackTrace, + GlobalExceptionDetailLevel.ToString => ex.ToString(), + _ => "An internal exception has occurred.", + }; } } + +public class GlobalExceptionHandlerMiddlewareOptions +{ + public GlobalExceptionDetailLevel DetailLevel { get; set; } +} + +public enum GlobalExceptionDetailLevel +{ + None, + Message, + StackTrace, + ToString, + Throw, +} diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Web/Middleware/IApplicationBuilderExtensions.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Web/Middleware/IApplicationBuilderExtensions.cs index 9e775d102..53148bf5f 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Web/Middleware/IApplicationBuilderExtensions.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Web/Middleware/IApplicationBuilderExtensions.cs @@ -2,53 +2,52 @@ using System; using System.Collections.Generic; -namespace Microsoft.AspNetCore.Builder +namespace Microsoft.AspNetCore.Builder; + +public static class IApplicationBuilderExtensions { - public static class IApplicationBuilderExtensions + public static IApplicationBuilder UseIPFiltering(this IApplicationBuilder app) + { + app.UseMiddleware(); + return app; + } + + public static IApplicationBuilder UseSecurityHeaders(this IApplicationBuilder app, Dictionary headers) + { + app.UseMiddleware(headers); + return app; + } + + public static IApplicationBuilder UseDebuggingMiddleware(this IApplicationBuilder app) + { + app.UseMiddleware(); + return app; + } + + public static IApplicationBuilder UseGlobalExceptionHandlerMiddleware(this IApplicationBuilder app, GlobalExceptionHandlerMiddlewareOptions options = default) + { + options ??= new GlobalExceptionHandlerMiddlewareOptions(); + app.UseMiddleware(options); + return app; + } + + public static IApplicationBuilder UseGlobalExceptionHandlerMiddleware(this IApplicationBuilder app, Action configureOptions) + { + var options = new GlobalExceptionHandlerMiddlewareOptions(); + configureOptions(options); + app.UseMiddleware(options); + return app; + } + + public static IApplicationBuilder UseLoggingStatusCodeMiddleware(this IApplicationBuilder app) + { + app.UseMiddleware(); + return app; + } + + public static IApplicationBuilder UseAccessTokenFromFormMiddleware(this IApplicationBuilder app) { - public static IApplicationBuilder UseIPFiltering(this IApplicationBuilder app) - { - app.UseMiddleware(); - return app; - } - - public static IApplicationBuilder UseSecurityHeaders(this IApplicationBuilder app, Dictionary headers) - { - app.UseMiddleware(headers); - return app; - } - - public static IApplicationBuilder UseDebuggingMiddleware(this IApplicationBuilder app) - { - app.UseMiddleware(); - return app; - } - - public static IApplicationBuilder UseGlobalExceptionHandlerMiddleware(this IApplicationBuilder app, GlobalExceptionHandlerMiddlewareOptions options = default) - { - options ??= new GlobalExceptionHandlerMiddlewareOptions(); - app.UseMiddleware(options); - return app; - } - - public static IApplicationBuilder UseGlobalExceptionHandlerMiddleware(this IApplicationBuilder app, Action configureOptions) - { - var options = new GlobalExceptionHandlerMiddlewareOptions(); - configureOptions(options); - app.UseMiddleware(options); - return app; - } - - public static IApplicationBuilder UseLoggingStatusCodeMiddleware(this IApplicationBuilder app) - { - app.UseMiddleware(); - return app; - } - - public static IApplicationBuilder UseAccessTokenFromFormMiddleware(this IApplicationBuilder app) - { - app.UseMiddleware(); - return app; - } + app.UseMiddleware(); + return app; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Web/Middleware/IPFilteringMiddleware.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Web/Middleware/IPFilteringMiddleware.cs index 1ee3fef97..6bef09788 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Web/Middleware/IPFilteringMiddleware.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Web/Middleware/IPFilteringMiddleware.cs @@ -2,25 +2,24 @@ using Microsoft.Extensions.Logging; using System.Threading.Tasks; -namespace ClassifiedAds.Infrastructure.Web.Middleware +namespace ClassifiedAds.Infrastructure.Web.Middleware; + +public class IPFilteringMiddleware { - public class IPFilteringMiddleware - { - private readonly RequestDelegate _next; - private readonly ILogger _logger; + private readonly RequestDelegate _next; + private readonly ILogger _logger; - public IPFilteringMiddleware(RequestDelegate next, ILogger logger) - { - _next = next; - _logger = logger; - } + public IPFilteringMiddleware(RequestDelegate next, ILogger logger) + { + _next = next; + _logger = logger; + } - public async Task InvokeAsync(HttpContext context) - { - var remoteIp = context.Connection.RemoteIpAddress; - _logger.LogInformation($"Request from Remote IP address: {remoteIp}"); + public async Task InvokeAsync(HttpContext context) + { + var remoteIp = context.Connection.RemoteIpAddress; + _logger.LogInformation($"Request from Remote IP address: {remoteIp}"); - await _next(context); - } + await _next(context); } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Web/Middleware/LoggingStatusCodeMiddleware.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Web/Middleware/LoggingStatusCodeMiddleware.cs index 820625860..4d26a5bd9 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Web/Middleware/LoggingStatusCodeMiddleware.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Web/Middleware/LoggingStatusCodeMiddleware.cs @@ -4,35 +4,34 @@ using System.Security.Claims; using System.Threading.Tasks; -namespace ClassifiedAds.Infrastructure.Web.Middleware +namespace ClassifiedAds.Infrastructure.Web.Middleware; + +public class LoggingStatusCodeMiddleware { - public class LoggingStatusCodeMiddleware - { - private readonly RequestDelegate _next; - private readonly ILogger _logger; + private readonly RequestDelegate _next; + private readonly ILogger _logger; - public LoggingStatusCodeMiddleware(RequestDelegate next, ILogger logger) - { - _next = next; - _logger = logger; - } + public LoggingStatusCodeMiddleware(RequestDelegate next, ILogger logger) + { + _next = next; + _logger = logger; + } - public async Task InvokeAsync(HttpContext context) - { - await _next(context); + public async Task InvokeAsync(HttpContext context) + { + await _next(context); - var statusCode = context.Response.StatusCode; - var path = context.Request.Path; - var method = context.Request.Method; - var userId = context.User.FindFirst(ClaimTypes.NameIdentifier)?.Value ?? context.User.FindFirst("sub")?.Value; - var remoteIp = context.Connection.RemoteIpAddress; + var statusCode = context.Response.StatusCode; + var path = context.Request.Path; + var method = context.Request.Method; + var userId = context.User.FindFirst(ClaimTypes.NameIdentifier)?.Value ?? context.User.FindFirst("sub")?.Value; + var remoteIp = context.Connection.RemoteIpAddress; - var statusCodes = new[] { StatusCodes.Status401Unauthorized, StatusCodes.Status403Forbidden }; + var statusCodes = new[] { StatusCodes.Status401Unauthorized, StatusCodes.Status403Forbidden }; - if (statusCodes.Contains(statusCode)) - { - _logger.LogWarning($"StatusCode: {statusCode}, UserId: {userId}, Path: {path}, Method: {method}, IP: {remoteIp}"); - } + if (statusCodes.Contains(statusCode)) + { + _logger.LogWarning($"StatusCode: {statusCode}, UserId: {userId}, Path: {path}, Method: {method}, IP: {remoteIp}"); } } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Web/Middleware/SecurityHeadersMiddleware.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Web/Middleware/SecurityHeadersMiddleware.cs index 50cefa153..193e34d39 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Web/Middleware/SecurityHeadersMiddleware.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Infrastructure/Web/Middleware/SecurityHeadersMiddleware.cs @@ -2,27 +2,26 @@ using System.Collections.Generic; using System.Threading.Tasks; -namespace ClassifiedAds.Infrastructure.Web.Middleware +namespace ClassifiedAds.Infrastructure.Web.Middleware; + +public class SecurityHeadersMiddleware { - public class SecurityHeadersMiddleware + private readonly RequestDelegate _next; + private readonly Dictionary _headers; + + public SecurityHeadersMiddleware(RequestDelegate next, Dictionary headers) { - private readonly RequestDelegate _next; - private readonly Dictionary _headers; + _next = next; + _headers = headers; + } - public SecurityHeadersMiddleware(RequestDelegate next, Dictionary headers) + public async Task Invoke(HttpContext context) + { + foreach (var header in _headers) { - _next = next; - _headers = headers; + context.Response.Headers[header.Key] = header.Value; } - public async Task Invoke(HttpContext context) - { - foreach (var header in _headers) - { - context.Response.Headers[header.Key] = header.Value; - } - - await _next(context); - } + await _next(context); } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Migrator/Program.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Migrator/Program.cs index 12307b4d1..719a2dede 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Migrator/Program.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Migrator/Program.cs @@ -8,65 +8,64 @@ using System; using System.Reflection; -namespace ClassifiedAds.Migrator +namespace ClassifiedAds.Migrator; + +public class Program { - public class Program + public static void Main(string[] args) { - public static void Main(string[] args) - { - var builder = WebApplication.CreateBuilder(args); + var builder = WebApplication.CreateBuilder(args); - // Add services to the container. - var services = builder.Services; - var configuration = builder.Configuration; + // Add services to the container. + var services = builder.Services; + var configuration = builder.Configuration; - builder.WebHost.UseClassifiedAdsLogger(configuration => - { - return new LoggingOptions(); - }); + builder.WebHost.UseClassifiedAdsLogger(configuration => + { + return new LoggingOptions(); + }); - if (string.Equals(configuration["CheckDependency:Enabled"], "true", StringComparison.OrdinalIgnoreCase)) - { - NetworkPortCheck.Wait(configuration["CheckDependency:Host"], 5); - } + if (string.Equals(configuration["CheckDependency:Enabled"], "true", StringComparison.OrdinalIgnoreCase)) + { + NetworkPortCheck.Wait(configuration["CheckDependency:Host"], 5); + } - services.AddDateTimeProvider(); + services.AddDateTimeProvider(); - services.AddPersistence(configuration["ConnectionStrings:ClassifiedAds"], - Assembly.GetExecutingAssembly().GetName().Name); + services.AddPersistence(configuration["ConnectionStrings:ClassifiedAds"], + Assembly.GetExecutingAssembly().GetName().Name); - services.AddIdentityServer() - .AddIdServerPersistence(configuration.GetConnectionString("IdentityServer"), - Assembly.GetExecutingAssembly().GetName().Name); + services.AddIdentityServer() + .AddIdServerPersistence(configuration.GetConnectionString("IdentityServer"), + Assembly.GetExecutingAssembly().GetName().Name); - // Configure the HTTP request pipeline. - var app = builder.Build(); + // Configure the HTTP request pipeline. + var app = builder.Build(); - Policy.Handle().WaitAndRetry(new[] - { - TimeSpan.FromSeconds(10), - TimeSpan.FromSeconds(20), - TimeSpan.FromSeconds(30), - }) - .Execute(() => - { - app.MigrateIdServerDb(); + Policy.Handle().WaitAndRetry(new[] + { + TimeSpan.FromSeconds(10), + TimeSpan.FromSeconds(20), + TimeSpan.FromSeconds(30), + }) + .Execute(() => + { + app.MigrateIdServerDb(); - var upgrader = DeployChanges.To - .SqlDatabase(configuration.GetConnectionString("ClassifiedAds")) - .WithScriptsEmbeddedInAssembly(Assembly.GetExecutingAssembly()) - .LogToConsole() - .Build(); + var upgrader = DeployChanges.To + .SqlDatabase(configuration.GetConnectionString("ClassifiedAds")) + .WithScriptsEmbeddedInAssembly(Assembly.GetExecutingAssembly()) + .LogToConsole() + .Build(); - var result = upgrader.PerformUpgrade(); + var result = upgrader.PerformUpgrade(); - if (!result.Successful) - { - throw result.Error; - } - }); + if (!result.Successful) + { + throw result.Error; + } + }); - app.Run(); - } + app.Run(); } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/AdsDbContext.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/AdsDbContext.cs index 174313368..24e8d9466 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/AdsDbContext.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/AdsDbContext.cs @@ -10,48 +10,47 @@ using System.Threading; using System.Threading.Tasks; -namespace ClassifiedAds.Persistence +namespace ClassifiedAds.Persistence; + +public class AdsDbContext : DbContext, IUnitOfWork, IDataProtectionKeyContext { - public class AdsDbContext : DbContext, IUnitOfWork, IDataProtectionKeyContext + private IDbContextTransaction _dbContextTransaction; + + public AdsDbContext(DbContextOptions options) + : base(options) { - private IDbContextTransaction _dbContextTransaction; + } - public AdsDbContext(DbContextOptions options) - : base(options) - { - } + public DbSet DataProtectionKeys { get; set; } - public DbSet DataProtectionKeys { get; set; } + public async Task BeginTransactionAsync(IsolationLevel isolationLevel = IsolationLevel.ReadCommitted, CancellationToken cancellationToken = default) + { + _dbContextTransaction = await Database.BeginTransactionAsync(isolationLevel, cancellationToken); + return _dbContextTransaction; + } - public async Task BeginTransactionAsync(IsolationLevel isolationLevel = IsolationLevel.ReadCommitted, CancellationToken cancellationToken = default) - { - _dbContextTransaction = await Database.BeginTransactionAsync(isolationLevel, cancellationToken); - return _dbContextTransaction; - } + public async Task BeginTransactionAsync(IsolationLevel isolationLevel = IsolationLevel.ReadCommitted, string lockName = null, CancellationToken cancellationToken = default) + { + _dbContextTransaction = await Database.BeginTransactionAsync(isolationLevel, cancellationToken); - public async Task BeginTransactionAsync(IsolationLevel isolationLevel = IsolationLevel.ReadCommitted, string lockName = null, CancellationToken cancellationToken = default) + var sqlLock = new SqlDistributedLock(_dbContextTransaction.GetDbTransaction() as SqlTransaction); + var lockScope = sqlLock.Acquire(lockName); + if (lockScope == null) { - _dbContextTransaction = await Database.BeginTransactionAsync(isolationLevel, cancellationToken); - - var sqlLock = new SqlDistributedLock(_dbContextTransaction.GetDbTransaction() as SqlTransaction); - var lockScope = sqlLock.Acquire(lockName); - if (lockScope == null) - { - throw new Exception($"Could not acquire lock: {lockName}"); - } - - return _dbContextTransaction; + throw new Exception($"Could not acquire lock: {lockName}"); } - public async Task CommitTransactionAsync(CancellationToken cancellationToken = default) - { - await _dbContextTransaction.CommitAsync(cancellationToken); - } + return _dbContextTransaction; + } - protected override void OnModelCreating(ModelBuilder builder) - { - base.OnModelCreating(builder); - builder.ApplyConfigurationsFromAssembly(Assembly.GetExecutingAssembly()); - } + public async Task CommitTransactionAsync(CancellationToken cancellationToken = default) + { + await _dbContextTransaction.CommitAsync(cancellationToken); + } + + protected override void OnModelCreating(ModelBuilder builder) + { + base.OnModelCreating(builder); + builder.ApplyConfigurationsFromAssembly(Assembly.GetExecutingAssembly()); } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/AdsDbContextMultiTenant.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/AdsDbContextMultiTenant.cs index 365adc47d..6cfa26cab 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/AdsDbContextMultiTenant.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/AdsDbContextMultiTenant.cs @@ -1,22 +1,21 @@ using ClassifiedAds.CrossCuttingConcerns.Tenants; using Microsoft.EntityFrameworkCore; -namespace ClassifiedAds.Persistence +namespace ClassifiedAds.Persistence; + +public class AdsDbContextMultiTenant : AdsDbContext { - public class AdsDbContextMultiTenant : AdsDbContext - { - private readonly IConnectionStringResolver _connectionStringResolver; + private readonly IConnectionStringResolver _connectionStringResolver; - public AdsDbContextMultiTenant( - IConnectionStringResolver connectionStringResolver) - : base(new DbContextOptions()) - { - _connectionStringResolver = connectionStringResolver; - } + public AdsDbContextMultiTenant( + IConnectionStringResolver connectionStringResolver) + : base(new DbContextOptions()) + { + _connectionStringResolver = connectionStringResolver; + } - protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) - { - optionsBuilder.UseSqlServer(_connectionStringResolver.ConnectionString); - } + protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) + { + optionsBuilder.UseSqlServer(_connectionStringResolver.ConnectionString); } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/CircuitBreakers/CircuitBreaker.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/CircuitBreakers/CircuitBreaker.cs index ffadd81d0..97c4a4d05 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/CircuitBreakers/CircuitBreaker.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/CircuitBreakers/CircuitBreaker.cs @@ -2,28 +2,27 @@ using System; using System.Collections.Generic; -namespace ClassifiedAds.Persistence.CircuitBreakers +namespace ClassifiedAds.Persistence.CircuitBreakers; + +public class CircuitBreaker : ICircuitBreaker { - public class CircuitBreaker : ICircuitBreaker - { - public Guid Id { get; set; } + public Guid Id { get; set; } - public string Name { get; set; } + public string Name { get; set; } - public CircuitStatus Status { get; set; } + public CircuitStatus Status { get; set; } - public DateTimeOffset CreatedDateTime { get; set; } + public DateTimeOffset CreatedDateTime { get; set; } - public DateTimeOffset LastStatusUpdated { get; set; } + public DateTimeOffset LastStatusUpdated { get; set; } - public ICollection CircuitBreakerLogs { get; set; } + public ICollection CircuitBreakerLogs { get; set; } - public void EnsureOkStatus() + public void EnsureOkStatus() + { + if (Status == CircuitStatus.Open) { - if (Status == CircuitStatus.Open) - { - throw new CircuitBreakerOpenException(); - } + throw new CircuitBreakerOpenException(); } } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/CircuitBreakers/CircuitBreakerLog.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/CircuitBreakers/CircuitBreakerLog.cs index 3b3ecdeba..cf333c24b 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/CircuitBreakers/CircuitBreakerLog.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/CircuitBreakers/CircuitBreakerLog.cs @@ -1,18 +1,17 @@ using ClassifiedAds.CrossCuttingConcerns.CircuitBreakers; using System; -namespace ClassifiedAds.Persistence.CircuitBreakers +namespace ClassifiedAds.Persistence.CircuitBreakers; + +public class CircuitBreakerLog { - public class CircuitBreakerLog - { - public Guid Id { get; set; } + public Guid Id { get; set; } - public Guid CircuitBreakerId { get; set; } + public Guid CircuitBreakerId { get; set; } - public CircuitStatus Status { get; set; } + public CircuitStatus Status { get; set; } - public bool Succeeded { get; set; } + public bool Succeeded { get; set; } - public DateTimeOffset CreatedDateTime { get; set; } - } + public DateTimeOffset CreatedDateTime { get; set; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/CircuitBreakers/CircuitBreakerManager.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/CircuitBreakers/CircuitBreakerManager.cs index 036c9d45c..fc228583e 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/CircuitBreakers/CircuitBreakerManager.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/CircuitBreakers/CircuitBreakerManager.cs @@ -4,117 +4,116 @@ using System; using System.Linq; -namespace ClassifiedAds.Persistence.CircuitBreakers +namespace ClassifiedAds.Persistence.CircuitBreakers; + +public class CircuitBreakerManager : ICircuitBreakerManager, IDisposable { - public class CircuitBreakerManager : ICircuitBreakerManager, IDisposable + private readonly AdsDbContext _dbContext; + private readonly IDateTimeProvider _dateTimeProvider; + + public CircuitBreakerManager(IDbContextFactory dbContextFactory, IDateTimeProvider dateTimeProvider) { - private readonly AdsDbContext _dbContext; - private readonly IDateTimeProvider _dateTimeProvider; + _dbContext = dbContextFactory.CreateDbContext(); + _dateTimeProvider = dateTimeProvider; + } - public CircuitBreakerManager(IDbContextFactory dbContextFactory, IDateTimeProvider dateTimeProvider) + public ICircuitBreaker GetCircuitBreaker(string name, TimeSpan openTime) + { + CircuitBreaker GetCircuitBreakerByName() { - _dbContext = dbContextFactory.CreateDbContext(); - _dateTimeProvider = dateTimeProvider; + return _dbContext.Set().Where(x => x.Name.Equals(name)).FirstOrDefault(); } - public ICircuitBreaker GetCircuitBreaker(string name, TimeSpan openTime) + var circuitBreaker = GetCircuitBreakerByName(); + if (circuitBreaker == null) { - CircuitBreaker GetCircuitBreakerByName() + try { - return _dbContext.Set().Where(x => x.Name.Equals(name)).FirstOrDefault(); - } + circuitBreaker = new CircuitBreaker + { + Name = name, + Status = CircuitStatus.Closed, + CreatedDateTime = _dateTimeProvider.Now, + LastStatusUpdated = _dateTimeProvider.Now, + }; - var circuitBreaker = GetCircuitBreakerByName(); - if (circuitBreaker == null) + _dbContext.Set().Add(circuitBreaker); + _dbContext.SaveChanges(); + } + catch (Exception) { - try - { - circuitBreaker = new CircuitBreaker - { - Name = name, - Status = CircuitStatus.Closed, - CreatedDateTime = _dateTimeProvider.Now, - LastStatusUpdated = _dateTimeProvider.Now, - }; - - _dbContext.Set().Add(circuitBreaker); - _dbContext.SaveChanges(); - } - catch (Exception) + circuitBreaker = GetCircuitBreakerByName(); + if (circuitBreaker == null) { - circuitBreaker = GetCircuitBreakerByName(); - if (circuitBreaker == null) - { - throw; - } + throw; } } - - if (circuitBreaker.Status == CircuitStatus.Open && circuitBreaker.LastStatusUpdated + openTime <= _dateTimeProvider.Now) - { - circuitBreaker.Status = CircuitStatus.HalfOpen; - circuitBreaker.LastStatusUpdated = _dateTimeProvider.Now; - _dbContext.SaveChanges(); - } - - return circuitBreaker; } - public void LogFailure(ICircuitBreaker circuitBreaker, int maximumNumberOfFailures, TimeSpan period) + if (circuitBreaker.Status == CircuitStatus.Open && circuitBreaker.LastStatusUpdated + openTime <= _dateTimeProvider.Now) { - _dbContext.Set().Add(new CircuitBreakerLog - { - CircuitBreakerId = ((CircuitBreaker)circuitBreaker).Id, - Status = ((CircuitBreaker)circuitBreaker).Status, - Succeeded = false, - CreatedDateTime = _dateTimeProvider.OffsetNow, - }); - - UpdateCircuitBreakerStatus(circuitBreaker, circuitBreaker.Status == CircuitStatus.HalfOpen, CircuitStatus.Open); - + circuitBreaker.Status = CircuitStatus.HalfOpen; + circuitBreaker.LastStatusUpdated = _dateTimeProvider.Now; _dbContext.SaveChanges(); + } - if (circuitBreaker.Status == CircuitStatus.Closed) - { - var sinceLastTime = _dateTimeProvider.OffsetNow - period; - var numberOfFailures = _dbContext.Set().Where(x => x.CircuitBreakerId == ((CircuitBreaker)circuitBreaker).Id - && x.Succeeded == false && x.CreatedDateTime >= sinceLastTime).Count(); + return circuitBreaker; + } - UpdateCircuitBreakerStatus(circuitBreaker, numberOfFailures >= maximumNumberOfFailures, CircuitStatus.Open); + public void LogFailure(ICircuitBreaker circuitBreaker, int maximumNumberOfFailures, TimeSpan period) + { + _dbContext.Set().Add(new CircuitBreakerLog + { + CircuitBreakerId = ((CircuitBreaker)circuitBreaker).Id, + Status = ((CircuitBreaker)circuitBreaker).Status, + Succeeded = false, + CreatedDateTime = _dateTimeProvider.OffsetNow, + }); - _dbContext.SaveChanges(); - } - } + UpdateCircuitBreakerStatus(circuitBreaker, circuitBreaker.Status == CircuitStatus.HalfOpen, CircuitStatus.Open); + + _dbContext.SaveChanges(); - public void LogSuccess(ICircuitBreaker circuitBreaker) + if (circuitBreaker.Status == CircuitStatus.Closed) { - _dbContext.Set().Add(new CircuitBreakerLog - { - CircuitBreakerId = ((CircuitBreaker)circuitBreaker).Id, - Status = ((CircuitBreaker)circuitBreaker).Status, - Succeeded = true, - CreatedDateTime = _dateTimeProvider.OffsetNow, - }); + var sinceLastTime = _dateTimeProvider.OffsetNow - period; + var numberOfFailures = _dbContext.Set().Where(x => x.CircuitBreakerId == ((CircuitBreaker)circuitBreaker).Id + && x.Succeeded == false && x.CreatedDateTime >= sinceLastTime).Count(); - UpdateCircuitBreakerStatus(circuitBreaker, circuitBreaker.Status == CircuitStatus.HalfOpen, CircuitStatus.Closed); + UpdateCircuitBreakerStatus(circuitBreaker, numberOfFailures >= maximumNumberOfFailures, CircuitStatus.Open); _dbContext.SaveChanges(); } + } - private void UpdateCircuitBreakerStatus(ICircuitBreaker circuitBreaker, bool shouldUpdate, CircuitStatus circuitStatus) + public void LogSuccess(ICircuitBreaker circuitBreaker) + { + _dbContext.Set().Add(new CircuitBreakerLog { - if (!shouldUpdate) - { - return; - } + CircuitBreakerId = ((CircuitBreaker)circuitBreaker).Id, + Status = ((CircuitBreaker)circuitBreaker).Status, + Succeeded = true, + CreatedDateTime = _dateTimeProvider.OffsetNow, + }); - circuitBreaker.Status = circuitStatus; - circuitBreaker.LastStatusUpdated = _dateTimeProvider.OffsetNow; - } + UpdateCircuitBreakerStatus(circuitBreaker, circuitBreaker.Status == CircuitStatus.HalfOpen, CircuitStatus.Closed); + + _dbContext.SaveChanges(); + } - public void Dispose() + private void UpdateCircuitBreakerStatus(ICircuitBreaker circuitBreaker, bool shouldUpdate, CircuitStatus circuitStatus) + { + if (!shouldUpdate) { - _dbContext.Dispose(); + return; } + + circuitBreaker.Status = circuitStatus; + circuitBreaker.LastStatusUpdated = _dateTimeProvider.OffsetNow; + } + + public void Dispose() + { + _dbContext.Dispose(); } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/IdServerPersistenceExtensions.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/IdServerPersistenceExtensions.cs index 6e7b11d95..6d521b6e0 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/IdServerPersistenceExtensions.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/IdServerPersistenceExtensions.cs @@ -8,13 +8,26 @@ using System.Collections.Generic; using System.Linq; -namespace Microsoft.Extensions.DependencyInjection +namespace Microsoft.Extensions.DependencyInjection; + +public static class IdServerPersistenceExtensions { - public static class IdServerPersistenceExtensions + public static IIdentityServerBuilder AddIdServerPersistence(this IIdentityServerBuilder services, string connectionString, string migrationsAssembly = "") { - public static IIdentityServerBuilder AddIdServerPersistence(this IIdentityServerBuilder services, string connectionString, string migrationsAssembly = "") + services.AddConfigurationStore(options => { - services.AddConfigurationStore(options => + options.ConfigureDbContext = builder => + builder.UseSqlServer(connectionString, + sql => + { + if (!string.IsNullOrEmpty(migrationsAssembly)) + { + sql.MigrationsAssembly(migrationsAssembly); + } + }); + options.DefaultSchema = "idsv"; + }) + .AddOperationalStore(options => { options.ConfigureDbContext = builder => builder.UseSqlServer(connectionString, @@ -26,349 +39,335 @@ public static IIdentityServerBuilder AddIdServerPersistence(this IIdentityServer } }); options.DefaultSchema = "idsv"; - }) - .AddOperationalStore(options => - { - options.ConfigureDbContext = builder => - builder.UseSqlServer(connectionString, - sql => - { - if (!string.IsNullOrEmpty(migrationsAssembly)) - { - sql.MigrationsAssembly(migrationsAssembly); - } - }); - options.DefaultSchema = "idsv"; - // this enables automatic token cleanup. this is optional. - options.EnableTokenCleanup = true; - options.TokenCleanupInterval = 30; // interval in seconds - }); - return services; - } + // this enables automatic token cleanup. this is optional. + options.EnableTokenCleanup = true; + options.TokenCleanupInterval = 30; // interval in seconds + }); + return services; + } - public static void MigrateIdServerDb(this IApplicationBuilder app) + public static void MigrateIdServerDb(this IApplicationBuilder app) + { + using (var serviceScope = app.ApplicationServices.GetService().CreateScope()) { - using (var serviceScope = app.ApplicationServices.GetService().CreateScope()) - { - serviceScope.ServiceProvider.GetRequiredService().Database.Migrate(); + serviceScope.ServiceProvider.GetRequiredService().Database.Migrate(); - var context = serviceScope.ServiceProvider.GetRequiredService(); - context.Database.Migrate(); + var context = serviceScope.ServiceProvider.GetRequiredService(); + context.Database.Migrate(); - var clients = new List(); + var clients = new List(); - if (!context.Clients.Any(x => x.ClientId == "Swagger")) + if (!context.Clients.Any(x => x.ClientId == "Swagger")) + { + clients.Add(new Client { - clients.Add(new Client + ClientId = "Swagger", + ClientName = "Swagger", + AllowedGrantTypes = GrantTypes.Code.Combines(GrantTypes.ClientCredentials), + RequirePkce = true, + RedirectUris = { - ClientId = "Swagger", - ClientName = "Swagger", - AllowedGrantTypes = GrantTypes.Code.Combines(GrantTypes.ClientCredentials), - RequirePkce = true, - RedirectUris = - { - "https://localhost:44312/oauth2-redirect.html", - "http://host.docker.internal:9002/oauth2-redirect.html", - }, - AllowedScopes = - { - IdentityServerConstants.StandardScopes.OpenId, - IdentityServerConstants.StandardScopes.Profile, - "ClassifiedAds.WebAPI", - }, - ClientSecrets = - { - new Secret("secret".Sha256()), - }, - RequireConsent = false, - }); - } + "https://localhost:44312/oauth2-redirect.html", + "http://host.docker.internal:9002/oauth2-redirect.html", + }, + AllowedScopes = + { + IdentityServerConstants.StandardScopes.OpenId, + IdentityServerConstants.StandardScopes.Profile, + "ClassifiedAds.WebAPI", + }, + ClientSecrets = + { + new Secret("secret".Sha256()), + }, + RequireConsent = false, + }); + } - if (!context.Clients.Any(x => x.ClientId == "ReverseProxy.Yarp")) + if (!context.Clients.Any(x => x.ClientId == "ReverseProxy.Yarp")) + { + clients.Add(new Client { - clients.Add(new Client + ClientId = "ReverseProxy.Yarp", + ClientName = "ReverseProxy Yarp", + AllowedGrantTypes = GrantTypes.Code.Combines(GrantTypes.ResourceOwnerPassword), + RequirePkce = true, + RedirectUris = { - ClientId = "ReverseProxy.Yarp", - ClientName = "ReverseProxy Yarp", - AllowedGrantTypes = GrantTypes.Code.Combines(GrantTypes.ResourceOwnerPassword), - RequirePkce = true, - RedirectUris = - { - "https://localhost:44348/signin-oidc" - }, - PostLogoutRedirectUris = - { - "https://localhost:44348/signout-callback-oidc" - }, - AllowedScopes = - { - IdentityServerConstants.StandardScopes.OpenId, - IdentityServerConstants.StandardScopes.Profile, - "ClassifiedAds.WebAPI", - }, - ClientSecrets = - { - new Secret("secret".Sha256()), - }, - AllowOfflineAccess = true, - RequireConsent = true, - }); - } + "https://localhost:44348/signin-oidc" + }, + PostLogoutRedirectUris = + { + "https://localhost:44348/signout-callback-oidc" + }, + AllowedScopes = + { + IdentityServerConstants.StandardScopes.OpenId, + IdentityServerConstants.StandardScopes.Profile, + "ClassifiedAds.WebAPI", + }, + ClientSecrets = + { + new Secret("secret".Sha256()), + }, + AllowOfflineAccess = true, + RequireConsent = true, + }); + } - if (!context.Clients.Any(x => x.ClientId == "ClassifiedAds.WebMVC")) + if (!context.Clients.Any(x => x.ClientId == "ClassifiedAds.WebMVC")) + { + clients.Add(new Client { - clients.Add(new Client + ClientId = "ClassifiedAds.WebMVC", + ClientName = "ClassifiedAds Web MVC", + AllowedGrantTypes = GrantTypes.Code.Combines(GrantTypes.ResourceOwnerPassword), + RequirePkce = true, + RedirectUris = { - ClientId = "ClassifiedAds.WebMVC", - ClientName = "ClassifiedAds Web MVC", - AllowedGrantTypes = GrantTypes.Code.Combines(GrantTypes.ResourceOwnerPassword), - RequirePkce = true, - RedirectUris = - { - "https://localhost:44364/signin-oidc", - "http://host.docker.internal:9003/signin-oidc", - }, - PostLogoutRedirectUris = - { - "https://localhost:44364/signout-callback-oidc", - "http://host.docker.internal:9003/signout-callback-oidc", - }, - AllowedScopes = - { - IdentityServerConstants.StandardScopes.OpenId, - IdentityServerConstants.StandardScopes.Profile, - "ClassifiedAds.WebAPI", - }, - ClientSecrets = - { - new Secret("secret".Sha256()), - }, - AllowOfflineAccess = true, - RequireConsent = true, - }); - } + "https://localhost:44364/signin-oidc", + "http://host.docker.internal:9003/signin-oidc", + }, + PostLogoutRedirectUris = + { + "https://localhost:44364/signout-callback-oidc", + "http://host.docker.internal:9003/signout-callback-oidc", + }, + AllowedScopes = + { + IdentityServerConstants.StandardScopes.OpenId, + IdentityServerConstants.StandardScopes.Profile, + "ClassifiedAds.WebAPI", + }, + ClientSecrets = + { + new Secret("secret".Sha256()), + }, + AllowOfflineAccess = true, + RequireConsent = true, + }); + } - if (!context.Clients.Any(x => x.ClientId == "ClassifiedAds.BlazorServerSide")) + if (!context.Clients.Any(x => x.ClientId == "ClassifiedAds.BlazorServerSide")) + { + clients.Add(new Client { - clients.Add(new Client + ClientId = "ClassifiedAds.BlazorServerSide", + ClientName = "ClassifiedAds BlazorServerSide", + AllowedGrantTypes = GrantTypes.Code.Combines(GrantTypes.ResourceOwnerPassword), + RequirePkce = true, + RedirectUris = { - ClientId = "ClassifiedAds.BlazorServerSide", - ClientName = "ClassifiedAds BlazorServerSide", - AllowedGrantTypes = GrantTypes.Code.Combines(GrantTypes.ResourceOwnerPassword), - RequirePkce = true, - RedirectUris = - { - "https://localhost:44331/signin-oidc", - "http://host.docker.internal:9008/signin-oidc", - }, - PostLogoutRedirectUris = - { - "https://localhost:44331/signout-callback-oidc", - "http://host.docker.internal:9008/signout-callback-oidc", - }, - AllowedScopes = - { - IdentityServerConstants.StandardScopes.OpenId, - IdentityServerConstants.StandardScopes.Profile, - "ClassifiedAds.WebAPI", - }, - ClientSecrets = - { - new Secret("secret".Sha256()), - }, - AllowOfflineAccess = true, - RequireConsent = true, - }); - } + "https://localhost:44331/signin-oidc", + "http://host.docker.internal:9008/signin-oidc", + }, + PostLogoutRedirectUris = + { + "https://localhost:44331/signout-callback-oidc", + "http://host.docker.internal:9008/signout-callback-oidc", + }, + AllowedScopes = + { + IdentityServerConstants.StandardScopes.OpenId, + IdentityServerConstants.StandardScopes.Profile, + "ClassifiedAds.WebAPI", + }, + ClientSecrets = + { + new Secret("secret".Sha256()), + }, + AllowOfflineAccess = true, + RequireConsent = true, + }); + } - if (!context.Clients.Any(x => x.ClientId == "ClassifiedAds.BlazorWebAssembly")) + if (!context.Clients.Any(x => x.ClientId == "ClassifiedAds.BlazorWebAssembly")) + { + clients.Add(new Client { - clients.Add(new Client - { - ClientId = "ClassifiedAds.BlazorWebAssembly", - ClientName = "ClassifiedAds BlazorWebAssembly", - AllowedGrantTypes = GrantTypes.Code, - RequireClientSecret = false, - RequirePkce = true, - RedirectUris = - { - "https://localhost:44348/authentication/login-callback", - }, - PostLogoutRedirectUris = - { - "https://localhost:44348/authentication/logout-callback", - }, - AllowedScopes = - { - IdentityServerConstants.StandardScopes.OpenId, - IdentityServerConstants.StandardScopes.Profile, - "ClassifiedAds.WebAPI", - }, - ClientSecrets = - { - new Secret("secret".Sha256()), - }, - AllowOfflineAccess = true, - RequireConsent = true, - }); - } + ClientId = "ClassifiedAds.BlazorWebAssembly", + ClientName = "ClassifiedAds BlazorWebAssembly", + AllowedGrantTypes = GrantTypes.Code, + RequireClientSecret = false, + RequirePkce = true, + RedirectUris = + { + "https://localhost:44348/authentication/login-callback", + }, + PostLogoutRedirectUris = + { + "https://localhost:44348/authentication/logout-callback", + }, + AllowedScopes = + { + IdentityServerConstants.StandardScopes.OpenId, + IdentityServerConstants.StandardScopes.Profile, + "ClassifiedAds.WebAPI", + }, + ClientSecrets = + { + new Secret("secret".Sha256()), + }, + AllowOfflineAccess = true, + RequireConsent = true, + }); + } - if (!context.Clients.Any(x => x.ClientId == "ClassifiedAds.Angular")) + if (!context.Clients.Any(x => x.ClientId == "ClassifiedAds.Angular")) + { + clients.Add(new Client { - clients.Add(new Client - { - ClientId = "ClassifiedAds.Angular", - ClientName = "ClassifiedAds Angular", - AllowedGrantTypes = GrantTypes.Code, - RequireClientSecret = false, - RequirePkce = true, - AllowAccessTokensViaBrowser = true, - RedirectUris = - { - "http://localhost:4200/oidc-login-redirect", - }, - PostLogoutRedirectUris = - { - "http://localhost:4200/?postLogout=true", - }, - AllowedCorsOrigins = - { - "http://localhost:4200", - }, - AllowedScopes = - { - IdentityServerConstants.StandardScopes.OpenId, - IdentityServerConstants.StandardScopes.Profile, - "ClassifiedAds.WebAPI", - }, - ClientSecrets = - { - new Secret("secret".Sha256()), - }, - AllowOfflineAccess = true, - RequireConsent = true, - }); - } + ClientId = "ClassifiedAds.Angular", + ClientName = "ClassifiedAds Angular", + AllowedGrantTypes = GrantTypes.Code, + RequireClientSecret = false, + RequirePkce = true, + AllowAccessTokensViaBrowser = true, + RedirectUris = + { + "http://localhost:4200/oidc-login-redirect", + }, + PostLogoutRedirectUris = + { + "http://localhost:4200/?postLogout=true", + }, + AllowedCorsOrigins = + { + "http://localhost:4200", + }, + AllowedScopes = + { + IdentityServerConstants.StandardScopes.OpenId, + IdentityServerConstants.StandardScopes.Profile, + "ClassifiedAds.WebAPI", + }, + ClientSecrets = + { + new Secret("secret".Sha256()), + }, + AllowOfflineAccess = true, + RequireConsent = true, + }); + } - if (!context.Clients.Any(x => x.ClientId == "ClassifiedAds.React")) + if (!context.Clients.Any(x => x.ClientId == "ClassifiedAds.React")) + { + clients.Add(new Client { - clients.Add(new Client - { - ClientId = "ClassifiedAds.React", - ClientName = "ClassifiedAds React", - AllowedGrantTypes = GrantTypes.Code, - RequireClientSecret = false, - RequirePkce = true, - AllowAccessTokensViaBrowser = true, - RedirectUris = - { - "http://localhost:3000/oidc-login-redirect", - }, - PostLogoutRedirectUris = - { - "http://localhost:3000/?postLogout=true", - }, - AllowedCorsOrigins = - { - "http://localhost:3000", - }, - AllowedScopes = - { - IdentityServerConstants.StandardScopes.OpenId, - IdentityServerConstants.StandardScopes.Profile, - "ClassifiedAds.WebAPI", - }, - ClientSecrets = - { - new Secret("secret".Sha256()), - }, - AllowOfflineAccess = true, - RequireConsent = true, - }); - } + ClientId = "ClassifiedAds.React", + ClientName = "ClassifiedAds React", + AllowedGrantTypes = GrantTypes.Code, + RequireClientSecret = false, + RequirePkce = true, + AllowAccessTokensViaBrowser = true, + RedirectUris = + { + "http://localhost:3000/oidc-login-redirect", + }, + PostLogoutRedirectUris = + { + "http://localhost:3000/?postLogout=true", + }, + AllowedCorsOrigins = + { + "http://localhost:3000", + }, + AllowedScopes = + { + IdentityServerConstants.StandardScopes.OpenId, + IdentityServerConstants.StandardScopes.Profile, + "ClassifiedAds.WebAPI", + }, + ClientSecrets = + { + new Secret("secret".Sha256()), + }, + AllowOfflineAccess = true, + RequireConsent = true, + }); + } - if (!context.Clients.Any(x => x.ClientId == "ClassifiedAds.Vue")) + if (!context.Clients.Any(x => x.ClientId == "ClassifiedAds.Vue")) + { + clients.Add(new Client { - clients.Add(new Client - { - ClientId = "ClassifiedAds.Vue", - ClientName = "ClassifiedAds Vue", - AllowedGrantTypes = GrantTypes.Code, - RequireClientSecret = false, - RequirePkce = true, - AllowAccessTokensViaBrowser = true, - RedirectUris = - { - "http://localhost:8080/oidc-login-redirect", - }, - PostLogoutRedirectUris = - { - "http://localhost:8080/?postLogout=true", - }, - AllowedCorsOrigins = - { - "http://localhost:8080", - }, - AllowedScopes = - { - IdentityServerConstants.StandardScopes.OpenId, - IdentityServerConstants.StandardScopes.Profile, - "ClassifiedAds.WebAPI", - }, - ClientSecrets = - { - new Secret("secret".Sha256()), - }, - AllowOfflineAccess = true, - RequireConsent = true, - }); - } + ClientId = "ClassifiedAds.Vue", + ClientName = "ClassifiedAds Vue", + AllowedGrantTypes = GrantTypes.Code, + RequireClientSecret = false, + RequirePkce = true, + AllowAccessTokensViaBrowser = true, + RedirectUris = + { + "http://localhost:8080/oidc-login-redirect", + }, + PostLogoutRedirectUris = + { + "http://localhost:8080/?postLogout=true", + }, + AllowedCorsOrigins = + { + "http://localhost:8080", + }, + AllowedScopes = + { + IdentityServerConstants.StandardScopes.OpenId, + IdentityServerConstants.StandardScopes.Profile, + "ClassifiedAds.WebAPI", + }, + ClientSecrets = + { + new Secret("secret".Sha256()), + }, + AllowOfflineAccess = true, + RequireConsent = true, + }); + } - if (clients.Any()) - { - context.Clients.AddRange(clients.Select(x => x.ToEntity())); - context.SaveChanges(); - } + if (clients.Any()) + { + context.Clients.AddRange(clients.Select(x => x.ToEntity())); + context.SaveChanges(); + } - if (!context.IdentityResources.Any()) + if (!context.IdentityResources.Any()) + { + var identityResources = new List() { - var identityResources = new List() - { - new IdentityResources.OpenId(), - new IdentityResources.Profile(), - }; + new IdentityResources.OpenId(), + new IdentityResources.Profile(), + }; - context.IdentityResources.AddRange(identityResources.Select(x => x.ToEntity())); + context.IdentityResources.AddRange(identityResources.Select(x => x.ToEntity())); - context.SaveChanges(); - } + context.SaveChanges(); + } - if (!context.ApiScopes.Any()) + if (!context.ApiScopes.Any()) + { + var apiScopes = new List() { - var apiScopes = new List() - { - new ApiScope("ClassifiedAds.WebAPI", "ClassifiedAds Web API"), - }; + new ApiScope("ClassifiedAds.WebAPI", "ClassifiedAds Web API"), + }; - context.ApiScopes.AddRange(apiScopes.Select(x => x.ToEntity())); - context.SaveChanges(); - } + context.ApiScopes.AddRange(apiScopes.Select(x => x.ToEntity())); + context.SaveChanges(); + } - if (!context.ApiResources.Any()) + if (!context.ApiResources.Any()) + { + var apiResources = new List { - var apiResources = new List + new ApiResource("ClassifiedAds.WebAPI", "ClassifiedAds Web API", new[] { "role" }) { - new ApiResource("ClassifiedAds.WebAPI", "ClassifiedAds Web API", new[] { "role" }) - { - Scopes = { "ClassifiedAds.WebAPI" }, - }, - }; + Scopes = { "ClassifiedAds.WebAPI" }, + }, + }; - context.ApiResources.AddRange(apiResources.Select(x => x.ToEntity())); + context.ApiResources.AddRange(apiResources.Select(x => x.ToEntity())); - context.SaveChanges(); - } + context.SaveChanges(); } } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/Locks/LockManager.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/Locks/LockManager.cs index 07451a363..01365c5dc 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/Locks/LockManager.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/Locks/LockManager.cs @@ -5,22 +5,22 @@ using System; using System.Data; -namespace ClassifiedAds.Persistence.Locks +namespace ClassifiedAds.Persistence.Locks; + +public class LockManager : ILockManager { - public class LockManager : ILockManager - { - private readonly AdsDbContext _dbContext; - private readonly IDateTimeProvider _dateTimeProvider; + private readonly AdsDbContext _dbContext; + private readonly IDateTimeProvider _dateTimeProvider; - public LockManager(AdsDbContext dbContext, IDateTimeProvider dateTimeProvider) - { - _dbContext = dbContext; - _dateTimeProvider = dateTimeProvider; - } + public LockManager(AdsDbContext dbContext, IDateTimeProvider dateTimeProvider) + { + _dbContext = dbContext; + _dateTimeProvider = dateTimeProvider; + } - private void CreateLock(string entityName, string entityId) - { - string sql = @" + private void CreateLock(string entityName, string entityId) + { + string sql = @" merge into [dbo].[Locks] with (holdlock) t using @@ -31,24 +31,24 @@ when not matched then insert ([EntityName], [EntityId]) values (s.[EntityName], s.[EntityId]); "; - _dbContext.Database.ExecuteSqlRaw(sql, - new SqlParameter("entityName", entityName), - new SqlParameter("entityId", entityId)); - } + _dbContext.Database.ExecuteSqlRaw(sql, + new SqlParameter("entityName", entityName), + new SqlParameter("entityId", entityId)); + } - public bool AcquireLock(string entityName, string entityId, string ownerId, TimeSpan expirationIn) - { - CreateLock(entityName, entityId); + public bool AcquireLock(string entityName, string entityId, string ownerId, TimeSpan expirationIn) + { + CreateLock(entityName, entityId); - if (ExtendLock(entityName, entityId, ownerId, expirationIn)) - { - return true; - } + if (ExtendLock(entityName, entityId, ownerId, expirationIn)) + { + return true; + } - var now = _dateTimeProvider.OffsetNow; - var expired = now + expirationIn; + var now = _dateTimeProvider.OffsetNow; + var expired = now + expirationIn; - string sql = @" + string sql = @" Update Locks set OwnerId = @OwnerId, AcquiredDateTime = @AcquiredDateTime, ExpiredDateTime = @ExpiredDateTime @@ -56,39 +56,39 @@ public bool AcquireLock(string entityName, string entityId, string ownerId, Time and EntityName = @EntityName and (OwnerId is NULL or ExpiredDateTime < @AcquiredDateTime)"; - var rs = _dbContext.Database.ExecuteSqlRaw(sql, - new SqlParameter("EntityName", entityName), - new SqlParameter("EntityId", entityId), - new SqlParameter("OwnerId", ownerId), - new SqlParameter("AcquiredDateTime", SqlDbType.DateTimeOffset) { Value = now }, - new SqlParameter("ExpiredDateTime", SqlDbType.DateTimeOffset) { Value = expired }); + var rs = _dbContext.Database.ExecuteSqlRaw(sql, + new SqlParameter("EntityName", entityName), + new SqlParameter("EntityId", entityId), + new SqlParameter("OwnerId", ownerId), + new SqlParameter("AcquiredDateTime", SqlDbType.DateTimeOffset) { Value = now }, + new SqlParameter("ExpiredDateTime", SqlDbType.DateTimeOffset) { Value = expired }); - return rs > 0; - } + return rs > 0; + } - public bool ExtendLock(string entityName, string entityId, string ownerId, TimeSpan expirationIn) - { - var now = _dateTimeProvider.OffsetNow; - var expired = now + expirationIn; + public bool ExtendLock(string entityName, string entityId, string ownerId, TimeSpan expirationIn) + { + var now = _dateTimeProvider.OffsetNow; + var expired = now + expirationIn; - string sql = @" + string sql = @" Update Locks set ExpiredDateTime = @ExpiredDateTime where EntityId = @EntityId and EntityName = @EntityName and OwnerId = @OwnerId"; - var rs = _dbContext.Database.ExecuteSqlRaw(sql, - new SqlParameter("EntityName", entityName), - new SqlParameter("EntityId", entityId), - new SqlParameter("OwnerId", ownerId), - new SqlParameter("ExpiredDateTime", SqlDbType.DateTimeOffset) { Value = expired }); + var rs = _dbContext.Database.ExecuteSqlRaw(sql, + new SqlParameter("EntityName", entityName), + new SqlParameter("EntityId", entityId), + new SqlParameter("OwnerId", ownerId), + new SqlParameter("ExpiredDateTime", SqlDbType.DateTimeOffset) { Value = expired }); - return rs > 0; - } + return rs > 0; + } - public bool ReleaseLock(string entityName, string entityId, string ownerId) - { - string sql = @" + public bool ReleaseLock(string entityName, string entityId, string ownerId) + { + string sql = @" Update Locks set OwnerId = NULL, AcquiredDateTime = NULL, ExpiredDateTime = NULL @@ -96,50 +96,49 @@ public bool ReleaseLock(string entityName, string entityId, string ownerId) and EntityName = @EntityName and OwnerId = @OwnerId"; - _ = _dbContext.Database.ExecuteSqlRaw(sql, - new SqlParameter("EntityName", entityName), - new SqlParameter("EntityId", entityId), - new SqlParameter("OwnerId", ownerId)); + _ = _dbContext.Database.ExecuteSqlRaw(sql, + new SqlParameter("EntityName", entityName), + new SqlParameter("EntityId", entityId), + new SqlParameter("OwnerId", ownerId)); - return true; - } + return true; + } - public bool ReleaseLocks(string ownerId) - { - string sql = @" + public bool ReleaseLocks(string ownerId) + { + string sql = @" Update Locks set OwnerId = NULL, AcquiredDateTime = NULL, ExpiredDateTime = NULL where OwnerId = @OwnerId"; - _ = _dbContext.Database.ExecuteSqlRaw(sql, - new SqlParameter("OwnerId", ownerId)); + _ = _dbContext.Database.ExecuteSqlRaw(sql, + new SqlParameter("OwnerId", ownerId)); - return true; - } + return true; + } - public bool ReleaseExpiredLocks() - { - var now = _dateTimeProvider.OffsetNow; + public bool ReleaseExpiredLocks() + { + var now = _dateTimeProvider.OffsetNow; - string sql = @" + string sql = @" Update Locks set OwnerId = NULL, AcquiredDateTime = NULL, ExpiredDateTime = NULL where ExpiredDateTime < @now"; - _ = _dbContext.Database.ExecuteSqlRaw(sql, - new SqlParameter("now", SqlDbType.DateTimeOffset) { Value = now }); + _ = _dbContext.Database.ExecuteSqlRaw(sql, + new SqlParameter("now", SqlDbType.DateTimeOffset) { Value = now }); - return true; - } + return true; + } - public void EnsureAcquiringLock(string entityName, string entityId, string ownerId, TimeSpan expirationIn) + public void EnsureAcquiringLock(string entityName, string entityId, string ownerId, TimeSpan expirationIn) + { + if (!AcquireLock(entityName, entityId, ownerId, expirationIn)) { - if (!AcquireLock(entityName, entityId, ownerId, expirationIn)) - { - throw new CouldNotAcquireLockException(); - } + throw new CouldNotAcquireLockException(); } } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/Locks/SqlDistributedLock.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/Locks/SqlDistributedLock.cs index a9f6e5141..672a50383 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/Locks/SqlDistributedLock.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/Locks/SqlDistributedLock.cs @@ -4,139 +4,138 @@ using System; using System.Data; -namespace ClassifiedAds.Persistence.Locks +namespace ClassifiedAds.Persistence.Locks; + +public class SqlDistributedLock : IDistributedLock { - public class SqlDistributedLock : IDistributedLock - { - public const int AlreadyHeldReturnCode = 103; + public const int AlreadyHeldReturnCode = 103; - private readonly SqlConnection _connection; - private readonly SqlTransaction _transaction; - private readonly string _connectionString; + private readonly SqlConnection _connection; + private readonly SqlTransaction _transaction; + private readonly string _connectionString; - public bool HasTransaction + public bool HasTransaction + { + get { - get - { - return _transaction != null; - } + return _transaction != null; } + } - public SqlDistributedLock(SqlConnection connection) - { - _connection = connection; - } + public SqlDistributedLock(SqlConnection connection) + { + _connection = connection; + } + + public SqlDistributedLock(SqlTransaction transaction) + { + _transaction = transaction; + _connection = _transaction.Connection; + } + + public SqlDistributedLock(string connectionString) + { + _connectionString = connectionString; + _connection = new SqlConnection(connectionString); + } + + public IDistributedLockScope Acquire(string lockName) + { + SqlParameter returnValue; + var acquireCommand = CreateAcquireCommand(0, lockName, -1, out returnValue); + + acquireCommand.ExecuteNonQuery(); - public SqlDistributedLock(SqlTransaction transaction) + if (ParseReturnCode((int)returnValue.Value)) { - _transaction = transaction; - _connection = _transaction.Connection; + return new SqlDistributedLockScope(_connection, _transaction, lockName); } - - public SqlDistributedLock(string connectionString) + else { - _connectionString = connectionString; - _connection = new SqlConnection(connectionString); + return null; } + } + + public IDistributedLockScope TryAcquire(string lockName) + { + SqlParameter returnValue; + var acquireCommand = CreateAcquireCommand(30, lockName, 0, out returnValue); - public IDistributedLockScope Acquire(string lockName) + acquireCommand.ExecuteNonQuery(); + + if (ParseReturnCode((int)returnValue.Value)) { - SqlParameter returnValue; - var acquireCommand = CreateAcquireCommand(0, lockName, -1, out returnValue); - - acquireCommand.ExecuteNonQuery(); - - if (ParseReturnCode((int)returnValue.Value)) - { - return new SqlDistributedLockScope(_connection, _transaction, lockName); - } - else - { - return null; - } + return new SqlDistributedLockScope(_connection, _transaction, lockName); } - - public IDistributedLockScope TryAcquire(string lockName) + else { - SqlParameter returnValue; - var acquireCommand = CreateAcquireCommand(30, lockName, 0, out returnValue); - - acquireCommand.ExecuteNonQuery(); - - if (ParseReturnCode((int)returnValue.Value)) - { - return new SqlDistributedLockScope(_connection, _transaction, lockName); - } - else - { - return null; - } + return null; } + } - private SqlCommand CreateAcquireCommand(int commandTimeout, string lockName, int lockTimeout, out SqlParameter returnValue) - { - _connection.EnsureOpen(); + private SqlCommand CreateAcquireCommand(int commandTimeout, string lockName, int lockTimeout, out SqlParameter returnValue) + { + _connection.EnsureOpen(); - SqlCommand command = _connection.CreateCommand(); - command.Transaction = _transaction; + SqlCommand command = _connection.CreateCommand(); + command.Transaction = _transaction; - returnValue = command.Parameters.Add(new SqlParameter { ParameterName = "Result", DbType = DbType.Int32, Direction = ParameterDirection.Output }); - command.CommandText = - $@"IF APPLOCK_MODE('public', @Resource, @LockOwner) != 'NoLock' {(HasTransaction ? " OR APPLOCK_MODE('public', @Resource, 'Session') != 'NoLock'" : string.Empty)} + returnValue = command.Parameters.Add(new SqlParameter { ParameterName = "Result", DbType = DbType.Int32, Direction = ParameterDirection.Output }); + command.CommandText = + $@"IF APPLOCK_MODE('public', @Resource, @LockOwner) != 'NoLock' {(HasTransaction ? " OR APPLOCK_MODE('public', @Resource, 'Session') != 'NoLock'" : string.Empty)} SET @Result = {AlreadyHeldReturnCode} ELSE EXEC @Result = dbo.sp_getapplock @Resource = @Resource, @LockMode = @LockMode, @LockOwner = @LockOwner, @LockTimeout = @LockTimeout, @DbPrincipal = 'public'" - ; + ; + + command.CommandTimeout = commandTimeout; - command.CommandTimeout = commandTimeout; + command.Parameters.Add(new SqlParameter("Resource", lockName)); + command.Parameters.Add(new SqlParameter("LockMode", "Exclusive")); + command.Parameters.Add(new SqlParameter("LockOwner", HasTransaction ? "Transaction" : "Session")); + command.Parameters.Add(new SqlParameter("LockTimeout", lockTimeout)); - command.Parameters.Add(new SqlParameter("Resource", lockName)); - command.Parameters.Add(new SqlParameter("LockMode", "Exclusive")); - command.Parameters.Add(new SqlParameter("LockOwner", HasTransaction ? "Transaction" : "Session")); - command.Parameters.Add(new SqlParameter("LockTimeout", lockTimeout)); + return command; + } - return command; + /// + /// sp_getapplock exit codes documented at + /// https://docs.microsoft.com/en-us/sql/relational-databases/system-stored-procedures/sp-getapplock-transact-sql#return-code-values + /// + /// code returned after calling sp_getapplock + /// true/false + public static bool ParseReturnCode(int returnCode) + { + switch (returnCode) + { + case 0: + case 1: + return true; + case -1: + return false; + case -2: + throw new OperationCanceledException("The lock request was canceled."); + case -3: + throw new Exception("The lock request was chosen as a deadlock victim."); + case -999: + throw new ArgumentException("parameter validation or other error"); + case AlreadyHeldReturnCode: + return false; } - /// - /// sp_getapplock exit codes documented at - /// https://docs.microsoft.com/en-us/sql/relational-databases/system-stored-procedures/sp-getapplock-transact-sql#return-code-values - /// - /// code returned after calling sp_getapplock - /// true/false - public static bool ParseReturnCode(int returnCode) + if (returnCode <= 0) { - switch (returnCode) - { - case 0: - case 1: - return true; - case -1: - return false; - case -2: - throw new OperationCanceledException("The lock request was canceled."); - case -3: - throw new Exception("The lock request was chosen as a deadlock victim."); - case -999: - throw new ArgumentException("parameter validation or other error"); - case AlreadyHeldReturnCode: - return false; - } - - if (returnCode <= 0) - { - throw new InvalidOperationException($"Could not acquire lock with return code: {returnCode}"); - } - - return false; + throw new InvalidOperationException($"Could not acquire lock with return code: {returnCode}"); } - public void Dispose() + return false; + } + + public void Dispose() + { + if (!string.IsNullOrEmpty(_connectionString)) { - if (!string.IsNullOrEmpty(_connectionString)) - { - _connection.Dispose(); - } + _connection.Dispose(); } } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/Locks/SqlDistributedLockScope.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/Locks/SqlDistributedLockScope.cs index 632de23ee..315b23dfc 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/Locks/SqlDistributedLockScope.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/Locks/SqlDistributedLockScope.cs @@ -3,107 +3,106 @@ using System; using System.Data; -namespace ClassifiedAds.Persistence.Locks +namespace ClassifiedAds.Persistence.Locks; + +public class SqlDistributedLockScope : IDistributedLockScope { - public class SqlDistributedLockScope : IDistributedLockScope - { - private readonly SqlConnection _connection; - private readonly SqlTransaction _transaction; - private readonly string _lockName; + private readonly SqlConnection _connection; + private readonly SqlTransaction _transaction; + private readonly string _lockName; - public bool HasTransaction + public bool HasTransaction + { + get { - get - { - return _transaction != null; - } + return _transaction != null; } + } + + public SqlDistributedLockScope(SqlConnection connection, SqlTransaction transaction, string lockName) + { + _connection = connection; + _transaction = transaction; + _lockName = lockName; + } - public SqlDistributedLockScope(SqlConnection connection, SqlTransaction transaction, string lockName) + public void Dispose() + { + if (HasTransaction) { - _connection = connection; - _transaction = transaction; - _lockName = lockName; + return; } - public void Dispose() + SqlParameter returnValue; + var releaseCommand = CreateReleaseCommand(_lockName, false, out returnValue); + releaseCommand.ExecuteNonQuery(); + + if (ParseReturnCode((int)returnValue.Value)) { - if (HasTransaction) - { - return; - } - - SqlParameter returnValue; - var releaseCommand = CreateReleaseCommand(_lockName, false, out returnValue); - releaseCommand.ExecuteNonQuery(); - - if (ParseReturnCode((int)returnValue.Value)) - { - } } + } - public bool StillHoldingLock() - { - var command = _connection.CreateCommand(); - command.Transaction = _transaction; + public bool StillHoldingLock() + { + var command = _connection.CreateCommand(); + command.Transaction = _transaction; - command.CommandText = @"SELECT APPLOCK_MODE('public', @Resource, @LockOwner)"; - command.Parameters.Add(new SqlParameter("Resource", _lockName)); - command.Parameters.Add(new SqlParameter("LockOwner", HasTransaction ? "Transaction" : "Session")); - var lockMode = (string)command.ExecuteScalar(); + command.CommandText = @"SELECT APPLOCK_MODE('public', @Resource, @LockOwner)"; + command.Parameters.Add(new SqlParameter("Resource", _lockName)); + command.Parameters.Add(new SqlParameter("LockOwner", HasTransaction ? "Transaction" : "Session")); + var lockMode = (string)command.ExecuteScalar(); - return lockMode != "NoLock"; - } + return lockMode != "NoLock"; + } - private SqlCommand CreateReleaseCommand(string lockName, bool isTry, out SqlParameter returnValue) - { - var command = _connection.CreateCommand(); - command.Transaction = _transaction; + private SqlCommand CreateReleaseCommand(string lockName, bool isTry, out SqlParameter returnValue) + { + var command = _connection.CreateCommand(); + command.Transaction = _transaction; - if (isTry) - { - command.CommandText = - @"IF APPLOCK_MODE('public', @Resource, @LockOwner) != 'NoLock' + if (isTry) + { + command.CommandText = + @"IF APPLOCK_MODE('public', @Resource, @LockOwner) != 'NoLock' EXEC @Result = dbo.sp_releaseapplock @Resource, @LockOwner ELSE SET @Result = 0" - ; - } - else - { - command.CommandText = "dbo.sp_releaseapplock"; - command.CommandType = CommandType.StoredProcedure; - } - - command.Parameters.Add(new SqlParameter("Resource", lockName)); - command.Parameters.Add(new SqlParameter("LockOwner", HasTransaction ? "Transaction" : "Session")); - - if (isTry) - { - returnValue = command.Parameters.Add(new SqlParameter { ParameterName = "Result", DbType = DbType.Int32, Direction = ParameterDirection.Output }); - } - else - { - returnValue = command.Parameters.Add(new SqlParameter { DbType = DbType.Int32, Direction = ParameterDirection.ReturnValue }); - } - - return command; + ; } + else + { + command.CommandText = "dbo.sp_releaseapplock"; + command.CommandType = CommandType.StoredProcedure; + } + + command.Parameters.Add(new SqlParameter("Resource", lockName)); + command.Parameters.Add(new SqlParameter("LockOwner", HasTransaction ? "Transaction" : "Session")); - /// - /// sp_releaseapplock exit codes documented at - /// https://docs.microsoft.com/en-us/sql/relational-databases/system-stored-procedures/sp-releaseapplock-transact-sql#return-code-values - /// - /// code returned after calling sp_releaseapplock - /// true/false - public static bool ParseReturnCode(int returnCode) + if (isTry) + { + returnValue = command.Parameters.Add(new SqlParameter { ParameterName = "Result", DbType = DbType.Int32, Direction = ParameterDirection.Output }); + } + else { - if (returnCode >= 0) - { - return true; - } + returnValue = command.Parameters.Add(new SqlParameter { DbType = DbType.Int32, Direction = ParameterDirection.ReturnValue }); + } + + return command; + } - throw new InvalidOperationException($"Could not release lock with return code: {returnCode}"); + /// + /// sp_releaseapplock exit codes documented at + /// https://docs.microsoft.com/en-us/sql/relational-databases/system-stored-procedures/sp-releaseapplock-transact-sql#return-code-values + /// + /// code returned after calling sp_releaseapplock + /// true/false + public static bool ParseReturnCode(int returnCode) + { + if (returnCode >= 0) + { + return true; } + + throw new InvalidOperationException($"Could not release lock with return code: {returnCode}"); } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/MappingConfigurations/AuditLogEntryConfiguration.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/MappingConfigurations/AuditLogEntryConfiguration.cs index d33fc562f..2936feb28 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/MappingConfigurations/AuditLogEntryConfiguration.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/MappingConfigurations/AuditLogEntryConfiguration.cs @@ -2,14 +2,13 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata.Builders; -namespace ClassifiedAds.Persistence.MappingConfigurations +namespace ClassifiedAds.Persistence.MappingConfigurations; + +public class AuditLogEntryConfiguration : IEntityTypeConfiguration { - public class AuditLogEntryConfiguration : IEntityTypeConfiguration + public void Configure(EntityTypeBuilder builder) { - public void Configure(EntityTypeBuilder builder) - { - builder.ToTable("AuditLogEntries"); - builder.Property(x => x.Id).HasDefaultValueSql("newsequentialid()"); - } + builder.ToTable("AuditLogEntries"); + builder.Property(x => x.Id).HasDefaultValueSql("newsequentialid()"); } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/MappingConfigurations/CircuitBreakerConfiguration.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/MappingConfigurations/CircuitBreakerConfiguration.cs index 5fe4e1aa5..5b943193d 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/MappingConfigurations/CircuitBreakerConfiguration.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/MappingConfigurations/CircuitBreakerConfiguration.cs @@ -2,14 +2,13 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata.Builders; -namespace ClassifiedAds.Persistence.MappingConfigurations +namespace ClassifiedAds.Persistence.MappingConfigurations; + +public class CircuitBreakerConfiguration : IEntityTypeConfiguration { - public class CircuitBreakerConfiguration : IEntityTypeConfiguration + public void Configure(EntityTypeBuilder builder) { - public void Configure(EntityTypeBuilder builder) - { - builder.ToTable("CircuitBreakers"); - builder.HasIndex(x => new { x.Name }).IsUnique(); - } + builder.ToTable("CircuitBreakers"); + builder.HasIndex(x => new { x.Name }).IsUnique(); } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/MappingConfigurations/CircuitBreakerLogConfiguration.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/MappingConfigurations/CircuitBreakerLogConfiguration.cs index ed51af968..3bd432369 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/MappingConfigurations/CircuitBreakerLogConfiguration.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/MappingConfigurations/CircuitBreakerLogConfiguration.cs @@ -2,13 +2,12 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata.Builders; -namespace ClassifiedAds.Persistence.MappingConfigurations +namespace ClassifiedAds.Persistence.MappingConfigurations; + +public class CircuitBreakerLogConfiguration : IEntityTypeConfiguration { - public class CircuitBreakerLogConfiguration : IEntityTypeConfiguration + public void Configure(EntityTypeBuilder builder) { - public void Configure(EntityTypeBuilder builder) - { - builder.ToTable("CircuitBreakerLogs"); - } + builder.ToTable("CircuitBreakerLogs"); } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/MappingConfigurations/ConfigurationEntryConfiguration.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/MappingConfigurations/ConfigurationEntryConfiguration.cs index 6466acc3f..03fd97da5 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/MappingConfigurations/ConfigurationEntryConfiguration.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/MappingConfigurations/ConfigurationEntryConfiguration.cs @@ -4,25 +4,24 @@ using System; using System.Collections.Generic; -namespace ClassifiedAds.Persistence.MappingConfigurations +namespace ClassifiedAds.Persistence.MappingConfigurations; + +public class ConfigurationEntryConfiguration : IEntityTypeConfiguration { - public class ConfigurationEntryConfiguration : IEntityTypeConfiguration + public void Configure(EntityTypeBuilder builder) { - public void Configure(EntityTypeBuilder builder) - { - builder.ToTable("ConfigurationEntries"); - builder.Property(x => x.Id).HasDefaultValueSql("newsequentialid()"); + builder.ToTable("ConfigurationEntries"); + builder.Property(x => x.Id).HasDefaultValueSql("newsequentialid()"); - // Seed - builder.HasData(new List + // Seed + builder.HasData(new List + { + new ConfigurationEntry { - new ConfigurationEntry - { - Id = Guid.Parse("8A051AA5-BCD1-EA11-B098-AC728981BD15"), - Key = "SecurityHeaders:Test-Read-From-SqlServer", - Value = "this-is-read-from-sqlserver", - }, - }); - } + Id = Guid.Parse("8A051AA5-BCD1-EA11-B098-AC728981BD15"), + Key = "SecurityHeaders:Test-Read-From-SqlServer", + Value = "this-is-read-from-sqlserver", + }, + }); } } \ No newline at end of file diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/MappingConfigurations/CustomMigrationHistoryConfiguration.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/MappingConfigurations/CustomMigrationHistoryConfiguration.cs index 6cc893f33..1cf7118cc 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/MappingConfigurations/CustomMigrationHistoryConfiguration.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/MappingConfigurations/CustomMigrationHistoryConfiguration.cs @@ -2,14 +2,13 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata.Builders; -namespace ClassifiedAds.Persistence.MappingConfigurations +namespace ClassifiedAds.Persistence.MappingConfigurations; + +public class CustomMigrationHistoryConfiguration : IEntityTypeConfiguration { - public class CustomMigrationHistoryConfiguration : IEntityTypeConfiguration + public void Configure(EntityTypeBuilder builder) { - public void Configure(EntityTypeBuilder builder) - { - builder.ToTable("_CustomMigrationHistories"); - builder.Property(x => x.Id).HasDefaultValueSql("newsequentialid()"); - } + builder.ToTable("_CustomMigrationHistories"); + builder.Property(x => x.Id).HasDefaultValueSql("newsequentialid()"); } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/MappingConfigurations/LocalizationEntryConfiguration.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/MappingConfigurations/LocalizationEntryConfiguration.cs index c2b759a19..568c3329d 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/MappingConfigurations/LocalizationEntryConfiguration.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/MappingConfigurations/LocalizationEntryConfiguration.cs @@ -4,33 +4,32 @@ using System; using System.Collections.Generic; -namespace ClassifiedAds.Persistence.MappingConfigurations +namespace ClassifiedAds.Persistence.MappingConfigurations; + +public class LocalizationEntryConfiguration : IEntityTypeConfiguration { - public class LocalizationEntryConfiguration : IEntityTypeConfiguration + public void Configure(EntityTypeBuilder builder) { - public void Configure(EntityTypeBuilder builder) - { - builder.ToTable("LocalizationEntries"); - builder.Property(x => x.Id).HasDefaultValueSql("newsequentialid()"); + builder.ToTable("LocalizationEntries"); + builder.Property(x => x.Id).HasDefaultValueSql("newsequentialid()"); - // Seed - builder.HasData(new List + // Seed + builder.HasData(new List + { + new LocalizationEntry + { + Id = Guid.Parse("29A4AACB-4DDF-4F85-ACED-C5283A8BDD7F"), + Name = "Test", + Value = "Test", + Culture = "en-US", + }, + new LocalizationEntry { - new LocalizationEntry - { - Id = Guid.Parse("29A4AACB-4DDF-4F85-ACED-C5283A8BDD7F"), - Name = "Test", - Value = "Test", - Culture = "en-US", - }, - new LocalizationEntry - { - Id = Guid.Parse("5A262D8A-B0D9-45D3-8C0E-18B2C882B9FE"), - Name = "Test", - Value = "Kiem Tra", - Culture = "vi-VN", - }, - }); - } + Id = Guid.Parse("5A262D8A-B0D9-45D3-8C0E-18B2C882B9FE"), + Name = "Test", + Value = "Kiem Tra", + Culture = "vi-VN", + }, + }); } } \ No newline at end of file diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/MappingConfigurations/LockConfiguration.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/MappingConfigurations/LockConfiguration.cs index bb3dc8894..254981c07 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/MappingConfigurations/LockConfiguration.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/MappingConfigurations/LockConfiguration.cs @@ -2,15 +2,14 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata.Builders; -namespace ClassifiedAds.Persistence.MappingConfigurations +namespace ClassifiedAds.Persistence.MappingConfigurations; + +public class LockConfiguration : IEntityTypeConfiguration { - public class LockConfiguration : IEntityTypeConfiguration + public void Configure(EntityTypeBuilder builder) { - public void Configure(EntityTypeBuilder builder) - { - builder.ToTable("Locks"); - builder.HasKey(x => new { x.EntityId, x.EntityName }); - builder.HasIndex(x => new { x.OwnerId }); - } + builder.ToTable("Locks"); + builder.HasKey(x => new { x.EntityId, x.EntityName }); + builder.HasIndex(x => new { x.OwnerId }); } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/MappingConfigurations/OutboxEventConfiguration.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/MappingConfigurations/OutboxEventConfiguration.cs index ac93f772c..3596280ca 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/MappingConfigurations/OutboxEventConfiguration.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/MappingConfigurations/OutboxEventConfiguration.cs @@ -2,14 +2,13 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata.Builders; -namespace ClassifiedAds.Persistence.MappingConfigurations +namespace ClassifiedAds.Persistence.MappingConfigurations; + +public class OutboxEventConfiguration : IEntityTypeConfiguration { - public class OutboxEventConfiguration : IEntityTypeConfiguration + public void Configure(EntityTypeBuilder builder) { - public void Configure(EntityTypeBuilder builder) - { - builder.ToTable("OutboxEvents"); - builder.Property(x => x.Id).HasDefaultValueSql("newsequentialid()"); - } + builder.ToTable("OutboxEvents"); + builder.Property(x => x.Id).HasDefaultValueSql("newsequentialid()"); } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/MappingConfigurations/PasswordHistoryConfiguration.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/MappingConfigurations/PasswordHistoryConfiguration.cs index 712067f75..91002e9af 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/MappingConfigurations/PasswordHistoryConfiguration.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/MappingConfigurations/PasswordHistoryConfiguration.cs @@ -2,14 +2,13 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata.Builders; -namespace ClassifiedAds.Persistence.MappingConfigurations +namespace ClassifiedAds.Persistence.MappingConfigurations; + +public class PasswordHistoryConfiguration : IEntityTypeConfiguration { - public class PasswordHistoryConfiguration : IEntityTypeConfiguration + public void Configure(EntityTypeBuilder builder) { - public void Configure(EntityTypeBuilder builder) - { - builder.ToTable("PasswordHistories"); - builder.Property(x => x.Id).HasDefaultValueSql("newsequentialid()"); - } + builder.ToTable("PasswordHistories"); + builder.Property(x => x.Id).HasDefaultValueSql("newsequentialid()"); } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/MappingConfigurations/RoleClaimConfiguration.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/MappingConfigurations/RoleClaimConfiguration.cs index b59e5456a..b23b564df 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/MappingConfigurations/RoleClaimConfiguration.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/MappingConfigurations/RoleClaimConfiguration.cs @@ -2,14 +2,13 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata.Builders; -namespace ClassifiedAds.Persistence.MappingConfigurations +namespace ClassifiedAds.Persistence.MappingConfigurations; + +public class RoleClaimConfiguration : IEntityTypeConfiguration { - public class RoleClaimConfiguration : IEntityTypeConfiguration + public void Configure(EntityTypeBuilder builder) { - public void Configure(EntityTypeBuilder builder) - { - builder.ToTable("RoleClaims"); - builder.Property(x => x.Id).HasDefaultValueSql("newsequentialid()"); - } + builder.ToTable("RoleClaims"); + builder.Property(x => x.Id).HasDefaultValueSql("newsequentialid()"); } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/MappingConfigurations/RoleConfiguration.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/MappingConfigurations/RoleConfiguration.cs index 57d5e6351..dfee4a396 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/MappingConfigurations/RoleConfiguration.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/MappingConfigurations/RoleConfiguration.cs @@ -2,22 +2,21 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata.Builders; -namespace ClassifiedAds.Persistence.MappingConfigurations +namespace ClassifiedAds.Persistence.MappingConfigurations; + +public class RoleConfiguration : IEntityTypeConfiguration { - public class RoleConfiguration : IEntityTypeConfiguration + public void Configure(EntityTypeBuilder builder) { - public void Configure(EntityTypeBuilder builder) - { - builder.ToTable("Roles"); - builder.Property(x => x.Id).HasDefaultValueSql("newsequentialid()"); + builder.ToTable("Roles"); + builder.Property(x => x.Id).HasDefaultValueSql("newsequentialid()"); - builder.HasMany(x => x.Claims) - .WithOne(x => x.Role) - .OnDelete(DeleteBehavior.Cascade); + builder.HasMany(x => x.Claims) + .WithOne(x => x.Role) + .OnDelete(DeleteBehavior.Cascade); - builder.HasMany(x => x.UserRoles) - .WithOne(x => x.Role) - .OnDelete(DeleteBehavior.Cascade); - } + builder.HasMany(x => x.UserRoles) + .WithOne(x => x.Role) + .OnDelete(DeleteBehavior.Cascade); } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/MappingConfigurations/UserClaimConfiguration.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/MappingConfigurations/UserClaimConfiguration.cs index e54c53c82..17bec66c8 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/MappingConfigurations/UserClaimConfiguration.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/MappingConfigurations/UserClaimConfiguration.cs @@ -2,14 +2,13 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata.Builders; -namespace ClassifiedAds.Persistence.MappingConfigurations +namespace ClassifiedAds.Persistence.MappingConfigurations; + +public class UserClaimConfiguration : IEntityTypeConfiguration { - public class UserClaimConfiguration : IEntityTypeConfiguration + public void Configure(EntityTypeBuilder builder) { - public void Configure(EntityTypeBuilder builder) - { - builder.ToTable("UserClaims"); - builder.Property(x => x.Id).HasDefaultValueSql("newsequentialid()"); - } + builder.ToTable("UserClaims"); + builder.Property(x => x.Id).HasDefaultValueSql("newsequentialid()"); } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/MappingConfigurations/UserConfiguration.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/MappingConfigurations/UserConfiguration.cs index bc37e3700..e17d2aba8 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/MappingConfigurations/UserConfiguration.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/MappingConfigurations/UserConfiguration.cs @@ -4,38 +4,37 @@ using System; using System.Collections.Generic; -namespace ClassifiedAds.Persistence.MappingConfigurations +namespace ClassifiedAds.Persistence.MappingConfigurations; + +public class UserConfiguration : IEntityTypeConfiguration { - public class UserConfiguration : IEntityTypeConfiguration + public void Configure(EntityTypeBuilder builder) { - public void Configure(EntityTypeBuilder builder) - { - builder.ToTable("Users"); - builder.Property(x => x.Id).HasDefaultValueSql("newsequentialid()"); + builder.ToTable("Users"); + builder.Property(x => x.Id).HasDefaultValueSql("newsequentialid()"); - builder.HasMany(x => x.Claims) - .WithOne(x => x.User) - .OnDelete(DeleteBehavior.Cascade); + builder.HasMany(x => x.Claims) + .WithOne(x => x.User) + .OnDelete(DeleteBehavior.Cascade); - builder.HasMany(x => x.UserRoles) - .WithOne(x => x.User) - .OnDelete(DeleteBehavior.Cascade); + builder.HasMany(x => x.UserRoles) + .WithOne(x => x.User) + .OnDelete(DeleteBehavior.Cascade); - // Seed - builder.HasData(new List + // Seed + builder.HasData(new List + { + new User { - new User - { - Id = Guid.Parse("12837D3D-793F-EA11-BECB-5CEA1D05F660"), - UserName = "phong@gmail.com", - NormalizedUserName = "PHONG@GMAIL.COM", - Email = "phong@gmail.com", - NormalizedEmail = "PHONG@GMAIL.COM", - PasswordHash = "AQAAAAEAACcQAAAAELBcKuXWkiRQEYAkD/qKs9neac5hxWs3bkegIHpGLtf+zFHuKnuI3lBqkWO9TMmFAQ==", // v*7Un8b4rcN@<-RN - SecurityStamp = "5M2QLL65J6H6VFIS7VZETKXY27KNVVYJ", - LockoutEnabled = true, - }, - }); - } + Id = Guid.Parse("12837D3D-793F-EA11-BECB-5CEA1D05F660"), + UserName = "phong@gmail.com", + NormalizedUserName = "PHONG@GMAIL.COM", + Email = "phong@gmail.com", + NormalizedEmail = "PHONG@GMAIL.COM", + PasswordHash = "AQAAAAEAACcQAAAAELBcKuXWkiRQEYAkD/qKs9neac5hxWs3bkegIHpGLtf+zFHuKnuI3lBqkWO9TMmFAQ==", // v*7Un8b4rcN@<-RN + SecurityStamp = "5M2QLL65J6H6VFIS7VZETKXY27KNVVYJ", + LockoutEnabled = true, + }, + }); } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/MappingConfigurations/UserRoleConfiguration.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/MappingConfigurations/UserRoleConfiguration.cs index d34427b65..0fc53eb72 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/MappingConfigurations/UserRoleConfiguration.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/MappingConfigurations/UserRoleConfiguration.cs @@ -2,14 +2,13 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata.Builders; -namespace ClassifiedAds.Persistence.MappingConfigurations +namespace ClassifiedAds.Persistence.MappingConfigurations; + +public class UserRoleConfiguration : IEntityTypeConfiguration { - public class UserRoleConfiguration : IEntityTypeConfiguration + public void Configure(EntityTypeBuilder builder) { - public void Configure(EntityTypeBuilder builder) - { - builder.ToTable("UserRoles"); - builder.Property(x => x.Id).HasDefaultValueSql("newsequentialid()"); - } + builder.ToTable("UserRoles"); + builder.Property(x => x.Id).HasDefaultValueSql("newsequentialid()"); } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/MappingConfigurations/UserTokenConfiguration.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/MappingConfigurations/UserTokenConfiguration.cs index aa2284351..ef26cdf1a 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/MappingConfigurations/UserTokenConfiguration.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/MappingConfigurations/UserTokenConfiguration.cs @@ -2,14 +2,13 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata.Builders; -namespace ClassifiedAds.Persistence.MappingConfigurations +namespace ClassifiedAds.Persistence.MappingConfigurations; + +public class UserTokenConfiguration : IEntityTypeConfiguration { - public class UserTokenConfiguration : IEntityTypeConfiguration + public void Configure(EntityTypeBuilder builder) { - public void Configure(EntityTypeBuilder builder) - { - builder.ToTable("UserTokens"); - builder.Property(x => x.Id).HasDefaultValueSql("newsequentialid()"); - } + builder.ToTable("UserTokens"); + builder.Property(x => x.Id).HasDefaultValueSql("newsequentialid()"); } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/PersistenceExtensions.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/PersistenceExtensions.cs index dd0f6fd45..28f64a6f7 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/PersistenceExtensions.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/PersistenceExtensions.cs @@ -10,71 +10,70 @@ using Microsoft.EntityFrameworkCore; using System; -namespace Microsoft.Extensions.DependencyInjection +namespace Microsoft.Extensions.DependencyInjection; + +public static class PersistenceExtensions { - public static class PersistenceExtensions + public static IServiceCollection AddPersistence(this IServiceCollection services, string connectionString, string migrationsAssembly = "") { - public static IServiceCollection AddPersistence(this IServiceCollection services, string connectionString, string migrationsAssembly = "") - { - services.AddDbContext(options => options.UseSqlServer(connectionString, sql => + services.AddDbContext(options => options.UseSqlServer(connectionString, sql => + { + if (!string.IsNullOrEmpty(migrationsAssembly)) { - if (!string.IsNullOrEmpty(migrationsAssembly)) - { - sql.MigrationsAssembly(migrationsAssembly); - } - })) - .AddDbContextFactory((Action)null, ServiceLifetime.Scoped) - .AddRepositories(); + sql.MigrationsAssembly(migrationsAssembly); + } + })) + .AddDbContextFactory((Action)null, ServiceLifetime.Scoped) + .AddRepositories(); - services.AddScoped(typeof(IDistributedLock), _ => new SqlDistributedLock(connectionString)); + services.AddScoped(typeof(IDistributedLock), _ => new SqlDistributedLock(connectionString)); - return services; - } + return services; + } - public static IServiceCollection AddMultiTenantPersistence(this IServiceCollection services, Type connectionStringResolverType, Type tenantResolverType) - { - services.AddScoped(typeof(IConnectionStringResolver), connectionStringResolverType); - services.AddScoped(typeof(ITenantResolver), tenantResolverType); + public static IServiceCollection AddMultiTenantPersistence(this IServiceCollection services, Type connectionStringResolverType, Type tenantResolverType) + { + services.AddScoped(typeof(IConnectionStringResolver), connectionStringResolverType); + services.AddScoped(typeof(ITenantResolver), tenantResolverType); - services.AddDbContext(options => { }) - .AddScoped(typeof(AdsDbContext), services => - { - return services.GetRequiredService(); - }) - .AddRepositories(); + services.AddDbContext(options => { }) + .AddScoped(typeof(AdsDbContext), services => + { + return services.GetRequiredService(); + }) + .AddRepositories(); + + services.AddScoped(typeof(IDistributedLock), services => + { + return new SqlDistributedLock(services.GetRequiredService>().ConnectionString); + }); - services.AddScoped(typeof(IDistributedLock), services => - { - return new SqlDistributedLock(services.GetRequiredService>().ConnectionString); - }); + return services; + } - return services; - } + private static IServiceCollection AddRepositories(this IServiceCollection services) + { + services.AddScoped(typeof(IRepository<,>), typeof(Repository<,>)) + .AddScoped(typeof(IAuditLogEntryRepository), typeof(AuditLogEntryRepository)) + .AddScoped(typeof(IUserRepository), typeof(UserRepository)) + .AddScoped(typeof(IRoleRepository), typeof(RoleRepository)); - private static IServiceCollection AddRepositories(this IServiceCollection services) + services.AddScoped(typeof(IUnitOfWork), services => { - services.AddScoped(typeof(IRepository<,>), typeof(Repository<,>)) - .AddScoped(typeof(IAuditLogEntryRepository), typeof(AuditLogEntryRepository)) - .AddScoped(typeof(IUserRepository), typeof(UserRepository)) - .AddScoped(typeof(IRoleRepository), typeof(RoleRepository)); + return services.GetRequiredService(); + }); - services.AddScoped(typeof(IUnitOfWork), services => - { - return services.GetRequiredService(); - }); + services.AddScoped(); + services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - - return services; - } + return services; + } - public static void MigrateAdsDb(this IApplicationBuilder app) + public static void MigrateAdsDb(this IApplicationBuilder app) + { + using (var serviceScope = app.ApplicationServices.GetService().CreateScope()) { - using (var serviceScope = app.ApplicationServices.GetService().CreateScope()) - { - serviceScope.ServiceProvider.GetRequiredService().Database.Migrate(); - } + serviceScope.ServiceProvider.GetRequiredService().Database.Migrate(); } } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/Repositories/AuditLogEntryRepository.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/Repositories/AuditLogEntryRepository.cs index 7524b3452..0540e724f 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/Repositories/AuditLogEntryRepository.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/Repositories/AuditLogEntryRepository.cs @@ -5,35 +5,34 @@ using System; using System.Linq; -namespace ClassifiedAds.Persistence.Repositories +namespace ClassifiedAds.Persistence.Repositories; + +public class AuditLogEntryRepository : Repository, IAuditLogEntryRepository { - public class AuditLogEntryRepository : Repository, IAuditLogEntryRepository + public AuditLogEntryRepository(AdsDbContext dbContext, IDateTimeProvider dateTimeProvider) + : base(dbContext, dateTimeProvider) + { + } + + public IQueryable Get(AuditLogEntryQueryOptions queryOptions) { - public AuditLogEntryRepository(AdsDbContext dbContext, IDateTimeProvider dateTimeProvider) - : base(dbContext, dateTimeProvider) + var query = GetQueryableSet(); + + if (queryOptions.UserId != Guid.Empty) { + query = query.Where(x => x.UserId == queryOptions.UserId); } - public IQueryable Get(AuditLogEntryQueryOptions queryOptions) + if (!string.IsNullOrEmpty(queryOptions.ObjectId)) { - var query = GetQueryableSet(); - - if (queryOptions.UserId != Guid.Empty) - { - query = query.Where(x => x.UserId == queryOptions.UserId); - } - - if (!string.IsNullOrEmpty(queryOptions.ObjectId)) - { - query = query.Where(x => x.ObjectId == queryOptions.ObjectId); - } - - if (queryOptions.AsNoTracking) - { - query = query.AsNoTracking(); - } + query = query.Where(x => x.ObjectId == queryOptions.ObjectId); + } - return query; + if (queryOptions.AsNoTracking) + { + query = query.AsNoTracking(); } + + return query; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/Repositories/Repository.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/Repositories/Repository.cs index 8dd58bd6d..1b94d831d 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/Repositories/Repository.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/Repositories/Repository.cs @@ -13,112 +13,111 @@ using System.Threading; using System.Threading.Tasks; -namespace ClassifiedAds.Persistence.Repositories +namespace ClassifiedAds.Persistence.Repositories; + +public class Repository : IRepository + where T : Entity, IAggregateRoot { - public class Repository : IRepository - where T : Entity, IAggregateRoot - { - private readonly AdsDbContext _dbContext; - private readonly IDateTimeProvider _dateTimeProvider; + private readonly AdsDbContext _dbContext; + private readonly IDateTimeProvider _dateTimeProvider; - protected DbSet DbSet => _dbContext.Set(); + protected DbSet DbSet => _dbContext.Set(); - public IUnitOfWork UnitOfWork + public IUnitOfWork UnitOfWork + { + get { - get - { - return _dbContext; - } + return _dbContext; } + } - public Repository(AdsDbContext dbContext, IDateTimeProvider dateTimeProvider) - { - _dbContext = dbContext; - _dateTimeProvider = dateTimeProvider; - } + public Repository(AdsDbContext dbContext, IDateTimeProvider dateTimeProvider) + { + _dbContext = dbContext; + _dateTimeProvider = dateTimeProvider; + } - public async Task AddOrUpdateAsync(T entity, CancellationToken cancellationToken = default) + public async Task AddOrUpdateAsync(T entity, CancellationToken cancellationToken = default) + { + if (entity.Id.Equals(default(TKey))) { - if (entity.Id.Equals(default(TKey))) - { - await AddAsync(entity, cancellationToken); - } - else - { - await UpdateAsync(entity, cancellationToken); - } + await AddAsync(entity, cancellationToken); } - - public async Task AddAsync(T entity, CancellationToken cancellationToken = default) + else { - entity.CreatedDateTime = _dateTimeProvider.OffsetNow; - await DbSet.AddAsync(entity, cancellationToken); + await UpdateAsync(entity, cancellationToken); } + } - public Task UpdateAsync(T entity, CancellationToken cancellationToken = default) - { - entity.UpdatedDateTime = _dateTimeProvider.OffsetNow; - return Task.CompletedTask; - } + public async Task AddAsync(T entity, CancellationToken cancellationToken = default) + { + entity.CreatedDateTime = _dateTimeProvider.OffsetNow; + await DbSet.AddAsync(entity, cancellationToken); + } - public void Delete(T entity) - { - DbSet.Remove(entity); - } + public Task UpdateAsync(T entity, CancellationToken cancellationToken = default) + { + entity.UpdatedDateTime = _dateTimeProvider.OffsetNow; + return Task.CompletedTask; + } - public IQueryable GetQueryableSet() - { - return _dbContext.Set(); - } + public void Delete(T entity) + { + DbSet.Remove(entity); + } - public Task FirstOrDefaultAsync(IQueryable query) - { - return query.FirstOrDefaultAsync(); - } + public IQueryable GetQueryableSet() + { + return _dbContext.Set(); + } - public Task SingleOrDefaultAsync(IQueryable query) - { - return query.SingleOrDefaultAsync(); - } + public Task FirstOrDefaultAsync(IQueryable query) + { + return query.FirstOrDefaultAsync(); + } - public Task> ToListAsync(IQueryable query) - { - return query.ToListAsync(); - } + public Task SingleOrDefaultAsync(IQueryable query) + { + return query.SingleOrDefaultAsync(); + } - public void BulkInsert(IEnumerable entities) - { - _dbContext.BulkInsert(entities); - } + public Task> ToListAsync(IQueryable query) + { + return query.ToListAsync(); + } - public void BulkInsert(IEnumerable entities, Expression> columnNamesSelector) - { - _dbContext.BulkInsert(entities, columnNamesSelector); - } + public void BulkInsert(IEnumerable entities) + { + _dbContext.BulkInsert(entities); + } - public void BulkUpdate(IEnumerable entities, Expression> columnNamesSelector) - { - _dbContext.BulkUpdate(entities, columnNamesSelector); - } + public void BulkInsert(IEnumerable entities, Expression> columnNamesSelector) + { + _dbContext.BulkInsert(entities, columnNamesSelector); + } - public void BulkDelete(IEnumerable entities) - { - _dbContext.BulkDelete(entities); - } + public void BulkUpdate(IEnumerable entities, Expression> columnNamesSelector) + { + _dbContext.BulkUpdate(entities, columnNamesSelector); + } - public void BulkMerge(IEnumerable entities, Expression> idSelector, Expression> updateColumnNamesSelector, Expression> insertColumnNamesSelector) - { - _dbContext.BulkMerge(entities, idSelector, updateColumnNamesSelector, insertColumnNamesSelector); - } + public void BulkDelete(IEnumerable entities) + { + _dbContext.BulkDelete(entities); + } - public void SetRowVersion(T entity, byte[] version) - { - _dbContext.Entry(entity).OriginalValues[nameof(entity.RowVersion)] = version; - } + public void BulkMerge(IEnumerable entities, Expression> idSelector, Expression> updateColumnNamesSelector, Expression> insertColumnNamesSelector) + { + _dbContext.BulkMerge(entities, idSelector, updateColumnNamesSelector, insertColumnNamesSelector); + } - public bool IsDbUpdateConcurrencyException(Exception ex) - { - return ex is DbUpdateConcurrencyException; - } + public void SetRowVersion(T entity, byte[] version) + { + _dbContext.Entry(entity).OriginalValues[nameof(entity.RowVersion)] = version; + } + + public bool IsDbUpdateConcurrencyException(Exception ex) + { + return ex is DbUpdateConcurrencyException; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/Repositories/RoleRepository.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/Repositories/RoleRepository.cs index 1da3d9cc2..e03e19456 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/Repositories/RoleRepository.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/Repositories/RoleRepository.cs @@ -5,40 +5,39 @@ using System; using System.Linq; -namespace ClassifiedAds.Persistence.Repositories +namespace ClassifiedAds.Persistence.Repositories; + +public class RoleRepository : Repository, IRoleRepository { - public class RoleRepository : Repository, IRoleRepository + public RoleRepository(AdsDbContext dbContext, IDateTimeProvider dateTimeProvider) + : base(dbContext, dateTimeProvider) + { + } + + public IQueryable Get(RoleQueryOptions queryOptions) { - public RoleRepository(AdsDbContext dbContext, IDateTimeProvider dateTimeProvider) - : base(dbContext, dateTimeProvider) + var query = GetQueryableSet(); + + if (queryOptions.IncludeClaims) { + query = query.Include(x => x.Claims); } - public IQueryable Get(RoleQueryOptions queryOptions) + if (queryOptions.IncludeUserRoles) { - var query = GetQueryableSet(); - - if (queryOptions.IncludeClaims) - { - query = query.Include(x => x.Claims); - } - - if (queryOptions.IncludeUserRoles) - { - query = query.Include(x => x.UserRoles); - } - - if (queryOptions.IncludeUsers) - { - query = query.Include("UserRoles.User"); - } + query = query.Include(x => x.UserRoles); + } - if (queryOptions.AsNoTracking) - { - query = query = query.AsNoTracking(); - } + if (queryOptions.IncludeUsers) + { + query = query.Include("UserRoles.User"); + } - return query; + if (queryOptions.AsNoTracking) + { + query = query = query.AsNoTracking(); } + + return query; } } diff --git a/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/Repositories/UserRepository.cs b/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/Repositories/UserRepository.cs index 3373cb1a2..fcbbf42ae 100644 --- a/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/Repositories/UserRepository.cs +++ b/src/IdentityServer/IdentityServer4/ClassifiedAds.Persistence/Repositories/UserRepository.cs @@ -5,50 +5,49 @@ using System; using System.Linq; -namespace ClassifiedAds.Persistence.Repositories +namespace ClassifiedAds.Persistence.Repositories; + +public class UserRepository : Repository, IUserRepository { - public class UserRepository : Repository, IUserRepository + public UserRepository(AdsDbContext dbContext, IDateTimeProvider dateTimeProvider) + : base(dbContext, dateTimeProvider) { - public UserRepository(AdsDbContext dbContext, IDateTimeProvider dateTimeProvider) - : base(dbContext, dateTimeProvider) + } + + public IQueryable Get(UserQueryOptions queryOptions) + { + var query = GetQueryableSet(); + + if (queryOptions.IncludePasswordHistories) + { + query = query.Include(x => x.PasswordHistories); + } + + if (queryOptions.IncludeTokens) + { + query = query.Include(x => x.Tokens); + } + + if (queryOptions.IncludeClaims) + { + query = query.Include(x => x.Claims); + } + + if (queryOptions.IncludeUserRoles) { + query = query.Include(x => x.UserRoles); } - public IQueryable Get(UserQueryOptions queryOptions) + if (queryOptions.IncludeRoles) { - var query = GetQueryableSet(); - - if (queryOptions.IncludePasswordHistories) - { - query = query.Include(x => x.PasswordHistories); - } - - if (queryOptions.IncludeTokens) - { - query = query.Include(x => x.Tokens); - } - - if (queryOptions.IncludeClaims) - { - query = query.Include(x => x.Claims); - } - - if (queryOptions.IncludeUserRoles) - { - query = query.Include(x => x.UserRoles); - } - - if (queryOptions.IncludeRoles) - { - query = query.Include("UserRoles.Role"); - } - - if (queryOptions.AsNoTracking) - { - query = query = query.AsNoTracking(); - } - - return query; + query = query.Include("UserRoles.Role"); } + + if (queryOptions.AsNoTracking) + { + query = query = query.AsNoTracking(); + } + + return query; } }