From 55acf208843176530b32defd499a06c156246cb4 Mon Sep 17 00:00:00 2001 From: eggwhat Date: Thu, 16 May 2024 21:31:51 +0200 Subject: [PATCH 1/9] (#87) split endpoint to two commands --- .../Program.cs | 2 +- ...dOrganization.cs => CreateOrganization.cs} | 6 ++- .../Commands/CreateRootOrganization.cs | 16 ++++++ .../Handlers/CreateOrganizationHandler.cs | 50 +++++++++++++++++++ ...er.cs => CreateRootOrganizationHandler.cs} | 25 ++++------ .../Events/OrganizationCreated.cs | 18 +++++++ .../Events/RootOrganizationCreated.cs | 16 ++++++ .../RootOrganizationNotFoundException.cs | 13 +++++ .../Entities/Organization.cs | 48 +++++++++++++----- .../Extensions.cs | 2 +- .../Logging/Extensions.cs | 2 +- .../Logging/MessageToLogTemplateMapper.cs | 2 +- .../Mongo/Documents/Extensions.cs | 10 ++-- .../Mongo/Documents/OrganizationDocument.cs | 3 +- 14 files changed, 171 insertions(+), 42 deletions(-) rename MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Application/Commands/{AddOrganization.cs => CreateOrganization.cs} (65%) create mode 100644 MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Application/Commands/CreateRootOrganization.cs create mode 100644 MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Application/Commands/Handlers/CreateOrganizationHandler.cs rename MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Application/Commands/Handlers/{AddOrganizationHandler.cs => CreateRootOrganizationHandler.cs} (51%) create mode 100644 MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Application/Events/OrganizationCreated.cs create mode 100644 MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Application/Events/RootOrganizationCreated.cs create mode 100644 MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Application/Exceptions/RootOrganizationNotFoundException.cs diff --git a/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Api/Program.cs b/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Api/Program.cs index a2a623dda..409bcec2e 100644 --- a/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Api/Program.cs +++ b/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Api/Program.cs @@ -37,7 +37,7 @@ public static async Task Main(string[] args) .Get>("organizations/organizer/{organizerId}") .Get>("organizations/root") .Get>("organizations/{organizationId}/children") - .Post("organizations", + .Post("organizations", afterDispatch: (cmd, ctx) => ctx.Response.Created($"organizations/root")) .Post("organizations/{organizationId}/organizer") .Delete("organizations/{organizationId}/organizer/{organizerId}") diff --git a/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Application/Commands/AddOrganization.cs b/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Application/Commands/CreateOrganization.cs similarity index 65% rename from MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Application/Commands/AddOrganization.cs rename to MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Application/Commands/CreateOrganization.cs index dca309f06..083448c53 100644 --- a/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Application/Commands/AddOrganization.cs +++ b/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Application/Commands/CreateOrganization.cs @@ -2,16 +2,18 @@ namespace MiniSpace.Services.Organizations.Application.Commands { - public class AddOrganization: ICommand + public class CreateOrganization: ICommand { public Guid OrganizationId { get; } public string Name { get; } + public Guid RootId { get; } public Guid ParentId { get; } - public AddOrganization(Guid organizationId, string name, Guid parentId) + public CreateOrganization(Guid organizationId, string name, Guid rootId, Guid parentId) { OrganizationId = organizationId == Guid.Empty ? Guid.NewGuid() : organizationId; Name = name; + RootId = rootId; ParentId = parentId; } } diff --git a/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Application/Commands/CreateRootOrganization.cs b/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Application/Commands/CreateRootOrganization.cs new file mode 100644 index 000000000..a8e630776 --- /dev/null +++ b/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Application/Commands/CreateRootOrganization.cs @@ -0,0 +1,16 @@ +using Convey.CQRS.Commands; + +namespace MiniSpace.Services.Organizations.Application.Commands +{ + public class CreateRootOrganization: ICommand + { + public Guid OrganizationId { get; } + public string Name { get; } + + public CreateRootOrganization(Guid organizationId, string name) + { + OrganizationId = organizationId == Guid.Empty ? Guid.NewGuid() : organizationId; + Name = name; + } + } +} \ No newline at end of file diff --git a/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Application/Commands/Handlers/CreateOrganizationHandler.cs b/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Application/Commands/Handlers/CreateOrganizationHandler.cs new file mode 100644 index 000000000..575a86037 --- /dev/null +++ b/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Application/Commands/Handlers/CreateOrganizationHandler.cs @@ -0,0 +1,50 @@ +using Convey.CQRS.Commands; +using MiniSpace.Services.Organizations.Application.Events; +using MiniSpace.Services.Organizations.Application.Exceptions; +using MiniSpace.Services.Organizations.Application.Services; +using MiniSpace.Services.Organizations.Core.Entities; +using MiniSpace.Services.Organizations.Core.Repositories; + +namespace MiniSpace.Services.Organizations.Application.Commands.Handlers +{ + public class CreateOrganizationHandler : ICommandHandler + { + private readonly IOrganizationRepository _organizationRepository; + private readonly IAppContext _appContext; + private readonly IMessageBroker _messageBroker; + + public CreateOrganizationHandler(IOrganizationRepository organizationRepository, IAppContext appContext, + IMessageBroker messageBroker) + { + _organizationRepository = organizationRepository; + _appContext = appContext; + _messageBroker = messageBroker; + } + + public async Task HandleAsync(CreateOrganization command, CancellationToken cancellationToken) + { + var identity = _appContext.Identity; + if(identity.IsAuthenticated && !identity.IsAdmin) + { + throw new Exceptions.UnauthorizedAccessException("admin"); + } + + var root = await _organizationRepository.GetAsync(command.RootId); + if(root is null) + { + throw new RootOrganizationNotFoundException(command.RootId); + } + + var parent = root.GetSubOrganization(command.ParentId); + if(parent is null) + { + throw new ParentOrganizationNotFoundException(command.ParentId); + } + + var organization = new Organization(command.OrganizationId, command.Name); + parent.AddSubOrganization(organization); + await _organizationRepository.UpdateAsync(root); + await _messageBroker.PublishAsync(new OrganizationCreated(organization.Id, organization.Name, parent.Id)); + } + } +} \ No newline at end of file diff --git a/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Application/Commands/Handlers/AddOrganizationHandler.cs b/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Application/Commands/Handlers/CreateRootOrganizationHandler.cs similarity index 51% rename from MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Application/Commands/Handlers/AddOrganizationHandler.cs rename to MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Application/Commands/Handlers/CreateRootOrganizationHandler.cs index ede5a3d92..76bff3b40 100644 --- a/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Application/Commands/Handlers/AddOrganizationHandler.cs +++ b/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Application/Commands/Handlers/CreateRootOrganizationHandler.cs @@ -1,22 +1,26 @@ using Convey.CQRS.Commands; -using MiniSpace.Services.Organizations.Application.Exceptions; +using MiniSpace.Services.Organizations.Application.Events; +using MiniSpace.Services.Organizations.Application.Services; using MiniSpace.Services.Organizations.Core.Entities; using MiniSpace.Services.Organizations.Core.Repositories; namespace MiniSpace.Services.Organizations.Application.Commands.Handlers { - public class AddOrganizationHandler : ICommandHandler + public class CreateRootOrganizationHandler : ICommandHandler { private readonly IOrganizationRepository _organizationRepository; private readonly IAppContext _appContext; + private readonly IMessageBroker _messageBroker; - public AddOrganizationHandler(IOrganizationRepository organizationRepository, IAppContext appContext) + public CreateRootOrganizationHandler(IOrganizationRepository organizationRepository, IAppContext appContext, + IMessageBroker messageBroker) { _organizationRepository = organizationRepository; _appContext = appContext; + _messageBroker = messageBroker; } - public async Task HandleAsync(AddOrganization command, CancellationToken cancellationToken) + public async Task HandleAsync(CreateRootOrganization command, CancellationToken cancellationToken) { var identity = _appContext.Identity; if(identity.IsAuthenticated && !identity.IsAdmin) @@ -24,18 +28,9 @@ public async Task HandleAsync(AddOrganization command, CancellationToken cancell throw new Exceptions.UnauthorizedAccessException("admin"); } - var organization = new Organization(command.OrganizationId, command.Name, command.ParentId); - if(command.ParentId != Guid.Empty) - { - var parent = await _organizationRepository.GetAsync(command.ParentId); - if(parent is null) - { - throw new ParentOrganizationNotFoundException(command.ParentId); - } - parent.MakeParent(); - await _organizationRepository.UpdateAsync(parent); - } + var organization = new Organization(command.OrganizationId, command.Name); await _organizationRepository.AddAsync(organization); + await _messageBroker.PublishAsync(new RootOrganizationCreated(organization.Id, organization.Name)); } } } \ No newline at end of file diff --git a/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Application/Events/OrganizationCreated.cs b/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Application/Events/OrganizationCreated.cs new file mode 100644 index 000000000..7eebf8d42 --- /dev/null +++ b/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Application/Events/OrganizationCreated.cs @@ -0,0 +1,18 @@ +using Convey.CQRS.Events; + +namespace MiniSpace.Services.Organizations.Application.Events +{ + public class OrganizationCreated: IEvent + { + public Guid OrganizationId { get; } + public string Name { get; } + public Guid ParentId { get; } + + public OrganizationCreated(Guid organizationId, string name, Guid parentId) + { + OrganizationId = organizationId; + Name = name; + ParentId = parentId; + } + } +} \ No newline at end of file diff --git a/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Application/Events/RootOrganizationCreated.cs b/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Application/Events/RootOrganizationCreated.cs new file mode 100644 index 000000000..c22ace7ba --- /dev/null +++ b/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Application/Events/RootOrganizationCreated.cs @@ -0,0 +1,16 @@ +using Convey.CQRS.Events; + +namespace MiniSpace.Services.Organizations.Application.Events +{ + public class RootOrganizationCreated: IEvent + { + public Guid OrganizationId { get; } + public string Name { get; } + + public RootOrganizationCreated(Guid organizationId, string name) + { + OrganizationId = organizationId; + Name = name; + } + } +} \ No newline at end of file diff --git a/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Application/Exceptions/RootOrganizationNotFoundException.cs b/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Application/Exceptions/RootOrganizationNotFoundException.cs new file mode 100644 index 000000000..afe37377d --- /dev/null +++ b/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Application/Exceptions/RootOrganizationNotFoundException.cs @@ -0,0 +1,13 @@ +namespace MiniSpace.Services.Organizations.Application.Exceptions +{ + public class RootOrganizationNotFoundException : AppException + { + public override string Code { get; } = "root_organization_not_found"; + public Guid OrganizationId { get; } + + public RootOrganizationNotFoundException(Guid organizationId) : base($"Root organization with ID: '{organizationId}' was not found.") + { + OrganizationId = organizationId; + } + } +} \ No newline at end of file diff --git a/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Core/Entities/Organization.cs b/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Core/Entities/Organization.cs index ff915096d..b77782868 100644 --- a/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Core/Entities/Organization.cs +++ b/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Core/Entities/Organization.cs @@ -5,9 +5,8 @@ namespace MiniSpace.Services.Organizations.Core.Entities public class Organization : AggregateRoot { private ISet _organizers = new HashSet(); + private ISet _subOrganizations = new HashSet(); public string Name { get; private set; } - public Guid ParentId { get; private set; } - public bool IsLeaf { get; private set; } public IEnumerable Organizers { @@ -15,13 +14,28 @@ public IEnumerable Organizers private set => _organizers = new HashSet(value); } - public Organization(Guid id, string name, Guid parentId, bool isLeaf = true, IEnumerable organizers = null) + public IEnumerable SubOrganizations + { + get => _subOrganizations; + private set => _subOrganizations = new HashSet(value); + } + + public Organization(Guid id, string name, IEnumerable organizers = null, + IEnumerable subOrganizations = null) { Id = id; Name = name; - ParentId = parentId; - IsLeaf = isLeaf; Organizers = organizers ?? Enumerable.Empty(); + SubOrganizations = subOrganizations ?? Enumerable.Empty(); + } + + public void AddOrganizer(Guid organizerId) + { + if(Organizers.Any(x => x.Id == organizerId)) + { + throw new OrganizerAlreadyAddedToOrganizationException(organizerId, Id); + } + _organizers.Add(new Organizer(organizerId)); } public void RemoveOrganizer(Guid organizerId) @@ -34,18 +48,26 @@ public void RemoveOrganizer(Guid organizerId) _organizers.Remove(organizer); } - public void AddOrganizer(Guid organizerId) + public Organization GetSubOrganization(Guid id) { - if(Organizers.Any(x => x.Id == organizerId)) + if (Id == id) { - throw new OrganizerAlreadyAddedToOrganizationException(organizerId, Id); + return this; } - _organizers.Add(new Organizer(organizerId)); + + foreach (var subOrg in SubOrganizations) + { + var result = subOrg.GetSubOrganization(id); + if (result != null) + { + return result; + } + } + + return null; } - - - public void MakeParent() - => IsLeaf = false; + public void AddSubOrganization(Organization organization) + => _subOrganizations.Add(organization); } } \ No newline at end of file diff --git a/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Infrastructure/Extensions.cs b/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Infrastructure/Extensions.cs index f020d0ce7..efbe7351e 100644 --- a/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Infrastructure/Extensions.cs +++ b/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Infrastructure/Extensions.cs @@ -88,7 +88,7 @@ public static IApplicationBuilder UseInfrastructure(this IApplicationBuilder app .UseMetrics() .UseCertificateAuthentication() .UseRabbitMq() - .SubscribeCommand() + .SubscribeCommand() .SubscribeCommand() .SubscribeCommand() .SubscribeEvent() diff --git a/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Infrastructure/Logging/Extensions.cs b/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Infrastructure/Logging/Extensions.cs index 827297347..c104dfd46 100644 --- a/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Infrastructure/Logging/Extensions.cs +++ b/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Infrastructure/Logging/Extensions.cs @@ -9,7 +9,7 @@ internal static class Extensions { public static IConveyBuilder AddHandlersLogging(this IConveyBuilder builder) { - var assembly = typeof(AddOrganization).Assembly; + var assembly = typeof(CreateOrganization).Assembly; builder.Services.AddSingleton(new MessageToLogTemplateMapper()); diff --git a/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Infrastructure/Logging/MessageToLogTemplateMapper.cs b/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Infrastructure/Logging/MessageToLogTemplateMapper.cs index 598978f10..aa72e370c 100644 --- a/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Infrastructure/Logging/MessageToLogTemplateMapper.cs +++ b/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Infrastructure/Logging/MessageToLogTemplateMapper.cs @@ -10,7 +10,7 @@ private static IReadOnlyDictionary MessageTemplates => new Dictionary { { - typeof(AddOrganization), new HandlerLogTemplate + typeof(CreateOrganization), new HandlerLogTemplate { After = "Added a new organization with id: {OrganizationId}." } diff --git a/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Infrastructure/Mongo/Documents/Extensions.cs b/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Infrastructure/Mongo/Documents/Extensions.cs index 6322ec5c9..788a25f1f 100644 --- a/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Infrastructure/Mongo/Documents/Extensions.cs +++ b/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Infrastructure/Mongo/Documents/Extensions.cs @@ -6,16 +6,15 @@ namespace MiniSpace.Services.Organizations.Infrastructure.Mongo.Documents public static class Extensions { public static Organization AsEntity(this OrganizationDocument document) - => new Organization(document.Id, document.Name, document.ParentId, document.IsLeaf, document.Organizers); + => new Organization(document.Id, document.Name, document.Organizers, document.SubOrganizations); public static OrganizationDocument AsDocument(this Organization entity) => new OrganizationDocument() { Id = entity.Id, Name = entity.Name, - ParentId = entity.ParentId, - IsLeaf = entity.IsLeaf, - Organizers = entity.Organizers + Organizers = entity.Organizers, + SubOrganizations = entity.SubOrganizations }; public static OrganizationDto AsDto(this OrganizationDocument document) @@ -23,8 +22,7 @@ public static OrganizationDto AsDto(this OrganizationDocument document) { Id = document.Id, Name = document.Name, - ParentId = document.ParentId, - IsLeaf = document.IsLeaf + Org }; public static OrganizationDetailsDto AsDetailsDto(this OrganizationDocument document) diff --git a/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Infrastructure/Mongo/Documents/OrganizationDocument.cs b/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Infrastructure/Mongo/Documents/OrganizationDocument.cs index 24946e59b..d021944d3 100644 --- a/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Infrastructure/Mongo/Documents/OrganizationDocument.cs +++ b/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Infrastructure/Mongo/Documents/OrganizationDocument.cs @@ -7,8 +7,7 @@ public class OrganizationDocument: IIdentifiable { public Guid Id { get; set; } public string Name { get; set; } - public Guid ParentId { get; set; } - public bool IsLeaf { get; set; } public IEnumerable Organizers { get; set; } + public IEnumerable SubOrganizations { get; set; } } } \ No newline at end of file From 9036f4f0172c33ff7ff4a9cd82242585ed38b96b Mon Sep 17 00:00:00 2001 From: eggwhat Date: Thu, 16 May 2024 21:40:48 +0200 Subject: [PATCH 2/9] (#87) update commands for new organization entity --- .../Commands/AddOrganizerToOrganization.cs | 4 +++- .../Handlers/AddOrganizerToOrganizationHandler.cs | 12 +++++++++--- .../RemoveOrganizerFromOrganizationHandler.cs | 12 +++++++++--- .../Commands/RemoveOrganizerFromOrganization.cs | 4 +++- 4 files changed, 24 insertions(+), 8 deletions(-) diff --git a/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Application/Commands/AddOrganizerToOrganization.cs b/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Application/Commands/AddOrganizerToOrganization.cs index d50e78262..47077c04b 100644 --- a/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Application/Commands/AddOrganizerToOrganization.cs +++ b/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Application/Commands/AddOrganizerToOrganization.cs @@ -4,11 +4,13 @@ namespace MiniSpace.Services.Organizations.Application.Commands { public class AddOrganizerToOrganization: ICommand { + public Guid RootOrganizationId { get; set; } public Guid OrganizationId { get; set; } public Guid OrganizerId { get; set; } - public AddOrganizerToOrganization(Guid organizationId, Guid organizerId) + public AddOrganizerToOrganization(Guid rootOrganizationId, Guid organizationId, Guid organizerId) { + RootOrganizationId = rootOrganizationId; OrganizationId = organizationId; OrganizerId = organizerId; } diff --git a/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Application/Commands/Handlers/AddOrganizerToOrganizationHandler.cs b/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Application/Commands/Handlers/AddOrganizerToOrganizationHandler.cs index d38e6b2a4..d5e3e59cb 100644 --- a/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Application/Commands/Handlers/AddOrganizerToOrganizationHandler.cs +++ b/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Application/Commands/Handlers/AddOrganizerToOrganizationHandler.cs @@ -31,8 +31,14 @@ public async Task HandleAsync(AddOrganizerToOrganization command, CancellationTo throw new Exceptions.UnauthorizedAccessException("admin"); } - var organization = await _organizationRepository.GetAsync(command.OrganizationId); - if (organization is null) + var root = await _organizationRepository.GetAsync(command.RootOrganizationId); + if (root is null) + { + throw new RootOrganizationNotFoundException(command.RootOrganizationId); + } + + var organization = root.GetSubOrganization(command.OrganizationId); + if (organization == null) { throw new OrganizationNotFoundException(command.OrganizationId); } @@ -44,7 +50,7 @@ public async Task HandleAsync(AddOrganizerToOrganization command, CancellationTo } organization.AddOrganizer(command.OrganizerId); - await _organizationRepository.UpdateAsync(organization); + await _organizationRepository.UpdateAsync(root); await _messageBroker.PublishAsync(new OrganizerAddedToOrganization(organization.Id, organizer.Id)); } } diff --git a/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Application/Commands/Handlers/RemoveOrganizerFromOrganizationHandler.cs b/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Application/Commands/Handlers/RemoveOrganizerFromOrganizationHandler.cs index 341fca7c5..d20145909 100644 --- a/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Application/Commands/Handlers/RemoveOrganizerFromOrganizationHandler.cs +++ b/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Application/Commands/Handlers/RemoveOrganizerFromOrganizationHandler.cs @@ -29,8 +29,14 @@ public async Task HandleAsync(RemoveOrganizerFromOrganization command, Cancellat throw new Exceptions.UnauthorizedAccessException("admin"); } - var organization = await _organizationRepository.GetAsync(command.OrganizationId); - if(organization is null) + var root = await _organizationRepository.GetAsync(command.RootOrganizationId); + if (root is null) + { + throw new RootOrganizationNotFoundException(command.RootOrganizationId); + } + + var organization = root.GetSubOrganization(command.OrganizationId); + if (organization == null) { throw new OrganizationNotFoundException(command.OrganizationId); } @@ -42,7 +48,7 @@ public async Task HandleAsync(RemoveOrganizerFromOrganization command, Cancellat } organization.RemoveOrganizer(organizer.Id); - await _organizationRepository.UpdateAsync(organization); + await _organizationRepository.UpdateAsync(root); } } } \ No newline at end of file diff --git a/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Application/Commands/RemoveOrganizerFromOrganization.cs b/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Application/Commands/RemoveOrganizerFromOrganization.cs index 8f553940e..100ada5dd 100644 --- a/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Application/Commands/RemoveOrganizerFromOrganization.cs +++ b/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Application/Commands/RemoveOrganizerFromOrganization.cs @@ -4,11 +4,13 @@ namespace MiniSpace.Services.Organizations.Application.Commands { public class RemoveOrganizerFromOrganization : ICommand { + public Guid RootOrganizationId { get; set; } public Guid OrganizationId { get; set; } public Guid OrganizerId { get; set; } - public RemoveOrganizerFromOrganization(Guid organizationId, Guid organizerId) + public RemoveOrganizerFromOrganization(Guid rootOrganizationId, Guid organizationId, Guid organizerId) { + RootOrganizationId = rootOrganizationId; OrganizationId = organizationId; OrganizerId = organizerId; } From 47f4aa2f433edbe95c7d8dddc06348926793dd8f Mon Sep 17 00:00:00 2001 From: eggwhat Date: Fri, 17 May 2024 00:38:52 +0200 Subject: [PATCH 3/9] (#87) update queries --- .../Entities/Event.cs | 2 +- .../Dto/OrganizationDetailsDto.cs | 15 +++++++++++-- .../Dto/OrganizationDto.cs | 15 +++++++++++-- .../Queries/GetChildrenOrganizations.cs | 1 + .../Queries/GetOrganization.cs | 1 + .../Queries/GetOrganizationDetails.cs | 1 + .../Queries/GetOrganizerOrganizations.cs | 1 + .../Entities/Organization.cs | 21 +++++++++++++++++++ .../Mongo/Documents/Extensions.cs | 5 +---- .../GetChildrenOrganizationsHandler.cs | 10 +++++++-- .../Handlers/GetOrganizationDetailsHandler.cs | 6 +++--- .../Handlers/GetOrganizationHandler.cs | 6 +++--- .../GetOrganizerOrganizationsHandler.cs | 11 +++++++--- .../Handlers/GetRootOrganizationsHandler.cs | 2 +- 14 files changed, 76 insertions(+), 21 deletions(-) diff --git a/MiniSpace.Services.Events/src/MiniSpace.Services.Events.Core/Entities/Event.cs b/MiniSpace.Services.Events/src/MiniSpace.Services.Events.Core/Entities/Event.cs index da9c0ffe0..85d16564c 100644 --- a/MiniSpace.Services.Events/src/MiniSpace.Services.Events.Core/Entities/Event.cs +++ b/MiniSpace.Services.Events/src/MiniSpace.Services.Events.Core/Entities/Event.cs @@ -216,4 +216,4 @@ private void ChangeState(State state) public bool IsOrganizer(Guid organizerId) => Organizer.Id == organizerId; } -} \ No newline at end of file +} \ No newline at end of file diff --git a/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Application/Dto/OrganizationDetailsDto.cs b/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Application/Dto/OrganizationDetailsDto.cs index a25f6c34e..2c7d353bd 100644 --- a/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Application/Dto/OrganizationDetailsDto.cs +++ b/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Application/Dto/OrganizationDetailsDto.cs @@ -1,4 +1,5 @@ using System.Collections; +using MiniSpace.Services.Organizations.Core.Entities; namespace MiniSpace.Services.Organizations.Application.DTO { @@ -6,8 +7,18 @@ public class OrganizationDetailsDto { public Guid Id { get; set; } public string Name { get; set; } - public Guid ParentId { get; set; } - public bool IsLeaf { get; set; } public IEnumerable Organizers { get; set; } + + public OrganizationDetailsDto() + { + + } + + public OrganizationDetailsDto(Organization organization) + { + Id = organization.Id; + Name = organization.Name; + Organizers = organization.Organizers.Select(o => o.Id); + } } } \ No newline at end of file diff --git a/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Application/Dto/OrganizationDto.cs b/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Application/Dto/OrganizationDto.cs index 50ee020cc..fc71ebfea 100644 --- a/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Application/Dto/OrganizationDto.cs +++ b/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Application/Dto/OrganizationDto.cs @@ -1,11 +1,22 @@ +using MiniSpace.Services.Organizations.Core.Entities; + namespace MiniSpace.Services.Organizations.Application.DTO { public class OrganizationDto { public Guid Id { get; set; } public string Name { get; set; } - public Guid ParentId { get; set; } - public bool IsLeaf { get; set; } + + public OrganizationDto() + { + + } + + public OrganizationDto (Organization organization) + { + Id = organization.Id; + Name = organization.Name; + } } } diff --git a/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Application/Queries/GetChildrenOrganizations.cs b/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Application/Queries/GetChildrenOrganizations.cs index a71d10e0a..d1d50bb07 100644 --- a/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Application/Queries/GetChildrenOrganizations.cs +++ b/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Application/Queries/GetChildrenOrganizations.cs @@ -6,5 +6,6 @@ namespace MiniSpace.Services.Organizations.Application.Queries public class GetChildrenOrganizations: IQuery> { public Guid ParentId { get; set; } + public Guid RootId { get; set; } } } \ No newline at end of file diff --git a/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Application/Queries/GetOrganization.cs b/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Application/Queries/GetOrganization.cs index cbcb88480..14b6b9b70 100644 --- a/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Application/Queries/GetOrganization.cs +++ b/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Application/Queries/GetOrganization.cs @@ -6,5 +6,6 @@ namespace MiniSpace.Services.Organizations.Application.Queries public class GetOrganization : IQuery { public Guid OrganizationId { get; set; } + public Guid RootId { get; set; } } } \ No newline at end of file diff --git a/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Application/Queries/GetOrganizationDetails.cs b/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Application/Queries/GetOrganizationDetails.cs index 46b266a07..abf38f0c6 100644 --- a/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Application/Queries/GetOrganizationDetails.cs +++ b/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Application/Queries/GetOrganizationDetails.cs @@ -6,5 +6,6 @@ namespace MiniSpace.Services.Organizations.Application.Queries public class GetOrganizationDetails : IQuery { public Guid OrganizationId { get; set; } + public Guid RootId { get; set; } } } \ No newline at end of file diff --git a/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Application/Queries/GetOrganizerOrganizations.cs b/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Application/Queries/GetOrganizerOrganizations.cs index 327e8da53..b48d8f014 100644 --- a/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Application/Queries/GetOrganizerOrganizations.cs +++ b/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Application/Queries/GetOrganizerOrganizations.cs @@ -6,6 +6,7 @@ namespace MiniSpace.Services.Organizations.Application.Queries public class GetOrganizerOrganizations: IQuery> { public Guid OrganizerId { get; set; } + public Guid RootId { get; set; } } } diff --git a/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Core/Entities/Organization.cs b/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Core/Entities/Organization.cs index b77782868..7a7b31531 100644 --- a/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Core/Entities/Organization.cs +++ b/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Core/Entities/Organization.cs @@ -69,5 +69,26 @@ public Organization GetSubOrganization(Guid id) public void AddSubOrganization(Organization organization) => _subOrganizations.Add(organization); + + public static List FindOrganizations(Guid targetOrganizerId, Organization rootOrganization) + { + var organizations = new List(); + FindOrganizationsRecursive(targetOrganizerId, rootOrganization, organizations); + return organizations; + } + + private static void FindOrganizationsRecursive(Guid targetOrganizerId, Organization currentOrganization, + ICollection organizations) + { + if (currentOrganization.Organizers.Any(x => x.Id == targetOrganizerId)) + { + organizations.Add(currentOrganization); + } + + foreach (var subOrg in currentOrganization.SubOrganizations) + { + FindOrganizationsRecursive(targetOrganizerId, subOrg, organizations); + } + } } } \ No newline at end of file diff --git a/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Infrastructure/Mongo/Documents/Extensions.cs b/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Infrastructure/Mongo/Documents/Extensions.cs index 788a25f1f..e76f3bb24 100644 --- a/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Infrastructure/Mongo/Documents/Extensions.cs +++ b/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Infrastructure/Mongo/Documents/Extensions.cs @@ -21,8 +21,7 @@ public static OrganizationDto AsDto(this OrganizationDocument document) => new OrganizationDto() { Id = document.Id, - Name = document.Name, - Org + Name = document.Name }; public static OrganizationDetailsDto AsDetailsDto(this OrganizationDocument document) @@ -30,8 +29,6 @@ public static OrganizationDetailsDto AsDetailsDto(this OrganizationDocument docu { Id = document.Id, Name = document.Name, - ParentId = document.ParentId, - IsLeaf = document.IsLeaf, Organizers = document.Organizers.Select(x => x.Id) }; diff --git a/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Infrastructure/Mongo/Queries/Handlers/GetChildrenOrganizationsHandler.cs b/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Infrastructure/Mongo/Queries/Handlers/GetChildrenOrganizationsHandler.cs index ab868a7de..7081a3475 100644 --- a/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Infrastructure/Mongo/Queries/Handlers/GetChildrenOrganizationsHandler.cs +++ b/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Infrastructure/Mongo/Queries/Handlers/GetChildrenOrganizationsHandler.cs @@ -16,9 +16,15 @@ public GetChildrenOrganizationsHandler(IMongoRepository> HandleAsync(GetChildrenOrganizations query, CancellationToken cancellationToken) { - var organizations = await _repository.FindAsync(o => o.ParentId == query.ParentId); + var root = await _repository.GetAsync(o => o.Id == query.RootId); + if (root == null) + { + return Enumerable.Empty(); + } - return organizations.Select(o => o.AsDto()); + var parent = root.AsEntity().GetSubOrganization(query.ParentId); + return parent == null ? Enumerable.Empty() + : parent.SubOrganizations.Select(o => new OrganizationDto(o)); } } } \ No newline at end of file diff --git a/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Infrastructure/Mongo/Queries/Handlers/GetOrganizationDetailsHandler.cs b/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Infrastructure/Mongo/Queries/Handlers/GetOrganizationDetailsHandler.cs index dd249addd..f420f0238 100644 --- a/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Infrastructure/Mongo/Queries/Handlers/GetOrganizationDetailsHandler.cs +++ b/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Infrastructure/Mongo/Queries/Handlers/GetOrganizationDetailsHandler.cs @@ -18,9 +18,9 @@ public GetOrganizationDetailsHandler(IMongoRepository HandleAsync(GetOrganizationDetails query, CancellationToken cancellationToken) { - var organization = await _repository.GetAsync(query.OrganizationId); - - return organization?.AsDetailsDto(); + var root = await _repository.GetAsync(o => o.Id == query.RootId); + var organization = root?.AsEntity().GetSubOrganization(query.OrganizationId); + return organization == null ? null : new OrganizationDetailsDto(organization); } } } \ No newline at end of file diff --git a/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Infrastructure/Mongo/Queries/Handlers/GetOrganizationHandler.cs b/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Infrastructure/Mongo/Queries/Handlers/GetOrganizationHandler.cs index d8cb184f9..c01bbd2e9 100644 --- a/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Infrastructure/Mongo/Queries/Handlers/GetOrganizationHandler.cs +++ b/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Infrastructure/Mongo/Queries/Handlers/GetOrganizationHandler.cs @@ -17,9 +17,9 @@ public GetOrganizationHandler(IMongoRepository repos public async Task HandleAsync(GetOrganization query, CancellationToken cancellationToken) { - var organization = await _repository.GetAsync(query.OrganizationId); - - return organization?.AsDto(); + var root = await _repository.GetAsync(o => o.Id == query.RootId); + var organization = root?.AsEntity().GetSubOrganization(query.OrganizationId); + return organization == null ? null : new OrganizationDto(organization); } } } \ No newline at end of file diff --git a/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Infrastructure/Mongo/Queries/Handlers/GetOrganizerOrganizationsHandler.cs b/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Infrastructure/Mongo/Queries/Handlers/GetOrganizerOrganizationsHandler.cs index 0a587fbf6..16977a82c 100644 --- a/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Infrastructure/Mongo/Queries/Handlers/GetOrganizerOrganizationsHandler.cs +++ b/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Infrastructure/Mongo/Queries/Handlers/GetOrganizerOrganizationsHandler.cs @@ -27,10 +27,15 @@ public async Task> HandleAsync(GetOrganizerOrganiza return Enumerable.Empty(); } - var organizations = await _repository - .FindAsync(o => o.Organizers.Any(x => x.Id == query.OrganizerId)); + var roots = (await _repository.FindAsync(o => true)).Select(o =>o.AsEntity()); + var organizerOrganizations = new List(); + foreach (var root in roots) + { + var organizations = Organization.FindOrganizations(query.OrganizerId, root); + organizerOrganizations.AddRange(organizations); + } - return organizations.Select(o => o.AsDto()); + return organizerOrganizations.Select(o => new OrganizationDto(o)); } } } \ No newline at end of file diff --git a/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Infrastructure/Mongo/Queries/Handlers/GetRootOrganizationsHandler.cs b/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Infrastructure/Mongo/Queries/Handlers/GetRootOrganizationsHandler.cs index a4ca6c3c4..87f1ab43e 100644 --- a/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Infrastructure/Mongo/Queries/Handlers/GetRootOrganizationsHandler.cs +++ b/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Infrastructure/Mongo/Queries/Handlers/GetRootOrganizationsHandler.cs @@ -16,6 +16,6 @@ public GetRootOrganizationsHandler(IMongoRepository } public async Task> HandleAsync(GetRootOrganizations query, CancellationToken cancellationToken) - => (await _repository.FindAsync(o => o.ParentId == Guid.Empty)).Select(o => o.AsDto()); + => (await _repository.FindAsync(o => true)).Select(o =>o.AsDto()); } } \ No newline at end of file From 015e2f4e034348c10b5b7ff8c2fa7661fca45e68 Mon Sep 17 00:00:00 2001 From: eggwhat Date: Fri, 17 May 2024 00:52:32 +0200 Subject: [PATCH 4/9] (#87) add endpoint for getting all suborganizations ids --- .../Program.cs | 1 + .../Queries/GetAllChildrenOrganizations.cs | 11 +++++++ .../Entities/Organization.cs | 18 ++++++++++++ .../GetAllChildrenOrganizationsHandler.cs | 29 +++++++++++++++++++ 4 files changed, 59 insertions(+) create mode 100644 MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Application/Queries/GetAllChildrenOrganizations.cs create mode 100644 MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Infrastructure/Mongo/Queries/Handlers/GetAllChildrenOrganizationsHandler.cs diff --git a/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Api/Program.cs b/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Api/Program.cs index 409bcec2e..61c70c019 100644 --- a/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Api/Program.cs +++ b/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Api/Program.cs @@ -37,6 +37,7 @@ public static async Task Main(string[] args) .Get>("organizations/organizer/{organizerId}") .Get>("organizations/root") .Get>("organizations/{organizationId}/children") + .Get>("organizations/{organizationId}/children/all") .Post("organizations", afterDispatch: (cmd, ctx) => ctx.Response.Created($"organizations/root")) .Post("organizations/{organizationId}/organizer") diff --git a/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Application/Queries/GetAllChildrenOrganizations.cs b/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Application/Queries/GetAllChildrenOrganizations.cs new file mode 100644 index 000000000..b67f2f095 --- /dev/null +++ b/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Application/Queries/GetAllChildrenOrganizations.cs @@ -0,0 +1,11 @@ +using Convey.CQRS.Queries; +using MiniSpace.Services.Organizations.Application.DTO; + +namespace MiniSpace.Services.Organizations.Application.Queries +{ + public class GetAllChildrenOrganizations: IQuery> + { + public Guid ParentId { get; set; } + public Guid RootId { get; set; } + } +} \ No newline at end of file diff --git a/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Core/Entities/Organization.cs b/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Core/Entities/Organization.cs index 7a7b31531..97f74fa47 100644 --- a/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Core/Entities/Organization.cs +++ b/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Core/Entities/Organization.cs @@ -90,5 +90,23 @@ private static void FindOrganizationsRecursive(Guid targetOrganizerId, Organizat FindOrganizationsRecursive(targetOrganizerId, subOrg, organizations); } } + + public static List FindAllChildrenOrganizations(Organization rootOrganization) + { + var organizations = new List(); + FindAllChildrenOrganizationsRecursive(rootOrganization, organizations); + return organizations; + } + + private static void FindAllChildrenOrganizationsRecursive(Organization currentOrganization, + ICollection organizations) + { + organizations.Add(currentOrganization.Id); + + foreach (var subOrg in currentOrganization.SubOrganizations) + { + FindAllChildrenOrganizationsRecursive(subOrg, organizations); + } + } } } \ No newline at end of file diff --git a/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Infrastructure/Mongo/Queries/Handlers/GetAllChildrenOrganizationsHandler.cs b/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Infrastructure/Mongo/Queries/Handlers/GetAllChildrenOrganizationsHandler.cs new file mode 100644 index 000000000..11b7de693 --- /dev/null +++ b/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Infrastructure/Mongo/Queries/Handlers/GetAllChildrenOrganizationsHandler.cs @@ -0,0 +1,29 @@ +using Convey.CQRS.Queries; +using Convey.Persistence.MongoDB; +using MiniSpace.Services.Organizations.Application.Queries; +using MiniSpace.Services.Organizations.Core.Entities; +using MiniSpace.Services.Organizations.Infrastructure.Mongo.Documents; + +namespace MiniSpace.Services.Organizations.Infrastructure.Mongo.Queries.Handlers +{ + public class GetAllChildrenOrganizationsHandler : IQueryHandler> + { + private readonly IMongoRepository _repository; + + public GetAllChildrenOrganizationsHandler(IMongoRepository repository) + => _repository = repository; + + public async Task> HandleAsync(GetAllChildrenOrganizations query, CancellationToken cancellationToken) + { + var root = await _repository.GetAsync(o => o.Id == query.RootId); + var organization = root?.AsEntity().GetSubOrganization(query.ParentId); + var result = new List(); + if (organization != null) + { + result.AddRange(Organization.FindAllChildrenOrganizations(organization)); + } + + return result; + } + } +} \ No newline at end of file From 5cd8a62629145fe9720006e6c1686fba63f877b1 Mon Sep 17 00:00:00 2001 From: eggwhat Date: Fri, 17 May 2024 17:23:52 +0200 Subject: [PATCH 5/9] (#87) update endpoint declaration --- .../src/MiniSpace.Services.Organizations.Api/Program.cs | 4 +++- .../Queries/GetAllChildrenOrganizations.cs | 2 +- .../Queries/GetChildrenOrganizations.cs | 2 +- .../Queries/Handlers/GetAllChildrenOrganizationsHandler.cs | 2 +- .../Mongo/Queries/Handlers/GetChildrenOrganizationsHandler.cs | 2 +- 5 files changed, 7 insertions(+), 5 deletions(-) diff --git a/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Api/Program.cs b/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Api/Program.cs index 61c70c019..809763244 100644 --- a/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Api/Program.cs +++ b/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Api/Program.cs @@ -38,8 +38,10 @@ public static async Task Main(string[] args) .Get>("organizations/root") .Get>("organizations/{organizationId}/children") .Get>("organizations/{organizationId}/children/all") - .Post("organizations", + .Post("organizations", afterDispatch: (cmd, ctx) => ctx.Response.Created($"organizations/root")) + .Post("organizations/{organizationId}/children", + afterDispatch: (cmd, ctx) => ctx.Response.Created($"organizations/{cmd.OrganizationId}")) .Post("organizations/{organizationId}/organizer") .Delete("organizations/{organizationId}/organizer/{organizerId}") )) diff --git a/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Application/Queries/GetAllChildrenOrganizations.cs b/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Application/Queries/GetAllChildrenOrganizations.cs index b67f2f095..be66f4b12 100644 --- a/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Application/Queries/GetAllChildrenOrganizations.cs +++ b/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Application/Queries/GetAllChildrenOrganizations.cs @@ -5,7 +5,7 @@ namespace MiniSpace.Services.Organizations.Application.Queries { public class GetAllChildrenOrganizations: IQuery> { - public Guid ParentId { get; set; } + public Guid OrganizationId { get; set; } public Guid RootId { get; set; } } } \ No newline at end of file diff --git a/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Application/Queries/GetChildrenOrganizations.cs b/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Application/Queries/GetChildrenOrganizations.cs index d1d50bb07..2212c82be 100644 --- a/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Application/Queries/GetChildrenOrganizations.cs +++ b/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Application/Queries/GetChildrenOrganizations.cs @@ -5,7 +5,7 @@ namespace MiniSpace.Services.Organizations.Application.Queries { public class GetChildrenOrganizations: IQuery> { - public Guid ParentId { get; set; } + public Guid OrganizationId { get; set; } public Guid RootId { get; set; } } } \ No newline at end of file diff --git a/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Infrastructure/Mongo/Queries/Handlers/GetAllChildrenOrganizationsHandler.cs b/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Infrastructure/Mongo/Queries/Handlers/GetAllChildrenOrganizationsHandler.cs index 11b7de693..149cc4237 100644 --- a/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Infrastructure/Mongo/Queries/Handlers/GetAllChildrenOrganizationsHandler.cs +++ b/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Infrastructure/Mongo/Queries/Handlers/GetAllChildrenOrganizationsHandler.cs @@ -16,7 +16,7 @@ public GetAllChildrenOrganizationsHandler(IMongoRepository> HandleAsync(GetAllChildrenOrganizations query, CancellationToken cancellationToken) { var root = await _repository.GetAsync(o => o.Id == query.RootId); - var organization = root?.AsEntity().GetSubOrganization(query.ParentId); + var organization = root?.AsEntity().GetSubOrganization(query.OrganizationId); var result = new List(); if (organization != null) { diff --git a/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Infrastructure/Mongo/Queries/Handlers/GetChildrenOrganizationsHandler.cs b/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Infrastructure/Mongo/Queries/Handlers/GetChildrenOrganizationsHandler.cs index 7081a3475..e8406e010 100644 --- a/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Infrastructure/Mongo/Queries/Handlers/GetChildrenOrganizationsHandler.cs +++ b/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Infrastructure/Mongo/Queries/Handlers/GetChildrenOrganizationsHandler.cs @@ -22,7 +22,7 @@ public async Task> HandleAsync(GetChildrenOrganizat return Enumerable.Empty(); } - var parent = root.AsEntity().GetSubOrganization(query.ParentId); + var parent = root.AsEntity().GetSubOrganization(query.OrganizationId); return parent == null ? Enumerable.Empty() : parent.SubOrganizations.Select(o => new OrganizationDto(o)); } From 81d89b8bb0f005030dec1a021eee50b2a61b4ded Mon Sep 17 00:00:00 2001 From: eggwhat Date: Fri, 17 May 2024 17:26:11 +0200 Subject: [PATCH 6/9] (#31) update ntrada endpoints for organizations service --- .../src/MiniSpace.APIGateway/ntrada.yml | 20 ++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/MiniSpace.APIGateway/src/MiniSpace.APIGateway/ntrada.yml b/MiniSpace.APIGateway/src/MiniSpace.APIGateway/ntrada.yml index 492edb433..0a5b2acb0 100644 --- a/MiniSpace.APIGateway/src/MiniSpace.APIGateway/ntrada.yml +++ b/MiniSpace.APIGateway/src/MiniSpace.APIGateway/ntrada.yml @@ -609,23 +609,24 @@ modules: use: downstream downstream: organizations-service/organizations auth: true + + - upstream: /{organizationId}/children + method: POST + use: downstream + downstream: organizations-service/organizations/{organizationId}/children + auth: true - - upstream: /organizer/{organizationId}/organizer + - upstream: /{organizationId}/organizer method: POST use: downstream downstream: organizations-service/organizations/{organizationId}/organizer auth: true - - upstream: /organizer/{organizationId}/organizer/{organizerId} + - upstream: /{organizationId}/organizer/{organizerId} method: DELETE use: downstream downstream: organizations-service/organizations/{organizationId}/organizer/{organizerId} auth: true - - - upstream: / - method: GET - use: downstream - downstream: organizations-service/organizations - upstream: /{organizationId} method: GET @@ -647,6 +648,11 @@ modules: use: downstream downstream: organizations-service/organizations/{organizationId}/children + - upstream: /{organizationId}/children/all + method: GET + use: downstream + downstream: organizations-service/organizations/{organizationId}/children/all + - upstream: /organizer/{organizerId} method: GET use: downstream From d8f28c97375aa9214f49ad27d9b7b37e01f54208 Mon Sep 17 00:00:00 2001 From: eggwhat Date: Fri, 17 May 2024 17:28:04 +0200 Subject: [PATCH 7/9] (#87) update logging messages --- .../Logging/MessageToLogTemplateMapper.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Infrastructure/Logging/MessageToLogTemplateMapper.cs b/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Infrastructure/Logging/MessageToLogTemplateMapper.cs index aa72e370c..e95de21b2 100644 --- a/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Infrastructure/Logging/MessageToLogTemplateMapper.cs +++ b/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Infrastructure/Logging/MessageToLogTemplateMapper.cs @@ -9,10 +9,16 @@ internal sealed class MessageToLogTemplateMapper : IMessageToLogTemplateMapper private static IReadOnlyDictionary MessageTemplates => new Dictionary { + { + typeof(CreateRootOrganization), new HandlerLogTemplate + { + After = "Created a new root organization with id: {OrganizationId}." + } + }, { typeof(CreateOrganization), new HandlerLogTemplate { - After = "Added a new organization with id: {OrganizationId}." + After = "Added a new child organization with id: {OrganizationId} for parent with id: {ParentId}." } }, { From f919761b06b27fb301200d48daf2a4a926f3b4d5 Mon Sep 17 00:00:00 2001 From: eggwhat Date: Fri, 17 May 2024 17:59:11 +0200 Subject: [PATCH 8/9] (#87) fix issue with mongo document serialization --- .../Entities/Organization.cs | 8 ++++---- .../Mongo/Documents/Extensions.cs | 4 ++-- .../Mongo/Documents/OrganizationDocument.cs | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Core/Entities/Organization.cs b/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Core/Entities/Organization.cs index 97f74fa47..05ff15b83 100644 --- a/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Core/Entities/Organization.cs +++ b/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Core/Entities/Organization.cs @@ -20,13 +20,13 @@ public IEnumerable SubOrganizations private set => _subOrganizations = new HashSet(value); } - public Organization(Guid id, string name, IEnumerable organizers = null, - IEnumerable subOrganizations = null) + public Organization(Guid id, string name, IEnumerable organizationOrganizers = null, + IEnumerable organizations = null) { Id = id; Name = name; - Organizers = organizers ?? Enumerable.Empty(); - SubOrganizations = subOrganizations ?? Enumerable.Empty(); + Organizers = organizationOrganizers ?? Enumerable.Empty(); + SubOrganizations = organizations ?? Enumerable.Empty(); } public void AddOrganizer(Guid organizerId) diff --git a/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Infrastructure/Mongo/Documents/Extensions.cs b/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Infrastructure/Mongo/Documents/Extensions.cs index e76f3bb24..343da89eb 100644 --- a/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Infrastructure/Mongo/Documents/Extensions.cs +++ b/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Infrastructure/Mongo/Documents/Extensions.cs @@ -6,7 +6,7 @@ namespace MiniSpace.Services.Organizations.Infrastructure.Mongo.Documents public static class Extensions { public static Organization AsEntity(this OrganizationDocument document) - => new Organization(document.Id, document.Name, document.Organizers, document.SubOrganizations); + => new Organization(document.Id, document.Name, document.Organizers, document.SubOrganizations.Select(o => o.AsEntity())); public static OrganizationDocument AsDocument(this Organization entity) => new OrganizationDocument() @@ -14,7 +14,7 @@ public static OrganizationDocument AsDocument(this Organization entity) Id = entity.Id, Name = entity.Name, Organizers = entity.Organizers, - SubOrganizations = entity.SubOrganizations + SubOrganizations = entity.SubOrganizations.Select(o => o.AsDocument()) }; public static OrganizationDto AsDto(this OrganizationDocument document) diff --git a/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Infrastructure/Mongo/Documents/OrganizationDocument.cs b/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Infrastructure/Mongo/Documents/OrganizationDocument.cs index d021944d3..5e7a31dcb 100644 --- a/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Infrastructure/Mongo/Documents/OrganizationDocument.cs +++ b/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Infrastructure/Mongo/Documents/OrganizationDocument.cs @@ -8,6 +8,6 @@ public class OrganizationDocument: IIdentifiable public Guid Id { get; set; } public string Name { get; set; } public IEnumerable Organizers { get; set; } - public IEnumerable SubOrganizations { get; set; } + public IEnumerable SubOrganizations { get; set; } } } \ No newline at end of file From 6b90192e10f25f50e68de783eb850f2cda8a7437 Mon Sep 17 00:00:00 2001 From: eggwhat Date: Fri, 17 May 2024 18:08:52 +0200 Subject: [PATCH 9/9] (#87) add validation for organization name --- .../Commands/Handlers/CreateOrganizationHandler.cs | 5 +++++ .../Handlers/CreateRootOrganizationHandler.cs | 6 ++++++ .../Exceptions/InvalidOrganizationNameException.cs | 13 +++++++++++++ 3 files changed, 24 insertions(+) create mode 100644 MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Application/Exceptions/InvalidOrganizationNameException.cs diff --git a/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Application/Commands/Handlers/CreateOrganizationHandler.cs b/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Application/Commands/Handlers/CreateOrganizationHandler.cs index 575a86037..056f13b66 100644 --- a/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Application/Commands/Handlers/CreateOrganizationHandler.cs +++ b/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Application/Commands/Handlers/CreateOrganizationHandler.cs @@ -41,6 +41,11 @@ public async Task HandleAsync(CreateOrganization command, CancellationToken canc throw new ParentOrganizationNotFoundException(command.ParentId); } + if (string.IsNullOrWhiteSpace(command.Name)) + { + throw new InvalidOrganizationNameException(command.Name); + } + var organization = new Organization(command.OrganizationId, command.Name); parent.AddSubOrganization(organization); await _organizationRepository.UpdateAsync(root); diff --git a/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Application/Commands/Handlers/CreateRootOrganizationHandler.cs b/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Application/Commands/Handlers/CreateRootOrganizationHandler.cs index 76bff3b40..1d21c515b 100644 --- a/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Application/Commands/Handlers/CreateRootOrganizationHandler.cs +++ b/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Application/Commands/Handlers/CreateRootOrganizationHandler.cs @@ -1,5 +1,6 @@ using Convey.CQRS.Commands; using MiniSpace.Services.Organizations.Application.Events; +using MiniSpace.Services.Organizations.Application.Exceptions; using MiniSpace.Services.Organizations.Application.Services; using MiniSpace.Services.Organizations.Core.Entities; using MiniSpace.Services.Organizations.Core.Repositories; @@ -27,6 +28,11 @@ public async Task HandleAsync(CreateRootOrganization command, CancellationToken { throw new Exceptions.UnauthorizedAccessException("admin"); } + + if (string.IsNullOrWhiteSpace(command.Name)) + { + throw new InvalidOrganizationNameException(command.Name); + } var organization = new Organization(command.OrganizationId, command.Name); await _organizationRepository.AddAsync(organization); diff --git a/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Application/Exceptions/InvalidOrganizationNameException.cs b/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Application/Exceptions/InvalidOrganizationNameException.cs new file mode 100644 index 000000000..14f29be86 --- /dev/null +++ b/MiniSpace.Services.Organizations/src/MiniSpace.Services.Organizations.Application/Exceptions/InvalidOrganizationNameException.cs @@ -0,0 +1,13 @@ +namespace MiniSpace.Services.Organizations.Application.Exceptions +{ + public class InvalidOrganizationNameException : AppException + { + public override string Code { get; } = "invalid_organization_name"; + public string Name { get; } + + public InvalidOrganizationNameException(string name) : base($"Invalid organization name: {name}.") + { + Name = name; + } + } +} \ No newline at end of file