diff --git a/DysonNetwork.Drive/Billing/UsageService.cs b/DysonNetwork.Drive/Billing/UsageService.cs
new file mode 100644
index 0000000..87ac4b1
--- /dev/null
+++ b/DysonNetwork.Drive/Billing/UsageService.cs
@@ -0,0 +1,6 @@
+namespace DysonNetwork.Drive.Billing;
+
+public class UsageService
+{
+
+}
\ No newline at end of file
diff --git a/DysonNetwork.Drive/Client/src/views/index.vue b/DysonNetwork.Drive/Client/src/views/index.vue
index fd02bf1..3f615b4 100644
--- a/DysonNetwork.Drive/Client/src/views/index.vue
+++ b/DysonNetwork.Drive/Client/src/views/index.vue
@@ -149,7 +149,8 @@ const renderSingleSelectTag: SelectRenderTag = ({ option }) => {
)
}
-function renderPoolSelectLabel(option: SelectOption & SnFilePool, selected: boolean) {
+function renderPoolSelectLabel(option: SelectOption & SnFilePool) {
+ const policy: any = option.policy_config
return h(
'div',
{
@@ -171,7 +172,7 @@ function renderPoolSelectLabel(option: SelectOption & SnFilePool, selected: bool
},
},
[
- option.public_usable &&
+ policy.public_usable &&
h(
NTag,
{
@@ -181,7 +182,7 @@ function renderPoolSelectLabel(option: SelectOption & SnFilePool, selected: bool
},
{ default: () => 'Public Shared' },
),
- option.public_indexable &&
+ policy.public_indexable &&
h(
NTag,
{
@@ -191,7 +192,7 @@ function renderPoolSelectLabel(option: SelectOption & SnFilePool, selected: bool
},
{ default: () => 'Public Indexable' },
),
- option.allow_encryption &&
+ policy.allow_encryption &&
h(
NTag,
{
diff --git a/DysonNetwork.Drive/Migrations/20250725051034_UpdateCloudFileThumbnail.Designer.cs b/DysonNetwork.Drive/Migrations/20250725051034_UpdateCloudFileThumbnail.Designer.cs
deleted file mode 100644
index a962603..0000000
--- a/DysonNetwork.Drive/Migrations/20250725051034_UpdateCloudFileThumbnail.Designer.cs
+++ /dev/null
@@ -1,194 +0,0 @@
-//
-using System;
-using System.Collections.Generic;
-using DysonNetwork.Drive;
-using DysonNetwork.Shared.Data;
-using Microsoft.EntityFrameworkCore;
-using Microsoft.EntityFrameworkCore.Infrastructure;
-using Microsoft.EntityFrameworkCore.Migrations;
-using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
-using NodaTime;
-using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
-
-#nullable disable
-
-namespace DysonNetwork.Drive.Migrations
-{
- [DbContext(typeof(AppDatabase))]
- [Migration("20250725051034_UpdateCloudFileThumbnail")]
- partial class UpdateCloudFileThumbnail
- {
- ///
- protected override void BuildTargetModel(ModelBuilder modelBuilder)
- {
-#pragma warning disable 612, 618
- modelBuilder
- .HasAnnotation("ProductVersion", "9.0.7")
- .HasAnnotation("Relational:MaxIdentifierLength", 63);
-
- NpgsqlModelBuilderExtensions.HasPostgresExtension(modelBuilder, "postgis");
- NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
-
- modelBuilder.Entity("DysonNetwork.Drive.Storage.CloudFile", b =>
- {
- b.Property("Id")
- .HasMaxLength(32)
- .HasColumnType("character varying(32)")
- .HasColumnName("id");
-
- b.Property("AccountId")
- .HasColumnType("uuid")
- .HasColumnName("account_id");
-
- b.Property("CreatedAt")
- .HasColumnType("timestamp with time zone")
- .HasColumnName("created_at");
-
- b.Property("DeletedAt")
- .HasColumnType("timestamp with time zone")
- .HasColumnName("deleted_at");
-
- b.Property("Description")
- .HasMaxLength(4096)
- .HasColumnType("character varying(4096)")
- .HasColumnName("description");
-
- b.Property>("FileMeta")
- .IsRequired()
- .HasColumnType("jsonb")
- .HasColumnName("file_meta");
-
- b.Property("HasCompression")
- .HasColumnType("boolean")
- .HasColumnName("has_compression");
-
- b.Property("HasThumbnail")
- .HasColumnType("boolean")
- .HasColumnName("has_thumbnail");
-
- b.Property("Hash")
- .HasMaxLength(256)
- .HasColumnType("character varying(256)")
- .HasColumnName("hash");
-
- b.Property("IsMarkedRecycle")
- .HasColumnType("boolean")
- .HasColumnName("is_marked_recycle");
-
- b.Property("MimeType")
- .HasMaxLength(256)
- .HasColumnType("character varying(256)")
- .HasColumnName("mime_type");
-
- b.Property("Name")
- .IsRequired()
- .HasMaxLength(1024)
- .HasColumnType("character varying(1024)")
- .HasColumnName("name");
-
- b.Property>("SensitiveMarks")
- .HasColumnType("jsonb")
- .HasColumnName("sensitive_marks");
-
- b.Property("Size")
- .HasColumnType("bigint")
- .HasColumnName("size");
-
- b.Property("StorageId")
- .HasMaxLength(32)
- .HasColumnType("character varying(32)")
- .HasColumnName("storage_id");
-
- b.Property("StorageUrl")
- .HasMaxLength(4096)
- .HasColumnType("character varying(4096)")
- .HasColumnName("storage_url");
-
- b.Property("UpdatedAt")
- .HasColumnType("timestamp with time zone")
- .HasColumnName("updated_at");
-
- b.Property("UploadedAt")
- .HasColumnType("timestamp with time zone")
- .HasColumnName("uploaded_at");
-
- b.Property("UploadedTo")
- .HasMaxLength(128)
- .HasColumnType("character varying(128)")
- .HasColumnName("uploaded_to");
-
- b.Property>("UserMeta")
- .HasColumnType("jsonb")
- .HasColumnName("user_meta");
-
- b.HasKey("Id")
- .HasName("pk_files");
-
- b.ToTable("files", (string)null);
- });
-
- modelBuilder.Entity("DysonNetwork.Drive.Storage.CloudFileReference", b =>
- {
- b.Property("Id")
- .ValueGeneratedOnAdd()
- .HasColumnType("uuid")
- .HasColumnName("id");
-
- b.Property("CreatedAt")
- .HasColumnType("timestamp with time zone")
- .HasColumnName("created_at");
-
- b.Property("DeletedAt")
- .HasColumnType("timestamp with time zone")
- .HasColumnName("deleted_at");
-
- b.Property("ExpiredAt")
- .HasColumnType("timestamp with time zone")
- .HasColumnName("expired_at");
-
- b.Property("FileId")
- .IsRequired()
- .HasMaxLength(32)
- .HasColumnType("character varying(32)")
- .HasColumnName("file_id");
-
- b.Property("ResourceId")
- .IsRequired()
- .HasMaxLength(1024)
- .HasColumnType("character varying(1024)")
- .HasColumnName("resource_id");
-
- b.Property("UpdatedAt")
- .HasColumnType("timestamp with time zone")
- .HasColumnName("updated_at");
-
- b.Property("Usage")
- .IsRequired()
- .HasMaxLength(1024)
- .HasColumnType("character varying(1024)")
- .HasColumnName("usage");
-
- b.HasKey("Id")
- .HasName("pk_file_references");
-
- b.HasIndex("FileId")
- .HasDatabaseName("ix_file_references_file_id");
-
- b.ToTable("file_references", (string)null);
- });
-
- modelBuilder.Entity("DysonNetwork.Drive.Storage.CloudFileReference", b =>
- {
- b.HasOne("DysonNetwork.Drive.Storage.CloudFile", "File")
- .WithMany()
- .HasForeignKey("FileId")
- .OnDelete(DeleteBehavior.Cascade)
- .IsRequired()
- .HasConstraintName("fk_file_references_files_file_id");
-
- b.Navigation("File");
- });
-#pragma warning restore 612, 618
- }
- }
-}
diff --git a/DysonNetwork.Drive/Migrations/20250725051034_UpdateCloudFileThumbnail.cs b/DysonNetwork.Drive/Migrations/20250725051034_UpdateCloudFileThumbnail.cs
deleted file mode 100644
index 369dcd9..0000000
--- a/DysonNetwork.Drive/Migrations/20250725051034_UpdateCloudFileThumbnail.cs
+++ /dev/null
@@ -1,29 +0,0 @@
-using Microsoft.EntityFrameworkCore.Migrations;
-
-#nullable disable
-
-namespace DysonNetwork.Drive.Migrations
-{
- ///
- public partial class UpdateCloudFileThumbnail : Migration
- {
- ///
- protected override void Up(MigrationBuilder migrationBuilder)
- {
- migrationBuilder.AddColumn(
- name: "has_thumbnail",
- table: "files",
- type: "boolean",
- nullable: false,
- defaultValue: false);
- }
-
- ///
- protected override void Down(MigrationBuilder migrationBuilder)
- {
- migrationBuilder.DropColumn(
- name: "has_thumbnail",
- table: "files");
- }
- }
-}
diff --git a/DysonNetwork.Drive/Migrations/20250725163615_AddCloudFilePool.Designer.cs b/DysonNetwork.Drive/Migrations/20250725163615_AddCloudFilePool.Designer.cs
deleted file mode 100644
index a771bdc..0000000
--- a/DysonNetwork.Drive/Migrations/20250725163615_AddCloudFilePool.Designer.cs
+++ /dev/null
@@ -1,253 +0,0 @@
-//
-using System;
-using System.Collections.Generic;
-using DysonNetwork.Drive;
-using DysonNetwork.Drive.Storage;
-using DysonNetwork.Shared.Data;
-using Microsoft.EntityFrameworkCore;
-using Microsoft.EntityFrameworkCore.Infrastructure;
-using Microsoft.EntityFrameworkCore.Migrations;
-using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
-using NodaTime;
-using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
-
-#nullable disable
-
-namespace DysonNetwork.Drive.Migrations
-{
- [DbContext(typeof(AppDatabase))]
- [Migration("20250725163615_AddCloudFilePool")]
- partial class AddCloudFilePool
- {
- ///
- protected override void BuildTargetModel(ModelBuilder modelBuilder)
- {
-#pragma warning disable 612, 618
- modelBuilder
- .HasAnnotation("ProductVersion", "9.0.7")
- .HasAnnotation("Relational:MaxIdentifierLength", 63);
-
- NpgsqlModelBuilderExtensions.HasPostgresExtension(modelBuilder, "postgis");
- NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
-
- modelBuilder.Entity("DysonNetwork.Drive.Storage.CloudFile", b =>
- {
- b.Property("Id")
- .HasMaxLength(32)
- .HasColumnType("character varying(32)")
- .HasColumnName("id");
-
- b.Property("AccountId")
- .HasColumnType("uuid")
- .HasColumnName("account_id");
-
- b.Property("CreatedAt")
- .HasColumnType("timestamp with time zone")
- .HasColumnName("created_at");
-
- b.Property("DeletedAt")
- .HasColumnType("timestamp with time zone")
- .HasColumnName("deleted_at");
-
- b.Property("Description")
- .HasMaxLength(4096)
- .HasColumnType("character varying(4096)")
- .HasColumnName("description");
-
- b.Property>("FileMeta")
- .IsRequired()
- .HasColumnType("jsonb")
- .HasColumnName("file_meta");
-
- b.Property("HasCompression")
- .HasColumnType("boolean")
- .HasColumnName("has_compression");
-
- b.Property("HasThumbnail")
- .HasColumnType("boolean")
- .HasColumnName("has_thumbnail");
-
- b.Property("Hash")
- .HasMaxLength(256)
- .HasColumnType("character varying(256)")
- .HasColumnName("hash");
-
- b.Property("IsMarkedRecycle")
- .HasColumnType("boolean")
- .HasColumnName("is_marked_recycle");
-
- b.Property("MimeType")
- .HasMaxLength(256)
- .HasColumnType("character varying(256)")
- .HasColumnName("mime_type");
-
- b.Property("Name")
- .IsRequired()
- .HasMaxLength(1024)
- .HasColumnType("character varying(1024)")
- .HasColumnName("name");
-
- b.Property("PoolId")
- .HasColumnType("uuid")
- .HasColumnName("pool_id");
-
- b.Property>("SensitiveMarks")
- .HasColumnType("jsonb")
- .HasColumnName("sensitive_marks");
-
- b.Property("Size")
- .HasColumnType("bigint")
- .HasColumnName("size");
-
- b.Property("StorageId")
- .HasMaxLength(32)
- .HasColumnType("character varying(32)")
- .HasColumnName("storage_id");
-
- b.Property("StorageUrl")
- .HasMaxLength(4096)
- .HasColumnType("character varying(4096)")
- .HasColumnName("storage_url");
-
- b.Property("UpdatedAt")
- .HasColumnType("timestamp with time zone")
- .HasColumnName("updated_at");
-
- b.Property("UploadedAt")
- .HasColumnType("timestamp with time zone")
- .HasColumnName("uploaded_at");
-
- b.Property("UploadedTo")
- .HasMaxLength(128)
- .HasColumnType("character varying(128)")
- .HasColumnName("uploaded_to");
-
- b.Property>("UserMeta")
- .HasColumnType("jsonb")
- .HasColumnName("user_meta");
-
- b.HasKey("Id")
- .HasName("pk_files");
-
- b.HasIndex("PoolId")
- .HasDatabaseName("ix_files_pool_id");
-
- b.ToTable("files", (string)null);
- });
-
- modelBuilder.Entity("DysonNetwork.Drive.Storage.CloudFileReference", b =>
- {
- b.Property("Id")
- .ValueGeneratedOnAdd()
- .HasColumnType("uuid")
- .HasColumnName("id");
-
- b.Property("CreatedAt")
- .HasColumnType("timestamp with time zone")
- .HasColumnName("created_at");
-
- b.Property("DeletedAt")
- .HasColumnType("timestamp with time zone")
- .HasColumnName("deleted_at");
-
- b.Property("ExpiredAt")
- .HasColumnType("timestamp with time zone")
- .HasColumnName("expired_at");
-
- b.Property("FileId")
- .IsRequired()
- .HasMaxLength(32)
- .HasColumnType("character varying(32)")
- .HasColumnName("file_id");
-
- b.Property("ResourceId")
- .IsRequired()
- .HasMaxLength(1024)
- .HasColumnType("character varying(1024)")
- .HasColumnName("resource_id");
-
- b.Property("UpdatedAt")
- .HasColumnType("timestamp with time zone")
- .HasColumnName("updated_at");
-
- b.Property("Usage")
- .IsRequired()
- .HasMaxLength(1024)
- .HasColumnType("character varying(1024)")
- .HasColumnName("usage");
-
- b.HasKey("Id")
- .HasName("pk_file_references");
-
- b.HasIndex("FileId")
- .HasDatabaseName("ix_file_references_file_id");
-
- b.ToTable("file_references", (string)null);
- });
-
- modelBuilder.Entity("DysonNetwork.Drive.Storage.FilePool", b =>
- {
- b.Property("Id")
- .ValueGeneratedOnAdd()
- .HasColumnType("uuid")
- .HasColumnName("id");
-
- b.Property("BillingConfig")
- .IsRequired()
- .HasColumnType("jsonb")
- .HasColumnName("billing_config");
-
- b.Property("CreatedAt")
- .HasColumnType("timestamp with time zone")
- .HasColumnName("created_at");
-
- b.Property("DeletedAt")
- .HasColumnType("timestamp with time zone")
- .HasColumnName("deleted_at");
-
- b.Property("Name")
- .IsRequired()
- .HasMaxLength(1024)
- .HasColumnType("character varying(1024)")
- .HasColumnName("name");
-
- b.Property("StorageConfig")
- .IsRequired()
- .HasColumnType("jsonb")
- .HasColumnName("storage_config");
-
- b.Property("UpdatedAt")
- .HasColumnType("timestamp with time zone")
- .HasColumnName("updated_at");
-
- b.HasKey("Id")
- .HasName("pk_pools");
-
- b.ToTable("pools", (string)null);
- });
-
- modelBuilder.Entity("DysonNetwork.Drive.Storage.CloudFile", b =>
- {
- b.HasOne("DysonNetwork.Drive.Storage.FilePool", "Pool")
- .WithMany()
- .HasForeignKey("PoolId")
- .HasConstraintName("fk_files_pools_pool_id");
-
- b.Navigation("Pool");
- });
-
- modelBuilder.Entity("DysonNetwork.Drive.Storage.CloudFileReference", b =>
- {
- b.HasOne("DysonNetwork.Drive.Storage.CloudFile", "File")
- .WithMany()
- .HasForeignKey("FileId")
- .OnDelete(DeleteBehavior.Cascade)
- .IsRequired()
- .HasConstraintName("fk_file_references_files_file_id");
-
- b.Navigation("File");
- });
-#pragma warning restore 612, 618
- }
- }
-}
diff --git a/DysonNetwork.Drive/Migrations/20250725170254_AddCloudFileEncrypt.cs b/DysonNetwork.Drive/Migrations/20250725170254_AddCloudFileEncrypt.cs
deleted file mode 100644
index dcc5a80..0000000
--- a/DysonNetwork.Drive/Migrations/20250725170254_AddCloudFileEncrypt.cs
+++ /dev/null
@@ -1,29 +0,0 @@
-using Microsoft.EntityFrameworkCore.Migrations;
-
-#nullable disable
-
-namespace DysonNetwork.Drive.Migrations
-{
- ///
- public partial class AddCloudFileEncrypt : Migration
- {
- ///
- protected override void Up(MigrationBuilder migrationBuilder)
- {
- migrationBuilder.AddColumn(
- name: "is_encrypted",
- table: "files",
- type: "boolean",
- nullable: false,
- defaultValue: false);
- }
-
- ///
- protected override void Down(MigrationBuilder migrationBuilder)
- {
- migrationBuilder.DropColumn(
- name: "is_encrypted",
- table: "files");
- }
- }
-}
diff --git a/DysonNetwork.Drive/Migrations/20250725183846_EnrichCloudPoolConfigure.Designer.cs b/DysonNetwork.Drive/Migrations/20250725183846_EnrichCloudPoolConfigure.Designer.cs
deleted file mode 100644
index f098e3e..0000000
--- a/DysonNetwork.Drive/Migrations/20250725183846_EnrichCloudPoolConfigure.Designer.cs
+++ /dev/null
@@ -1,277 +0,0 @@
-//
-using System;
-using System.Collections.Generic;
-using DysonNetwork.Drive;
-using DysonNetwork.Drive.Storage;
-using DysonNetwork.Shared.Data;
-using Microsoft.EntityFrameworkCore;
-using Microsoft.EntityFrameworkCore.Infrastructure;
-using Microsoft.EntityFrameworkCore.Migrations;
-using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
-using NodaTime;
-using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
-
-#nullable disable
-
-namespace DysonNetwork.Drive.Migrations
-{
- [DbContext(typeof(AppDatabase))]
- [Migration("20250725183846_EnrichCloudPoolConfigure")]
- partial class EnrichCloudPoolConfigure
- {
- ///
- protected override void BuildTargetModel(ModelBuilder modelBuilder)
- {
-#pragma warning disable 612, 618
- modelBuilder
- .HasAnnotation("ProductVersion", "9.0.7")
- .HasAnnotation("Relational:MaxIdentifierLength", 63);
-
- NpgsqlModelBuilderExtensions.HasPostgresExtension(modelBuilder, "postgis");
- NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
-
- modelBuilder.Entity("DysonNetwork.Drive.Storage.CloudFile", b =>
- {
- b.Property("Id")
- .HasMaxLength(32)
- .HasColumnType("character varying(32)")
- .HasColumnName("id");
-
- b.Property("AccountId")
- .HasColumnType("uuid")
- .HasColumnName("account_id");
-
- b.Property("CreatedAt")
- .HasColumnType("timestamp with time zone")
- .HasColumnName("created_at");
-
- b.Property("DeletedAt")
- .HasColumnType("timestamp with time zone")
- .HasColumnName("deleted_at");
-
- b.Property("Description")
- .HasMaxLength(4096)
- .HasColumnType("character varying(4096)")
- .HasColumnName("description");
-
- b.Property>("FileMeta")
- .IsRequired()
- .HasColumnType("jsonb")
- .HasColumnName("file_meta");
-
- b.Property("HasCompression")
- .HasColumnType("boolean")
- .HasColumnName("has_compression");
-
- b.Property("HasThumbnail")
- .HasColumnType("boolean")
- .HasColumnName("has_thumbnail");
-
- b.Property("Hash")
- .HasMaxLength(256)
- .HasColumnType("character varying(256)")
- .HasColumnName("hash");
-
- b.Property("IsEncrypted")
- .HasColumnType("boolean")
- .HasColumnName("is_encrypted");
-
- b.Property("IsMarkedRecycle")
- .HasColumnType("boolean")
- .HasColumnName("is_marked_recycle");
-
- b.Property("MimeType")
- .HasMaxLength(256)
- .HasColumnType("character varying(256)")
- .HasColumnName("mime_type");
-
- b.Property("Name")
- .IsRequired()
- .HasMaxLength(1024)
- .HasColumnType("character varying(1024)")
- .HasColumnName("name");
-
- b.Property("PoolId")
- .HasColumnType("uuid")
- .HasColumnName("pool_id");
-
- b.Property>("SensitiveMarks")
- .HasColumnType("jsonb")
- .HasColumnName("sensitive_marks");
-
- b.Property("Size")
- .HasColumnType("bigint")
- .HasColumnName("size");
-
- b.Property("StorageId")
- .HasMaxLength(32)
- .HasColumnType("character varying(32)")
- .HasColumnName("storage_id");
-
- b.Property("StorageUrl")
- .HasMaxLength(4096)
- .HasColumnType("character varying(4096)")
- .HasColumnName("storage_url");
-
- b.Property("UpdatedAt")
- .HasColumnType("timestamp with time zone")
- .HasColumnName("updated_at");
-
- b.Property("UploadedAt")
- .HasColumnType("timestamp with time zone")
- .HasColumnName("uploaded_at");
-
- b.Property("UploadedTo")
- .HasMaxLength(128)
- .HasColumnType("character varying(128)")
- .HasColumnName("uploaded_to");
-
- b.Property>("UserMeta")
- .HasColumnType("jsonb")
- .HasColumnName("user_meta");
-
- b.HasKey("Id")
- .HasName("pk_files");
-
- b.HasIndex("PoolId")
- .HasDatabaseName("ix_files_pool_id");
-
- b.ToTable("files", (string)null);
- });
-
- modelBuilder.Entity("DysonNetwork.Drive.Storage.CloudFileReference", b =>
- {
- b.Property("Id")
- .ValueGeneratedOnAdd()
- .HasColumnType("uuid")
- .HasColumnName("id");
-
- b.Property("CreatedAt")
- .HasColumnType("timestamp with time zone")
- .HasColumnName("created_at");
-
- b.Property("DeletedAt")
- .HasColumnType("timestamp with time zone")
- .HasColumnName("deleted_at");
-
- b.Property("ExpiredAt")
- .HasColumnType("timestamp with time zone")
- .HasColumnName("expired_at");
-
- b.Property("FileId")
- .IsRequired()
- .HasMaxLength(32)
- .HasColumnType("character varying(32)")
- .HasColumnName("file_id");
-
- b.Property("ResourceId")
- .IsRequired()
- .HasMaxLength(1024)
- .HasColumnType("character varying(1024)")
- .HasColumnName("resource_id");
-
- b.Property("UpdatedAt")
- .HasColumnType("timestamp with time zone")
- .HasColumnName("updated_at");
-
- b.Property("Usage")
- .IsRequired()
- .HasMaxLength(1024)
- .HasColumnType("character varying(1024)")
- .HasColumnName("usage");
-
- b.HasKey("Id")
- .HasName("pk_file_references");
-
- b.HasIndex("FileId")
- .HasDatabaseName("ix_file_references_file_id");
-
- b.ToTable("file_references", (string)null);
- });
-
- modelBuilder.Entity("DysonNetwork.Drive.Storage.FilePool", b =>
- {
- b.Property("Id")
- .ValueGeneratedOnAdd()
- .HasColumnType("uuid")
- .HasColumnName("id");
-
- b.Property("AllowAnonymous")
- .HasColumnType("boolean")
- .HasColumnName("allow_anonymous");
-
- b.Property("AllowEncryption")
- .HasColumnType("boolean")
- .HasColumnName("allow_encryption");
-
- b.Property("BillingConfig")
- .IsRequired()
- .HasColumnType("jsonb")
- .HasColumnName("billing_config");
-
- b.Property("CreatedAt")
- .HasColumnType("timestamp with time zone")
- .HasColumnName("created_at");
-
- b.Property("DeletedAt")
- .HasColumnType("timestamp with time zone")
- .HasColumnName("deleted_at");
-
- b.Property("Name")
- .IsRequired()
- .HasMaxLength(1024)
- .HasColumnType("character varying(1024)")
- .HasColumnName("name");
-
- b.Property("NoMetadata")
- .HasColumnType("boolean")
- .HasColumnName("no_metadata");
-
- b.Property("NoOptimization")
- .HasColumnType("boolean")
- .HasColumnName("no_optimization");
-
- b.Property("RequirePrivilege")
- .HasColumnType("integer")
- .HasColumnName("require_privilege");
-
- b.Property("StorageConfig")
- .IsRequired()
- .HasColumnType("jsonb")
- .HasColumnName("storage_config");
-
- b.Property("UpdatedAt")
- .HasColumnType("timestamp with time zone")
- .HasColumnName("updated_at");
-
- b.HasKey("Id")
- .HasName("pk_pools");
-
- b.ToTable("pools", (string)null);
- });
-
- modelBuilder.Entity("DysonNetwork.Drive.Storage.CloudFile", b =>
- {
- b.HasOne("DysonNetwork.Drive.Storage.FilePool", "Pool")
- .WithMany()
- .HasForeignKey("PoolId")
- .HasConstraintName("fk_files_pools_pool_id");
-
- b.Navigation("Pool");
- });
-
- modelBuilder.Entity("DysonNetwork.Drive.Storage.CloudFileReference", b =>
- {
- b.HasOne("DysonNetwork.Drive.Storage.CloudFile", "File")
- .WithMany()
- .HasForeignKey("FileId")
- .OnDelete(DeleteBehavior.Cascade)
- .IsRequired()
- .HasConstraintName("fk_file_references_files_file_id");
-
- b.Navigation("File");
- });
-#pragma warning restore 612, 618
- }
- }
-}
diff --git a/DysonNetwork.Drive/Migrations/20250725183846_EnrichCloudPoolConfigure.cs b/DysonNetwork.Drive/Migrations/20250725183846_EnrichCloudPoolConfigure.cs
deleted file mode 100644
index fe6463b..0000000
--- a/DysonNetwork.Drive/Migrations/20250725183846_EnrichCloudPoolConfigure.cs
+++ /dev/null
@@ -1,73 +0,0 @@
-using Microsoft.EntityFrameworkCore.Migrations;
-
-#nullable disable
-
-namespace DysonNetwork.Drive.Migrations
-{
- ///
- public partial class EnrichCloudPoolConfigure : Migration
- {
- ///
- protected override void Up(MigrationBuilder migrationBuilder)
- {
- migrationBuilder.AddColumn(
- name: "allow_anonymous",
- table: "pools",
- type: "boolean",
- nullable: false,
- defaultValue: false);
-
- migrationBuilder.AddColumn(
- name: "allow_encryption",
- table: "pools",
- type: "boolean",
- nullable: false,
- defaultValue: false);
-
- migrationBuilder.AddColumn(
- name: "no_metadata",
- table: "pools",
- type: "boolean",
- nullable: false,
- defaultValue: false);
-
- migrationBuilder.AddColumn(
- name: "no_optimization",
- table: "pools",
- type: "boolean",
- nullable: false,
- defaultValue: false);
-
- migrationBuilder.AddColumn(
- name: "require_privilege",
- table: "pools",
- type: "integer",
- nullable: false,
- defaultValue: 0);
- }
-
- ///
- protected override void Down(MigrationBuilder migrationBuilder)
- {
- migrationBuilder.DropColumn(
- name: "allow_anonymous",
- table: "pools");
-
- migrationBuilder.DropColumn(
- name: "allow_encryption",
- table: "pools");
-
- migrationBuilder.DropColumn(
- name: "no_metadata",
- table: "pools");
-
- migrationBuilder.DropColumn(
- name: "no_optimization",
- table: "pools");
-
- migrationBuilder.DropColumn(
- name: "require_privilege",
- table: "pools");
- }
- }
-}
diff --git a/DysonNetwork.Drive/Migrations/20250725184107_NullableFileMeta.Designer.cs b/DysonNetwork.Drive/Migrations/20250725184107_NullableFileMeta.Designer.cs
deleted file mode 100644
index 8f18dd3..0000000
--- a/DysonNetwork.Drive/Migrations/20250725184107_NullableFileMeta.Designer.cs
+++ /dev/null
@@ -1,276 +0,0 @@
-//
-using System;
-using System.Collections.Generic;
-using DysonNetwork.Drive;
-using DysonNetwork.Drive.Storage;
-using DysonNetwork.Shared.Data;
-using Microsoft.EntityFrameworkCore;
-using Microsoft.EntityFrameworkCore.Infrastructure;
-using Microsoft.EntityFrameworkCore.Migrations;
-using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
-using NodaTime;
-using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
-
-#nullable disable
-
-namespace DysonNetwork.Drive.Migrations
-{
- [DbContext(typeof(AppDatabase))]
- [Migration("20250725184107_NullableFileMeta")]
- partial class NullableFileMeta
- {
- ///
- protected override void BuildTargetModel(ModelBuilder modelBuilder)
- {
-#pragma warning disable 612, 618
- modelBuilder
- .HasAnnotation("ProductVersion", "9.0.7")
- .HasAnnotation("Relational:MaxIdentifierLength", 63);
-
- NpgsqlModelBuilderExtensions.HasPostgresExtension(modelBuilder, "postgis");
- NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
-
- modelBuilder.Entity("DysonNetwork.Drive.Storage.CloudFile", b =>
- {
- b.Property("Id")
- .HasMaxLength(32)
- .HasColumnType("character varying(32)")
- .HasColumnName("id");
-
- b.Property("AccountId")
- .HasColumnType("uuid")
- .HasColumnName("account_id");
-
- b.Property("CreatedAt")
- .HasColumnType("timestamp with time zone")
- .HasColumnName("created_at");
-
- b.Property("DeletedAt")
- .HasColumnType("timestamp with time zone")
- .HasColumnName("deleted_at");
-
- b.Property("Description")
- .HasMaxLength(4096)
- .HasColumnType("character varying(4096)")
- .HasColumnName("description");
-
- b.Property>("FileMeta")
- .HasColumnType("jsonb")
- .HasColumnName("file_meta");
-
- b.Property("HasCompression")
- .HasColumnType("boolean")
- .HasColumnName("has_compression");
-
- b.Property("HasThumbnail")
- .HasColumnType("boolean")
- .HasColumnName("has_thumbnail");
-
- b.Property("Hash")
- .HasMaxLength(256)
- .HasColumnType("character varying(256)")
- .HasColumnName("hash");
-
- b.Property("IsEncrypted")
- .HasColumnType("boolean")
- .HasColumnName("is_encrypted");
-
- b.Property("IsMarkedRecycle")
- .HasColumnType("boolean")
- .HasColumnName("is_marked_recycle");
-
- b.Property("MimeType")
- .HasMaxLength(256)
- .HasColumnType("character varying(256)")
- .HasColumnName("mime_type");
-
- b.Property("Name")
- .IsRequired()
- .HasMaxLength(1024)
- .HasColumnType("character varying(1024)")
- .HasColumnName("name");
-
- b.Property("PoolId")
- .HasColumnType("uuid")
- .HasColumnName("pool_id");
-
- b.Property>("SensitiveMarks")
- .HasColumnType("jsonb")
- .HasColumnName("sensitive_marks");
-
- b.Property("Size")
- .HasColumnType("bigint")
- .HasColumnName("size");
-
- b.Property("StorageId")
- .HasMaxLength(32)
- .HasColumnType("character varying(32)")
- .HasColumnName("storage_id");
-
- b.Property("StorageUrl")
- .HasMaxLength(4096)
- .HasColumnType("character varying(4096)")
- .HasColumnName("storage_url");
-
- b.Property("UpdatedAt")
- .HasColumnType("timestamp with time zone")
- .HasColumnName("updated_at");
-
- b.Property("UploadedAt")
- .HasColumnType("timestamp with time zone")
- .HasColumnName("uploaded_at");
-
- b.Property("UploadedTo")
- .HasMaxLength(128)
- .HasColumnType("character varying(128)")
- .HasColumnName("uploaded_to");
-
- b.Property>("UserMeta")
- .HasColumnType("jsonb")
- .HasColumnName("user_meta");
-
- b.HasKey("Id")
- .HasName("pk_files");
-
- b.HasIndex("PoolId")
- .HasDatabaseName("ix_files_pool_id");
-
- b.ToTable("files", (string)null);
- });
-
- modelBuilder.Entity("DysonNetwork.Drive.Storage.CloudFileReference", b =>
- {
- b.Property("Id")
- .ValueGeneratedOnAdd()
- .HasColumnType("uuid")
- .HasColumnName("id");
-
- b.Property("CreatedAt")
- .HasColumnType("timestamp with time zone")
- .HasColumnName("created_at");
-
- b.Property("DeletedAt")
- .HasColumnType("timestamp with time zone")
- .HasColumnName("deleted_at");
-
- b.Property("ExpiredAt")
- .HasColumnType("timestamp with time zone")
- .HasColumnName("expired_at");
-
- b.Property("FileId")
- .IsRequired()
- .HasMaxLength(32)
- .HasColumnType("character varying(32)")
- .HasColumnName("file_id");
-
- b.Property("ResourceId")
- .IsRequired()
- .HasMaxLength(1024)
- .HasColumnType("character varying(1024)")
- .HasColumnName("resource_id");
-
- b.Property("UpdatedAt")
- .HasColumnType("timestamp with time zone")
- .HasColumnName("updated_at");
-
- b.Property("Usage")
- .IsRequired()
- .HasMaxLength(1024)
- .HasColumnType("character varying(1024)")
- .HasColumnName("usage");
-
- b.HasKey("Id")
- .HasName("pk_file_references");
-
- b.HasIndex("FileId")
- .HasDatabaseName("ix_file_references_file_id");
-
- b.ToTable("file_references", (string)null);
- });
-
- modelBuilder.Entity("DysonNetwork.Drive.Storage.FilePool", b =>
- {
- b.Property("Id")
- .ValueGeneratedOnAdd()
- .HasColumnType("uuid")
- .HasColumnName("id");
-
- b.Property("AllowAnonymous")
- .HasColumnType("boolean")
- .HasColumnName("allow_anonymous");
-
- b.Property("AllowEncryption")
- .HasColumnType("boolean")
- .HasColumnName("allow_encryption");
-
- b.Property("BillingConfig")
- .IsRequired()
- .HasColumnType("jsonb")
- .HasColumnName("billing_config");
-
- b.Property("CreatedAt")
- .HasColumnType("timestamp with time zone")
- .HasColumnName("created_at");
-
- b.Property("DeletedAt")
- .HasColumnType("timestamp with time zone")
- .HasColumnName("deleted_at");
-
- b.Property("Name")
- .IsRequired()
- .HasMaxLength(1024)
- .HasColumnType("character varying(1024)")
- .HasColumnName("name");
-
- b.Property("NoMetadata")
- .HasColumnType("boolean")
- .HasColumnName("no_metadata");
-
- b.Property("NoOptimization")
- .HasColumnType("boolean")
- .HasColumnName("no_optimization");
-
- b.Property("RequirePrivilege")
- .HasColumnType("integer")
- .HasColumnName("require_privilege");
-
- b.Property("StorageConfig")
- .IsRequired()
- .HasColumnType("jsonb")
- .HasColumnName("storage_config");
-
- b.Property("UpdatedAt")
- .HasColumnType("timestamp with time zone")
- .HasColumnName("updated_at");
-
- b.HasKey("Id")
- .HasName("pk_pools");
-
- b.ToTable("pools", (string)null);
- });
-
- modelBuilder.Entity("DysonNetwork.Drive.Storage.CloudFile", b =>
- {
- b.HasOne("DysonNetwork.Drive.Storage.FilePool", "Pool")
- .WithMany()
- .HasForeignKey("PoolId")
- .HasConstraintName("fk_files_pools_pool_id");
-
- b.Navigation("Pool");
- });
-
- modelBuilder.Entity("DysonNetwork.Drive.Storage.CloudFileReference", b =>
- {
- b.HasOne("DysonNetwork.Drive.Storage.CloudFile", "File")
- .WithMany()
- .HasForeignKey("FileId")
- .OnDelete(DeleteBehavior.Cascade)
- .IsRequired()
- .HasConstraintName("fk_file_references_files_file_id");
-
- b.Navigation("File");
- });
-#pragma warning restore 612, 618
- }
- }
-}
diff --git a/DysonNetwork.Drive/Migrations/20250725184107_NullableFileMeta.cs b/DysonNetwork.Drive/Migrations/20250725184107_NullableFileMeta.cs
deleted file mode 100644
index d71f8e6..0000000
--- a/DysonNetwork.Drive/Migrations/20250725184107_NullableFileMeta.cs
+++ /dev/null
@@ -1,36 +0,0 @@
-using System.Collections.Generic;
-using Microsoft.EntityFrameworkCore.Migrations;
-
-#nullable disable
-
-namespace DysonNetwork.Drive.Migrations
-{
- ///
- public partial class NullableFileMeta : Migration
- {
- ///
- protected override void Up(MigrationBuilder migrationBuilder)
- {
- migrationBuilder.AlterColumn>(
- name: "file_meta",
- table: "files",
- type: "jsonb",
- nullable: true,
- oldClrType: typeof(Dictionary),
- oldType: "jsonb");
- }
-
- ///
- protected override void Down(MigrationBuilder migrationBuilder)
- {
- migrationBuilder.AlterColumn>(
- name: "file_meta",
- table: "files",
- type: "jsonb",
- nullable: false,
- oldClrType: typeof(Dictionary),
- oldType: "jsonb",
- oldNullable: true);
- }
- }
-}
diff --git a/DysonNetwork.Drive/Migrations/20250726034305_FilePoolAuthorize.Designer.cs b/DysonNetwork.Drive/Migrations/20250726034305_FilePoolAuthorize.Designer.cs
deleted file mode 100644
index 0232deb..0000000
--- a/DysonNetwork.Drive/Migrations/20250726034305_FilePoolAuthorize.Designer.cs
+++ /dev/null
@@ -1,288 +0,0 @@
-//
-using System;
-using System.Collections.Generic;
-using DysonNetwork.Drive;
-using DysonNetwork.Drive.Storage;
-using DysonNetwork.Shared.Data;
-using Microsoft.EntityFrameworkCore;
-using Microsoft.EntityFrameworkCore.Infrastructure;
-using Microsoft.EntityFrameworkCore.Migrations;
-using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
-using NodaTime;
-using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
-
-#nullable disable
-
-namespace DysonNetwork.Drive.Migrations
-{
- [DbContext(typeof(AppDatabase))]
- [Migration("20250726034305_FilePoolAuthorize")]
- partial class FilePoolAuthorize
- {
- ///
- protected override void BuildTargetModel(ModelBuilder modelBuilder)
- {
-#pragma warning disable 612, 618
- modelBuilder
- .HasAnnotation("ProductVersion", "9.0.7")
- .HasAnnotation("Relational:MaxIdentifierLength", 63);
-
- NpgsqlModelBuilderExtensions.HasPostgresExtension(modelBuilder, "postgis");
- NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
-
- modelBuilder.Entity("DysonNetwork.Drive.Storage.CloudFile", b =>
- {
- b.Property("Id")
- .HasMaxLength(32)
- .HasColumnType("character varying(32)")
- .HasColumnName("id");
-
- b.Property("AccountId")
- .HasColumnType("uuid")
- .HasColumnName("account_id");
-
- b.Property("CreatedAt")
- .HasColumnType("timestamp with time zone")
- .HasColumnName("created_at");
-
- b.Property("DeletedAt")
- .HasColumnType("timestamp with time zone")
- .HasColumnName("deleted_at");
-
- b.Property("Description")
- .HasMaxLength(4096)
- .HasColumnType("character varying(4096)")
- .HasColumnName("description");
-
- b.Property>("FileMeta")
- .HasColumnType("jsonb")
- .HasColumnName("file_meta");
-
- b.Property("HasCompression")
- .HasColumnType("boolean")
- .HasColumnName("has_compression");
-
- b.Property("HasThumbnail")
- .HasColumnType("boolean")
- .HasColumnName("has_thumbnail");
-
- b.Property("Hash")
- .HasMaxLength(256)
- .HasColumnType("character varying(256)")
- .HasColumnName("hash");
-
- b.Property("IsEncrypted")
- .HasColumnType("boolean")
- .HasColumnName("is_encrypted");
-
- b.Property("IsMarkedRecycle")
- .HasColumnType("boolean")
- .HasColumnName("is_marked_recycle");
-
- b.Property("MimeType")
- .HasMaxLength(256)
- .HasColumnType("character varying(256)")
- .HasColumnName("mime_type");
-
- b.Property("Name")
- .IsRequired()
- .HasMaxLength(1024)
- .HasColumnType("character varying(1024)")
- .HasColumnName("name");
-
- b.Property("PoolId")
- .HasColumnType("uuid")
- .HasColumnName("pool_id");
-
- b.Property>("SensitiveMarks")
- .HasColumnType("jsonb")
- .HasColumnName("sensitive_marks");
-
- b.Property("Size")
- .HasColumnType("bigint")
- .HasColumnName("size");
-
- b.Property("StorageId")
- .HasMaxLength(32)
- .HasColumnType("character varying(32)")
- .HasColumnName("storage_id");
-
- b.Property("StorageUrl")
- .HasMaxLength(4096)
- .HasColumnType("character varying(4096)")
- .HasColumnName("storage_url");
-
- b.Property("UpdatedAt")
- .HasColumnType("timestamp with time zone")
- .HasColumnName("updated_at");
-
- b.Property("UploadedAt")
- .HasColumnType("timestamp with time zone")
- .HasColumnName("uploaded_at");
-
- b.Property("UploadedTo")
- .HasMaxLength(128)
- .HasColumnType("character varying(128)")
- .HasColumnName("uploaded_to");
-
- b.Property>("UserMeta")
- .HasColumnType("jsonb")
- .HasColumnName("user_meta");
-
- b.HasKey("Id")
- .HasName("pk_files");
-
- b.HasIndex("PoolId")
- .HasDatabaseName("ix_files_pool_id");
-
- b.ToTable("files", (string)null);
- });
-
- modelBuilder.Entity("DysonNetwork.Drive.Storage.CloudFileReference", b =>
- {
- b.Property("Id")
- .ValueGeneratedOnAdd()
- .HasColumnType("uuid")
- .HasColumnName("id");
-
- b.Property("CreatedAt")
- .HasColumnType("timestamp with time zone")
- .HasColumnName("created_at");
-
- b.Property("DeletedAt")
- .HasColumnType("timestamp with time zone")
- .HasColumnName("deleted_at");
-
- b.Property("ExpiredAt")
- .HasColumnType("timestamp with time zone")
- .HasColumnName("expired_at");
-
- b.Property("FileId")
- .IsRequired()
- .HasMaxLength(32)
- .HasColumnType("character varying(32)")
- .HasColumnName("file_id");
-
- b.Property("ResourceId")
- .IsRequired()
- .HasMaxLength(1024)
- .HasColumnType("character varying(1024)")
- .HasColumnName("resource_id");
-
- b.Property("UpdatedAt")
- .HasColumnType("timestamp with time zone")
- .HasColumnName("updated_at");
-
- b.Property("Usage")
- .IsRequired()
- .HasMaxLength(1024)
- .HasColumnType("character varying(1024)")
- .HasColumnName("usage");
-
- b.HasKey("Id")
- .HasName("pk_file_references");
-
- b.HasIndex("FileId")
- .HasDatabaseName("ix_file_references_file_id");
-
- b.ToTable("file_references", (string)null);
- });
-
- modelBuilder.Entity("DysonNetwork.Drive.Storage.FilePool", b =>
- {
- b.Property("Id")
- .ValueGeneratedOnAdd()
- .HasColumnType("uuid")
- .HasColumnName("id");
-
- b.Property("AccountId")
- .HasColumnType("uuid")
- .HasColumnName("account_id");
-
- b.Property("AllowAnonymous")
- .HasColumnType("boolean")
- .HasColumnName("allow_anonymous");
-
- b.Property("AllowEncryption")
- .HasColumnType("boolean")
- .HasColumnName("allow_encryption");
-
- b.Property("BillingConfig")
- .IsRequired()
- .HasColumnType("jsonb")
- .HasColumnName("billing_config");
-
- b.Property("CreatedAt")
- .HasColumnType("timestamp with time zone")
- .HasColumnName("created_at");
-
- b.Property("DeletedAt")
- .HasColumnType("timestamp with time zone")
- .HasColumnName("deleted_at");
-
- b.Property("Name")
- .IsRequired()
- .HasMaxLength(1024)
- .HasColumnType("character varying(1024)")
- .HasColumnName("name");
-
- b.Property("NoMetadata")
- .HasColumnType("boolean")
- .HasColumnName("no_metadata");
-
- b.Property("NoOptimization")
- .HasColumnType("boolean")
- .HasColumnName("no_optimization");
-
- b.Property("PublicIndexable")
- .HasColumnType("boolean")
- .HasColumnName("public_indexable");
-
- b.Property("PublicUsable")
- .HasColumnType("boolean")
- .HasColumnName("public_usable");
-
- b.Property("RequirePrivilege")
- .HasColumnType("integer")
- .HasColumnName("require_privilege");
-
- b.Property("StorageConfig")
- .IsRequired()
- .HasColumnType("jsonb")
- .HasColumnName("storage_config");
-
- b.Property("UpdatedAt")
- .HasColumnType("timestamp with time zone")
- .HasColumnName("updated_at");
-
- b.HasKey("Id")
- .HasName("pk_pools");
-
- b.ToTable("pools", (string)null);
- });
-
- modelBuilder.Entity("DysonNetwork.Drive.Storage.CloudFile", b =>
- {
- b.HasOne("DysonNetwork.Drive.Storage.FilePool", "Pool")
- .WithMany()
- .HasForeignKey("PoolId")
- .HasConstraintName("fk_files_pools_pool_id");
-
- b.Navigation("Pool");
- });
-
- modelBuilder.Entity("DysonNetwork.Drive.Storage.CloudFileReference", b =>
- {
- b.HasOne("DysonNetwork.Drive.Storage.CloudFile", "File")
- .WithMany()
- .HasForeignKey("FileId")
- .OnDelete(DeleteBehavior.Cascade)
- .IsRequired()
- .HasConstraintName("fk_file_references_files_file_id");
-
- b.Navigation("File");
- });
-#pragma warning restore 612, 618
- }
- }
-}
diff --git a/DysonNetwork.Drive/Migrations/20250726034305_FilePoolAuthorize.cs b/DysonNetwork.Drive/Migrations/20250726034305_FilePoolAuthorize.cs
deleted file mode 100644
index cae21fc..0000000
--- a/DysonNetwork.Drive/Migrations/20250726034305_FilePoolAuthorize.cs
+++ /dev/null
@@ -1,51 +0,0 @@
-using System;
-using Microsoft.EntityFrameworkCore.Migrations;
-
-#nullable disable
-
-namespace DysonNetwork.Drive.Migrations
-{
- ///
- public partial class FilePoolAuthorize : Migration
- {
- ///
- protected override void Up(MigrationBuilder migrationBuilder)
- {
- migrationBuilder.AddColumn(
- name: "account_id",
- table: "pools",
- type: "uuid",
- nullable: true);
-
- migrationBuilder.AddColumn(
- name: "public_indexable",
- table: "pools",
- type: "boolean",
- nullable: false,
- defaultValue: false);
-
- migrationBuilder.AddColumn(
- name: "public_usable",
- table: "pools",
- type: "boolean",
- nullable: false,
- defaultValue: false);
- }
-
- ///
- protected override void Down(MigrationBuilder migrationBuilder)
- {
- migrationBuilder.DropColumn(
- name: "account_id",
- table: "pools");
-
- migrationBuilder.DropColumn(
- name: "public_indexable",
- table: "pools");
-
- migrationBuilder.DropColumn(
- name: "public_usable",
- table: "pools");
- }
- }
-}
diff --git a/DysonNetwork.Drive/Migrations/20250725170254_AddCloudFileEncrypt.Designer.cs b/DysonNetwork.Drive/Migrations/20250726103203_AddCloudFilePool.Designer.cs
similarity index 96%
rename from DysonNetwork.Drive/Migrations/20250725170254_AddCloudFileEncrypt.Designer.cs
rename to DysonNetwork.Drive/Migrations/20250726103203_AddCloudFilePool.Designer.cs
index bcb7d8e..b08c290 100644
--- a/DysonNetwork.Drive/Migrations/20250725170254_AddCloudFileEncrypt.Designer.cs
+++ b/DysonNetwork.Drive/Migrations/20250726103203_AddCloudFilePool.Designer.cs
@@ -16,8 +16,8 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
namespace DysonNetwork.Drive.Migrations
{
[DbContext(typeof(AppDatabase))]
- [Migration("20250725170254_AddCloudFileEncrypt")]
- partial class AddCloudFileEncrypt
+ [Migration("20250726103203_AddCloudFilePool")]
+ partial class AddCloudFilePool
{
///
protected override void BuildTargetModel(ModelBuilder modelBuilder)
@@ -55,7 +55,6 @@ namespace DysonNetwork.Drive.Migrations
.HasColumnName("description");
b.Property>("FileMeta")
- .IsRequired()
.HasColumnType("jsonb")
.HasColumnName("file_meta");
@@ -196,6 +195,10 @@ namespace DysonNetwork.Drive.Migrations
.HasColumnType("uuid")
.HasColumnName("id");
+ b.Property("AccountId")
+ .HasColumnType("uuid")
+ .HasColumnName("account_id");
+
b.Property("BillingConfig")
.IsRequired()
.HasColumnType("jsonb")
@@ -215,6 +218,11 @@ namespace DysonNetwork.Drive.Migrations
.HasColumnType("character varying(1024)")
.HasColumnName("name");
+ b.Property("PolicyConfig")
+ .IsRequired()
+ .HasColumnType("jsonb")
+ .HasColumnName("policy_config");
+
b.Property("StorageConfig")
.IsRequired()
.HasColumnType("jsonb")
diff --git a/DysonNetwork.Drive/Migrations/20250725163615_AddCloudFilePool.cs b/DysonNetwork.Drive/Migrations/20250726103203_AddCloudFilePool.cs
similarity index 62%
rename from DysonNetwork.Drive/Migrations/20250725163615_AddCloudFilePool.cs
rename to DysonNetwork.Drive/Migrations/20250726103203_AddCloudFilePool.cs
index 64ee4ab..d06532f 100644
--- a/DysonNetwork.Drive/Migrations/20250725163615_AddCloudFilePool.cs
+++ b/DysonNetwork.Drive/Migrations/20250726103203_AddCloudFilePool.cs
@@ -1,4 +1,5 @@
using System;
+using System.Collections.Generic;
using DysonNetwork.Drive.Storage;
using Microsoft.EntityFrameworkCore.Migrations;
using NodaTime;
@@ -13,6 +14,28 @@ namespace DysonNetwork.Drive.Migrations
///
protected override void Up(MigrationBuilder migrationBuilder)
{
+ migrationBuilder.AlterColumn>(
+ name: "file_meta",
+ table: "files",
+ type: "jsonb",
+ nullable: true,
+ oldClrType: typeof(Dictionary),
+ oldType: "jsonb");
+
+ migrationBuilder.AddColumn(
+ name: "has_thumbnail",
+ table: "files",
+ type: "boolean",
+ nullable: false,
+ defaultValue: false);
+
+ migrationBuilder.AddColumn(
+ name: "is_encrypted",
+ table: "files",
+ type: "boolean",
+ nullable: false,
+ defaultValue: false);
+
migrationBuilder.AddColumn(
name: "pool_id",
table: "files",
@@ -27,6 +50,8 @@ namespace DysonNetwork.Drive.Migrations
name = table.Column(type: "character varying(1024)", maxLength: 1024, nullable: false),
storage_config = table.Column(type: "jsonb", nullable: false),
billing_config = table.Column(type: "jsonb", nullable: false),
+ policy_config = table.Column(type: "jsonb", nullable: false),
+ account_id = table.Column(type: "uuid", nullable: true),
created_at = table.Column(type: "timestamp with time zone", nullable: false),
updated_at = table.Column(type: "timestamp with time zone", nullable: false),
deleted_at = table.Column(type: "timestamp with time zone", nullable: true)
@@ -63,9 +88,26 @@ namespace DysonNetwork.Drive.Migrations
name: "ix_files_pool_id",
table: "files");
+ migrationBuilder.DropColumn(
+ name: "has_thumbnail",
+ table: "files");
+
+ migrationBuilder.DropColumn(
+ name: "is_encrypted",
+ table: "files");
+
migrationBuilder.DropColumn(
name: "pool_id",
table: "files");
+
+ migrationBuilder.AlterColumn>(
+ name: "file_meta",
+ table: "files",
+ type: "jsonb",
+ nullable: false,
+ oldClrType: typeof(Dictionary),
+ oldType: "jsonb",
+ oldNullable: true);
}
}
}
diff --git a/DysonNetwork.Drive/Migrations/AppDatabaseModelSnapshot.cs b/DysonNetwork.Drive/Migrations/AppDatabaseModelSnapshot.cs
index 4328b3b..44cedb3 100644
--- a/DysonNetwork.Drive/Migrations/AppDatabaseModelSnapshot.cs
+++ b/DysonNetwork.Drive/Migrations/AppDatabaseModelSnapshot.cs
@@ -196,14 +196,6 @@ namespace DysonNetwork.Drive.Migrations
.HasColumnType("uuid")
.HasColumnName("account_id");
- b.Property("AllowAnonymous")
- .HasColumnType("boolean")
- .HasColumnName("allow_anonymous");
-
- b.Property("AllowEncryption")
- .HasColumnType("boolean")
- .HasColumnName("allow_encryption");
-
b.Property("BillingConfig")
.IsRequired()
.HasColumnType("jsonb")
@@ -223,25 +215,10 @@ namespace DysonNetwork.Drive.Migrations
.HasColumnType("character varying(1024)")
.HasColumnName("name");
- b.Property("NoMetadata")
- .HasColumnType("boolean")
- .HasColumnName("no_metadata");
-
- b.Property("NoOptimization")
- .HasColumnType("boolean")
- .HasColumnName("no_optimization");
-
- b.Property("PublicIndexable")
- .HasColumnType("boolean")
- .HasColumnName("public_indexable");
-
- b.Property("PublicUsable")
- .HasColumnType("boolean")
- .HasColumnName("public_usable");
-
- b.Property("RequirePrivilege")
- .HasColumnType("integer")
- .HasColumnName("require_privilege");
+ b.Property("PolicyConfig")
+ .IsRequired()
+ .HasColumnType("jsonb")
+ .HasColumnName("policy_config");
b.Property("StorageConfig")
.IsRequired()
diff --git a/DysonNetwork.Drive/Startup/ServiceCollectionExtensions.cs b/DysonNetwork.Drive/Startup/ServiceCollectionExtensions.cs
index c848be3..0dc0459 100644
--- a/DysonNetwork.Drive/Startup/ServiceCollectionExtensions.cs
+++ b/DysonNetwork.Drive/Startup/ServiceCollectionExtensions.cs
@@ -138,6 +138,7 @@ public static class ServiceCollectionExtensions
{
services.AddScoped();
services.AddScoped();
+ services.AddScoped();
return services;
}
diff --git a/DysonNetwork.Drive/Storage/FileController.cs b/DysonNetwork.Drive/Storage/FileController.cs
index 036f55a..c07835f 100644
--- a/DysonNetwork.Drive/Storage/FileController.cs
+++ b/DysonNetwork.Drive/Storage/FileController.cs
@@ -1,4 +1,5 @@
using DysonNetwork.Shared.Proto;
+using Grpc.Core;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
@@ -45,7 +46,14 @@ public class FileController(
return PhysicalFile(filePath, file.MimeType ?? "application/octet-stream", file.Name);
}
- var dest = await fs.GetRemoteStorageConfig(file.PoolId.Value);
+ var pool = await fs.GetPoolAsync(file.PoolId.Value);
+ if (pool is null) return StatusCode(StatusCodes.Status410Gone, "The pool of the file no longer exists or not accessible.");
+ var dest = pool.StorageConfig;
+
+ if (!pool.PolicyConfig.AllowAnonymous)
+ if(HttpContext.Items["CurrentUser"] is not Account currentUser) return Unauthorized();
+ // TODO: Provide ability to add access log
+
var fileName = string.IsNullOrWhiteSpace(file.StorageId) ? file.Id : file.StorageId;
if (!original && file.HasCompression)
@@ -115,7 +123,7 @@ public class FileController(
[HttpGet("{id}/info")]
public async Task> GetFileInfo(string id)
{
- var file = await db.Files.FindAsync(id);
+ var file = await fs.GetFileAsync(id);
if (file is null) return NotFound();
return file;
diff --git a/DysonNetwork.Drive/Storage/FilePool.cs b/DysonNetwork.Drive/Storage/FilePool.cs
index 0054984..47c3522 100644
--- a/DysonNetwork.Drive/Storage/FilePool.cs
+++ b/DysonNetwork.Drive/Storage/FilePool.cs
@@ -24,19 +24,26 @@ public class BillingConfig
public double CostMultiplier { get; set; } = 1.0;
}
-public class FilePool : ModelBase, IIdentifiedResource
+public class PolicyConfig
{
- public Guid Id { get; set; } = Guid.NewGuid();
- [MaxLength(1024)] public string Name { get; set; } = string.Empty;
- [Column(TypeName = "jsonb")] public RemoteStorageConfig StorageConfig { get; set; } = new();
- [Column(TypeName = "jsonb")] public BillingConfig BillingConfig { get; set; } = new();
public bool PublicIndexable { get; set; } = false;
public bool PublicUsable { get; set; } = false;
public bool NoOptimization { get; set; } = false;
public bool NoMetadata { get; set; } = false;
public bool AllowEncryption { get; set; } = true;
public bool AllowAnonymous { get; set; } = true;
- public int RequirePrivilege { get; set; } = 0;
+ public List? AcceptTypes { get; set; }
+ public long? MaxFileSize { get; set; }
+ public int RequirePrivilege { get; set; } = 0;
+}
+
+public class FilePool : ModelBase, IIdentifiedResource
+{
+ public Guid Id { get; set; } = Guid.NewGuid();
+ [MaxLength(1024)] public string Name { get; set; } = string.Empty;
+ [Column(TypeName = "jsonb")] public RemoteStorageConfig StorageConfig { get; set; } = new();
+ [Column(TypeName = "jsonb")] public BillingConfig BillingConfig { get; set; } = new();
+ [Column(TypeName = "jsonb")] public PolicyConfig PolicyConfig { get; set; } = new();
public Guid? AccountId { get; set; }
diff --git a/DysonNetwork.Drive/Storage/FilePoolController.cs b/DysonNetwork.Drive/Storage/FilePoolController.cs
index 515f054..5fed999 100644
--- a/DysonNetwork.Drive/Storage/FilePoolController.cs
+++ b/DysonNetwork.Drive/Storage/FilePoolController.cs
@@ -17,7 +17,7 @@ public class FilePoolController(AppDatabase db) : ControllerBase
var accountId = Guid.Parse(currentUser.Id);
var pools = await db.Pools
- .Where(p => p.PublicUsable || p.AccountId == accountId)
+ .Where(p => p.PolicyConfig.PublicUsable || p.AccountId == accountId)
.ToListAsync();
return Ok(pools);
diff --git a/DysonNetwork.Drive/Storage/FileService.cs b/DysonNetwork.Drive/Storage/FileService.cs
index a0b01bf..289eab7 100644
--- a/DysonNetwork.Drive/Storage/FileService.cs
+++ b/DysonNetwork.Drive/Storage/FileService.cs
@@ -45,6 +45,7 @@ public class FileService(
var file = await db.Files
.Where(f => f.Id == fileId)
+ .Include(f => f.Pool)
.FirstOrDefaultAsync();
if (file != null)
@@ -75,6 +76,7 @@ public class FileService(
{
var dbFiles = await db.Files
.Where(f => uncachedIds.Contains(f.Id))
+ .Include(f => f.Pool)
.ToListAsync();
// Add to cache
@@ -118,7 +120,7 @@ public class FileService(
if (!string.IsNullOrWhiteSpace(encryptPassword))
{
- if (!pool.AllowEncryption) throw new InvalidOperationException("Encryption is not allowed in this pool");
+ if (!pool.PolicyConfig.AllowEncryption) throw new InvalidOperationException("Encryption is not allowed in this pool");
var encryptedPath = Path.Combine(Path.GetTempPath(), $"{fileId}.encrypted");
FileEncryptor.EncryptFile(ogFilePath, encryptedPath, encryptPassword);
File.Delete(ogFilePath); // Delete original unencrypted
@@ -136,7 +138,7 @@ public class FileService(
Size = fileSize,
Hash = hash,
AccountId = Guid.Parse(account.Id),
- IsEncrypted = !string.IsNullOrWhiteSpace(encryptPassword) && pool.AllowEncryption
+ IsEncrypted = !string.IsNullOrWhiteSpace(encryptPassword) && pool.PolicyConfig.AllowEncryption
};
var existingFile = await db.Files.AsNoTracking().FirstOrDefaultAsync(f => f.Hash == hash);
@@ -160,7 +162,7 @@ public class FileService(
}
// Extract metadata on the current thread for a faster initial response
- if (!pool.NoMetadata)
+ if (!pool.PolicyConfig.NoMetadata)
await ExtractMetadataAsync(file, ogFilePath, stream);
db.Files.Add(file);
@@ -302,7 +304,7 @@ public class FileService(
{
logger.LogInformation("Processing file {FileId} in background...", fileId);
- if (!pool.NoOptimization)
+ if (!pool.PolicyConfig.NoOptimization)
switch (contentType.Split('/')[0])
{
case "image" when !AnimatedImageTypes.Contains(contentType):
diff --git a/DysonNetwork.Drive/Storage/TusService.cs b/DysonNetwork.Drive/Storage/TusService.cs
index 5475e76..93fd74e 100644
--- a/DysonNetwork.Drive/Storage/TusService.cs
+++ b/DysonNetwork.Drive/Storage/TusService.cs
@@ -1,12 +1,14 @@
using System.Net;
using System.Text;
using System.Text.Json;
+using DysonNetwork.Shared.Auth;
using DysonNetwork.Shared.Proto;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using tusdotnet.Interfaces;
using tusdotnet.Models;
using tusdotnet.Models.Configuration;
+using tusdotnet.Stores;
namespace DysonNetwork.Drive.Storage;
@@ -29,25 +31,63 @@ public abstract class TusService
}
var httpContext = eventContext.HttpContext;
- if (httpContext.Items["CurrentUser"] is not Account user)
+ if (httpContext.Items["CurrentUser"] is not Account currentUser)
{
eventContext.FailRequest(HttpStatusCode.Unauthorized);
return;
}
- if (!user.IsSuperuser)
+ if (eventContext.Intent != IntentType.CreateFile) return;
+
+ using var scope = httpContext.RequestServices.CreateScope();
+
+ if (!currentUser.IsSuperuser)
{
- using var scope = httpContext.RequestServices.CreateScope();
var pm = scope.ServiceProvider.GetRequiredService();
var allowed = await pm.HasPermissionAsync(new HasPermissionRequest
- { Actor = $"user:{user.Id}", Area = "global", Key = "files.create" });
+ { Actor = $"user:{currentUser.Id}", Area = "global", Key = "files.create" });
if (!allowed.HasPermission)
eventContext.FailRequest(HttpStatusCode.Forbidden);
}
var filePool = httpContext.Request.Headers["X-FilePool"].FirstOrDefault();
- if (!string.IsNullOrEmpty(filePool) && !Guid.TryParse(filePool, out _))
+ if (string.IsNullOrEmpty(filePool)) filePool = configuration["Storage:PreferredRemote"];
+ if (!Guid.TryParse(filePool, out _))
+ {
eventContext.FailRequest(HttpStatusCode.BadRequest, "Invalid file pool id");
+ return;
+ }
+
+ var fs = scope.ServiceProvider.GetRequiredService();
+ var pool = await fs.GetPoolAsync(Guid.Parse(filePool!));
+ if (pool is null)
+ {
+ eventContext.FailRequest(HttpStatusCode.BadRequest, "Pool not found");
+ return;
+ }
+
+ if (pool.PolicyConfig.RequirePrivilege > 0)
+ {
+ if (currentUser.PerkSubscription is null)
+ {
+ eventContext.FailRequest(
+ HttpStatusCode.Forbidden,
+ $"You need to have join the Stellar Program tier {pool.PolicyConfig.RequirePrivilege} to use this pool"
+ );
+ return;
+ }
+
+ var privilege =
+ PerkSubscriptionPrivilege.GetPrivilegeFromIdentifier(currentUser.PerkSubscription.Identifier);
+ if (privilege < pool.PolicyConfig.RequirePrivilege)
+ {
+ eventContext.FailRequest(
+ HttpStatusCode.Forbidden,
+ $"You need to have join the Stellar Program tier {pool.PolicyConfig.RequirePrivilege} to use this pool"
+ );
+ return;
+ }
+ }
},
OnFileCompleteAsync = async eventContext =>
{
@@ -72,25 +112,101 @@ public abstract class TusService
if (string.IsNullOrEmpty(filePool))
filePool = configuration["Storage:PreferredRemote"];
- var fileService = services.GetRequiredService();
- var info = await fileService.ProcessNewFileAsync(
- user,
- file.Id,
- filePool,
- fileStream,
- fileName,
- contentType,
- encryptPassword
- );
+ try
+ {
+ var fileService = services.GetRequiredService();
+ var info = await fileService.ProcessNewFileAsync(
+ user,
+ file.Id,
+ filePool!,
+ fileStream,
+ fileName,
+ contentType,
+ encryptPassword
+ );
- using var finalScope = eventContext.HttpContext.RequestServices.CreateScope();
- var jsonOptions = finalScope.ServiceProvider.GetRequiredService>().Value
- .JsonSerializerOptions;
- var infoJson = JsonSerializer.Serialize(info, jsonOptions);
- eventContext.HttpContext.Response.Headers.Append("X-FileInfo", infoJson);
+ using var finalScope = eventContext.HttpContext.RequestServices.CreateScope();
+ var jsonOptions = finalScope.ServiceProvider.GetRequiredService>().Value
+ .JsonSerializerOptions;
+ var infoJson = JsonSerializer.Serialize(info, jsonOptions);
+ eventContext.HttpContext.Response.Headers.Append("X-FileInfo", infoJson);
+ }
+ catch (Exception ex)
+ {
+ eventContext.HttpContext.Response.StatusCode = StatusCodes.Status400BadRequest;
+ await eventContext.HttpContext.Response.WriteAsync(ex.Message);
+ if (eventContext.Store is TusDiskStore disk)
+ await disk.DeleteFileAsync(file.Id, eventContext.CancellationToken);
+ }
+ finally
+ {
+ // Dispose the stream after all processing is complete
+ await fileStream.DisposeAsync();
+ }
+ },
+ OnBeforeCreateAsync = async eventContext =>
+ {
+ var filePool = eventContext.HttpContext.Request.Headers["X-FilePool"].FirstOrDefault();
+ if (string.IsNullOrEmpty(filePool)) filePool = configuration["Storage:PreferredRemote"];
+ if (!Guid.TryParse(filePool, out _))
+ {
+ eventContext.FailRequest(HttpStatusCode.BadRequest, "Invalid file pool id");
+ return;
+ }
- // Dispose the stream after all processing is complete
- await fileStream.DisposeAsync();
+ var metadata = eventContext.Metadata;
+ var contentType = metadata.TryGetValue("content-type", out var ct) ? ct.GetString(Encoding.UTF8) : null;
+
+ var scope = eventContext.HttpContext.RequestServices.CreateScope();
+
+ var rejected = false;
+
+ var fs = scope.ServiceProvider.GetRequiredService();
+ var pool = await fs.GetPoolAsync(Guid.Parse(filePool!));
+ if (pool is null)
+ {
+ eventContext.FailRequest(HttpStatusCode.BadRequest, "Pool not found");
+ rejected = true;
+ }
+
+ var logger = scope.ServiceProvider.GetRequiredService>();
+
+ // Do the policy check
+ var policy = pool!.PolicyConfig;
+ if (!rejected && policy.AcceptTypes is not null)
+ {
+ if (contentType is null)
+ {
+ eventContext.FailRequest(
+ HttpStatusCode.BadRequest,
+ "Content type is required by the pool's policy"
+ );
+ rejected = true;
+ }
+ else if (!policy.AcceptTypes.Contains(contentType))
+ {
+ eventContext.FailRequest(
+ HttpStatusCode.Forbidden,
+ $"Content type {contentType} is not allowed by the pool's policy"
+ );
+ rejected = true;
+ }
+ }
+
+ if (!rejected && policy.MaxFileSize is not null)
+ {
+ if (eventContext.UploadLength > policy.MaxFileSize)
+ {
+ eventContext.FailRequest(
+ HttpStatusCode.Forbidden,
+ $"File size {eventContext.UploadLength} is larger than the pool's maximum file size {policy.MaxFileSize}"
+ );
+ rejected = true;
+ }
+ }
+
+ if (rejected)
+ logger.LogInformation("File rejected #{FileId}", eventContext.FileId);
},
OnCreateCompleteAsync = eventContext =>
{
diff --git a/DysonNetwork.Shared/Auth/PerkSubscriptionPrivilege.cs b/DysonNetwork.Shared/Auth/PerkSubscriptionPrivilege.cs
new file mode 100644
index 0000000..74f40ea
--- /dev/null
+++ b/DysonNetwork.Shared/Auth/PerkSubscriptionPrivilege.cs
@@ -0,0 +1,16 @@
+namespace DysonNetwork.Shared.Auth;
+
+public static class PerkSubscriptionPrivilege
+{
+ public static int GetPrivilegeFromIdentifier(string identifier)
+ {
+ // Reference from the DysonNetwork.Pass
+ return identifier switch
+ {
+ "solian.stellar.primary" => 1,
+ "solian.stellar.nova" => 2,
+ "solian.stellar.supernova" => 3,
+ _ => 0
+ };
+ }
+}
\ No newline at end of file
diff --git a/DysonNetwork.sln.DotSettings.user b/DysonNetwork.sln.DotSettings.user
index d087cad..f6e0c99 100644
--- a/DysonNetwork.sln.DotSettings.user
+++ b/DysonNetwork.sln.DotSettings.user
@@ -41,6 +41,7 @@
ForceIncluded
ForceIncluded
ForceIncluded
+ ForceIncluded
ForceIncluded
ForceIncluded
ForceIncluded
@@ -65,6 +66,7 @@
ForceIncluded
ForceIncluded
ForceIncluded
+ ForceIncluded
ForceIncluded
ForceIncluded
ForceIncluded