✨ Remix file service
This commit is contained in:
@@ -29,7 +29,7 @@ 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?> FileMeta { get; set; } = null!;
|
||||
public Dictionary<string, object>? UserMeta { get; set; } = null!;
|
||||
public string? MimeType { get; set; }
|
||||
public string? Hash { get; set; }
|
||||
@@ -45,7 +45,7 @@ public class CloudFile : ModelBase, ICloudFile, IIdentifiedResource
|
||||
|
||||
[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?> 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; }
|
||||
|
@@ -5,15 +5,18 @@ using Duration = NodaTime.Duration;
|
||||
|
||||
namespace DysonNetwork.Drive.Storage
|
||||
{
|
||||
public class FileReferenceServiceGrpc(FileReferenceService fileReferenceService) : Shared.Proto.FileReferenceService.FileReferenceServiceBase
|
||||
public class FileReferenceServiceGrpc(FileReferenceService fileReferenceService)
|
||||
: Shared.Proto.FileReferenceService.FileReferenceServiceBase
|
||||
{
|
||||
public override async Task<Shared.Proto.CloudFileReference> CreateReference(CreateReferenceRequest request, ServerCallContext context)
|
||||
public override async Task<Shared.Proto.CloudFileReference> CreateReference(CreateReferenceRequest request,
|
||||
ServerCallContext context)
|
||||
{
|
||||
Instant? expiredAt = null;
|
||||
if (request.ExpiredAt != null)
|
||||
expiredAt = Instant.FromUnixTimeSeconds(request.ExpiredAt.Seconds);
|
||||
else if (request.Duration != null)
|
||||
expiredAt = SystemClock.Instance.GetCurrentInstant() + Duration.FromTimeSpan(request.Duration.ToTimeSpan());
|
||||
expiredAt = SystemClock.Instance.GetCurrentInstant() +
|
||||
Duration.FromTimeSpan(request.Duration.ToTimeSpan());
|
||||
|
||||
var reference = await fileReferenceService.CreateReferenceAsync(
|
||||
request.FileId,
|
||||
@@ -24,7 +27,8 @@ namespace DysonNetwork.Drive.Storage
|
||||
return reference.ToProtoValue();
|
||||
}
|
||||
|
||||
public override async Task<GetReferencesResponse> GetReferences(GetReferencesRequest request, ServerCallContext context)
|
||||
public override async Task<GetReferencesResponse> GetReferences(GetReferencesRequest request,
|
||||
ServerCallContext context)
|
||||
{
|
||||
var references = await fileReferenceService.GetReferencesAsync(request.FileId);
|
||||
var response = new GetReferencesResponse();
|
||||
@@ -32,13 +36,15 @@ namespace DysonNetwork.Drive.Storage
|
||||
return response;
|
||||
}
|
||||
|
||||
public override async Task<GetReferenceCountResponse> GetReferenceCount(GetReferenceCountRequest request, ServerCallContext context)
|
||||
public override async Task<GetReferenceCountResponse> GetReferenceCount(GetReferenceCountRequest request,
|
||||
ServerCallContext context)
|
||||
{
|
||||
var count = await fileReferenceService.GetReferenceCountAsync(request.FileId);
|
||||
return new GetReferenceCountResponse { Count = count };
|
||||
}
|
||||
|
||||
public override async Task<GetReferencesResponse> GetResourceReferences(GetResourceReferencesRequest request, ServerCallContext context)
|
||||
public override async Task<GetReferencesResponse> GetResourceReferences(GetResourceReferencesRequest request,
|
||||
ServerCallContext context)
|
||||
{
|
||||
var references = await fileReferenceService.GetResourceReferencesAsync(request.ResourceId, request.Usage);
|
||||
var response = new GetReferencesResponse();
|
||||
@@ -46,7 +52,8 @@ namespace DysonNetwork.Drive.Storage
|
||||
return response;
|
||||
}
|
||||
|
||||
public override async Task<GetResourceFilesResponse> GetResourceFiles(GetResourceFilesRequest request, ServerCallContext context)
|
||||
public override async Task<GetResourceFilesResponse> GetResourceFiles(GetResourceFilesRequest request,
|
||||
ServerCallContext context)
|
||||
{
|
||||
var files = await fileReferenceService.GetResourceFilesAsync(request.ResourceId, request.Usage);
|
||||
var response = new GetResourceFilesResponse();
|
||||
@@ -54,19 +61,27 @@ namespace DysonNetwork.Drive.Storage
|
||||
return response;
|
||||
}
|
||||
|
||||
public override async Task<DeleteResourceReferencesResponse> DeleteResourceReferences(DeleteResourceReferencesRequest request, ServerCallContext context)
|
||||
public override async Task<DeleteResourceReferencesResponse> DeleteResourceReferences(
|
||||
DeleteResourceReferencesRequest request, ServerCallContext context)
|
||||
{
|
||||
var deletedCount = await fileReferenceService.DeleteResourceReferencesAsync(request.ResourceId, request.Usage);
|
||||
var deletedCount = 0;
|
||||
if (request.Usage is null)
|
||||
deletedCount = await fileReferenceService.DeleteResourceReferencesAsync(request.ResourceId);
|
||||
else
|
||||
deletedCount =
|
||||
await fileReferenceService.DeleteResourceReferencesAsync(request.ResourceId, request.Usage!);
|
||||
return new DeleteResourceReferencesResponse { DeletedCount = deletedCount };
|
||||
}
|
||||
|
||||
public override async Task<DeleteReferenceResponse> DeleteReference(DeleteReferenceRequest request, ServerCallContext context)
|
||||
public override async Task<DeleteReferenceResponse> DeleteReference(DeleteReferenceRequest request,
|
||||
ServerCallContext context)
|
||||
{
|
||||
var success = await fileReferenceService.DeleteReferenceAsync(Guid.Parse(request.ReferenceId));
|
||||
return new DeleteReferenceResponse { Success = success };
|
||||
}
|
||||
|
||||
public override async Task<UpdateResourceFilesResponse> UpdateResourceFiles(UpdateResourceFilesRequest request, ServerCallContext context)
|
||||
public override async Task<UpdateResourceFilesResponse> UpdateResourceFiles(UpdateResourceFilesRequest request,
|
||||
ServerCallContext context)
|
||||
{
|
||||
Instant? expiredAt = null;
|
||||
if (request.ExpiredAt != null)
|
||||
@@ -75,7 +90,8 @@ namespace DysonNetwork.Drive.Storage
|
||||
}
|
||||
else if (request.Duration != null)
|
||||
{
|
||||
expiredAt = SystemClock.Instance.GetCurrentInstant() + Duration.FromTimeSpan(request.Duration.ToTimeSpan());
|
||||
expiredAt = SystemClock.Instance.GetCurrentInstant() +
|
||||
Duration.FromTimeSpan(request.Duration.ToTimeSpan());
|
||||
}
|
||||
|
||||
var references = await fileReferenceService.UpdateResourceFilesAsync(
|
||||
@@ -89,7 +105,8 @@ namespace DysonNetwork.Drive.Storage
|
||||
return response;
|
||||
}
|
||||
|
||||
public override async Task<SetReferenceExpirationResponse> SetReferenceExpiration(SetReferenceExpirationRequest request, ServerCallContext context)
|
||||
public override async Task<SetReferenceExpirationResponse> SetReferenceExpiration(
|
||||
SetReferenceExpirationRequest request, ServerCallContext context)
|
||||
{
|
||||
Instant? expiredAt = null;
|
||||
if (request.ExpiredAt != null)
|
||||
@@ -98,21 +115,25 @@ namespace DysonNetwork.Drive.Storage
|
||||
}
|
||||
else if (request.Duration != null)
|
||||
{
|
||||
expiredAt = SystemClock.Instance.GetCurrentInstant() + Duration.FromTimeSpan(request.Duration.ToTimeSpan());
|
||||
expiredAt = SystemClock.Instance.GetCurrentInstant() +
|
||||
Duration.FromTimeSpan(request.Duration.ToTimeSpan());
|
||||
}
|
||||
|
||||
var success = await fileReferenceService.SetReferenceExpirationAsync(Guid.Parse(request.ReferenceId), expiredAt);
|
||||
var success =
|
||||
await fileReferenceService.SetReferenceExpirationAsync(Guid.Parse(request.ReferenceId), expiredAt);
|
||||
return new SetReferenceExpirationResponse { Success = success };
|
||||
}
|
||||
|
||||
public override async Task<SetFileReferencesExpirationResponse> SetFileReferencesExpiration(SetFileReferencesExpirationRequest request, ServerCallContext context)
|
||||
public override async Task<SetFileReferencesExpirationResponse> SetFileReferencesExpiration(
|
||||
SetFileReferencesExpirationRequest request, ServerCallContext context)
|
||||
{
|
||||
var expiredAt = Instant.FromUnixTimeSeconds(request.ExpiredAt.Seconds);
|
||||
var updatedCount = await fileReferenceService.SetFileReferencesExpirationAsync(request.FileId, expiredAt);
|
||||
return new SetFileReferencesExpirationResponse { UpdatedCount = updatedCount };
|
||||
}
|
||||
|
||||
public override async Task<HasFileReferencesResponse> HasFileReferences(HasFileReferencesRequest request, ServerCallContext context)
|
||||
public override async Task<HasFileReferencesResponse> HasFileReferences(HasFileReferencesRequest request,
|
||||
ServerCallContext context)
|
||||
{
|
||||
var hasReferences = await fileReferenceService.HasFileReferencesAsync(request.FileId);
|
||||
return new HasFileReferencesResponse { HasReferences = hasReferences };
|
||||
|
@@ -12,7 +12,8 @@ namespace DysonNetwork.Drive.Storage
|
||||
return file?.ToProtoValue() ?? throw new RpcException(new Status(StatusCode.NotFound, "File not found"));
|
||||
}
|
||||
|
||||
public override async Task<Shared.Proto.CloudFile> UpdateFile(UpdateFileRequest request, ServerCallContext context)
|
||||
public override async Task<Shared.Proto.CloudFile> UpdateFile(UpdateFileRequest request,
|
||||
ServerCallContext context)
|
||||
{
|
||||
var file = await fileService.GetFileAsync(request.File.Id);
|
||||
if (file == null)
|
||||
@@ -33,113 +34,10 @@ namespace DysonNetwork.Drive.Storage
|
||||
return new Empty();
|
||||
}
|
||||
|
||||
public override async Task<Shared.Proto.CloudFile> ProcessNewFile(IAsyncStreamReader<ProcessNewFileRequest> requestStream,
|
||||
ServerCallContext context)
|
||||
{
|
||||
ProcessNewFileRequest? metadataRequest = null;
|
||||
var chunks = new List<byte[]>();
|
||||
|
||||
await foreach (var message in requestStream.ReadAllAsync())
|
||||
{
|
||||
if (message.DataCase == ProcessNewFileRequest.DataOneofCase.Metadata)
|
||||
{
|
||||
metadataRequest = message;
|
||||
}
|
||||
else if (message.DataCase == ProcessNewFileRequest.DataOneofCase.Chunk)
|
||||
{
|
||||
chunks.Add(message.Chunk.ToByteArray());
|
||||
}
|
||||
}
|
||||
|
||||
if (metadataRequest == null || metadataRequest.Metadata == null)
|
||||
{
|
||||
throw new RpcException(new Status(StatusCode.InvalidArgument, "Missing file metadata"));
|
||||
}
|
||||
|
||||
var metadata = metadataRequest.Metadata;
|
||||
using var memoryStream = new MemoryStream();
|
||||
foreach (var chunk in chunks)
|
||||
{
|
||||
await memoryStream.WriteAsync(chunk);
|
||||
}
|
||||
|
||||
memoryStream.Position = 0;
|
||||
|
||||
// Assuming you have an Account object available or can create a dummy one for now
|
||||
// You might need to adjust this based on how accounts are handled in your system
|
||||
var dummyAccount = new Account { Id = metadata.AccountId };
|
||||
|
||||
var cloudFile = await fileService.ProcessNewFileAsync(
|
||||
dummyAccount,
|
||||
metadata.FileId,
|
||||
memoryStream,
|
||||
metadata.FileName,
|
||||
metadata.ContentType
|
||||
);
|
||||
return cloudFile.ToProtoValue();
|
||||
}
|
||||
|
||||
public override async Task<Shared.Proto.CloudFile> UploadFileToRemote(
|
||||
IAsyncStreamReader<UploadFileToRemoteRequest> requestStream, ServerCallContext context)
|
||||
{
|
||||
UploadFileToRemoteRequest? metadataRequest = null;
|
||||
var chunks = new List<byte[]>();
|
||||
|
||||
await foreach (var message in requestStream.ReadAllAsync())
|
||||
{
|
||||
if (message.DataCase == UploadFileToRemoteRequest.DataOneofCase.Metadata)
|
||||
{
|
||||
metadataRequest = message;
|
||||
}
|
||||
else if (message.DataCase == UploadFileToRemoteRequest.DataOneofCase.Chunk)
|
||||
{
|
||||
chunks.Add(message.Chunk.ToByteArray());
|
||||
}
|
||||
}
|
||||
|
||||
if (metadataRequest == null || metadataRequest.Metadata == null)
|
||||
{
|
||||
throw new RpcException(new Status(StatusCode.InvalidArgument, "Missing upload metadata"));
|
||||
}
|
||||
|
||||
var metadata = metadataRequest.Metadata;
|
||||
using var memoryStream = new MemoryStream();
|
||||
foreach (var chunk in chunks)
|
||||
{
|
||||
await memoryStream.WriteAsync(chunk);
|
||||
}
|
||||
|
||||
memoryStream.Position = 0;
|
||||
|
||||
var file = await fileService.GetFileAsync(metadata.FileId);
|
||||
if (file == null)
|
||||
{
|
||||
throw new RpcException(new Status(StatusCode.NotFound, "File not found"));
|
||||
}
|
||||
|
||||
var uploadedFile = await fileService.UploadFileToRemoteAsync(
|
||||
file,
|
||||
memoryStream,
|
||||
metadata.TargetRemote,
|
||||
metadata.Suffix
|
||||
);
|
||||
return uploadedFile.ToProtoValue();
|
||||
}
|
||||
|
||||
public override async Task<Empty> DeleteFileData(DeleteFileDataRequest request, ServerCallContext context)
|
||||
{
|
||||
var file = await fileService.GetFileAsync(request.FileId);
|
||||
if (file == null)
|
||||
{
|
||||
throw new RpcException(new Status(StatusCode.NotFound, "File not found"));
|
||||
}
|
||||
|
||||
await fileService.DeleteFileDataAsync(file);
|
||||
return new Empty();
|
||||
}
|
||||
|
||||
public override async Task<LoadFromReferenceResponse> LoadFromReference(LoadFromReferenceRequest request,
|
||||
ServerCallContext context)
|
||||
public override async Task<LoadFromReferenceResponse> LoadFromReference(
|
||||
LoadFromReferenceRequest request,
|
||||
ServerCallContext context
|
||||
)
|
||||
{
|
||||
// Assuming CloudFileReferenceObject is a simple class/struct that holds an ID
|
||||
// You might need to define this or adjust the LoadFromReference method in FileService
|
||||
|
Reference in New Issue
Block a user