Edition Get and Delete

This commit is contained in:
mborzyszkowski 2020-11-08 10:53:14 +01:00
parent df11ff9005
commit 74e3957274
8 changed files with 207 additions and 1 deletions

View File

@ -18,12 +18,22 @@ namespace InternshipSystem.Api
.ForMember(
result => result.Status,
opt => opt.MapFrom(edition => edition.IsOpen ? "Open" : "Archival"));
CreateMap<Edition, EditionManagementResult>();
CreateMap<Edition, EditionFullResult>();
CreateMap<Edition, EditionConfigurationResult>();
CreateMap<InternshipSubject, InternshipSubject>();
CreateMap<EditionSubject, InternshipSubject>().IncludeMembers(es => es.Subject);
CreateMap<EditionSubject, InternshipSubject>()
.IncludeMembers(es => es.Subject);
CreateMap<EditionInternshipType, InternshipType>()
.IncludeMembers(eit => eit.InternshipType);
CreateMap<InternshipType, InternshipType>();
}
}
}

View File

@ -0,0 +1,127 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using AutoMapper;
using AutoMapper.QueryableExtensions;
using InternshipSystem.Api.Queries.SearchQuery;
using InternshipSystem.Api.Result;
using InternshipSystem.Api.Security;
using InternshipSystem.Repository;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
namespace InternshipSystem.Api.Controllers
{
[ApiController]
[Route("editionManagement")]
public class EditionManagementController : ControllerBase
{
private InternshipDbContext Context { get; }
private IMapper Mapper { get; }
public EditionManagementController(IMapper mapper, InternshipDbContext context)
{
Context = context;
Mapper = mapper;
}
[HttpGet]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
[Authorize(Policy = Policies.IsOverseer)]
public async Task<ActionResult<IReadOnlyCollection<EditionManagementResult>>> GetEditions([FromQuery] EditionSearchQuery searchQuery, CancellationToken token) =>
await Context.Editions
.Include(e => e.Course)
.ProjectTo<EditionManagementResult>(Mapper.ConfigurationProvider)
.Skip(searchQuery.Page * searchQuery.PerPage)
.Take(searchQuery.PerPage)
.ToListAsync(token);
[HttpGet("{editionId}")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
[Authorize(Policy = Policies.IsOverseer)]
public async Task<ActionResult<EditionFullResult>> GetFullEdition(CancellationToken token)
{
var edition = await Context.Editions
.Include(e => e.Course)
.Include(e => e.AvailableSubjects)
.ThenInclude(s => s.Subject)
.Include(e => e.AvailableInternshipTypes)
.ThenInclude(i => i.InternshipType)
.ProjectTo<EditionFullResult>(Mapper.ConfigurationProvider)
.FirstOrDefaultAsync(token);
if (edition == null)
{
return NotFound();
}
return Ok(edition);
}
[HttpPut]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
[Authorize(Policy = Policies.IsOverseer)]
public async Task<ActionResult> UpsertEdition(EditionForm editionForm, CancellationToken token)
{
var validator = new EditionForm.Validator();
// TODO: complete validation rules
var validationResult = await validator.ValidateAsync(editionForm, token);
if (!validationResult.IsValid)
{
return BadRequest(validationResult.ToString());
}
// TODO: complete add/update
return Ok();
}
[HttpDelete("{editionId}")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
[ProducesResponseType(StatusCodes.Status409Conflict)]
[Authorize(Policy = Policies.IsOverseer)]
public async Task<ActionResult> DeleteEdition(Guid editionId, CancellationToken token)
{
var editionToDelete = await Context.Editions
.Include(e => e.AvailableSubjects)
.Include(e => e.AvailableInternshipTypes)
.FirstOrDefaultAsync(e => e.Id.Equals(editionId), token);
if (editionToDelete == null)
{
return NotFound();
}
var referencedInternships =
await Context
.Entry(editionToDelete)
.Collection(e => e.Internships)
.Query()
.CountAsync(token);
if (referencedInternships > 0)
{
return Conflict();
}
Context.Editions.Attach(editionToDelete);
Context.Editions.Remove(editionToDelete);
await Context.SaveChangesAsync(token);
return Ok();
}
}
}

View File

@ -0,0 +1,27 @@
using System;
using System.Collections.Generic;
using FluentValidation;
using InternshipSystem.Core;
using InternshipSystem.Core.Entity.Internship;
namespace InternshipSystem.Api.Controllers
{
public class EditionForm
{
public Guid Id { get; set; }
public DateTime EditionStart { get; set; }
public DateTime EditionFinish { get; set; }
public DateTime ReportingStart { get; set; }
public Course Course { get; set; }
public List<InternshipSubject> AvailableSubjects { get; set; }
public List<InternshipType> AvailableInternshipTypes { get; set; }
public class Validator : AbstractValidator<EditionForm>
{
public Validator()
{
//TODO: later
}
}
}
}

View File

@ -0,0 +1,7 @@
namespace InternshipSystem.Api.Queries.SearchQuery
{
public class EditionSearchQuery : SearchQuery
{
}
}

View File

@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using InternshipSystem.Core;
using InternshipSystem.Core.Entity.Internship;
namespace InternshipSystem.Api.Result
{
public class EditionFullResult
{
public Guid Id { get; set; }
public DateTime EditionStart { get; set; }
public DateTime EditionFinish { get; set; }
public DateTime ReportingStart { get; set; }
public Course Course { get; set; }
public List<InternshipSubject> AvailableSubjects { get; set; }
public List<InternshipType> AvailableInternshipTypes { get; set; }
}
}

View File

@ -0,0 +1,14 @@
using System;
using InternshipSystem.Core;
namespace InternshipSystem.Api.Result
{
public class EditionManagementResult
{
public Guid Id { get; set; }
public DateTime EditionStart { get; set; }
public DateTime EditionFinish { get; set; }
public DateTime ReportingStart { get; set; }
public Course Course { get; set; }
}
}

View File

@ -3,5 +3,6 @@
public static class Policies
{
public const string RegisteredOnly = "RegisteredForEditionOnly";
public const string IsOverseer = "IsOverseer";
}
}

View File

@ -38,6 +38,8 @@ namespace InternshipSystem.Api
.AddAuthorization(o =>
{
o.AddPolicy(Policies.RegisteredOnly, policy => policy.RequireClaim("Edition"));
//TODO: change to claim for InternshipRepresentative
o.AddPolicy(Policies.IsOverseer, policy => policy.RequireClaim("PersonNumber"));
})
.AddHttpClient<GutCasClient>();