feat/documents (#61)
add get scan endpoint add document scan endpoint Co-authored-by: MaxchilKH <m.w.bohdanowicz@gmail.com>
This commit is contained in:
parent
b98ab42c4d
commit
7124b457dc
@ -1,11 +1,16 @@
|
||||
using System.Threading;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Mime;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using InternshipSystem.Api.Queries;
|
||||
using InternshipSystem.Api.Security;
|
||||
using InternshipSystem.Api.Services;
|
||||
using InternshipSystem.Api.Service;
|
||||
using InternshipSystem.Repository;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace InternshipSystem.Api.Controllers
|
||||
{
|
||||
@ -13,11 +18,13 @@ namespace InternshipSystem.Api.Controllers
|
||||
[Route("document")]
|
||||
public class DocumentsController : ControllerBase
|
||||
{
|
||||
private readonly IInternshipService _internshipService;
|
||||
private readonly InternshipDbContext _context;
|
||||
private readonly FileValidator _fileValidator;
|
||||
|
||||
public DocumentsController(IInternshipService internshipService)
|
||||
public DocumentsController(InternshipDbContext context, FileValidator fileValidator)
|
||||
{
|
||||
_internshipService = internshipService;
|
||||
_context = context;
|
||||
_fileValidator = fileValidator;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -34,18 +41,75 @@ namespace InternshipSystem.Api.Controllers
|
||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
|
||||
[Authorize(Policy = Policies.RegisteredOnly)]
|
||||
public async Task<ActionResult> AddDocumentToInternship([FromBody] DocumentPublishRequest documentRequest,
|
||||
[FromServices] User user, CancellationToken cancellationToken)
|
||||
public async Task<ActionResult> AddDocumentToInternship(
|
||||
[FromBody] DocumentPublishRequest documentRequest,
|
||||
[FromServices] User user,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
var validator = new DocumentPublishRequest.Validator();
|
||||
var validationResult = await validator.ValidateAsync(documentRequest, cancellationToken);
|
||||
|
||||
if (!validationResult.IsValid)
|
||||
var result = await validator.ValidateAsync(documentRequest, cancellationToken);
|
||||
|
||||
if (!result.IsValid)
|
||||
{
|
||||
return BadRequest(validationResult.ToString());
|
||||
return BadRequest(result.ToString());
|
||||
}
|
||||
|
||||
return await _internshipService.AddDocumentToInternship(documentRequest, user, cancellationToken);
|
||||
var edition = await _context.Editions.FirstAsync(e => e.Id == user.EditionId, cancellationToken);
|
||||
|
||||
var internship =
|
||||
await _context.Entry(edition)
|
||||
.Collection(e => e.Internships)
|
||||
.Query()
|
||||
.FirstAsync(i => i.Student.Id == user.PersonNumber, cancellationToken);
|
||||
|
||||
internship.AddNewDocument(documentRequest.Description, documentRequest.Type);
|
||||
|
||||
return Ok();
|
||||
}
|
||||
|
||||
[HttpPut("{documentId}/scan")]
|
||||
[Authorize(Policy = Policies.RegisteredOnly)]
|
||||
public async Task<ActionResult> AddDocumentScan(long documentId, IFormFile documentScan, [FromServices] User user, CancellationToken cancellationToken)
|
||||
{
|
||||
await using var memoryStream = new MemoryStream();
|
||||
await documentScan.CopyToAsync(memoryStream, cancellationToken);
|
||||
|
||||
if (!_fileValidator.IsValidFile(memoryStream.ToArray()))
|
||||
{
|
||||
return BadRequest("error.document.scan");
|
||||
}
|
||||
|
||||
var edition = await _context.Editions.FirstAsync(e => e.Id == user.EditionId, cancellationToken);
|
||||
|
||||
var internship =
|
||||
await _context.Entry(edition)
|
||||
.Collection(e => e.Internships)
|
||||
.Query()
|
||||
.Include(i => i.Documentation)
|
||||
.FirstAsync(i => i.Student.Id == user.PersonNumber, cancellationToken);
|
||||
|
||||
internship.UpdateDocumentScan(documentId, memoryStream.ToArray());
|
||||
|
||||
return Ok();
|
||||
}
|
||||
|
||||
[HttpGet("{documentId}/scan")]
|
||||
[Authorize(Policy = Policies.RegisteredOnly)]
|
||||
public async Task<ActionResult> GetDocumentScan(long documentId, [FromServices] User user, CancellationToken cancellationToken)
|
||||
{
|
||||
var edition = await _context.Editions.FirstAsync(e => e.Id == user.EditionId, cancellationToken);
|
||||
|
||||
var internship =
|
||||
await _context.Entry(edition)
|
||||
.Collection(e => e.Internships)
|
||||
.Query()
|
||||
.Include(i => i.Documentation)
|
||||
.FirstAsync(i => i.Student.Id == user.PersonNumber, cancellationToken);
|
||||
|
||||
var document = internship.Documentation.First(d => d.Id == documentId);
|
||||
var stream = new MemoryStream(document.Scan);
|
||||
|
||||
return File(stream, "application/pdf");
|
||||
}
|
||||
}
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
using FluentValidation;
|
||||
using InternshipSystem.Core.ValueObject;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
|
||||
namespace InternshipSystem.Api.Queries
|
||||
{
|
||||
@ -7,14 +8,12 @@ namespace InternshipSystem.Api.Queries
|
||||
{
|
||||
public long? Id { get; set; }
|
||||
public string Description { get; set; }
|
||||
public byte[] Scan { get; set; }
|
||||
public DocumentType Type { get; set; }
|
||||
|
||||
public class Validator : AbstractValidator<DocumentPublishRequest>
|
||||
{
|
||||
public Validator()
|
||||
{
|
||||
RuleFor(document => document.Scan).NotEmpty();
|
||||
RuleFor(document => document.Type).NotEmpty();
|
||||
}
|
||||
}
|
||||
|
30
src/InternshipSystem.Api/Service/FileValidator.cs
Normal file
30
src/InternshipSystem.Api/Service/FileValidator.cs
Normal file
@ -0,0 +1,30 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace InternshipSystem.Api.Service
|
||||
{
|
||||
public class FileValidator
|
||||
{
|
||||
private readonly Dictionary<string, byte[]> validFileTypes;
|
||||
|
||||
public FileValidator()
|
||||
{
|
||||
validFileTypes = new Dictionary<string, byte[]> {
|
||||
{ "pdf", new byte[] { 0x25, 0x50, 0x44, 0x46 } }
|
||||
};
|
||||
}
|
||||
|
||||
public bool IsValidFile(byte[] scan)
|
||||
{
|
||||
return IsFileValidType(scan);
|
||||
}
|
||||
|
||||
private bool IsFileValidType(byte[] scan)
|
||||
{
|
||||
var validSignatures = validFileTypes.Values;
|
||||
var header = scan[..4];
|
||||
|
||||
return validSignatures.Any(sig => header.SequenceEqual(header));
|
||||
}
|
||||
}
|
||||
}
|
@ -1,13 +0,0 @@
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using InternshipSystem.Api.Queries;
|
||||
using InternshipSystem.Api.Security;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace InternshipSystem.Api.Services
|
||||
{
|
||||
public interface IInternshipService
|
||||
{
|
||||
Task<ActionResult> AddDocumentToInternship(DocumentPublishRequest documentRequest, User user, CancellationToken cancellationToken);
|
||||
}
|
||||
}
|
@ -1,58 +0,0 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using AutoMapper;
|
||||
using InternshipSystem.Api.Queries;
|
||||
using InternshipSystem.Api.Security;
|
||||
using InternshipSystem.Core;
|
||||
using InternshipSystem.Repository;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace InternshipSystem.Api.Services
|
||||
{
|
||||
public class InternshipService : IInternshipService
|
||||
{
|
||||
private readonly InternshipDbContext _context;
|
||||
private IMapper Mapper { get; }
|
||||
|
||||
public InternshipService(InternshipDbContext context, IMapper mapper)
|
||||
{
|
||||
_context = context;
|
||||
Mapper = mapper;
|
||||
}
|
||||
|
||||
public async Task<ActionResult> AddDocumentToInternship(DocumentPublishRequest documentRequest, User user,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
var edition = await _context.Editions.FindAsync(user.EditionId);
|
||||
|
||||
var internship = await _context.Entry(edition)
|
||||
.Collection(e => e.Internships)
|
||||
.Query()
|
||||
.Include(i => i.Documentation)
|
||||
.SingleAsync(i => i.Student.Id == user.PersonNumber, cancellationToken);
|
||||
|
||||
var document = Mapper.Map<Document>(documentRequest);
|
||||
|
||||
if (documentRequest.Id.HasValue)
|
||||
{
|
||||
try
|
||||
{
|
||||
internship.UpdateDocument(document);
|
||||
}
|
||||
catch (InvalidOperationException)
|
||||
{
|
||||
return new NotFoundResult();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
internship.AddNewDocument(document);
|
||||
}
|
||||
|
||||
await _context.SaveChangesAsync(cancellationToken);
|
||||
return new OkResult();
|
||||
}
|
||||
}
|
||||
}
|
@ -7,7 +7,7 @@ using InternshipSystem.Api.Extensions;
|
||||
using InternshipSystem.Api.ModelBinders;
|
||||
using InternshipSystem.Api.Options;
|
||||
using InternshipSystem.Api.Security;
|
||||
using InternshipSystem.Api.Services;
|
||||
using InternshipSystem.Api.Service;
|
||||
using InternshipSystem.Repository;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
@ -44,7 +44,7 @@ namespace InternshipSystem.Api
|
||||
.AddDbContext<InternshipDbContext>(o =>
|
||||
o.UseNpgsql(Configuration.GetConnectionString("InternshipDatabase")))
|
||||
.AddScoped<DatabaseFiller>()
|
||||
.AddScoped<IInternshipService, InternshipService>()
|
||||
.AddScoped<FileValidator>()
|
||||
.AddScoped<JwtTokenService>()
|
||||
.AddAutoMapper(cfg => cfg.AddProfile<ApiProfile>());
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using InternshipSystem.Core.ValueObject;
|
||||
|
||||
namespace InternshipSystem.Core.Entity.Internship
|
||||
{
|
||||
@ -14,24 +15,7 @@ namespace InternshipSystem.Core.Entity.Internship
|
||||
|
||||
public Edition Edition { get; set; }
|
||||
|
||||
public float? Grade { get; set; }
|
||||
|
||||
public void UpdateDocument(Document document)
|
||||
{
|
||||
var oldDocument = Documentation.First(d => d.Id == document.Id);
|
||||
|
||||
oldDocument.Description = document.Description ?? oldDocument.Description;
|
||||
oldDocument.Scan = document.Scan ?? oldDocument.Scan;
|
||||
oldDocument.Type = document.Type;
|
||||
oldDocument.State = DocumentState.Submitted;
|
||||
}
|
||||
|
||||
public void AddNewDocument(Document document)
|
||||
{
|
||||
document.State = DocumentState.Submitted;
|
||||
|
||||
Documentation.Add(document);
|
||||
}
|
||||
public float? Grade { get; set; }
|
||||
|
||||
public static Internship CreateStudentsInternship(Student student)
|
||||
{
|
||||
@ -46,5 +30,25 @@ namespace InternshipSystem.Core.Entity.Internship
|
||||
|
||||
return internship;
|
||||
}
|
||||
|
||||
public void AddNewDocument(string description, DocumentType type)
|
||||
{
|
||||
var document = new Document
|
||||
{
|
||||
Description = description,
|
||||
Type = type,
|
||||
State = DocumentState.Draft
|
||||
};
|
||||
|
||||
Documentation.Add(document);
|
||||
}
|
||||
|
||||
public void UpdateDocumentScan(long documentId, byte[] documentScan)
|
||||
{
|
||||
var document = Documentation.First(d => d.Id == documentId);
|
||||
|
||||
document.Scan = documentScan;
|
||||
document.State = DocumentState.Submitted;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user