diff --git a/DysonNetwork.Drive/DysonNetwork.Drive.csproj b/DysonNetwork.Drive/DysonNetwork.Drive.csproj
index 9edd5ba..19bfcab 100644
--- a/DysonNetwork.Drive/DysonNetwork.Drive.csproj
+++ b/DysonNetwork.Drive/DysonNetwork.Drive.csproj
@@ -67,4 +67,8 @@
+
+
+
+
diff --git a/DysonNetwork.Drive/Storage/CloudFile.cs b/DysonNetwork.Drive/Storage/CloudFile.cs
index c5c6f35..6911dc2 100644
--- a/DysonNetwork.Drive/Storage/CloudFile.cs
+++ b/DysonNetwork.Drive/Storage/CloudFile.cs
@@ -1,9 +1,8 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
-using System.Text.Json.Serialization;
using DysonNetwork.Shared.Data;
-using DysonNetwork.Shared.Proto;
using NodaTime;
+using NodaTime.Serialization.Protobuf;
namespace DysonNetwork.Drive.Storage;
@@ -97,6 +96,46 @@ public class CloudFile : ModelBase, ICloudFile, IIdentifiedResource
}
public string ResourceIdentifier => $"file/{Id}";
+
+ ///
+ /// Converts the CloudFile to a protobuf message
+ ///
+ /// The protobuf message representation of this object
+ public Shared.Proto.CloudFile ToProtoValue()
+ {
+ var protoFile = new Shared.Proto.CloudFile
+ {
+ Id = Id,
+ Name = Name ?? string.Empty,
+ MimeType = MimeType ?? string.Empty,
+ Hash = Hash ?? string.Empty,
+ Size = Size,
+ HasCompression = HasCompression,
+ Url = StorageUrl ?? string.Empty,
+ ContentType = MimeType ?? string.Empty,
+ UploadedAt = UploadedAt?.ToTimestamp()
+ };
+
+ // Convert FileMeta dictionary
+ if (FileMeta != null)
+ {
+ foreach (var (key, value) in FileMeta)
+ {
+ protoFile.FileMeta[key] = Google.Protobuf.WellKnownTypes.Value.ForString(value?.ToString() ?? string.Empty);
+ }
+ }
+
+ // Convert UserMeta dictionary
+ if (UserMeta != null)
+ {
+ foreach (var (key, value) in UserMeta)
+ {
+ protoFile.UserMeta[key] = Google.Protobuf.WellKnownTypes.Value.ForString(value?.ToString() ?? string.Empty);
+ }
+ }
+
+ return protoFile;
+ }
}
public enum ContentSensitiveMark
@@ -128,4 +167,21 @@ public class CloudFileReference : ModelBase
/// Optional expiration date for the file reference
///
public Instant? ExpiredAt { get; set; }
+
+ ///
+ /// Converts the CloudFileReference to a protobuf message
+ ///
+ /// The protobuf message representation of this object
+ public Shared.Proto.CloudFileReference ToProtoValue()
+ {
+ return new Shared.Proto.CloudFileReference
+ {
+ Id = Id.ToString(),
+ FileId = FileId,
+ File = File?.ToProtoValue(),
+ Usage = Usage,
+ ResourceId = ResourceId,
+ ExpiredAt = ExpiredAt?.ToTimestamp()
+ };
+ }
}
\ No newline at end of file
diff --git a/DysonNetwork.Shared/Data/CloudFileReferenceObject.cs b/DysonNetwork.Shared/Data/CloudFileReferenceObject.cs
index 37c0eab..b20826f 100644
--- a/DysonNetwork.Shared/Data/CloudFileReferenceObject.cs
+++ b/DysonNetwork.Shared/Data/CloudFileReferenceObject.cs
@@ -20,9 +20,9 @@ public class CloudFileReferenceObject : ModelBase, ICloudFile
///
/// Converts the current object to its protobuf representation
///
- public global::DysonNetwork.Shared.Proto.CloudFileReferenceObject ToProtoValue()
+ public Proto.CloudFile ToProtoValue()
{
- var proto = new global::DysonNetwork.Shared.Proto.CloudFileReferenceObject
+ var proto = new Proto.CloudFile
{
Id = Id,
Name = Name,
@@ -30,7 +30,6 @@ public class CloudFileReferenceObject : ModelBase, ICloudFile
Hash = Hash ?? string.Empty,
Size = Size,
HasCompression = HasCompression,
- // Backward compatibility fields
ContentType = MimeType ?? string.Empty,
Url = string.Empty // This should be set by the caller if needed
};
diff --git a/DysonNetwork.Shared/Proto/account.proto b/DysonNetwork.Shared/Proto/account.proto
index b7fad42..59afef5 100644
--- a/DysonNetwork.Shared/Proto/account.proto
+++ b/DysonNetwork.Shared/Proto/account.proto
@@ -55,8 +55,8 @@ message AccountProfile {
google.protobuf.StringValue picture_id = 17;
google.protobuf.StringValue background_id = 18;
- CloudFileReferenceObject picture = 19;
- CloudFileReferenceObject background = 20;
+ CloudFile picture = 19;
+ CloudFile background = 20;
string account_id = 21;
}
diff --git a/DysonNetwork.Shared/Proto/file.proto b/DysonNetwork.Shared/Proto/file.proto
index 593e2b7..92cd6f7 100644
--- a/DysonNetwork.Shared/Proto/file.proto
+++ b/DysonNetwork.Shared/Proto/file.proto
@@ -8,10 +8,11 @@ import "google/protobuf/timestamp.proto";
import "google/protobuf/struct.proto";
import "google/protobuf/empty.proto";
import "google/protobuf/field_mask.proto";
+import "google/protobuf/duration.proto";
-// CloudFileReferenceObject represents a reference to a file stored in cloud storage.
+// CloudFile represents a reference to a file stored in cloud storage.
// It contains metadata about the file that won't change, helping to reduce database load.
-message CloudFileReferenceObject {
+message CloudFile {
// Unique identifier for the file
string id = 1;
@@ -36,32 +37,44 @@ message CloudFileReferenceObject {
// Indicates if the file is stored with compression
bool has_compression = 8;
- // URL to access the file (kept for backward compatibility)
+ // URL to access the file
string url = 9;
- // Content type of the file (kept for backward compatibility)
+ // Content type of the file
string content_type = 10;
- // When the file was uploaded (kept for backward compatibility)
+ // When the file was uploaded
google.protobuf.Timestamp uploaded_at = 11;
-
- // Additional metadata (kept for backward compatibility)
- map metadata = 12;
}
// Service for file operations
service FileService {
// Get file reference by ID
- rpc GetFile(GetFileRequest) returns (CloudFileReferenceObject) {}
-
- // Create a new file reference
- rpc CreateFile(CreateFileRequest) returns (CloudFileReferenceObject) {}
+ rpc GetFile(GetFileRequest) returns (CloudFile);
// Update an existing file reference
- rpc UpdateFile(UpdateFileRequest) returns (CloudFileReferenceObject) {}
+ rpc UpdateFile(UpdateFileRequest) returns (CloudFile);
// Delete a file reference
- rpc DeleteFile(DeleteFileRequest) returns (google.protobuf.Empty) {}
+ rpc DeleteFile(DeleteFileRequest) returns (google.protobuf.Empty);
+
+ // Process and upload a new file
+ rpc ProcessNewFile(stream ProcessNewFileRequest) returns (CloudFile);
+
+ // Upload a file to remote storage
+ rpc UploadFileToRemote(stream UploadFileToRemoteRequest) returns (CloudFile);
+
+ // Delete file data from storage
+ rpc DeleteFileData(DeleteFileDataRequest) returns (google.protobuf.Empty);
+
+ // Load files from references
+ rpc LoadFromReference(LoadFromReferenceRequest) returns (LoadFromReferenceResponse);
+
+ // Check if a file is referenced by any resource
+ rpc IsReferenced(IsReferencedRequest) returns (IsReferencedResponse);
+
+ // Purge cache for a file
+ rpc PurgeCache(PurgeCacheRequest) returns (google.protobuf.Empty);
}
// Request message for GetFile
@@ -69,19 +82,220 @@ message GetFileRequest {
string id = 1;
}
-// Request message for CreateFile
-message CreateFileRequest {
- CloudFileReferenceObject file = 1;
-}
-
// Request message for UpdateFile
message UpdateFileRequest {
- CloudFileReferenceObject file = 1;
+ CloudFile file = 1;
google.protobuf.FieldMask update_mask = 2;
}
// Request message for DeleteFile
+message ProcessNewFileRequest {
+ oneof data {
+ FileMetadata metadata = 1;
+ bytes chunk = 2;
+ }
+}
+
+message FileMetadata {
+ string file_id = 1;
+ string file_name = 2;
+ string content_type = 3;
+ string account_id = 4;
+}
+
+message UploadFileToRemoteRequest {
+ oneof data {
+ UploadMetadata metadata = 1;
+ bytes chunk = 2;
+ }
+}
+
+message UploadMetadata {
+ string file_id = 1;
+ string target_remote = 2;
+ string suffix = 3;
+ string content_type = 4;
+}
+
message DeleteFileRequest {
string id = 1;
- bool hard_delete = 2;
+ bool purge = 2;
+}
+
+message DeleteFileDataRequest {
+ string file_id = 1;
+ bool force = 2;
+}
+
+message LoadFromReferenceRequest {
+ repeated string reference_ids = 1;
+}
+
+message LoadFromReferenceResponse {
+ repeated CloudFile files = 1;
+}
+
+message GetReferenceCountRequest {
+ string file_id = 1;
+}
+
+message GetReferenceCountResponse {
+ int32 count = 1;
+}
+
+message IsReferencedRequest {
+ string file_id = 1;
+}
+
+message IsReferencedResponse {
+ bool is_referenced = 1;
+}
+
+message PurgeCacheRequest {
+ string file_id = 1;
+}
+
+// CloudFileReference represents a reference to a CloudFile with additional metadata
+// about its usage in the system.
+message CloudFileReference {
+ // Unique identifier for the reference
+ string id = 1;
+
+ // Reference to the actual file
+ string file_id = 2;
+
+ // The actual file data (optional, can be populated when needed)
+ CloudFile file = 3;
+
+ // Description of how this file is being used
+ string usage = 4;
+
+ // ID of the resource that this file is associated with
+ string resource_id = 5;
+
+ // Optional expiration timestamp for the reference
+ google.protobuf.Timestamp expired_at = 6;
+}
+
+// Request/Response messages for FileReferenceService
+message CreateReferenceRequest {
+ string file_id = 1;
+ string usage = 2;
+ string resource_id = 3;
+ google.protobuf.Timestamp expired_at = 4;
+ google.protobuf.Duration duration = 5; // Alternative to expired_at
+}
+
+message GetReferencesRequest {
+ string file_id = 1;
+}
+
+message GetReferencesResponse {
+ repeated CloudFileReference references = 1;
+}
+
+message GetResourceReferencesRequest {
+ string resource_id = 1;
+ string usage = 2; // Optional
+}
+
+message GetResourceFilesRequest {
+ string resource_id = 1;
+ string usage = 2; // Optional
+}
+
+message GetResourceFilesResponse {
+ repeated CloudFile files = 1;
+}
+
+message DeleteResourceReferencesRequest {
+ string resource_id = 1;
+ string usage = 2; // Optional
+}
+
+message DeleteResourceReferencesResponse {
+ int32 deleted_count = 1;
+}
+
+message DeleteReferenceRequest {
+ string reference_id = 1;
+}
+
+message DeleteReferenceResponse {
+ bool success = 1;
+}
+
+message UpdateResourceFilesRequest {
+ string resource_id = 1;
+ repeated string file_ids = 2;
+ string usage = 3;
+ google.protobuf.Timestamp expired_at = 4;
+ google.protobuf.Duration duration = 5; // Alternative to expired_at
+}
+
+message UpdateResourceFilesResponse {
+ repeated CloudFileReference references = 1;
+}
+
+message SetReferenceExpirationRequest {
+ string reference_id = 1;
+ google.protobuf.Timestamp expired_at = 2;
+ google.protobuf.Duration duration = 3; // Alternative to expired_at
+}
+
+message SetReferenceExpirationResponse {
+ bool success = 1;
+}
+
+message SetFileReferencesExpirationRequest {
+ string file_id = 1;
+ google.protobuf.Timestamp expired_at = 2;
+}
+
+message SetFileReferencesExpirationResponse {
+ int32 updated_count = 1;
+}
+
+message HasFileReferencesRequest {
+ string file_id = 1;
+}
+
+message HasFileReferencesResponse {
+ bool has_references = 1;
+}
+
+// Service for managing file references
+service FileReferenceService {
+ // Creates a new reference to a file for a specific resource
+ rpc CreateReference(CreateReferenceRequest) returns (CloudFileReference);
+
+ // Gets all references to a file
+ rpc GetReferences(GetReferencesRequest) returns (GetReferencesResponse);
+
+ // Gets the number of references to a file
+ rpc GetReferenceCount(GetReferenceCountRequest) returns (GetReferenceCountResponse);
+
+ // Gets all references for a specific resource and optional usage
+ rpc GetResourceReferences(GetResourceReferencesRequest) returns (GetReferencesResponse);
+
+ // Gets all files referenced by a resource with optional usage filter
+ rpc GetResourceFiles(GetResourceFilesRequest) returns (GetResourceFilesResponse);
+
+ // Deletes references for a specific resource and optional usage
+ rpc DeleteResourceReferences(DeleteResourceReferencesRequest) returns (DeleteResourceReferencesResponse);
+
+ // Deletes a specific file reference
+ rpc DeleteReference(DeleteReferenceRequest) returns (DeleteReferenceResponse);
+
+ // Updates the files referenced by a resource
+ rpc UpdateResourceFiles(UpdateResourceFilesRequest) returns (UpdateResourceFilesResponse);
+
+ // Updates the expiration time for a file reference
+ rpc SetReferenceExpiration(SetReferenceExpirationRequest) returns (SetReferenceExpirationResponse);
+
+ // Updates the expiration time for all references to a file
+ rpc SetFileReferencesExpiration(SetFileReferencesExpirationRequest) returns (SetFileReferencesExpirationResponse);
+
+ // Checks if a file has any references
+ rpc HasFileReferences(HasFileReferencesRequest) returns (HasFileReferencesResponse);
}
diff --git a/DysonNetwork.sln.DotSettings.user b/DysonNetwork.sln.DotSettings.user
index 28064a5..c388d6b 100644
--- a/DysonNetwork.sln.DotSettings.user
+++ b/DysonNetwork.sln.DotSettings.user
@@ -43,6 +43,7 @@
ForceIncluded
ForceIncluded
ForceIncluded
+ ForceIncluded
ForceIncluded
ForceIncluded
ForceIncluded