♻️ Extract the Storage service to DysonNetwork.Drive microservice

This commit is contained in:
2025-07-06 17:29:26 +08:00
parent 6a3d04af3d
commit 14b79f16f4
71 changed files with 2629 additions and 346 deletions

View File

@ -0,0 +1,325 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using DysonNetwork.Drive.Interfaces;
using DysonNetwork.Drive.Models;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
namespace DysonNetwork.Drive.Controllers
{
[ApiController]
[Route("api/references")]
[Authorize]
public class FileReferenceController : ControllerBase
{
private readonly IFileReferenceService _referenceService;
private readonly ILogger<FileReferenceController> _logger;
public FileReferenceController(
IFileReferenceService referenceService,
ILogger<FileReferenceController> logger)
{
_referenceService = referenceService ?? throw new ArgumentNullException(nameof(referenceService));
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
}
[HttpPost]
[ProducesResponseType(typeof(CloudFileReference), StatusCodes.Status201Created)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public async Task<IActionResult> CreateReference([FromBody] CreateReferenceRequest request, CancellationToken cancellationToken = default)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
try
{
var reference = await _referenceService.CreateReferenceAsync(
request.FileId,
request.ResourceId,
request.ResourceType,
request.ReferenceType,
request.ReferenceId,
request.ReferenceName,
request.ReferenceMimeType,
request.ReferenceSize,
request.ReferenceUrl,
request.ReferenceThumbnailUrl,
request.ReferencePreviewUrl,
request.ReferenceMetadata,
request.Metadata,
cancellationToken);
return CreatedAtAction(
nameof(GetReference),
new { referenceId = reference.Id },
reference);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error creating file reference for file {FileId}", request.FileId);
return StatusCode(StatusCodes.Status500InternalServerError, new { message = "An error occurred while creating the file reference." });
}
}
[HttpGet("{referenceId}")]
[ProducesResponseType(typeof(CloudFileReference), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public async Task<IActionResult> GetReference(Guid referenceId, CancellationToken cancellationToken = default)
{
try
{
var reference = await _referenceService.GetReferenceAsync(referenceId, cancellationToken);
return Ok(reference);
}
catch (KeyNotFoundException ex)
{
_logger.LogWarning(ex, "Reference not found: {ReferenceId}", referenceId);
return NotFound(new { message = $"Reference with ID {referenceId} not found." });
}
catch (Exception ex)
{
_logger.LogError(ex, "Error retrieving reference: {ReferenceId}", referenceId);
return StatusCode(StatusCodes.Status500InternalServerError, new { message = "An error occurred while retrieving the reference." });
}
}
[HttpGet("file/{fileId}")]
[ProducesResponseType(typeof(IEnumerable<CloudFileReference>), StatusCodes.Status200OK)]
public async Task<IActionResult> GetReferencesForFile(Guid fileId, CancellationToken cancellationToken = default)
{
try
{
var references = await _referenceService.GetReferencesForFileAsync(fileId, cancellationToken);
return Ok(references);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error retrieving references for file: {FileId}", fileId);
return StatusCode(StatusCodes.Status500InternalServerError, new { message = "An error occurred while retrieving references for the file." });
}
}
[HttpGet("resource/{resourceType}/{resourceId}")]
[ProducesResponseType(typeof(IEnumerable<CloudFileReference>), StatusCodes.Status200OK)]
public async Task<IActionResult> GetReferencesForResource(
string resourceType,
string resourceId,
CancellationToken cancellationToken = default)
{
try
{
var references = await _referenceService.GetReferencesForResourceAsync(resourceId, resourceType, cancellationToken);
return Ok(references);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error retrieving references for resource: {ResourceType}/{ResourceId}", resourceType, resourceId);
return StatusCode(StatusCodes.Status500InternalServerError, new { message = "An error occurred while retrieving references for the resource." });
}
}
[HttpGet("type/{referenceType}")]
[ProducesResponseType(typeof(IEnumerable<CloudFileReference>), StatusCodes.Status200OK)]
public async Task<IActionResult> GetReferencesOfType(string referenceType, CancellationToken cancellationToken = default)
{
try
{
var references = await _referenceService.GetReferencesOfTypeAsync(referenceType, cancellationToken);
return Ok(references);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error retrieving references of type: {ReferenceType}", referenceType);
return StatusCode(StatusCodes.Status500InternalServerError, new { message = "An error occurred while retrieving references of the specified type." });
}
}
[HttpDelete("{referenceId}")]
[ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public async Task<IActionResult> DeleteReference(Guid referenceId, CancellationToken cancellationToken = default)
{
try
{
var deleted = await _referenceService.DeleteReferenceAsync(referenceId, cancellationToken);
if (!deleted)
{
return NotFound(new { message = $"Reference with ID {referenceId} not found." });
}
return NoContent();
}
catch (Exception ex)
{
_logger.LogError(ex, "Error deleting reference: {ReferenceId}", referenceId);
return StatusCode(StatusCodes.Status500InternalServerError, new { message = "An error occurred while deleting the reference." });
}
}
[HttpDelete("file/{fileId}")]
[ProducesResponseType(StatusCodes.Status200OK)]
public async Task<IActionResult> DeleteReferencesForFile(Guid fileId, CancellationToken cancellationToken = default)
{
try
{
var count = await _referenceService.DeleteReferencesForFileAsync(fileId, cancellationToken);
return Ok(new { count });
}
catch (Exception ex)
{
_logger.LogError(ex, "Error deleting references for file: {FileId}", fileId);
return StatusCode(StatusCodes.Status500InternalServerError, new { message = "An error occurred while deleting references for the file." });
}
}
[HttpDelete("resource/{resourceType}/{resourceId}")]
[ProducesResponseType(StatusCodes.Status200OK)]
public async Task<IActionResult> DeleteReferencesForResource(
string resourceType,
string resourceId,
CancellationToken cancellationToken = default)
{
try
{
var count = await _referenceService.DeleteReferencesForResourceAsync(resourceId, resourceType, cancellationToken);
return Ok(new { count });
}
catch (Exception ex)
{
_logger.LogError(ex, "Error deleting references for resource: {ResourceType}/{ResourceId}", resourceType, resourceId);
return StatusCode(StatusCodes.Status500InternalServerError, new { message = "An error occurred while deleting references for the resource." });
}
}
[HttpPut("{referenceId}/metadata")]
[ProducesResponseType(typeof(CloudFileReference), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public async Task<IActionResult> UpdateReferenceMetadata(
Guid referenceId,
[FromBody] Dictionary<string, object> metadata,
CancellationToken cancellationToken = default)
{
if (metadata == null || metadata.Count == 0)
{
return BadRequest(new { message = "No metadata provided." });
}
try
{
var reference = await _referenceService.UpdateReferenceMetadataAsync(referenceId, metadata, cancellationToken);
return Ok(reference);
}
catch (KeyNotFoundException ex)
{
_logger.LogWarning(ex, "Reference not found: {ReferenceId}", referenceId);
return NotFound(new { message = $"Reference with ID {referenceId} not found." });
}
catch (Exception ex)
{
_logger.LogError(ex, "Error updating reference metadata: {ReferenceId}", referenceId);
return StatusCode(StatusCodes.Status500InternalServerError, new { message = "An error occurred while updating the reference metadata." });
}
}
[HttpPut("{referenceId}/resource")]
[ProducesResponseType(typeof(CloudFileReference), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public async Task<IActionResult> UpdateReferenceResource(
Guid referenceId,
[FromBody] UpdateReferenceResourceRequest request,
CancellationToken cancellationToken = default)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
try
{
var reference = await _referenceService.UpdateReferenceResourceAsync(
referenceId,
request.NewResourceId,
request.NewResourceType,
cancellationToken);
return Ok(reference);
}
catch (KeyNotFoundException ex)
{
_logger.LogWarning(ex, "Reference not found: {ReferenceId}", referenceId);
return NotFound(new { message = $"Reference with ID {referenceId} not found." });
}
catch (Exception ex)
{
_logger.LogError(ex, "Error updating reference resource: {ReferenceId}", referenceId);
return StatusCode(StatusCodes.Status500InternalServerError, new { message = "An error occurred while updating the reference resource." });
}
}
[HttpGet("exists/{fileId}/{resourceType}/{resourceId}")]
[ProducesResponseType(typeof(bool), StatusCodes.Status200OK)]
public async Task<IActionResult> HasReference(
Guid fileId,
string resourceType,
string resourceId,
[FromQuery] string? referenceType = null,
CancellationToken cancellationToken = default)
{
try
{
var exists = await _referenceService.HasReferenceAsync(
fileId,
resourceId,
resourceType,
referenceType,
cancellationToken);
return Ok(new { exists });
}
catch (Exception ex)
{
_logger.LogError(
ex,
"Error checking reference existence - File: {FileId}, Resource: {ResourceType}/{ResourceId}, ReferenceType: {ReferenceType}",
fileId,
resourceType,
resourceId,
referenceType);
return StatusCode(StatusCodes.Status500InternalServerError, new { message = "An error occurred while checking reference existence." });
}
}
}
public class CreateReferenceRequest
{
public Guid FileId { get; set; }
public string ResourceId { get; set; } = null!;
public string ResourceType { get; set; } = null!;
public string ReferenceType { get; set; } = null!;
public string? ReferenceId { get; set; }
public string? ReferenceName { get; set; }
public string? ReferenceMimeType { get; set; }
public long? ReferenceSize { get; set; }
public string? ReferenceUrl { get; set; }
public string? ReferenceThumbnailUrl { get; set; }
public string? ReferencePreviewUrl { get; set; }
public string? ReferenceMetadata { get; set; }
public Dictionary<string, object>? Metadata { get; set; }
}
public class UpdateReferenceResourceRequest
{
public string NewResourceId { get; set; } = null!;
public string NewResourceType { get; set; } = null!;
}
}