From c006fb7a9c4969b3c2a8967467f7a15cddd58746 Mon Sep 17 00:00:00 2001 From: David Eggenberger Date: Sun, 24 Nov 2024 23:29:23 +0100 Subject: [PATCH] add Configuration infrastructure --- .../Server/Controllers/ChannelsController.cs | 28 +-- .../Web/Server/Controllers/StripeWebhook.cs | 68 ------- .../Web/Server/WebHooks/StripeWebhook.cs | 69 +++++++ .../Server/Controllers/IdentityController.cs | 71 -------- .../ExternalLoginCallbackController.cs | 12 +- .../IdentityOperationsController.cs | 74 ++++++++ .../Server/Controllers/TenantsController.cs | 168 +++++++++--------- .../Web/Server/Controllers/UsersController.cs | 15 ++ .../Configuration/ConfigurationObject.cs | 6 + .../ConfigurationObjectValidator.cs | 9 + .../Features/Configuration/Registrator.cs | 38 ++++ .../Shared/Features/Domain/AggregateRoot.cs | 23 --- .../Attributes/JoiningTableAttribute.cs | 10 -- .../Domain/Attributes/ValueObjectAttribute.cs | 6 - .../Configuration/IModuleConfiguration.cs | 6 - .../Modules/Configuration/Registrator.cs | 37 ---- Source/Shared/Features/Modules/Module.cs | 22 --- Source/Shared/Kernel/Errors/Errors.cs | 10 ++ .../Errors/Exceptions/NotFoundException.cs | 10 ++ .../Exceptions/UnAuthorizedException.cs | 10 ++ 20 files changed, 336 insertions(+), 356 deletions(-) delete mode 100644 Source/Modules/Subscriptions/Web/Server/Controllers/StripeWebhook.cs create mode 100644 Source/Modules/Subscriptions/Web/Server/WebHooks/StripeWebhook.cs delete mode 100644 Source/Modules/TenantIdentity/Web/Server/Controllers/IdentityController.cs rename Source/Modules/TenantIdentity/Web/Server/Controllers/{ => Infrastructure}/ExternalLoginCallbackController.cs (92%) create mode 100644 Source/Modules/TenantIdentity/Web/Server/Controllers/Infrastructure/IdentityOperationsController.cs create mode 100644 Source/Modules/TenantIdentity/Web/Server/Controllers/UsersController.cs create mode 100644 Source/Shared/Features/Configuration/ConfigurationObject.cs create mode 100644 Source/Shared/Features/Configuration/ConfigurationObjectValidator.cs create mode 100644 Source/Shared/Features/Configuration/Registrator.cs delete mode 100644 Source/Shared/Features/Domain/AggregateRoot.cs delete mode 100644 Source/Shared/Features/Domain/Attributes/JoiningTableAttribute.cs delete mode 100644 Source/Shared/Features/Domain/Attributes/ValueObjectAttribute.cs delete mode 100644 Source/Shared/Features/Modules/Configuration/IModuleConfiguration.cs delete mode 100644 Source/Shared/Features/Modules/Configuration/Registrator.cs delete mode 100644 Source/Shared/Features/Modules/Module.cs create mode 100644 Source/Shared/Kernel/Errors/Errors.cs create mode 100644 Source/Shared/Kernel/Errors/Exceptions/NotFoundException.cs create mode 100644 Source/Shared/Kernel/Errors/Exceptions/UnAuthorizedException.cs diff --git a/Source/Modules/Channels/Web/Server/Controllers/ChannelsController.cs b/Source/Modules/Channels/Web/Server/Controllers/ChannelsController.cs index 4fee5a5a..c8136038 100644 --- a/Source/Modules/Channels/Web/Server/Controllers/ChannelsController.cs +++ b/Source/Modules/Channels/Web/Server/Controllers/ChannelsController.cs @@ -9,26 +9,16 @@ using Modules.Channels.Features.DomainFeatures.Channels.Application.Queries; using Shared.Kernel.BuildingBlocks.Authorization.Attributes; using Modules.Channels.Web.Shared.DTOs.ChannelAggregate; +using Shared.Features.Server; namespace Modules.Channels.Web.Server.Controllers { [Route("api/[controller]")] [ApiController] - [ApiVersion("1.0")] - public class ChannelsController : ControllerBase + [Authorize] + public class ChannelsController : BaseController { - private readonly IMapper mapper; - private readonly ICommandDispatcher commandDispatcher; - private readonly IQueryDispatcher queryDispatcher; - private readonly IAuthorizationService authorizationService; - - public ChannelsController(ICommandDispatcher commandDispatcher, IQueryDispatcher queryDispatcher, IMapper mapper, IAuthorizationService authorizationService) - { - this.commandDispatcher = commandDispatcher; - this.queryDispatcher = queryDispatcher; - this.mapper = mapper; - this.authorizationService = authorizationService; - } + public ChannelsController(IServiceProvider serviceProvider) : base(serviceProvider) { } [HttpGet] public async Task> GetChannels(CancellationToken cancellationToken) @@ -87,15 +77,7 @@ public async Task UpdateChannel([FromBody] ChannelDTO updateChannelDTO, Cancella public async Task DeleteChannel([FromRoute] Guid id, CancellationToken cancellationToken) { Channel channel = await queryDispatcher.DispatchAsync(new GetChannelById { Id = id }, cancellationToken); - if ((await authorizationService.AuthorizeAsync(HttpContext.User, channel, "CreatorPolicy")).Succeeded) - { - await commandDispatcher.DispatchAsync(new DeleteChannel() { ChannelId = id }, cancellationToken); - return Ok(); - } - else - { - return Forbid(); - } + } } } diff --git a/Source/Modules/Subscriptions/Web/Server/Controllers/StripeWebhook.cs b/Source/Modules/Subscriptions/Web/Server/Controllers/StripeWebhook.cs deleted file mode 100644 index 719eb25d..00000000 --- a/Source/Modules/Subscriptions/Web/Server/Controllers/StripeWebhook.cs +++ /dev/null @@ -1,68 +0,0 @@ -//using Shared.Modules.Layers.Application.Messaging.Command; -//using Shared.Modules.Layers.Features.StripeIntegration; -//using Shared.Modules.Layers.Features.StripeIntegration.Commands; -//using Shared.Modules.Layers.Features.StripeIntegration.Configuration; -//using Microsoft.AspNetCore.Authorization; -//using Microsoft.AspNetCore.Http; -//using Microsoft.AspNetCore.Mvc; -//using Microsoft.Extensions.Options; -//using Stripe; -//using System.IO; - -//namespace Web.Server.Controllers.Stripe -//{ -// [Route("api/[controller]")] -// [ApiController] -// public class StripeWebhook : ControllerBase -// { -// private readonly StripeOptions stripeOptions; -// private readonly ICommandDispatcher commandDispatcher; -// public StripeWebhook(IOptions stripeOptions, ICommandDispatcher commandDispatcher) -// { -// this.stripeOptions = stripeOptions.Value; -// this.commandDispatcher = commandDispatcher; -// } - -// [HttpPost] -// [IgnoreAntiforgeryToken] -// [AllowAnonymous] -// public async Task Index() -// { -// var json = await new StreamReader(HttpContext.Request.Body).ReadToEndAsync(); -// try -// { -// var stripeEvent = EventUtility.ParseEvent(json); -// var signatureHeader = Request.Headers["Stripe-Signature"]; -// stripeEvent = EventUtility.ConstructEvent(json, -// signatureHeader, stripeOptions.EndpointSecret); - -// //More Events Events.Checkout... -// if (stripeEvent.Type == Events.CustomerSubscriptionCreated) -// { -// var subscription = stripeEvent.Data.Object as Subscription; -// await commandDispatcher.DispatchAsync(new CreateSubscriptionCommand { Subscription = subscription }); -// } -// else if (stripeEvent.Type == Events.CustomerSubscriptionUpdated) -// { -// var subscription = stripeEvent.Data.Object as Subscription; -// await commandDispatcher.DispatchAsync(new UpdateSubscriptionCommand { Subscription = subscription }); -// } -// else if (stripeEvent.Type == Events.CustomerSubscriptionDeleted) -// { -// var subscription = stripeEvent.Data.Object as Subscription; -// await commandDispatcher.DispatchAsync(new DeleteSubscriptionCommand { Subscription = subscription }); -// } -// else if (stripeEvent.Type == Events.CustomerSubscriptionTrialWillEnd) -// { -// var subscription = stripeEvent.Data.Object as Subscription; -// await commandDispatcher.DispatchAsync(new SubscriptionTrialEndedCommand { Subscription = subscription }); -// } -// return Ok(); -// } -// catch (StripeException e) -// { -// throw new StripeIntegrationException(e.Message); -// } -// } -// } -//} diff --git a/Source/Modules/Subscriptions/Web/Server/WebHooks/StripeWebhook.cs b/Source/Modules/Subscriptions/Web/Server/WebHooks/StripeWebhook.cs new file mode 100644 index 00000000..995c1ea9 --- /dev/null +++ b/Source/Modules/Subscriptions/Web/Server/WebHooks/StripeWebhook.cs @@ -0,0 +1,69 @@ +using Shared.Modules.Layers.Application.Messaging.Command; +using Shared.Modules.Layers.Features.StripeIntegration; +using Shared.Modules.Layers.Features.StripeIntegration.Commands; +using Shared.Modules.Layers.Features.StripeIntegration.Configuration; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Options; +using Stripe; +using System.IO; +using Shared.Features.Server; + +namespace Web.Server.Controllers.Stripe +{ + [Route("api/[controller]")] + [ApiController] + public class StripeWebhook : BaseController + { + private readonly StripeOptions stripeOptions; + private readonly ICommandDispatcher commandDispatcher; + public StripeWebhook(IOptions stripeOptions, ICommandDispatcher commandDispatcher) + { + this.stripeOptions = stripeOptions.Value; + this.commandDispatcher = commandDispatcher; + } + + [HttpPost] + [IgnoreAntiforgeryToken] + [AllowAnonymous] + public async Task Index() + { + var json = await new StreamReader(HttpContext.Request.Body).ReadToEndAsync(); + try + { + var stripeEvent = EventUtility.ParseEvent(json); + var signatureHeader = Request.Headers["Stripe-Signature"]; + stripeEvent = EventUtility.ConstructEvent(json, + signatureHeader, stripeOptions.EndpointSecret); + + //More Events Events.Checkout... + if (stripeEvent.Type == Events.CustomerSubscriptionCreated) + { + var subscription = stripeEvent.Data.Object as Subscription; + await commandDispatcher.DispatchAsync(new CreateSubscriptionCommand { Subscription = subscription }); + } + else if (stripeEvent.Type == Events.CustomerSubscriptionUpdated) + { + var subscription = stripeEvent.Data.Object as Subscription; + await commandDispatcher.DispatchAsync(new UpdateSubscriptionCommand { Subscription = subscription }); + } + else if (stripeEvent.Type == Events.CustomerSubscriptionDeleted) + { + var subscription = stripeEvent.Data.Object as Subscription; + await commandDispatcher.DispatchAsync(new DeleteSubscriptionCommand { Subscription = subscription }); + } + else if (stripeEvent.Type == Events.CustomerSubscriptionTrialWillEnd) + { + var subscription = stripeEvent.Data.Object as Subscription; + await commandDispatcher.DispatchAsync(new SubscriptionTrialEndedCommand { Subscription = subscription }); + } + return Ok(); + } + catch (StripeException e) + { + throw new StripeIntegrationException(e.Message); + } + } + } +} diff --git a/Source/Modules/TenantIdentity/Web/Server/Controllers/IdentityController.cs b/Source/Modules/TenantIdentity/Web/Server/Controllers/IdentityController.cs deleted file mode 100644 index 6de9d2d2..00000000 --- a/Source/Modules/TenantIdentity/Web/Server/Controllers/IdentityController.cs +++ /dev/null @@ -1,71 +0,0 @@ -//using AutoMapper; -//using Shared.Features.Messaging.Query; -//using Shared.Modules.Layers.Features.Identity; -//using Microsoft.AspNetCore.Authorization; -//using Microsoft.AspNetCore.Identity; -//using Microsoft.AspNetCore.Mvc; -//using Module.Shared.Modules.Layers.Features; -//using Modules.IdentityModule.Shared; -//using ApplicationUserManager = Shared.Modules.Layers.Features.Identity.ApplicationUserManager; - -//namespace Web.Server.Controllers.Identity -//{ -// [Route("api/[controller]")] -// [Authorize] -// [ApiController] -// public class IdentityController : ControllerBase -// { -// private readonly SignInManager signInManager; -// private readonly ApplicationUserManager applicationUserManager; -// private readonly IMapper mapper; -// private readonly IQueryDispatcher queryDispatcher; -// public IdentityController(SignInManager signInManager, ApplicationUserManager applicationUserManager, IMapper mapper) -// { -// this.signInManager = signInManager; -// this.applicationUserManager = applicationUserManager; -// this.mapper = mapper; -// } - -// [HttpGet] -// [AllowAnonymous] -// public ActionResult GetClaimsOfCurrentUser() -// { -// if (!User.Identity.IsAuthenticated) -// { -// return BFFUserInfoDTO.Anonymous; -// } -// return new BFFUserInfoDTO() -// { -// Claims = User.Claims.Select(claim => new ClaimValueDTO { Type = claim.Type, Value = claim.Value }).ToList() -// }; -// } - -// [HttpGet("selectTenant/{TeamId}")] -// public async Task SetTenantForCurrentUser(Guid tenantId, [FromQuery] string redirectUri) -// { -// ApplicationUser applicationUser = await applicationUserManager.FindByClaimsPrincipalAsync(HttpContext.User); - -// //var tenantMembershipsOfUserQuery = new GetAllTenantMembershipsOfUser() { UserId = applicationUser.Id }; -// //var tenantMemberships = await queryDispatcher.DispatchAsync>(tenantMembershipsOfUserQuery); - -// //if (tenantMemberships.Select(t => t.Tenant.Id).Contains(tenantId)) -// //{ -// // await applicationUserManager.SetTenantAsSelected(applicationUser, tenantId); -// // await signInManager.RefreshSignInAsync(applicationUser); -// //} -// //else -// //{ -// // throw new Exception(); -// //} - -// return LocalRedirect(redirectUri ?? "/"); -// } - -// [HttpGet("Logout")] -// public async Task LogoutCurrentUser([FromQuery] string redirectUri) -// { -// await signInManager.SignOutAsync(); -// return LocalRedirect(redirectUri ?? "/"); -// } -// } -//} diff --git a/Source/Modules/TenantIdentity/Web/Server/Controllers/ExternalLoginCallbackController.cs b/Source/Modules/TenantIdentity/Web/Server/Controllers/Infrastructure/ExternalLoginCallbackController.cs similarity index 92% rename from Source/Modules/TenantIdentity/Web/Server/Controllers/ExternalLoginCallbackController.cs rename to Source/Modules/TenantIdentity/Web/Server/Controllers/Infrastructure/ExternalLoginCallbackController.cs index dc938212..7db16127 100644 --- a/Source/Modules/TenantIdentity/Web/Server/Controllers/ExternalLoginCallbackController.cs +++ b/Source/Modules/TenantIdentity/Web/Server/Controllers/Infrastructure/ExternalLoginCallbackController.cs @@ -2,12 +2,14 @@ using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc; using Shared.Kernel.BuildingBlocks.Auth.Constants; -using Modules.TenantIdentity.Features.DomainFeatures.Users; using Shared.Kernel.Extensions.ClaimsPrincipal; -using Modules.TenantIdentity.Features.DomainFeatures.Users.Application.Commands; using Shared.Features.Server; +using System; +using System.Threading.Tasks; +using Modules.TenantIdentity.Features.DomainFeatures.Users; +using Modules.TenantIdentity.Features.DomainFeatures.Users.Application.Commands; -namespace Modules.TenantIdentity.Web.Server +namespace Modules.TenantIdentity.Web.Server.Controllers.IdentityOperations { [Route("api/[controller]")] [AllowAnonymous] @@ -16,8 +18,7 @@ public class ExternalLoginCallbackController : BaseController { private readonly SignInManager signInManager; private readonly UserManager userManager; - - public ExternalLoginCallbackController(SignInManager signInManager, UserManager userManager, IServiceProvider services) : base(services) + public ExternalLoginCallbackController(SignInManager signInManager, UserManager userManager, IServiceProvider serviceProvider) : base(serviceProvider) { this.signInManager = signInManager; this.userManager = userManager; @@ -27,6 +28,7 @@ public ExternalLoginCallbackController(SignInManager signInMana public async Task ExternalLoginCallback(string returnUrl = null) { var info = await signInManager.GetExternalLoginInfoAsync(); + var user = await userManager.FindByLoginAsync(info.LoginProvider, info.ProviderKey); if (info is not null && user is null) diff --git a/Source/Modules/TenantIdentity/Web/Server/Controllers/Infrastructure/IdentityOperationsController.cs b/Source/Modules/TenantIdentity/Web/Server/Controllers/Infrastructure/IdentityOperationsController.cs new file mode 100644 index 00000000..a9e533f7 --- /dev/null +++ b/Source/Modules/TenantIdentity/Web/Server/Controllers/Infrastructure/IdentityOperationsController.cs @@ -0,0 +1,74 @@ +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Identity; +using Microsoft.AspNetCore.Mvc; +using Modules.TenantIdentity.Features.DomainFeatures.Tenants.Application.Queries; +using Modules.TenantIdentity.Features.DomainFeatures.Users; +using Modules.TenantIdentity.Features.DomainFeatures.Users.Application.Commands; +using Modules.TenantIdentity.Features.DomainFeatures.Users.Application.Queries; +using Modules.TenantIdentity.Shared.DTOs.IdentityOperations; +using Shared.Features.Server; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Modules.TenantIdentity.Shared.DTOs.Tenant; +using Modules.IdentityModule.Shared; + +namespace Modules.TenantIdentity.Web.Server.Controllers.IdentityOperations +{ + [Route("api/[controller]")] + [Authorize] + [ApiController] + public class IdentityOperationsController : BaseController + { + private readonly SignInManager signInManager; + + public IdentityOperationsController(SignInManager signInManager, IServiceProvider serviceProvider) : base(serviceProvider) + { + this.signInManager = signInManager; + } + + [HttpGet] + [AllowAnonymous] + public ActionResult GetClaimsOfCurrentUser() + { + if (!User.Identity.IsAuthenticated) + { + return BFFUserInfoDTO.Anonymous; + } + return new BFFUserInfoDTO() + { + Claims = User.Claims.Select(claim => new ClaimValueDTO { Type = claim.Type, Value = claim.Value }).ToList() + }; + } + + [HttpGet("selectTenant/{TenantId}")] + public async Task SetTenantForCurrentUser(Guid tenantId, [FromQuery] string redirectUri) + { + var user = await queryDispatcher.DispatchAsync(new GetUserById { }); + + var tenantMembershipsOfUserQuery = new GetAllTenantMembershipsOfUser() { UserId = user.Id }; + var tenantMemberships = await queryDispatcher.DispatchAsync>(tenantMembershipsOfUserQuery); + + if (tenantMemberships.Select(t => t.TenantId).Contains(tenantId)) + { + var setSelectedTenantForUser = new SetSelectedTenantForUser { }; + await commandDispatcher.DispatchAsync(setSelectedTenantForUser); + await signInManager.RefreshSignInAsync(user); + } + else + { + throw new Exception(); + } + + return LocalRedirect(redirectUri ?? "/"); + } + + [HttpGet("Logout")] + public async Task LogoutCurrentUser([FromQuery] string redirectUri) + { + await signInManager.SignOutAsync(); + return LocalRedirect(redirectUri ?? "/"); + } + } +} diff --git a/Source/Modules/TenantIdentity/Web/Server/Controllers/TenantsController.cs b/Source/Modules/TenantIdentity/Web/Server/Controllers/TenantsController.cs index 3c821204..e211dcd4 100644 --- a/Source/Modules/TenantIdentity/Web/Server/Controllers/TenantsController.cs +++ b/Source/Modules/TenantIdentity/Web/Server/Controllers/TenantsController.cs @@ -1,102 +1,100 @@ -using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using Shared.Features.Server; namespace Modules.TenantIdentity.Web.Server.Controllers { public class TenantsController : ControllerBase { - //[Route("api/[controller]")] - //[ApiController] - //[AuthorizeTeamAdmin] - //public class TeamController : AuthorizedBaseController - //{ - // private readonly SignInManager signInManager; - // private readonly IHubContext notificationHubContext; - // private readonly IMapper mapper; - // public TeamController(IdentificationDbContext identificationDbContext, SignInManager signInManager, IHubContext notificationHubContext, IMapper mapper) - // { - // this.teamManager = teamManager; - // this.applicationUserManager = applicationUserManager; - // this.identificationDbContext = identificationDbContext; - // this.signInManager = signInManager; - // this.notificationHubContext = notificationHubContext; - // this.mapper = mapper; - // } + [Route("api/[controller]")] + [ApiController] + [Authorize] + public class TeamController : BaseController + { + public TeamController(IdentificationDbContext identificationDbContext, SignInManager signInManager, IHubContext notificationHubContext, IMapper mapper) + { + this.teamManager = teamManager; + this.applicationUserManager = applicationUserManager; + this.identificationDbContext = identificationDbContext; + this.signInManager = signInManager; + this.notificationHubContext = notificationHubContext; + } - // [AllowAnonymous] - // [HttpPost] - // public async Task> CreateTeam(TeamDTO team) - // { - // ApplicationUser applicationUser = await applicationUserManager.FindByClaimsPrincipalAsync(HttpContext.User); - // await teamManager.CreateNewAsync(applicationUser, team.Name); - // await signInManager.RefreshSignInAsync(applicationUser); - // return CreatedAtAction("CreateTeam", team); - // } + [AllowAnonymous] + [HttpPost] + public async Task> CreateTeam(TeamDTO team) + { + ApplicationUser applicationUser = await applicationUserManager.FindByClaimsPrincipalAsync(HttpContext.User); + await teamManager.CreateNewAsync(applicationUser, team.Name); + await signInManager.RefreshSignInAsync(applicationUser); + return CreatedAtAction("CreateTeam", team); + } - // [HttpGet] - // public async Task GetAdminInfo() - // { - // Team team = await teamManager.FindByClaimsPrincipalAsync(HttpContext.User); - // TeamMetrics teamMetrics = teamManager.GetMetricsForTeam(team); - // TeamAdminInfoDTO teamAdminInfoDTO = mapper.Map(team); - // teamAdminInfoDTO.Metrics = mapper.Map(teamMetrics); - // return teamAdminInfoDTO; - // } + [HttpGet] + public async Task GetAdminInfo() + { + Team team = await teamManager.FindByClaimsPrincipalAsync(HttpContext.User); + TeamMetrics teamMetrics = teamManager.GetMetricsForTeam(team); + TeamAdminInfoDTO teamAdminInfoDTO = mapper.Map(team); + teamAdminInfoDTO.Metrics = mapper.Map(teamMetrics); + return teamAdminInfoDTO; + } - // [HttpGet("allTeams")] - // public async Task> GetAllTeamsForUser() - // { - // ApplicationUser applicationUser = await applicationUserManager.FindByClaimsPrincipalAsync(HttpContext.User); - // List teamMemberships = applicationUserManager.GetAllTeamsWhereUserIsMember(applicationUser); - // return teamMemberships.Select(x => mapper.Map(x)); - // } + [HttpGet("allTeams")] + public async Task> GetAllTeamsForUser() + { + ApplicationUser applicationUser = await applicationUserManager.FindByClaimsPrincipalAsync(HttpContext.User); + List teamMemberships = applicationUserManager.GetAllTeamsWhereUserIsMember(applicationUser); + return teamMemberships.Select(x => mapper.Map(x)); + } - // [HttpPost("invite")] - // public async Task InviteUsers(InviteMembersDTO inviteUserToGroupDTO) - // { - // Tenant tenant = await teamManager.FindByClaimsPrincipalAsync(HttpContext.User); - // await teamManager.InviteMembersAsync(team, inviteUserToGroupDTO.Emails); - // return Ok(); - // } + [HttpPost("invite")] + public async Task InviteUsers(InviteMembersDTO inviteUserToGroupDTO) + { + Tenant tenant = await teamManager.FindByClaimsPrincipalAsync(HttpContext.User); + await teamManager.InviteMembersAsync(team, inviteUserToGroupDTO.Emails); + return Ok(); + } - // [HttpPost("invite/revoke")] - // public async Task RevokeInvitation(RevokeInvitationDTO revokeInvitationDTO) - // { - // Team team = await teamManager.FindByClaimsPrincipalAsync(HttpContext.User); - // ApplicationUser applicationUser = await applicationUserManager.FindByIdAsync(revokeInvitationDTO.UserId); - // await teamManager.RemoveInvitationAsync(team, applicationUser); - // return Ok(); - // } + [HttpPost("invite/revoke")] + public async Task RevokeInvitation(RevokeInvitationDTO revokeInvitationDTO) + { + Team team = await teamManager.FindByClaimsPrincipalAsync(HttpContext.User); + ApplicationUser applicationUser = await applicationUserManager.FindByIdAsync(revokeInvitationDTO.UserId); + await teamManager.RemoveInvitationAsync(team, applicationUser); + return Ok(); + } - // [HttpPost("changerole")] - // public async Task ChangeRoleOfTeamMember(ChangeRoleOfMemberDTO changeRoleOfTeamMemberDTO) - // { - // Team team = await teamManager.FindByClaimsPrincipalAsync(HttpContext.User); - // ApplicationUser applicationUser = await applicationUserManager.FindByIdAsync(changeRoleOfTeamMemberDTO.UserId); - // await teamManager.ChangeRoleOfMemberAsync(applicationUser, team, (TeamRole)changeRoleOfTeamMemberDTO.TargetRole); - // return Ok(); - // } + [HttpPost("changerole")] + public async Task ChangeRoleOfTeamMember(ChangeRoleOfMemberDTO changeRoleOfTeamMemberDTO) + { + Team team = await teamManager.FindByClaimsPrincipalAsync(HttpContext.User); + ApplicationUser applicationUser = await applicationUserManager.FindByIdAsync(changeRoleOfTeamMemberDTO.UserId); + await teamManager.ChangeRoleOfMemberAsync(applicationUser, team, (TeamRole)changeRoleOfTeamMemberDTO.TargetRole); + return Ok(); + } - // [HttpDelete("{id}")] - // public async Task DeleteTeam(Guid id) - // { - // Team team = await teamManager.FindByClaimsPrincipalAsync(HttpContext.User); - // ApplicationUser applicationUser = await applicationUserManager.FindByClaimsPrincipalAsync(HttpContext.User); - // if (team.CreatorId == applicationUser.Id) - // { - // await teamManager.DeleteAsync(team); - // } - // await signInManager.RefreshSignInAsync(applicationUser); - // } + [HttpDelete("{id}")] + public async Task DeleteTeam(Guid id) + { + Team team = await teamManager.FindByClaimsPrincipalAsync(HttpContext.User); + ApplicationUser applicationUser = await applicationUserManager.FindByClaimsPrincipalAsync(HttpContext.User); + if (team.CreatorId == applicationUser.Id) + { + await teamManager.DeleteAsync(team); + } + await signInManager.RefreshSignInAsync(applicationUser); + } - // [HttpDelete("removeMember/{id}")] - // public async Task RemoveMember(Guid id) - // { - // ApplicationUser applicationUser = await applicationUserManager.FindByIdAsync(id); - // Team team = await teamManager.FindByClaimsPrincipalAsync(HttpContext.User); - // await teamManager.RemoveMemberAsync(team, applicationUser); - // } - //} + [HttpDelete("removeMember/{id}")] + public async Task RemoveMember(Guid id) + { + ApplicationUser applicationUser = await applicationUserManager.FindByIdAsync(id); + Team team = await teamManager.FindByClaimsPrincipalAsync(HttpContext.User); + await teamManager.RemoveMemberAsync(team, applicationUser); + } + } } } diff --git a/Source/Modules/TenantIdentity/Web/Server/Controllers/UsersController.cs b/Source/Modules/TenantIdentity/Web/Server/Controllers/UsersController.cs new file mode 100644 index 00000000..52c4dbe6 --- /dev/null +++ b/Source/Modules/TenantIdentity/Web/Server/Controllers/UsersController.cs @@ -0,0 +1,15 @@ +using Microsoft.AspNetCore.Mvc; +using Shared.Features.Server; +using System; + +namespace Modules.TenantIdentity.Web.Server.Controllers +{ + [Route("api/[controller]")] + [ApiController] + public class UserController : BaseController + { + public UserController(IServiceProvider serviceProvider) : base(serviceProvider) + { + } + } +} diff --git a/Source/Shared/Features/Configuration/ConfigurationObject.cs b/Source/Shared/Features/Configuration/ConfigurationObject.cs new file mode 100644 index 00000000..5842c78d --- /dev/null +++ b/Source/Shared/Features/Configuration/ConfigurationObject.cs @@ -0,0 +1,6 @@ +namespace Shared.Features.Configuration +{ + public class ConfigurationObject + { + } +} diff --git a/Source/Shared/Features/Configuration/ConfigurationObjectValidator.cs b/Source/Shared/Features/Configuration/ConfigurationObjectValidator.cs new file mode 100644 index 00000000..e5534730 --- /dev/null +++ b/Source/Shared/Features/Configuration/ConfigurationObjectValidator.cs @@ -0,0 +1,9 @@ +using Microsoft.Extensions.Options; + +namespace Shared.Features.Configuration +{ + public abstract class ConfigurationObjectValidator : IValidateOptions where TConfiguration : ConfigurationObject + { + public abstract ValidateOptionsResult Validate(string name, TConfiguration options); + } +} diff --git a/Source/Shared/Features/Configuration/Registrator.cs b/Source/Shared/Features/Configuration/Registrator.cs new file mode 100644 index 00000000..eb12a4bd --- /dev/null +++ b/Source/Shared/Features/Configuration/Registrator.cs @@ -0,0 +1,38 @@ +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; + +namespace Shared.Features.Configuration +{ + public static class Registrator + { + public static IServiceCollection RegisterConfiguration(this IServiceCollection services, IConfiguration configuration) where TConfiguration : ConfigurationObject, new() + { + services.AddScoped(sp => + { + TConfiguration tc = new TConfiguration(); + configuration.GetSection(typeof(TConfiguration).Name).Bind(tc); + return tc; + }); + services.Configure(configuration.GetSection(nameof(TConfiguration))); + + return services; + } + + public static IServiceCollection RegisterConfiguration(this IServiceCollection services, IConfiguration configuration) + where TConfiguration : ConfigurationObject, new() + where TConfigurationValidator : ConfigurationObjectValidator, new() + { + services.AddScoped(sp => + { + TConfiguration tc = new TConfiguration(); + configuration.GetSection(typeof(TConfiguration).Name).Bind(tc); + return tc; + }); + services.Configure(configuration.GetSection(nameof(TConfiguration))); + services.AddSingleton, TConfigurationValidator>(); + + return services; + } + } +} diff --git a/Source/Shared/Features/Domain/AggregateRoot.cs b/Source/Shared/Features/Domain/AggregateRoot.cs deleted file mode 100644 index 18db6ce7..00000000 --- a/Source/Shared/Features/Domain/AggregateRoot.cs +++ /dev/null @@ -1,23 +0,0 @@ -using SendGrid.Helpers.Errors.Model; -using Shared.Kernel.BuildingBlocks.Auth.DomainKernel; -using Shared.Kernel.BuildingBlocks; -using Shared.SharedKernel.Interfaces; -using System.ComponentModel.DataAnnotations.Schema; - -namespace Shared.Features.Domain -{ - public class AggregateRoot : Entity, ITenantIdentifiable - { - [NotMapped] - public IExecutionContext ExecutionContext { get; set; } - public virtual Guid TenantId { get; set; } - - public void ThrowIfCallerIsNotInRole(TenantRole role) - { - if (ExecutionContext.TenantRole != role) - { - throw new UnauthorizedException(); - } - } - } -} diff --git a/Source/Shared/Features/Domain/Attributes/JoiningTableAttribute.cs b/Source/Shared/Features/Domain/Attributes/JoiningTableAttribute.cs deleted file mode 100644 index 76bc2a80..00000000 --- a/Source/Shared/Features/Domain/Attributes/JoiningTableAttribute.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace Shared.Features.DomainKernel.Attributes -{ - public class JoiningTableAttribute : Attribute - { - public JoiningTableAttribute(params string[] tables) - { - - } - } -} diff --git a/Source/Shared/Features/Domain/Attributes/ValueObjectAttribute.cs b/Source/Shared/Features/Domain/Attributes/ValueObjectAttribute.cs deleted file mode 100644 index 12237868..00000000 --- a/Source/Shared/Features/Domain/Attributes/ValueObjectAttribute.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace Shared.Features.DomainKernel.Attributes -{ - public class ValueObjectAttribute : Attribute - { - } -} diff --git a/Source/Shared/Features/Modules/Configuration/IModuleConfiguration.cs b/Source/Shared/Features/Modules/Configuration/IModuleConfiguration.cs deleted file mode 100644 index f3a93120..00000000 --- a/Source/Shared/Features/Modules/Configuration/IModuleConfiguration.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace Shared.Features.Modules.Configuration -{ - public interface IModuleConfiguration - { - } -} diff --git a/Source/Shared/Features/Modules/Configuration/Registrator.cs b/Source/Shared/Features/Modules/Configuration/Registrator.cs deleted file mode 100644 index f039d65b..00000000 --- a/Source/Shared/Features/Modules/Configuration/Registrator.cs +++ /dev/null @@ -1,37 +0,0 @@ -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Options; - -namespace Shared.Features.Modules.Configuration -{ - public static class Registrator - { - public static IServiceCollection RegisterModuleConfiguration(this IServiceCollection services, IConfiguration configuration) where TModuleConfiguration : class, IModuleConfiguration, new() - { - services.Configure(configuration.GetSection(nameof(TModuleConfiguration))); - services.AddScoped(sp => - { - TModuleConfiguration sc = new TModuleConfiguration(); - sp.GetRequiredService().GetSection(typeof(TModuleConfiguration).Name).Bind(sc); - return sc; - }); - - return services; - } - - public static IServiceCollection RegisterModuleConfiguration(this IServiceCollection services, IConfiguration configuration) where TModuleConfiguration : class, IModuleConfiguration, new() where TModuleConfigurationValidator : class, IValidateOptions - { - services.Configure(configuration.GetSection(nameof(TModuleConfiguration))); - services.AddScoped(sp => - { - TModuleConfiguration sc = new TModuleConfiguration(); - sp.GetRequiredService().GetSection(typeof(TModuleConfiguration).Name).Bind(sc); - return sc; - }); - - services.AddSingleton, TModuleConfigurationValidator>(); - - return services; - } - } -} diff --git a/Source/Shared/Features/Modules/Module.cs b/Source/Shared/Features/Modules/Module.cs deleted file mode 100644 index d4aa998e..00000000 --- a/Source/Shared/Features/Modules/Module.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System.Reflection; - -namespace Shared.Features.Modules -{ - public class Module - { - /// - /// Gets the startup class of the module. - /// - public IModuleStartup Startup { get; } - - /// - /// Gets the assembly of the module. - /// - public Assembly Assembly => Startup.GetType().Assembly; - - public Module(IModuleStartup startup) - { - Startup = startup; - } - } -} diff --git a/Source/Shared/Kernel/Errors/Errors.cs b/Source/Shared/Kernel/Errors/Errors.cs new file mode 100644 index 00000000..4a6012df --- /dev/null +++ b/Source/Shared/Kernel/Errors/Errors.cs @@ -0,0 +1,10 @@ +using Shared.Kernel.Errors.Exceptions; + +namespace Shared.Kernel.Errors +{ + public static class Errors + { + public static NotFoundException NotFound = new NotFoundException(); + public static UnAuthorizedException UnAuthorized = new UnAuthorizedException(); + } +} diff --git a/Source/Shared/Kernel/Errors/Exceptions/NotFoundException.cs b/Source/Shared/Kernel/Errors/Exceptions/NotFoundException.cs new file mode 100644 index 00000000..f93c1379 --- /dev/null +++ b/Source/Shared/Kernel/Errors/Exceptions/NotFoundException.cs @@ -0,0 +1,10 @@ +namespace Shared.Kernel.Errors.Exceptions +{ + public class NotFoundException : Exception + { + public NotFoundException() : base("Entity was not found") + { + + } + } +} diff --git a/Source/Shared/Kernel/Errors/Exceptions/UnAuthorizedException.cs b/Source/Shared/Kernel/Errors/Exceptions/UnAuthorizedException.cs new file mode 100644 index 00000000..61d7bff2 --- /dev/null +++ b/Source/Shared/Kernel/Errors/Exceptions/UnAuthorizedException.cs @@ -0,0 +1,10 @@ +namespace Shared.Kernel.Errors.Exceptions +{ + public class UnAuthorizedException : Exception + { + public UnAuthorizedException() : base("UnAuthorized to see the entity") + { + + } + } +}