Files
Ho Ngoc Hai 9c648c2d35 feat(cdn): Add CDN URL retrieval for public files and enhance caching mechanisms
- Introduced a new endpoint to retrieve CDN URLs for public files, falling back to pre-signed URLs when necessary.
- Enhanced caching for file metadata retrieval in GetFileQueryHandler to improve performance.
- Updated file handling commands to invalidate relevant caches upon file operations.
- Added configuration settings for CDN in appsettings.json to manage CDN behavior.
- Implemented new data models for CDN URL responses and integrated them into the API response structure.
2026-01-14 00:20:31 +07:00

139 lines
4.6 KiB
C#

using StorageService.Domain.SeedWork;
namespace StorageService.Domain.AggregatesModel.FolderAggregate;
/// <summary>
/// EN: Folder aggregate root - represents a logical folder for organizing files.
/// VI: Folder aggregate root - đại diện cho folder logic để tổ chức files.
/// </summary>
/// <remarks>
/// EN: CRITICAL: Folders are LOGICAL only (database). Storage uses flat UUID keys.
/// Folder rename/move is O(1) - only updates database, not storage.
/// VI: QUAN TRỌNG: Folders chỉ là LOGIC (database). Storage dùng flat UUID keys.
/// Đổi tên/di chuyển folder là O(1) - chỉ update database, không động storage.
/// </remarks>
public class Folder : Entity, IAggregateRoot
{
/// <summary>EN: Owner user ID / VI: ID user sở hữu</summary>
public string UserId { get; private set; } = default!;
/// <summary>EN: Parent folder ID (null = root) / VI: ID folder cha (null = root)</summary>
public Guid? ParentId { get; private set; }
/// <summary>EN: Folder name / VI: Tên folder</summary>
public string Name { get; private set; } = default!;
/// <summary>EN: Materialized path (e.g., /parent/child/) / VI: Đường dẫn (vd: /parent/child/)</summary>
public string Path { get; private set; } = default!;
/// <summary>EN: Nesting level (0 = root level) / VI: Cấp độ lồng (0 = cấp root)</summary>
public int Level { get; private set; }
/// <summary>EN: Created timestamp / VI: Thời gian tạo</summary>
public DateTime CreatedAt { get; private set; }
/// <summary>EN: Updated timestamp / VI: Thời gian cập nhật</summary>
public DateTime UpdatedAt { get; private set; }
/// <summary>EN: Soft delete flag / VI: Cờ xóa mềm</summary>
public bool IsDeleted { get; private set; }
/// <summary>EN: Deleted timestamp / VI: Thời gian xóa</summary>
public DateTime? DeletedAt { get; private set; }
// EN: For EF Core / VI: Cho EF Core
protected Folder() { }
/// <summary>
/// EN: Create a new root folder.
/// VI: Tạo folder root mới.
/// </summary>
public static Folder CreateRoot(string userId, string name)
{
return new Folder
{
Id = Guid.NewGuid(),
UserId = userId,
ParentId = null,
Name = name,
Path = $"/{name}/",
Level = 0,
CreatedAt = DateTime.UtcNow,
UpdatedAt = DateTime.UtcNow,
IsDeleted = false
};
}
/// <summary>
/// EN: Create a child folder.
/// VI: Tạo folder con.
/// </summary>
public Folder CreateChild(string name)
{
return new Folder
{
Id = Guid.NewGuid(),
UserId = UserId,
ParentId = Id,
Name = name,
Path = $"{Path}{name}/",
Level = Level + 1,
CreatedAt = DateTime.UtcNow,
UpdatedAt = DateTime.UtcNow,
IsDeleted = false
};
}
/// <summary>
/// EN: Rename folder. O(1) operation - only database update.
/// VI: Đổi tên folder. O(1) - chỉ update database.
/// </summary>
public void Rename(string newName)
{
if (IsDeleted)
throw new InvalidOperationException("Cannot rename deleted folder");
var oldPath = Path;
Name = newName;
// EN: Update path - need to update children paths too (via repository)
// VI: Update path - cần update paths của children (qua repository)
Path = ParentId == null
? $"/{newName}/"
: oldPath.Substring(0, oldPath.LastIndexOf('/', oldPath.Length - 2) + 1) + $"{newName}/";
UpdatedAt = DateTime.UtcNow;
}
/// <summary>
/// EN: Move folder to new parent.
/// VI: Di chuyển folder sang parent mới.
/// </summary>
public void MoveTo(Folder? newParent)
{
if (IsDeleted)
throw new InvalidOperationException("Cannot move deleted folder");
if (newParent != null && newParent.UserId != UserId)
throw new InvalidOperationException("Cannot move folder to different user");
ParentId = newParent?.Id;
Level = newParent == null ? 0 : newParent.Level + 1;
Path = newParent == null ? $"/{Name}/" : $"{newParent.Path}{Name}/";
UpdatedAt = DateTime.UtcNow;
}
/// <summary>
/// EN: Soft delete folder.
/// VI: Xóa mềm folder.
/// </summary>
public void Delete()
{
if (IsDeleted)
return;
IsDeleted = true;
DeletedAt = DateTime.UtcNow;
}
}