Swarm/DysonNetwork.Sphere/Storage/FileController.cs
LittleSheep 17de9a0f23 Add chat message handling and WebSocket integration
Introduce new `ChatService` for managing chat messages, including marking messages as read and checking read status. Add `WebSocketPacket` class for handling WebSocket communication and integrate it with `WebSocketService` to process chat-related packets. Enhance `ChatRoom` and `ChatMember` models with additional fields and relationships. Update `AppDatabase` to include new chat-related entities and adjust permissions for chat creation.
2025-05-02 19:51:32 +08:00

108 lines
3.4 KiB
C#

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Minio.DataModel.Args;
namespace DysonNetwork.Sphere.Storage;
[ApiController]
[Route("/files")]
public class FileController(
AppDatabase db,
FileService fs,
IConfiguration configuration,
IWebHostEnvironment env
) : ControllerBase
{
[HttpGet("{id}")]
public async Task<ActionResult> OpenFile(string id, [FromQuery] bool original = false)
{
var file = await db.Files.FindAsync(id);
if (file is null) return NotFound();
if (file.UploadedTo is null)
{
var tusStorePath = configuration.GetValue<string>("Tus:StorePath")!;
var filePath = Path.Combine(env.ContentRootPath, tusStorePath, file.Id);
if (!System.IO.File.Exists(filePath)) return new NotFoundResult();
return PhysicalFile(filePath, file.MimeType ?? "application/octet-stream", file.Name);
}
var dest = fs.GetRemoteStorageConfig(file.UploadedTo);
var fileName = file.Id;
if (!original && file.HasCompression)
{
fileName += ".compressed";
}
if (dest.ImageProxy is not null && (file.MimeType?.StartsWith("image/") ?? false))
{
var proxyUrl = dest.ImageProxy;
var baseUri = new Uri(proxyUrl.EndsWith('/') ? proxyUrl : $"{proxyUrl}/");
var fullUri = new Uri(baseUri, fileName);
return Redirect(fullUri.ToString());
}
if (dest.AccessProxy is not null)
{
var proxyUrl = dest.AccessProxy;
var baseUri = new Uri(proxyUrl.EndsWith('/') ? proxyUrl : $"{proxyUrl}/");
var fullUri = new Uri(baseUri, fileName);
return Redirect(fullUri.ToString());
}
if (dest.EnableSigned)
{
var client = fs.CreateMinioClient(dest);
if (client is null)
return BadRequest(
"Failed to configure client for remote destination, file got an invalid storage remote.");
var bucket = dest.Bucket;
var openUrl = await client.PresignedGetObjectAsync(
new PresignedGetObjectArgs()
.WithBucket(bucket)
.WithObject(file.Id)
.WithExpiry(3600)
);
return Redirect(openUrl);
}
// Fallback redirect to the S3 endpoint (public read)
var protocol = dest.EnableSsl ? "https" : "http";
// Use the path bucket lookup mode
return Redirect($"{protocol}://{dest.Endpoint}/{dest.Bucket}/{fileName}");
}
[HttpGet("{id}/info")]
public async Task<ActionResult<CloudFile>> GetFileInfo(string id)
{
var file = await db.Files.FindAsync(id);
if (file is null) return NotFound();
return file;
}
[Authorize]
[HttpDelete("{id}")]
public async Task<ActionResult> DeleteFile(string id)
{
if (HttpContext.Items["CurrentUser"] is not Account.Account currentUser) return Unauthorized();
var userId = currentUser.Id;
var file = await db.Files
.Where(e => e.Id == id)
.Where(e => e.Account.Id == userId)
.FirstOrDefaultAsync();
if (file is null) return NotFound();
await fs.DeleteFileAsync(file);
db.Files.Remove(file);
await db.SaveChangesAsync();
return NoContent();
}
}