using System.Security.Claims; using Books.Api.Authorization; using Books.Api.Commands.Companies; using Books.Api.Commands.UserAccess; using Books.Api.Domain.Companies; using Books.Api.Domain.UserAccess; using Books.Api.EventFlow.Repositories; using Books.Api.GraphQL.InputTypes; using Books.Api.GraphQL.Types; using EventFlow; using GraphQL; using GraphQL.Types; namespace Books.Api.GraphQL.Mutations; public class BooksMutation : ObjectGraphType { public BooksMutation() { Name = "Mutation"; Description = "Root mutation for the Books API"; // createCompany(input: CreateCompanyInput!): CompanyType Field("createCompany") .Description("Create a new company") .Argument>("input", "The company data") .ResolveAsync(async ctx => { var input = ctx.GetArgument("input"); var commandBus = ctx.RequestServices!.GetRequiredService(); var repository = ctx.RequestServices!.GetRequiredService(); var companyId = CompanyId.New; var command = new CreateCompanyCommand( companyId, input.Name, input.Cvr, input.Address, input.PostalCode, input.City, input.Country ?? "DK", input.FiscalYearStartMonth ?? 1, input.Currency ?? "DKK", input.VatRegistered ?? false, input.VatPeriodFrequency); await commandBus.PublishAsync(command, ctx.CancellationToken); // Grant the creating user owner access to the new company var httpContext = ctx.RequestServices!.GetRequiredService().HttpContext; var userId = httpContext?.User.FindFirst(ClaimTypes.NameIdentifier)?.Value; if (userId != null) { var accessId = UserCompanyAccessId.FromUserAndCompany(userId, companyId.Value); var grantCmd = new GrantUserCompanyAccessCommand( accessId, userId, companyId.Value, CompanyRole.Owner, userId); await commandBus.PublishAsync(grantCmd, ctx.CancellationToken); } // Return the created company (eventually consistent) return await repository.GetByIdAsync(companyId.Value, ctx.CancellationToken); }); // updateCompany(id: ID!, input: UpdateCompanyInput!): CompanyType Field("updateCompany") .Description("Update an existing company") .Argument>("id", "The company ID") .Argument>("input", "The updated company data") .ResolveAsync(async ctx => { var id = ctx.GetArgument("id"); // Require Owner or Accountant role to update a company var accessService = ctx.RequestServices!.GetRequiredService(); await accessService.RequireAccessAsync(id, CompanyRole.Accountant, ctx.CancellationToken); var input = ctx.GetArgument("input"); var commandBus = ctx.RequestServices!.GetRequiredService(); var repository = ctx.RequestServices!.GetRequiredService(); var companyId = CompanyId.With(id); var command = new UpdateCompanyCommand( companyId, input.Name, input.Cvr, input.Address, input.PostalCode, input.City, input.Country ?? "DK", input.FiscalYearStartMonth ?? 1, input.Currency ?? "DKK", input.VatRegistered ?? false, input.VatPeriodFrequency); await commandBus.PublishAsync(command, ctx.CancellationToken); return await repository.GetByIdAsync(companyId.Value, ctx.CancellationToken); }); } }