318 lines
13 KiB
C#
318 lines
13 KiB
C#
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();
|
|
}
|
|
}
|
|
}
|