155 lines
		
	
	
		
			5.0 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			155 lines
		
	
	
		
			5.0 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
using System.ComponentModel.DataAnnotations;
 | 
						|
using DysonNetwork.Shared.Models;
 | 
						|
using DysonNetwork.Shared.Proto;
 | 
						|
using Microsoft.AspNetCore.Authorization;
 | 
						|
using Microsoft.AspNetCore.Mvc;
 | 
						|
using Microsoft.EntityFrameworkCore;
 | 
						|
using NodaTime;
 | 
						|
 | 
						|
namespace DysonNetwork.Drive.Storage;
 | 
						|
 | 
						|
[ApiController]
 | 
						|
[Route("/api/bundles")]
 | 
						|
public class BundleController(AppDatabase db) : ControllerBase
 | 
						|
{
 | 
						|
    public class BundleRequest
 | 
						|
    {
 | 
						|
        [MaxLength(1024)] public string? Slug { get; set; }
 | 
						|
        [MaxLength(1024)] public string? Name { get; set; }
 | 
						|
        [MaxLength(8192)] public string? Description { get; set; }
 | 
						|
        [MaxLength(256)] public string? Passcode { get; set; }
 | 
						|
 | 
						|
        public Instant? ExpiredAt { get; set; }
 | 
						|
    }
 | 
						|
 | 
						|
    [HttpGet("{id:guid}")]
 | 
						|
    public async Task<ActionResult<SnFileBundle>> GetBundle([FromRoute] Guid id, [FromQuery] string? passcode)
 | 
						|
    {
 | 
						|
        var bundle = await db.Bundles
 | 
						|
            .Where(e => e.Id == id)
 | 
						|
            .Include(e => e.Files)
 | 
						|
            .FirstOrDefaultAsync();
 | 
						|
        if (bundle is null) return NotFound();
 | 
						|
        if (!bundle.VerifyPasscode(passcode)) return Forbid();
 | 
						|
 | 
						|
        return Ok(bundle);
 | 
						|
    }
 | 
						|
 | 
						|
    [HttpGet("me")]
 | 
						|
    [Authorize]
 | 
						|
    public async Task<ActionResult<List<SnFileBundle>>> ListBundles(
 | 
						|
        [FromQuery] string? term,
 | 
						|
        [FromQuery] int offset = 0,
 | 
						|
        [FromQuery] int take = 20
 | 
						|
    )
 | 
						|
    {
 | 
						|
        if (HttpContext.Items["CurrentUser"] is not Account currentUser) return Unauthorized();
 | 
						|
        var accountId = Guid.Parse(currentUser.Id);
 | 
						|
 | 
						|
        var query = db.Bundles
 | 
						|
            .Where(e => e.AccountId == accountId)
 | 
						|
            .OrderByDescending(e => e.CreatedAt)
 | 
						|
            .AsQueryable();
 | 
						|
        if (!string.IsNullOrEmpty(term))
 | 
						|
            query = query.Where(e => EF.Functions.ILike(e.Name, $"%{term}%"));
 | 
						|
 | 
						|
        var total = await query.CountAsync();
 | 
						|
        Response.Headers.Append("X-Total", total.ToString());
 | 
						|
 | 
						|
        var bundles = await query
 | 
						|
            .Skip(offset)
 | 
						|
            .Take(take)
 | 
						|
            .ToListAsync();
 | 
						|
 | 
						|
        return Ok(bundles);
 | 
						|
    }
 | 
						|
 | 
						|
    [HttpPost]
 | 
						|
    [Authorize]
 | 
						|
    public async Task<ActionResult<SnFileBundle>> CreateBundle([FromBody] BundleRequest request)
 | 
						|
    {
 | 
						|
        if (HttpContext.Items["CurrentUser"] is not Account currentUser) return Unauthorized();
 | 
						|
        var accountId = Guid.Parse(currentUser.Id);
 | 
						|
 | 
						|
        if (currentUser.PerkSubscription is null && !string.IsNullOrEmpty(request.Slug))
 | 
						|
            return StatusCode(403, "You must have a subscription to create a bundle with a custom slug");
 | 
						|
        if (string.IsNullOrEmpty(request.Slug))
 | 
						|
            request.Slug = Guid.NewGuid().ToString("N")[..6];
 | 
						|
        if (string.IsNullOrEmpty(request.Name))
 | 
						|
            request.Name = "Unnamed Bundle";
 | 
						|
 | 
						|
        var bundle = new SnFileBundle
 | 
						|
        {
 | 
						|
            Slug = request.Slug,
 | 
						|
            Name = request.Name,
 | 
						|
            Description = request.Description,
 | 
						|
            Passcode = request.Passcode,
 | 
						|
            ExpiredAt = request.ExpiredAt,
 | 
						|
            AccountId = accountId
 | 
						|
        }.HashPasscode();
 | 
						|
 | 
						|
        db.Bundles.Add(bundle);
 | 
						|
        await db.SaveChangesAsync();
 | 
						|
 | 
						|
        return Ok(bundle);
 | 
						|
    }
 | 
						|
 | 
						|
    [HttpPut("{id:guid}")]
 | 
						|
    [Authorize]
 | 
						|
    public async Task<ActionResult<SnFileBundle>> UpdateBundle([FromRoute] Guid id, [FromBody] BundleRequest request)
 | 
						|
    {
 | 
						|
        if (HttpContext.Items["CurrentUser"] is not Account currentUser) return Unauthorized();
 | 
						|
        var accountId = Guid.Parse(currentUser.Id);
 | 
						|
 | 
						|
        var bundle = await db.Bundles
 | 
						|
            .Where(e => e.Id == id)
 | 
						|
            .Where(e => e.AccountId == accountId)
 | 
						|
            .FirstOrDefaultAsync();
 | 
						|
        if (bundle is null) return NotFound();
 | 
						|
 | 
						|
        if (request.Slug != null && request.Slug != bundle.Slug)
 | 
						|
        {
 | 
						|
            if (currentUser.PerkSubscription is null)
 | 
						|
                return StatusCode(403, "You must have a subscription to change the slug of a bundle");
 | 
						|
            bundle.Slug = request.Slug;
 | 
						|
        }
 | 
						|
 | 
						|
        if (request.Name != null) bundle.Name = request.Name;
 | 
						|
        if (request.Description != null) bundle.Description = request.Description;
 | 
						|
        if (request.ExpiredAt != null) bundle.ExpiredAt = request.ExpiredAt;
 | 
						|
 | 
						|
        if (request.Passcode != null)
 | 
						|
        {
 | 
						|
            bundle.Passcode = request.Passcode;
 | 
						|
            bundle = bundle.HashPasscode();
 | 
						|
        }
 | 
						|
 | 
						|
        await db.SaveChangesAsync();
 | 
						|
 | 
						|
        return Ok(bundle);
 | 
						|
    }
 | 
						|
 | 
						|
    [HttpDelete("{id:guid}")]
 | 
						|
    [Authorize]
 | 
						|
    public async Task<ActionResult> DeleteBundle([FromRoute] Guid id)
 | 
						|
    {
 | 
						|
        if (HttpContext.Items["CurrentUser"] is not Account currentUser) return Unauthorized();
 | 
						|
        var accountId = Guid.Parse(currentUser.Id);
 | 
						|
 | 
						|
        var bundle = await db.Bundles
 | 
						|
            .Where(e => e.Id == id)
 | 
						|
            .Where(e => e.AccountId == accountId)
 | 
						|
            .FirstOrDefaultAsync();
 | 
						|
        if (bundle is null) return NotFound();
 | 
						|
 | 
						|
        db.Bundles.Remove(bundle);
 | 
						|
        await db.SaveChangesAsync();
 | 
						|
 | 
						|
        await db.Files
 | 
						|
            .Where(e => e.BundleId == id)
 | 
						|
            .ExecuteUpdateAsync(s => s.SetProperty(e => e.IsMarkedRecycle, true));
 | 
						|
 | 
						|
        return NoContent();
 | 
						|
    }
 | 
						|
}
 |