diff options
| author | Jake Mannens <jake@asger.xyz> | 2026-03-17 03:04:36 +1100 |
|---|---|---|
| committer | Jake Mannens <jake@asger.xyz> | 2026-03-25 01:57:41 +1100 |
| commit | c751709b1b4fe6f16fd84647e8e071455e7b78d6 (patch) | |
| tree | 47734a083d888660606e6cf6cf158c93e69a9807 /Controllers | |
v0.1av0.1a
Diffstat (limited to 'Controllers')
| -rw-r--r-- | Controllers/LoginController.cs | 50 | ||||
| -rw-r--r-- | Controllers/MediaController.cs | 113 |
2 files changed, 163 insertions, 0 deletions
diff --git a/Controllers/LoginController.cs b/Controllers/LoginController.cs new file mode 100644 index 0000000..b01553c --- /dev/null +++ b/Controllers/LoginController.cs @@ -0,0 +1,50 @@ +using HyperBooru.Services; +using Microsoft.AspNetCore.Authentication; +using Microsoft.AspNetCore.Authentication.Cookies; +using Microsoft.AspNetCore.Cryptography.KeyDerivation; +using Microsoft.AspNetCore.Mvc; +using System.Security.Claims; + +namespace HyperBooru.Controllers; + +[ApiController] +[Route("/")] +public class LoginController : Controller { + private IHttpContextAccessor httpContextAccessor; + + public LoginController(IHttpContextAccessor httpContextAccessor) => + this.httpContextAccessor = httpContextAccessor; + + [HttpPost("Login")] + public async Task<IActionResult> Login( + [FromForm] string username, + [FromForm] string password, + HBContext db) { + + var user = db.Users.FirstOrDefault(u => u.Username == username); + if(user is null) + return StatusCode(403); + + var hash = UserService.HashPassword(password); + if(hash != user.PasswordHash) + return StatusCode(403); + + var claims = new Claim[] { + new Claim(ClaimTypes.Name, user.Username), + new Claim("ObjectId", user.ObjectId.ToString()) + }; + + var claimsIdentity = new ClaimsIdentity( + claims, + CookieAuthenticationDefaults.AuthenticationScheme); + + var claimsPrincipal = new ClaimsPrincipal(claimsIdentity); + + await httpContextAccessor.HttpContext!.SignInAsync(claimsPrincipal); + return Ok(); + } + + [HttpPost("Logout")] + public async Task Logout() => + await httpContextAccessor.HttpContext!.SignOutAsync(); +} diff --git a/Controllers/MediaController.cs b/Controllers/MediaController.cs new file mode 100644 index 0000000..3368f45 --- /dev/null +++ b/Controllers/MediaController.cs @@ -0,0 +1,113 @@ +using HyperBooru.Services; +using HyperBooru.Util; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; + +namespace HyperBooru.Controllers; + +[ApiController] +[Route("/media")] +public class MediaController : Controller { + private IMediaService mediaService; + private IConfigService config; + private HBContext db; + + public MediaController( + IMediaService mediaService, + IConfigService config, + HBContext db) { + + this.mediaService = mediaService; + this.config = config; + this.db = db; + } + + [HttpGet("{mediaId}")] + public IActionResult Fetch([FromRoute] Guid mediaId) { + var media = db.Media + .Include(m => m.CurrentUploadedFile) + .First(m => m.Guid == mediaId); + if(media is null) + return NotFound(); + + var fs = System.IO.File.OpenRead(mediaService.GetPath(media)); + + return new FileStreamResult(fs, media.CurrentUploadedFile.MimeType); + } + + [HttpGet("thumb/{mediaId}")] + public IActionResult Thumbnail( + [FromRoute] Guid mediaId, + [FromQuery(Name = "w")] int? width, + [FromQuery(Name = "h")] int? height) { + + try { + var thumb = mediaService.GetThumbnail(mediaId, width, height); + return new FileStreamResult(thumb, "image/jpeg"); + } catch(ThumbnailException e) { + return BadRequest(e.Message); + } catch(ObjectNotFoundException e) { + return NotFound(e.Message); + } + } + + [HttpDelete("{mediaId}")] + public void Delete([FromRoute] Guid mediaId) { + mediaService.Delete(mediaId); + } + + [HttpPost] + public IActionResult Upload() { + if(Request.Form.Files.Count == 0) + return BadRequest("No files"); + + Media media = new(); + + foreach(var formFile in Request.Form.Files) { + try { + // Parse timestamps from headers + DateTime? lastAccessTime = + formFile.Headers["X-HyperBooru-LastAccessTime"] + .ElementAtOrDefault(0)? + .TryParseDateTimeUtc(); + DateTime? lastWriteTime = + formFile.Headers["X-HyperBooru-LastWriteTime"] + .ElementAtOrDefault(0)? + .TryParseDateTimeUtc(); + DateTime? createTime = + formFile.Headers["X-HyperBooru-CreateTime"] + .ElementAtOrDefault(0)? + .TryParseDateTimeUtc(); + + // Parse original path from headers + string? path = + formFile.Headers["X-HyperBooru-Path"] + .ElementAtOrDefault(0); + + object? pathType = null; + string? pathTypeString = + formFile.Headers["X-HyperBooru-PathType"] + .ElementAtOrDefault(0); + Enum.TryParse(typeof(PathType), pathTypeString, true, out pathType); + + media = mediaService.Create( + formFile.OpenReadStream(), + formFile.FileName, + formFile.Headers["X-HyperBooru-Checksum"] + .ElementAtOrDefault(0), + lastAccessTime, + lastWriteTime, + createTime, + path, + (PathType?) pathType); + } catch(MediaCreateException e) { + return BadRequest(e.Message); + } + } + + if(Request.Form.Files.Count == 1) + return Redirect($"/ViewMedia?m={media.Guid}"); + else + return Redirect($"/Gallery"); + } +}
\ No newline at end of file |
