♻️ Move most of models to the Shared package

This commit is contained in:
2025-07-06 22:34:52 +08:00
parent cb4acbb3fc
commit 65450e8511
170 changed files with 679 additions and 101121 deletions

View File

@ -1,130 +0,0 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Text.Json.Serialization;
using NodaTime;
namespace DysonNetwork.Sphere.Storage;
public class RemoteStorageConfig
{
public string Id { get; set; } = string.Empty;
public string Label { get; set; } = string.Empty;
public string Region { get; set; } = string.Empty;
public string Bucket { get; set; } = string.Empty;
public string Endpoint { get; set; } = string.Empty;
public string SecretId { get; set; } = string.Empty;
public string SecretKey { get; set; } = string.Empty;
public bool EnableSigned { get; set; }
public bool EnableSsl { get; set; }
public string? ImageProxy { get; set; }
public string? AccessProxy { get; set; }
}
/// <summary>
/// The class that used in jsonb columns which referenced the cloud file.
/// The aim of this class is to store some properties that won't change to a file to reduce the database load.
/// </summary>
public class CloudFileReferenceObject : ModelBase, ICloudFile
{
public string Id { get; set; } = null!;
public string Name { get; set; } = string.Empty;
public Dictionary<string, object>? FileMeta { get; set; } = null!;
public Dictionary<string, object>? UserMeta { get; set; } = null!;
public string? MimeType { get; set; }
public string? Hash { get; set; }
public long Size { get; set; }
public bool HasCompression { get; set; } = false;
}
public class CloudFile : ModelBase, ICloudFile, IIdentifiedResource
{
/// The id generated by TuS, basically just UUID remove the dash lines
[MaxLength(32)]
public string Id { get; set; } = Guid.NewGuid().ToString();
[MaxLength(1024)] public string Name { get; set; } = string.Empty;
[MaxLength(4096)] public string? Description { get; set; }
[Column(TypeName = "jsonb")] public Dictionary<string, object>? FileMeta { get; set; } = null!;
[Column(TypeName = "jsonb")] public Dictionary<string, object>? UserMeta { get; set; } = null!;
[Column(TypeName = "jsonb")] public List<ContentSensitiveMark>? SensitiveMarks { get; set; } = [];
[MaxLength(256)] public string? MimeType { get; set; }
[MaxLength(256)] public string? Hash { get; set; }
public long Size { get; set; }
public Instant? UploadedAt { get; set; }
[MaxLength(128)] public string? UploadedTo { get; set; }
public bool HasCompression { get; set; } = false;
/// <summary>
/// The field is set to true if the recycling job plans to delete the file.
/// Due to the unstable of the recycling job, this doesn't really delete the file until a human verifies it.
/// </summary>
public bool IsMarkedRecycle { get; set; } = false;
/// The object name which stored remotely,
/// multiple cloud file may have same storage id to indicate they are the same file
///
/// If the storage id was null and the uploaded at is not null, means it is an embedding file,
/// The embedding file means the file is store on another site,
/// or it is a webpage (based on mimetype)
[MaxLength(32)]
public string? StorageId { get; set; }
/// This field should be null when the storage id is filled
/// Indicates the off-site accessible url of the file
[MaxLength(4096)]
public string? StorageUrl { get; set; }
[JsonIgnore] public Account.Account Account { get; set; } = null!;
public Guid AccountId { get; set; }
public CloudFileReferenceObject ToReferenceObject()
{
return new CloudFileReferenceObject
{
CreatedAt = CreatedAt,
UpdatedAt = UpdatedAt,
DeletedAt = DeletedAt,
Id = Id,
Name = Name,
FileMeta = FileMeta,
UserMeta = UserMeta,
MimeType = MimeType,
Hash = Hash,
Size = Size,
HasCompression = HasCompression
};
}
public string ResourceIdentifier => $"file/{Id}";
}
public enum ContentSensitiveMark
{
Language,
SexualContent,
Violence,
Profanity,
HateSpeech,
Racism,
AdultContent,
DrugAbuse,
AlcoholAbuse,
Gambling,
SelfHarm,
ChildAbuse,
Other
}
public class CloudFileReference : ModelBase
{
public Guid Id { get; set; } = Guid.NewGuid();
[MaxLength(32)] public string FileId { get; set; } = null!;
public CloudFile File { get; set; } = null!;
[MaxLength(1024)] public string Usage { get; set; } = null!;
[MaxLength(1024)] public string ResourceId { get; set; } = null!;
/// <summary>
/// Optional expiration date for the file reference
/// </summary>
public Instant? ExpiredAt { get; set; }
}

View File

