last works on XFile Provider by Implememnting Tag Provider and also add Global Supports for ProvidedFor and References inside File Provider ...

This commit is contained in:
2025-12-08 14:12:31 +03:30
parent 4cf1e4d629
commit d14a918212
3 changed files with 613 additions and 16 deletions
+117
View File
@@ -22,6 +22,7 @@ namespace xFileService.Interfaces
{ {
// //
#region Props ... #region Props ...
IXFileTagProvider TagProvider { get; }
IHubContext<XFileEntityHub> Hub { get; } IHubContext<XFileEntityHub> Hub { get; }
IXFileRepository FileRepository { get; } IXFileRepository FileRepository { get; }
IXStorageProvider StorageProvider { get; } IXStorageProvider StorageProvider { get; }
@@ -53,6 +54,72 @@ namespace xFileService.Interfaces
Task<XQueryResult<XFileDto>> ToDtoQueryResult(XQueryResult<XFile> queryResult); Task<XQueryResult<XFileDto>> ToDtoQueryResult(XQueryResult<XFile> queryResult);
#endregion #endregion
//
#region Tags ...
/// <summary>
/// Attach Tag to Specified File ...
/// </summary>
/// <param name="tag"></param>
/// <param name="id"></param>
/// <param name="userInfo"></param>
/// <returns></returns>
Task TagAttach(
string tag,
Guid id,
XUserClaimsInfoDto userInfo = null
);
/// <summary>
/// Detach Tag fro Specified File ...
/// </summary>
/// <param name="tag"></param>
/// <param name="id"></param>
/// <param name="userInfo"></param>
/// <returns></returns>
Task TagDetach(
string tag,
Guid id,
XUserClaimsInfoDto userInfo = null
);
/// <summary>
/// Attach Tags for Specified File ...
/// </summary>
/// <param name="tags"></param>
/// <param name="id"></param>
/// <param name="userInfo"></param>
/// <returns></returns>
Task TagsAttach(
IEnumerable<string> tags,
Guid id,
XUserClaimsInfoDto userInfo = null
);
/// <summary>
/// Detach Tags for Specified File ...
/// </summary>
/// <param name="tags"></param>
/// <param name="id"></param>
/// <param name="userInfo"></param>
/// <returns></returns>
Task TagsDetach(
IEnumerable<string> tags,
Guid id,
XUserClaimsInfoDto userInfo = null
);
/// <summary>
/// Detach all Attached Tags for Specified File ...
/// </summary>
/// <param name="id"></param>
/// <param name="userInfo"></param>
/// <returns></returns>
Task TagsDetach(
Guid id,
XUserClaimsInfoDto userInfo = null
);
#endregion
// //
#region Tools ... #region Tools ...
/// <summary> /// <summary>
@@ -120,6 +187,56 @@ namespace xFileService.Interfaces
Task<XFileStreamDescriptorDto> GetFileDescriptor(string fileName); Task<XFileStreamDescriptorDto> GetFileDescriptor(string fileName);
#endregion #endregion
//
#region Reference ...
/// <summary>
/// Get Reference Identifier for Specified Provider and Specified File ...
/// </summary>
/// <param name="providedFor"></param>
/// <param name="id"></param>
/// <returns></returns>
string GetIdentifier(
string providedFor,
Guid id
);
/// <summary>
/// Check Specified File has Refernce to Provider ...
/// </summary>
/// <param name="providedFor"></param>
/// <returns></returns>
Task<bool> IsProvidedFor(
string providedFor,
Guid id
);
/// <summary>
/// Add Specified Reference to Specified File ...
/// </summary>
/// <param name="providedFor"></param>
/// <param name="id"></param>
/// <param name="userInfo"></param>
/// <returns></returns>
Task AddReference(
string providedFor,
Guid id,
XUserClaimsInfoDto userInfo = null
);
/// <summary>
/// Remove Specified Reference from Specified File ...
/// </summary>
/// <param name="providedFor"></param>
/// <param name="id"></param>
/// <param name="userInfo"></param>
/// <returns></returns>
Task RemoveReference(
string providedFor,
Guid id,
XUserClaimsInfoDto userInfo = null
);
#endregion
// //
#region Data Model ... #region Data Model ...
/// <summary> /// <summary>
+1 -1
View File
@@ -20,7 +20,7 @@ namespace xFileService.Models.Dtos
public string OwnerId { get; set; } public string OwnerId { get; set; }
public XPersonDto Owner { get; set; } public XPersonDto Owner { get; set; }
public IList<string> References = new List<string>(); public IList<string> References = new List<string>();
} }
} }
+495 -15
View File
@@ -31,6 +31,7 @@ namespace xFileService.Providers
{ {
// //
#region Props ... #region Props ...
public IXFileTagProvider TagProvider { get; }
public IHubContext<XFileEntityHub> Hub { get; } public IHubContext<XFileEntityHub> Hub { get; }
public IXFileRepository FileRepository { get; } public IXFileRepository FileRepository { get; }
public IXStorageProvider StorageProvider { get; } public IXStorageProvider StorageProvider { get; }
@@ -41,6 +42,7 @@ namespace xFileService.Providers
// //
#region Constructor ... #region Constructor ...
public XFileProvider( public XFileProvider(
IXFileTagProvider tagProvider,
IXFileRepository fileRepository, IXFileRepository fileRepository,
IXStorageProvider storageProvider, IXStorageProvider storageProvider,
IXIdentityProvider identityProvider, IXIdentityProvider identityProvider,
@@ -50,6 +52,7 @@ namespace xFileService.Providers
{ {
// //
Hub = hub; Hub = hub;
TagProvider = tagProvider;
FileRepository = fileRepository; FileRepository = fileRepository;
StorageProvider = storageProvider; StorageProvider = storageProvider;
IdentityProvider = identityProvider; IdentityProvider = identityProvider;
@@ -155,6 +158,262 @@ namespace xFileService.Providers
// //
return result; return result;
} }
/// <summary>
/// Check Specified User Info Has Permissions for Specified File ...
/// </summary>
/// <param name="id"></param>
/// <param name="userInfo"></param>
/// <returns></returns>
private async Task<bool> HasPermission(
Guid id,
XUserClaimsInfoDto userInfo = null
)
{
//
var result = false;
//
// Validate ...
result = !id.IsNull() &&
!id.IsDefaultGuid() &&
!userInfo.IsNullOrDefault();
if (!result)
{
XException.InvalidArgs.Throw();
}
//
// Check Item Exists ...
result = await IsExists(id);
if (!result)
{
XException.NotFound.Throw();
}
//
// Retrieve Dto ...
var dto = await Get(id);
result = !dto.IsNullOrDefault();
if (!result)
{
XException.ActionFailed.Throw();
}
//
result =
dto.OwnerId == userInfo.UserId ||
userInfo.Roles.Any(r => r.ToNormalString() == "admin");
//
return result;
}
#endregion
//
#region Tags ...
/// <summary>
/// Attach Tag to Specified File ...
/// </summary>
/// <param name="tag"></param>
/// <param name="id"></param>
/// <returns></returns>
public async Task TagAttach(
string tag,
Guid id,
XUserClaimsInfoDto userInfo = null
)
{
//
// Validate ...
var isValid = !tag.IsNullOrEmpty() &&
!id.IsNull() &&
!id.IsDefaultGuid() &&
!userInfo.IsNullOrDefault();
if (isValid)
{
//
// Check Permissions ...
isValid = await HasPermission(
id: id,
userInfo: userInfo
);
if (!isValid)
{
XException.NotAllowed.Throw();
}
//
try
{
await TagProvider.Attach(tag, id);
}
catch { }
}
}
/// <summary>
/// Detach Tag fro Specified File ...
/// </summary>
/// <param name="tag"></param>
/// <param name="id"></param>
/// <returns></returns>
public async Task TagDetach(
string tag,
Guid id,
XUserClaimsInfoDto userInfo = null
)
{
//
// Validate ...
var isValid = !tag.IsNullOrEmpty() &&
!id.IsNull() &&
!id.IsDefaultGuid();
if (isValid)
{
//
// Check Permissions ...
isValid = await HasPermission(
id: id,
userInfo: userInfo
);
if (!isValid)
{
XException.NotAllowed.Throw();
}
//
try
{
await TagProvider.Detach(tag, id);
}
catch { }
}
}
/// <summary>
/// Attach Tags for Specified File ...
/// </summary>
/// <param name="tags"></param>
/// <param name="id"></param>
/// <returns></returns>
public async Task TagsAttach(
IEnumerable<string> tags,
Guid id,
XUserClaimsInfoDto userInfo = null
)
{
//
// Validate ...
var isValid = !tags.IsNull() &&
tags.HasChild() &&
!id.IsNull() &&
!id.IsDefaultGuid();
if (isValid)
{
//
// Check Permissions ...
isValid = await HasPermission(
id: id,
userInfo: userInfo
);
if (!isValid)
{
XException.NotAllowed.Throw();
}
//
try
{
//
foreach (var tag in tags)
{
await TagAttach(tag, id);
}
}
catch { }
}
}
/// <summary>
/// Detach Tags for Specified File ...
/// </summary>
/// <param name="tags"></param>
/// <param name="id"></param>
/// <returns></returns>
public async Task TagsDetach(
IEnumerable<string> tags,
Guid id,
XUserClaimsInfoDto userInfo = null
)
{
//
// Validate ...
var isValid = !tags.IsNull() &&
tags.HasChild() &&
!id.IsNull() &&
!id.IsDefaultGuid();
if (isValid)
{
//
// Check Permissions ...
isValid = await HasPermission(
id: id,
userInfo: userInfo
);
if (!isValid)
{
XException.NotAllowed.Throw();
}
//
try
{
//
foreach (var tag in tags)
{
await TagDetach(tag, id);
}
}
catch { }
}
}
/// <summary>
/// Detach all Attached Tags for Specified File ...
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public async Task TagsDetach(
Guid id,
XUserClaimsInfoDto userInfo = null
)
{
//
// Validate ...
var isValid = !id.IsNull() && !id.IsDefaultGuid();
if (isValid)
{
//
// Check Permissions ...
isValid = await HasPermission(
id: id,
userInfo: userInfo
);
if (!isValid)
{
XException.NotAllowed.Throw();
}
//
try
{
//
var tags = await TagProvider.RemoveTagsFor(id);
}
catch { }
}
}
#endregion #endregion
// //
@@ -478,6 +737,17 @@ namespace xFileService.Providers
result.Add(model.Id); result.Add(model.Id);
} }
//
// Remove Tags ...
if (!result.IsNull() && result.HasChild())
{
//
foreach (var id in result)
{
await TagsDetach(id);
}
}
// //
return result; return result;
} }
@@ -642,6 +912,206 @@ namespace xFileService.Providers
} }
#endregion #endregion
//
#region Reference ...
/// <summary>
/// Get Reference Identifier for Specified Provider and Specified File ...
/// </summary>
/// <param name="providedFor"></param>
/// <param name="id"></param>
/// <returns></returns>
public string GetIdentifier(
string providedFor,
Guid id
)
{
return $"{providedFor}_{id}";
}
/// <summary>
/// Check Specified File has Refernce to Provider ...
/// </summary>
/// <param name="providedFor"></param>
/// <returns></returns>
public async Task<bool> IsProvidedFor(
string providedFor,
Guid id
)
{
//
// Validate ...
var isValid =
!providedFor.IsNullOrEmpty() &&
!id.IsNull() &&
!id.IsDefaultGuid();
if (!isValid)
{
XException.InvalidArgs.Throw();
}
//
// Check Exists ...
isValid = await IsExists(id);
if (!isValid)
{
XException.NotFound.Throw();
}
//
var dto = await Get(id);
isValid = !dto.IsNullOrDefault();
if (!isValid)
{
XException.ActionFailed.Throw();
}
//
var identifier = GetIdentifier(providedFor, id);
var result =
dto.References.IsNull() &&
dto.References.HasChild() &&
dto.References.Any(r => r.ToNormalString() == identifier.ToNormalString());
//
return result;
}
/// <summary>
/// Add Specified Reference to Specified File ...
/// </summary>
/// <param name="providedFor"></param>
/// <param name="id"></param>
/// <param name="userInfo"></param>
/// <returns></returns>
public async Task AddReference(
string providedFor,
Guid id,
XUserClaimsInfoDto userInfo = null
)
{
//
// Validate ...
var isValid =
!providedFor.IsNullOrEmpty() &&
!id.IsNull() &&
!id.IsDefaultGuid() &&
!userInfo.IsNullOrDefault();
if (!isValid)
{
XException.InvalidArgs.Throw();
}
//
// Check Has Reference or not ...
isValid = await IsProvidedFor(providedFor, id);
if (!isValid)
{
//
// Check Permissions ...
isValid = await HasPermission(
id: id,
userInfo: userInfo
);
if (!isValid)
{
XException.NotAllowed.Throw();
}
//
var dto = await Get(id);
isValid = !dto.IsNullOrDefault();
if (!isValid)
{
XException.ActionFailed.Throw();
}
//
var identifier = GetIdentifier(providedFor, id);
dto.References.Add(identifier);
//
dto = await Update(
id: dto.Id,
item: dto,
userInfo: userInfo
);
isValid = !dto.IsNullOrDefault();
if (!isValid)
{
XException.ActionFailed.Throw();
}
}
}
/// <summary>
/// Remove Specified Reference from Specified File ...
/// </summary>
/// <param name="providedFor"></param>
/// <param name="id"></param>
/// <param name="userInfo"></param>
/// <returns></returns>
public async Task RemoveReference(
string providedFor,
Guid id,
XUserClaimsInfoDto userInfo = null
)
{
//
// Validate ...
var isValid =
!providedFor.IsNullOrEmpty() &&
!id.IsNull() &&
!id.IsDefaultGuid() &&
!userInfo.IsNullOrDefault();
if (!isValid)
{
XException.InvalidArgs.Throw();
}
//
// Check Has Reference or not ...
isValid = await IsProvidedFor(providedFor, id);
if (isValid)
{
//
// Check Permissions ...
isValid = await HasPermission(
id: id,
userInfo: userInfo
);
if (!isValid)
{
XException.NotAllowed.Throw();
}
//
// Retrieve Dto ...
var dto = await Get(id);
isValid = !dto.IsNullOrDefault();
if (!isValid)
{
XException.ActionFailed.Throw();
}
//
var identifier = GetIdentifier(providedFor, id);
dto.References = dto.References
.Where(r => r.ToNormalString() != identifier.ToNormalString())
.ToList();
dto = await Update(
id: dto.Id,
item: dto,
userInfo: userInfo
);
isValid = !dto.IsNullOrDefault();
if (!isValid)
{
XException.ActionFailed.Throw();
}
}
}
#endregion
// //
#region Data Model ... #region Data Model ...
/// <summary> /// <summary>
@@ -831,6 +1301,18 @@ namespace xFileService.Providers
} }
// //
// Check Permissions ...
isValid = await HasPermission(
id: id,
userInfo: userInfo
);
if (!isValid)
{
XException.NotAllowed.Throw();
}
//
// Retrieve Entity ...
var entity = await FileRepository.GetAsync(id); var entity = await FileRepository.GetAsync(id);
if (entity.IsNullOrDefault()) if (entity.IsNullOrDefault())
{ {
@@ -845,9 +1327,11 @@ namespace xFileService.Providers
{ {
nameof(XFile.Id), nameof(XFile.Id),
nameof(XFile.Deleted), nameof(XFile.Deleted),
nameof(XFileDto.Owner) nameof(XFileDto.Owner),
nameof(XFile.References),
} }
); );
entity.References = item.References.ToListString();
if (entity.IsNullOrDefault()) if (entity.IsNullOrDefault())
{ {
XException.InvalidData.Throw(); XException.InvalidData.Throw();
@@ -861,16 +1345,7 @@ namespace xFileService.Providers
} }
// //
// Validate Action ... // Converts to Dto ...
isValid =
entity.OwnerId == userInfo.UserId ||
userInfo.Roles.Any(r => r.ToNormalString() == "admin".ToNormalString());
if (!isValid)
{
XException.NotAllowed.Throw();
}
//
var result = await ToDto(entity); var result = await ToDto(entity);
// //
@@ -915,10 +1390,11 @@ namespace xFileService.Providers
} }
// //
// Validate Action ... // Check Permissions ...
isValid = isValid = await HasPermission(
result.OwnerId == userInfo.UserId || id: id,
userInfo.Roles.Any(r => r.ToNormalString() == "admin".ToNormalString()); userInfo: userInfo
);
if (!isValid) if (!isValid)
{ {
XException.NotAllowed.Throw(); XException.NotAllowed.Throw();
@@ -938,6 +1414,10 @@ namespace xFileService.Providers
XException.ActionFailed.Throw(); XException.ActionFailed.Throw();
} }
//
// Removing Tags ...
await TagProvider.RemoveTagsFor(result.Id);
// //
return result; return result;
} }