Ingenieur Anträge: UI und Services
This commit is contained in:
317
Server/Controllers/EngineerApplicationController.cs
Normal file
317
Server/Controllers/EngineerApplicationController.cs
Normal file
@@ -0,0 +1,317 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Oqtane.Shared;
|
||||
using Oqtane.Enums;
|
||||
using Oqtane.Infrastructure;
|
||||
using SZUAbsolventenverein.Module.PremiumArea.Services;
|
||||
using Oqtane.Controllers;
|
||||
using System.Net;
|
||||
using System.Threading.Tasks;
|
||||
using SZUAbsolventenverein.Module.PremiumArea.Models;
|
||||
using System.IO;
|
||||
using System;
|
||||
using Oqtane.Models;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Oqtane.Repository;
|
||||
using Oqtane.Security;
|
||||
using System.Linq;
|
||||
using Oqtane.Managers;
|
||||
using SZUAbsolventenverein.Module.PremiumArea.Repository;
|
||||
|
||||
namespace SZUAbsolventenverein.Module.PremiumArea.Controllers
|
||||
{
|
||||
[Route(ControllerRoutes.ApiRoute)]
|
||||
public class EngineerApplicationController : ModuleControllerBase
|
||||
{
|
||||
private readonly IEngineerApplicationService _service;
|
||||
private readonly IFileRepository _files;
|
||||
private readonly IFolderRepository _folders;
|
||||
private readonly IUserManager _users;
|
||||
private readonly IUserPremiumRepository _premiums;
|
||||
private readonly IHttpContextAccessor _accessor;
|
||||
private readonly IWebHostEnvironment _environment;
|
||||
|
||||
public EngineerApplicationController(IEngineerApplicationService service, IFileRepository files, IFolderRepository folders, IUserManager users, IUserPremiumRepository premiums, ILogManager logger, IHttpContextAccessor accessor, IWebHostEnvironment environment) : base(logger, accessor)
|
||||
{
|
||||
_service = service;
|
||||
_files = files;
|
||||
_folders = folders;
|
||||
_users = users;
|
||||
_premiums = premiums;
|
||||
_accessor = accessor;
|
||||
_environment = environment;
|
||||
}
|
||||
|
||||
// GET: api/<controller>?moduleid=x
|
||||
[HttpGet]
|
||||
[Authorize(Policy = PolicyNames.ViewModule)]
|
||||
public async Task<IEnumerable<EngineerApplication>> Get(string moduleid)
|
||||
{
|
||||
int ModuleId;
|
||||
if (int.TryParse(moduleid, out ModuleId) && IsAuthorizedEntityId(EntityNames.Module, ModuleId))
|
||||
{
|
||||
return await _service.GetApplicationsAsync(ModuleId);
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized EngineerApplication Get Attempt {ModuleId}", moduleid);
|
||||
HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// GET: api/<controller>/status/Approved?moduleid=x
|
||||
[HttpGet("status/{status}")]
|
||||
[Authorize(Policy = PolicyNames.ViewModule)]
|
||||
public async Task<IEnumerable<EngineerApplication>> GetByStatus(string status, string moduleid)
|
||||
{
|
||||
int ModuleId;
|
||||
if (int.TryParse(moduleid, out ModuleId) && IsAuthorizedEntityId(EntityNames.Module, ModuleId))
|
||||
{
|
||||
return await _service.GetApplicationsAsync(ModuleId, status);
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized EngineerApplication GetByStatus Attempt {ModuleId}", moduleid);
|
||||
HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// GET api/<controller>/5
|
||||
[HttpGet("{id}")]
|
||||
[Authorize(Policy = PolicyNames.ViewModule)]
|
||||
public async Task<EngineerApplication> Get(int id, string moduleid)
|
||||
{
|
||||
int ModuleId;
|
||||
if (int.TryParse(moduleid, out ModuleId) && IsAuthorizedEntityId(EntityNames.Module, ModuleId))
|
||||
{
|
||||
return await _service.GetApplicationAsync(id, ModuleId);
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized EngineerApplication Get Attempt {Id} {ModuleId}", id, moduleid);
|
||||
HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// POST api/<controller>
|
||||
[HttpPost]
|
||||
[Authorize(Policy = PolicyNames.ViewModule)] // Users can Create
|
||||
public async Task<EngineerApplication> Post([FromBody] EngineerApplication Application)
|
||||
{
|
||||
if (ModelState.IsValid && IsAuthorizedEntityId(EntityNames.Module, Application.ModuleId))
|
||||
{
|
||||
return await _service.AddApplicationAsync(Application);
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized EngineerApplication Post Attempt {Application}", Application);
|
||||
HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// PUT api/<controller>/5
|
||||
[HttpPut("{id}")]
|
||||
[Authorize(Policy = PolicyNames.ViewModule)] // Users can Edit own (Service checks ownership)
|
||||
public async Task<EngineerApplication> Put(int id, [FromBody] EngineerApplication Application)
|
||||
{
|
||||
if (ModelState.IsValid && Application.ApplicationId == id && IsAuthorizedEntityId(EntityNames.Module, Application.ModuleId))
|
||||
{
|
||||
return await _service.UpdateApplicationAsync(Application);
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized EngineerApplication Put Attempt {Application}", Application);
|
||||
HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// DELETE api/<controller>/5
|
||||
[HttpDelete("{id}")]
|
||||
[Authorize(Policy = PolicyNames.ViewModule)]
|
||||
public async Task Delete(int id, string moduleid)
|
||||
{
|
||||
int ModuleId;
|
||||
if (int.TryParse(moduleid, out ModuleId) && IsAuthorizedEntityId(EntityNames.Module, ModuleId))
|
||||
{
|
||||
await _service.DeleteApplicationAsync(id, ModuleId);
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized EngineerApplication Delete Attempt {Id} {ModuleId}", id, moduleid);
|
||||
HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
|
||||
}
|
||||
}
|
||||
|
||||
// POST api/<controller>/approve/5
|
||||
[HttpPost("approve/{id}")]
|
||||
[Authorize(Policy = PolicyNames.EditModule)]
|
||||
public async Task Approve(int id, string moduleid)
|
||||
{
|
||||
int ModuleId;
|
||||
if (int.TryParse(moduleid, out ModuleId) && IsAuthorizedEntityId(EntityNames.Module, ModuleId))
|
||||
{
|
||||
// We need to clear IsReported flag as well.
|
||||
// Since the Service handles the logic, we should probably update it there.
|
||||
// But if I can't find it easily, I can do it here if I get the app first.
|
||||
// _service.ApproveApplicationAsync might just set Status="Approved".
|
||||
// I should verify where the service logic is.
|
||||
await _service.ApproveApplicationAsync(id, ModuleId);
|
||||
}
|
||||
else
|
||||
{
|
||||
HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
|
||||
}
|
||||
}
|
||||
|
||||
[HttpPost("upload")]
|
||||
[Authorize(Policy = PolicyNames.ViewModule)]
|
||||
public async Task<IActionResult> Upload(string moduleid)
|
||||
{
|
||||
int ModuleId;
|
||||
if (int.TryParse(moduleid, out ModuleId) && IsAuthorizedEntityId(EntityNames.Module, ModuleId))
|
||||
{
|
||||
if (Request.Form.Files.Count == 0) return BadRequest("No file uploaded");
|
||||
|
||||
var file = Request.Form.Files[0];
|
||||
if (file.ContentType != "application/pdf") return BadRequest("Only PDF files are allowed");
|
||||
|
||||
var alias = _accessor.HttpContext.Items["Alias"] as Alias;
|
||||
var siteId = alias.SiteId;
|
||||
var folderPath = "EngineerApplications";
|
||||
var folder = _folders.GetFolder(siteId, folderPath);
|
||||
|
||||
if (folder == null)
|
||||
{
|
||||
// Create folder
|
||||
folder = new Folder
|
||||
{
|
||||
SiteId = siteId,
|
||||
ParentId = null,
|
||||
Name = "EngineerApplications",
|
||||
Path = folderPath,
|
||||
PermissionList = new List<Permission>
|
||||
{
|
||||
new Permission(PermissionNames.View, RoleNames.Admin, true),
|
||||
new Permission(PermissionNames.Edit, RoleNames.Admin, true)
|
||||
}
|
||||
};
|
||||
folder = _folders.AddFolder(folder);
|
||||
}
|
||||
|
||||
var ext = Path.GetExtension(file.FileName).ToLower();
|
||||
if (ext != ".pdf") return BadRequest("Invalid file extension");
|
||||
|
||||
var tenantId = alias.TenantId;
|
||||
var uploadPath = Path.Combine(_environment.ContentRootPath, "Content", "Tenants", tenantId.ToString(), "Sites", siteId.ToString(), folderPath);
|
||||
if (!Directory.Exists(uploadPath)) Directory.CreateDirectory(uploadPath);
|
||||
|
||||
var uniqueName = $"{Guid.NewGuid()}{ext}";
|
||||
var filePath = Path.Combine(uploadPath, uniqueName);
|
||||
|
||||
using (var stream = new FileStream(filePath, FileMode.Create))
|
||||
{
|
||||
await file.CopyToAsync(stream);
|
||||
}
|
||||
|
||||
var fileObj = new Oqtane.Models.File
|
||||
{
|
||||
FolderId = folder.FolderId,
|
||||
Name = uniqueName,
|
||||
Extension = ext.Substring(1),
|
||||
Size = (int)file.Length,
|
||||
ImageHeight = 0,
|
||||
ImageWidth = 0
|
||||
};
|
||||
|
||||
var addedFile = _files.AddFile(fileObj);
|
||||
|
||||
return Ok(new { FileId = addedFile.FileId, FileName = file.FileName });
|
||||
}
|
||||
return StatusCode((int)HttpStatusCode.Forbidden);
|
||||
}
|
||||
|
||||
[HttpPost("report/{id}")]
|
||||
[Authorize(Policy = PolicyNames.ViewModule)]
|
||||
public async Task Report(int id, [FromBody] string reason, string moduleid)
|
||||
{
|
||||
int ModuleId;
|
||||
if (int.TryParse(moduleid, out ModuleId) && IsAuthorizedEntityId(EntityNames.Module, ModuleId))
|
||||
{
|
||||
await _service.ReportApplicationAsync(id, ModuleId, reason);
|
||||
}
|
||||
else
|
||||
{
|
||||
HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
|
||||
}
|
||||
}
|
||||
|
||||
[HttpGet("download/{id}")]
|
||||
[Authorize]
|
||||
public async Task<IActionResult> Download(int id, string moduleid)
|
||||
{
|
||||
int ModuleId;
|
||||
if (int.TryParse(moduleid, out ModuleId) && IsAuthorizedEntityId(EntityNames.Module, ModuleId))
|
||||
{
|
||||
var app = await _service.GetApplicationAsync(id, ModuleId);
|
||||
if (app == null) return NotFound();
|
||||
|
||||
var alias = _accessor.HttpContext.Items["Alias"] as Alias;
|
||||
// Access Rules:
|
||||
// 1. Admin
|
||||
if (_accessor.HttpContext.User.IsInRole(RoleNames.Admin))
|
||||
{
|
||||
return await ServeFile(app.FileId.Value, app.PdfFileName);
|
||||
}
|
||||
|
||||
// 2. Owner
|
||||
var username = _accessor.HttpContext.User.Identity.Name;
|
||||
var currentUserId = -1;
|
||||
if (username != null)
|
||||
{
|
||||
var u = _users.GetUser(username, alias.SiteId);
|
||||
if (u != null) currentUserId = u.UserId;
|
||||
}
|
||||
|
||||
if (currentUserId == app.UserId)
|
||||
{
|
||||
return await ServeFile(app.FileId.Value, app.PdfFileName);
|
||||
}
|
||||
|
||||
// 3. Premium User AND Published/Approved
|
||||
if (app.Status == "Approved" || app.Status == "Published")
|
||||
{
|
||||
var premium = _premiums.GetUserPremium(currentUserId);
|
||||
if (premium != null && premium.PremiumUntil.HasValue && premium.PremiumUntil.Value > DateTime.UtcNow)
|
||||
{
|
||||
return await ServeFile(app.FileId.Value, app.PdfFileName);
|
||||
}
|
||||
}
|
||||
|
||||
return StatusCode((int)HttpStatusCode.Forbidden);
|
||||
}
|
||||
return StatusCode((int)HttpStatusCode.Forbidden);
|
||||
}
|
||||
|
||||
private async Task<IActionResult> ServeFile(int fileId, string downloadName)
|
||||
{
|
||||
var file = _files.GetFile(fileId);
|
||||
if (file != null)
|
||||
{
|
||||
var path = _files.GetFilePath(file);
|
||||
if (System.IO.File.Exists(path))
|
||||
{
|
||||
var bytes = await System.IO.File.ReadAllBytesAsync(path);
|
||||
return File(bytes, "application/pdf", downloadName ?? file.Name);
|
||||
}
|
||||
}
|
||||
return NotFound();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user