@ -1,3 +1,4 @@
using DysonNetwork.Shared.Models;
using DysonNetwork.Sphere.Permission;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
@ -91,7 +92,7 @@ public class FileController(
[HttpDelete("{id}")]
public async Task<ActionResult> DeleteFile(string id)
{
if (HttpContext.Items["CurrentUser"] is not Account.Account currentUser) return Unauthorized();
if (HttpContext.Items["CurrentUser"] is not Shared.Models.Account currentUser) return Unauthorized();
var userId = currentUser.Id;
var file = await db.Files

View File

@ -1,3 +1,4 @@
using DysonNetwork.Shared.Models;
using Microsoft.EntityFrameworkCore;
using NodaTime;

View File

@ -1,3 +1,4 @@
using DysonNetwork.Shared.Models;
using EFCore.BulkExtensions;
using Microsoft.EntityFrameworkCore;
using NodaTime;

View File

@ -2,6 +2,7 @@ using System.Globalization;
using FFMpegCore;
using System.Security.Cryptography;
using AngleSharp.Text;
using DysonNetwork.Shared.Models;
using Microsoft.EntityFrameworkCore;
using Minio;
using Minio.DataModel.Args;
@ -58,7 +59,7 @@ public class FileService(
// The analysis file method no longer will remove the GPS EXIF data
// It should be handled on the client side, and for some specific cases it should be keep
public async Task<CloudFile> ProcessNewFileAsync(
Account.Account account,
Shared.Models.Account account,
string fileId,
Stream stream,
string fileName,

View File

@ -1,3 +1,4 @@
using DysonNetwork.Shared.Models;
using DysonNetwork.Sphere.Account;
using EFCore.BulkExtensions;
using Quartz;

View File

@ -1,3 +1,4 @@
using DysonNetwork.Shared.Models;
using Microsoft.EntityFrameworkCore;
using NodaTime;
using Quartz;
@ -6,8 +7,8 @@ namespace DysonNetwork.Sphere.Storage.Handlers;
public class LastActiveInfo
{
public Auth.Session Session { get; set; } = null!;
public Account.Account Account { get; set; } = null!;
public Session Session { get; set; } = null!;
public Shared.Models.Account Account { get; set; } = null!;
public Instant SeenAt { get; set; }
}

View File

@ -1,3 +1,4 @@
using DysonNetwork.Shared.Models;
using DysonNetwork.Sphere.Chat;
using EFCore.BulkExtensions;
using Microsoft.EntityFrameworkCore;

View File

@ -1,55 +0,0 @@
using NodaTime;
namespace DysonNetwork.Sphere.Storage;
/// <summary>
/// Common interface for cloud file entities that can be used in file operations.
/// This interface exposes the essential properties needed for file operations
/// and is implemented by both CloudFile and CloudFileReferenceObject.
/// </summary>
public interface ICloudFile
{
public Instant CreatedAt { get; }
public Instant UpdatedAt { get; }
public Instant? DeletedAt { get; }
/// <summary>
/// Gets the unique identifier of the cloud file.
/// </summary>
string Id { get; }
/// <summary>
/// Gets the name of the cloud file.
/// </summary>
string Name { get; }
/// <summary>
/// Gets the file metadata dictionary.
/// </summary>
Dictionary<string, object>? FileMeta { get; }
/// <summary>
/// Gets the user metadata dictionary.
/// </summary>
Dictionary<string, object>? UserMeta { get; }
/// <summary>
/// Gets the MIME type of the file.
/// </summary>
string? MimeType { get; }
/// <summary>
/// Gets the hash of the file content.
/// </summary>
string? Hash { get; }
/// <summary>
/// Gets the size of the file in bytes.
/// </summary>
long Size { get; }
/// <summary>
/// Gets whether the file has a compressed version available.
/// </summary>
bool HasCompression { get; }
}

View File

@ -29,7 +29,7 @@ public abstract class TusService
}
var httpContext = eventContext.HttpContext;
if (httpContext.Items["CurrentUser"] is not Account.Account user)
if (httpContext.Items["CurrentUser"] is not Shared.Models.Account user)
{
eventContext.FailRequest(HttpStatusCode.Unauthorized);
return;
@ -50,7 +50,7 @@ public abstract class TusService
var services = scope.ServiceProvider;
var httpContext = eventContext.HttpContext;
if (httpContext.Items["CurrentUser"] is not Account.Account user) return;
if (httpContext.Items["CurrentUser"] is not Shared.Models.Account user) return;
var file = await eventContext.GetFileAsync();
var metadata = await file.GetMetadataAsync(eventContext.CancellationToken);