using Microsoft.AspNetCore.Http; using Microsoft.EntityFrameworkCore; using WebApp.Data; using WebApp.DTOs; using WebApp.Entities; using WebApp.Mapping; namespace WebApp.Endpoints { public static class EventsEndpoints { const string GetEventEndpointName = "GetEvent"; public static RouteGroupBuilder MapEventsEndpoints(this WebApplication app) { var group = app.MapGroup("api/events") .WithParameterValidation(); // GET /events group.MapGet("/", async (ApplicationDbContext dbContext, HttpContext httpContext) => { var sort = httpContext.Request.Query["sort"].ToString(); IOrderedQueryable res; var r = dbContext.Events .Include(Eve => Eve.Organisation); if (sort is not null && sort.ToUpper() == "ASC") { res = r.OrderBy(Eve => Eve.EventId); } else { res = r.OrderByDescending(Eve => Eve.EventId); } return await res .Select(Eve => Eve.ToEventSummaryDto()) //EventSummaryDto .AsNoTracking() .ToListAsync(); }); // GET /events/1 group.MapGet("/{id}", async (int id, ApplicationDbContext dbContext, HttpContext httpContext, GeneralUseHelpers guhf) => { Event? Eve = await dbContext.Events.FindAsync(id); if (Eve is null) return Results.NotFound(); // Sprawdź, czy token należy do organizacji, a jeżeli tak, to do której. Token? token = await guhf.GetTokenFromHTTPContext(httpContext); Organisation? org = await guhf.GetOrganisationFromToken(token); // Jeśli token należy do organizacji, która utworzyła to wydarzenie, // to zwróć także EventRegistrations. W przeciwnym razie usuń to pole // przed jego wysłaniem! if (org is null || org.OrganisationId != Eve.OrganisationId) Eve.EventRegistrations = []; // DLACZEGO? Eve.Organisation = await guhf.GetOrganisationFromId(Eve.OrganisationId); EventDetailsDto EveDto = Eve.ToEventDetailsDto(); return Results.Ok(EveDto); //EventDetailsDto }) .WithName(GetEventEndpointName); // POST /events group.MapPost("/", async (EventCreateDto newEvent, ApplicationDbContext dbContext, HttpContext httpContext, GeneralUseHelpers guhf) => { // Uzyskaj organizację z tokenu Token? token = await guhf.GetTokenFromHTTPContext(httpContext); Organisation? org = await guhf.GetOrganisationFromToken(token); if (org is null) return Results.Unauthorized(); // dodajemy id organizacji z tokenu Event Eve = newEvent.ToEntity(); Eve.OrganisationId = org.OrganisationId; dbContext.Events.Add(Eve); await dbContext.SaveChangesAsync(); return Results.CreatedAtRoute( GetEventEndpointName, new { id = Eve.EventId }, Eve.ToEventDetailsDto()); //EventDetailsDto }); // PUT /events/1 group.MapPut("/{id}", async (int id, EventUpdateDto updatedEvent, ApplicationDbContext dbContext, GeneralUseHelpers guhf, HttpContext httpContext) => { // Uzyskaj organizację z tokenu Token? token = await guhf.GetTokenFromHTTPContext(httpContext); Organisation? org = await guhf.GetOrganisationFromToken(token); if (org is null) return Results.Unauthorized(); Console.Write(org.OrganisationId); var existingEvent = await dbContext.Events.FindAsync(id); if (existingEvent is null) { return Results.NotFound(); } // Sprawdź, czy organizacja ma prawo // do zmodyfikowania tego (EventId = id) eventu. if (org.OrganisationId != existingEvent.OrganisationId) return Results.StatusCode(403); var originalOrgId = existingEvent.OrganisationId; dbContext.Entry(existingEvent) .CurrentValues .SetValues(updatedEvent.ToEntity(id)); existingEvent.OrganisationId = originalOrgId; dbContext.Entry(existingEvent) .Collection(Eve => Eve.EventRegistrations) .IsModified = false; await dbContext.SaveChangesAsync(); return Results.NoContent(); }); // DELETE /events/1 group.MapDelete("/{id}", async (int id, ApplicationDbContext dbContext, GeneralUseHelpers guhf, HttpContext httpContext) => { // Uzyskaj organizację z tokenu Token? token = await guhf.GetTokenFromHTTPContext(httpContext); Organisation? org = await guhf.GetOrganisationFromToken(token); if (org is null) return Results.Unauthorized(); // Sprawdź, czy organizacja ma prawo // do usunięcia tego (EventId = id) eventu. Event? Eve = await dbContext.Events.FindAsync(id); if (Eve is null) return Results.NotFound(); else if (org.OrganisationId != Eve.OrganisationId) return Results.StatusCode(403); await dbContext.Events .Where(Eve => Eve.EventId == id) .ExecuteDeleteAsync(); return Results.NoContent(); }); // POST /events/search group.MapPost("/search/", async (EventSearchDto query, ApplicationDbContext dbContext, HttpContext httpContext, GeneralUseHelpers guhf) => { // Uzyskaj organizację z tokenu var sort = httpContext.Request.Query["sort"].ToString(); Token? token = await guhf.GetTokenFromHTTPContext(httpContext); Organisation? org = await guhf.GetOrganisationFromToken(token); List SearchResults = []; List AllEvents = await dbContext.Events.ToListAsync(); if (sort is null || sort.ToUpper() != "ASC") { AllEvents.Reverse(); // aby wyświetlało od najnowszych wydarzeń } foreach(Event e in AllEvents) { bool matchFound = true; // Logika wyszukiwania // Sprawdź wszystkie pola z EventSearchDto, np. if (query.OrganisationId is not null) { // Sprawdź, czy Event należy do query.OrganisationId. if (e.OrganisationId != query.OrganisationId) matchFound = false; } if (query.TitleOrDescription is not null) { var TitleMatch = guhf.SearchString(e.Title, query.TitleOrDescription); var DescMatch = guhf.SearchString(e.Description, query.TitleOrDescription); if (!TitleMatch && !DescMatch) matchFound = false; } //Zakres dat do wyszukiwania if(query.EventDateFrom is not null) { if (e.EventDate < query.EventDateFrom) matchFound = false; } if(query.EventDateTo is not null) { if (e.EventDate > query.EventDateTo) matchFound = false; } // ... // Jeśli Event jest tym, czego szuka użytkownik, // dodaj go do listy SearchResults. // // Uwaga! Zanim to zrobisz, sprawdź, czy użytkownik // jest twórcą danego wydarzenia! Jeżeli nim nie jest, // wyzeruj EventRegistrations! if (org is null || e.Organisation != org) { e.EventRegistrations.Clear(); } // UWAGA! TO NIE POWINNO TAK DZIAŁAĆ! // KTOKOLWIEK WIDZIAŁ, KTOKOLWIEK WIE CZEMU Organisation JEST null? e.Organisation = await guhf.GetOrganisationFromId(e.OrganisationId); if (matchFound) SearchResults.Add(e.ToEventSummaryDto()); } return Results.Ok(SearchResults); }); // POST /events/1/add_skill group.MapPost("/{id}/add_skill/", async (int id, SingleSkillDto dto, ApplicationDbContext dbContext, HttpContext httpContext, GeneralUseHelpers guhf) => { Event? Eve = await dbContext.Events.FindAsync(id); if (Eve is null) return Results.Json(new { message = "Event not found" }, statusCode: 404); // Sprawdź, czy token należy do organizacji, a jeżeli tak, to do której. Token? token = await guhf.GetTokenFromHTTPContext(httpContext); Organisation? org = await guhf.GetOrganisationFromToken(token); // Jeśli token należy do organizacji, która utworzyła to wydarzenie, // to zwróć także EventRegistrations. W przeciwnym razie usuń to pole // przed jego wysłaniem! if (org is null || org.OrganisationId != Eve.OrganisationId) return Results.Unauthorized(); // Szukamy skilla w bazie o ID takim, jak w otrzymanym DTO Skill? skill = await dbContext.Skills.FindAsync(dto.Skill); if (skill is null) { return Results.Json(new { message = "Skill not found" }, statusCode: 404); } // Sprawdzamy, czy to wydarzenie nie ma już takiego skilla. Jeżeli ma, nie ma sensu dodawać go kilkukrotnie. EventSkill? es = await dbContext.EventSkills.FirstOrDefaultAsync(e => e.EventId == id && e.SkillId == dto.Skill); if (es is null) { // Nie ma - zatem musimy dodać nowy EventSkill do bazy EventSkill newEs = dto.ToEventSkillEntity(Eve.EventId); dbContext.EventSkills.Add(newEs); await dbContext.SaveChangesAsync(); } else { // Ma - (ta para EventId <-> SkillId już istnieje w bazie); ten Event posiada już ten skill return Results.Json(new { message = "Skill already assinged to this event!" }, statusCode: 400); } return Results.Json(new { message = "Skill added to event successfully!" }, statusCode: 201); }); // POST /events/1/renive_skill group.MapPost("/{id}/remove_skill/", async (int id, SingleSkillDto dto, ApplicationDbContext dbContext, HttpContext httpContext, GeneralUseHelpers guhf) => { Event? Eve = await dbContext.Events.FindAsync(id); if (Eve is null) return Results.Json(new { message = "Event not found" }, statusCode: 404); // Sprawdź, czy token należy do organizacji, a jeżeli tak, to do której. Token? token = await guhf.GetTokenFromHTTPContext(httpContext); Organisation? org = await guhf.GetOrganisationFromToken(token); // Jeśli token należy do organizacji, która utworzyła to wydarzenie, // to zwróć także EventRegistrations. W przeciwnym razie usuń to pole // przed jego wysłaniem! if (org is null || org.OrganisationId != Eve.OrganisationId) return Results.Unauthorized(); // Szukamy skilla w bazie o ID takim, jak w otrzymanym DTO Skill? skill = await dbContext.Skills.FindAsync(dto.Skill); if (skill is null) { return Results.Json(new { message = "Skill not found" }, statusCode: 404); } // Sprawdzamy, czy to wydarzenie nie ma już takiego skilla. Jeżeli nie ma, to nie ma sensu kasować czegoś, czego nie ma. EventSkill? es = await dbContext.EventSkills.FirstOrDefaultAsync(e => e.EventId == id && e.SkillId == dto.Skill); if (es is not null) { // Ma - zatem musimy usunąć ten EventSkill z bazy await dbContext.EventSkills.Where(e => e.SkillId == dto.Skill) .ExecuteDeleteAsync(); } else { // Nie ma - (ta para EventId <-> SkillId nie istnieje w bazie); ten Event nie posiada tego skill'a return Results.Json(new { message = "This skill isn't assinged to this event!" }, statusCode: 400); } return Results.Json(new { message = "Skill removed from event successfully!" }, statusCode: 201); }); return group; } } }