Skip to content

Commit

Permalink
Add get staff endpoint and fix upsert staff endpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
NixFey committed Aug 1, 2024
1 parent 6872d2d commit 672a961
Show file tree
Hide file tree
Showing 6 changed files with 79 additions and 20 deletions.
11 changes: 11 additions & 0 deletions FiMAdminApi.Data/DataContext.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using FiMAdminApi.Data.Enums;
using FiMAdminApi.Data.Models;
using Microsoft.EntityFrameworkCore;

Expand All @@ -16,5 +17,15 @@ public class DataContext(DbContextOptions<DataContext> options) : DbContext(opti
protected override void ConfigureConventions(ModelConfigurationBuilder configurationBuilder)
{
configurationBuilder.Properties(typeof(Enum)).HaveConversion<string>();
configurationBuilder.Properties(typeof(IEnumerable<Enum>)).HaveConversion<IEnumerable<string>>();
}

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder
.Entity<EventStaff>()
.Property(e => e.Permissions)
.HasConversion(v => v.Select(p => p.ToString()).ToList(),
v => v.Select(Enum.Parse<EventPermission>).ToList());
}
}
1 change: 0 additions & 1 deletion FiMAdminApi/Clients/BlueAllianceDataClient.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
using System.Globalization;
using System.Net.Http.Headers;
using System.Net.Mime;
using System.Text;
using System.Text.Json;
using FiMAdminApi.Data.Models;
using FiMAdminApi.Extensions;
Expand Down
63 changes: 56 additions & 7 deletions FiMAdminApi/Endpoints/EventsEndpoints.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,15 @@ public static WebApplication RegisterEventsEndpoints(this WebApplication app, Ap
.RequireAuthorization();

eventsGroup.MapPut("{id:guid}", UpdateBasicInfo)
.WithSummary("Update basic event info");
.WithDescription("Update basic event info");
eventsGroup.MapGet("{eventId:guid}/staffs", GetEventStaff)
.WithDescription("Get all staff for an event");
eventsGroup.MapPut("{eventId:guid}/staffs", UpsertEventStaff)
.WithSummary("Create or update a staff user for an event");
.WithDescription("Create or update a staff user for an event");
eventsGroup.MapDelete("{eventId:guid}/staffs/{userId:guid}", DeleteEventStaff)
.WithSummary("Remove a staff user for an event");
.WithDescription("Remove a staff user for an event");
eventsGroup.MapPost("{eventId:guid}/notes", CreateEventNote)
.WithSummary("Create an event note");
.WithDescription("Create an event note");

return app;
}
Expand Down Expand Up @@ -67,6 +69,43 @@ private static async Task<Results<Ok<Event>, NotFound, ForbidHttpResult, Validat
return TypedResults.Ok(evt);
}

private static async Task<Results<Ok<EventStaffInfo[]>, NotFound, ForbidHttpResult>> GetEventStaff(
[FromRoute] Guid eventId,
[FromServices] DataContext dbContext,
[FromServices] IGotrueAdminClient<User> adminClient,
ClaimsPrincipal user,
[FromServices] IAuthorizationService authSvc)
{
if (!await dbContext.Events.AnyAsync(e => e.Id == eventId))
return TypedResults.NotFound();

var isAuthorized = await authSvc.AuthorizeAsync(user, eventId, new EventAuthorizationRequirement
{
NeededEventPermission = EventPermission.Event_ManageStaff,
NeededGlobalPermission = GlobalPermission.Events_Manage
});
if (!isAuthorized.Succeeded) return TypedResults.Forbid();

var staffs = await dbContext.EventStaffs.Where(s => s.EventId == eventId).ToListAsync();
var profiles = await dbContext.Profiles.Where(p => staffs.Select(s => s.UserId).Contains(p.Id)).ToListAsync();

var staffInfo = new List<EventStaffInfo>();
foreach (var staff in staffs)
{
var staffUser = await adminClient.GetUserById(staff.UserId.ToString());
staffInfo.Add(new EventStaffInfo
(
staff.EventId,
staff.UserId,
staffUser?.Email,
profiles.FirstOrDefault(p => p.Id == staff.UserId)?.Name,
staff.Permissions
));
}

return TypedResults.Ok(staffInfo.ToArray());
}

private static async Task<Results<Ok<EventStaff>, ForbidHttpResult, ValidationProblem>> UpsertEventStaff(
[FromRoute] Guid eventId,
[FromBody] UpsertEventStaffRequest request,
Expand All @@ -78,7 +117,7 @@ private static async Task<Results<Ok<EventStaff>, ForbidHttpResult, ValidationPr
var (_, validationErrors) = await MiniValidator.TryValidateAsync(request);
if (!await dbContext.Events.AnyAsync(e => e.Id == eventId))
validationErrors.Add("EventId", ["DoesNotExist"]);
if (await adminClient.GetUserById(request.UserId.ToString()) is not null)
if (await adminClient.GetUserById(request.UserId.ToString()) is null)
validationErrors.Add("UserId", ["DoesNotExist"]);
if (validationErrors.Count != 0) return TypedResults.ValidationProblem(validationErrors);

Expand All @@ -92,18 +131,21 @@ private static async Task<Results<Ok<EventStaff>, ForbidHttpResult, ValidationPr
var staffRecord =
await dbContext.EventStaffs.FirstOrDefaultAsync(s => s.EventId == eventId && s.UserId == request.UserId);
if (staffRecord is null)
{
staffRecord = new EventStaff
{
EventId = eventId,
UserId = request.UserId,
Permissions = request.Permissions
};
dbContext.EventStaffs.Add(staffRecord);
}
else
{
staffRecord.Permissions = request.Permissions;
dbContext.EventStaffs.Update(staffRecord);
}

dbContext.EventStaffs.Update(staffRecord);

await dbContext.SaveChangesAsync();

return TypedResults.Ok(staffRecord);
Expand Down Expand Up @@ -199,6 +241,13 @@ public class UpdateBasicInfoRequest
public required EventStatus Status { get; set; }
}

public record EventStaffInfo(
Guid EventId,
Guid UserId,
string? Email,
string? ProfileName,
IEnumerable<EventPermission>? Permissions);

public class UpsertEventStaffRequest
{
[Required]
Expand Down
2 changes: 1 addition & 1 deletion FiMAdminApi/FiMAdminApi.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="9.0.0-preview.6.24328.4" />
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="9.0.0-preview.6.24328.4" />
<PackageReference Include="MiniValidation" Version="0.9.1" />
<PackageReference Include="Supabase" Version="1.0.5" />
<PackageReference Include="Supabase" Version="1.1.1" />
<PackageReference Include="System.Collections" Version="4.3.0" />
<PackageReference Include="System.Text.Json" Version="9.0.0-preview.6.24327.7" />
</ItemGroup>
Expand Down
21 changes: 10 additions & 11 deletions FiMAdminApi/Infrastructure/ApiStartupExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -60,20 +60,19 @@ public static IEndpointRouteBuilder UseApiDocumentation(this IEndpointRouteBuild
}).ExcludeFromDescription();

// Serve API documentation
// TODO: Update to `/openapi/v1.json` when OpenAPI is working
app.MapGet("/docs", () =>
{
const string resp = """
<html>
<head>
<script src="https://unpkg.com/@stoplight/elements/web-components.min.js"></script>
<link rel="stylesheet" href="https://unpkg.com/@stoplight/elements/styles.min.css">
</head>
<body>
<elements-api apiDescriptionUrl="/openapi/v1.json" router="hash" basePath="/docs"/>
</body>
</html>
""";
<html>
<head>
<script src="https://unpkg.com/@stoplight/elements/web-components.min.js"></script>
<link rel="stylesheet" href="https://unpkg.com/@stoplight/elements/styles.min.css">
</head>
<body>
<elements-api apiDescriptionUrl="/openapi/v1.json" router="hash" basePath="/docs"/>
</body>
</html>
""";

return Results.Content(resp, MediaTypeNames.Text.Html);
}).ExcludeFromDescription();
Expand Down
1 change: 1 addition & 0 deletions FiMAdminApi/Infrastructure/SerializerContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ namespace FiMAdminApi.Infrastructure;
[JsonSerializable(typeof(EventsEndpoints.CreateEventNoteRequest))]
[JsonSerializable(typeof(User[]))]
[JsonSerializable(typeof(EventStaff))]
[JsonSerializable(typeof(EventsEndpoints.EventStaffInfo[]))]
[JsonSerializable(typeof(EventNote))]
[JsonSerializable(typeof(HealthEndpoints.ThinHealthReport))]
public partial class SerializerContext : JsonSerializerContext
Expand Down

0 comments on commit 672a961

Please sign in to comment.