-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
dbe3187
commit 8dab545
Showing
30 changed files
with
893 additions
and
16 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,5 @@ | ||
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation"> | ||
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation"> | ||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateConstants/@EntryIndexedValue"><Policy Inspect="True" Prefix="_" Suffix="" Style="aaBb" /></s:String> | ||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateStaticReadonly/@EntryIndexedValue"><Policy Inspect="True" Prefix="_" Suffix="" Style="aaBb" /></s:String> | ||
<s:Boolean x:Key="/Default/UserDictionary/Words/=virto/@EntryIndexedValue">True</s:Boolean> | ||
</wpf:ResourceDictionary> |
11 changes: 11 additions & 0 deletions
11
...irtoCommerce.FileExperienceApi.Core/Authorization/IFileAuthorizationRequirementFactory.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
using Microsoft.AspNetCore.Authorization; | ||
using VirtoCommerce.FileExperienceApi.Core.Models; | ||
|
||
namespace VirtoCommerce.FileExperienceApi.Core.Authorization | ||
{ | ||
public interface IFileAuthorizationRequirementFactory | ||
{ | ||
public string Scope { get; } | ||
IAuthorizationRequirement Create(File file, string permission); | ||
} | ||
} |
11 changes: 11 additions & 0 deletions
11
src/VirtoCommerce.FileExperienceApi.Core/Authorization/IFileAuthorizationService.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
using System.Security.Claims; | ||
using System.Threading.Tasks; | ||
using Microsoft.AspNetCore.Authorization; | ||
using VirtoCommerce.FileExperienceApi.Core.Models; | ||
|
||
namespace VirtoCommerce.FileExperienceApi.Core.Authorization; | ||
|
||
public interface IFileAuthorizationService | ||
{ | ||
Task<AuthorizationResult> AuthorizeAsync(ClaimsPrincipal user, File file, string permission); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
using VirtoCommerce.Platform.Core.Common; | ||
|
||
namespace VirtoCommerce.FileExperienceApi.Core.Models; | ||
|
||
public class File : Entity | ||
{ | ||
public string Scope { get; set; } | ||
public string Name { get; set; } | ||
public string ContentType { get; set; } | ||
public long Size { get; set; } | ||
public string Url { get; set; } | ||
public string OwnerEntityId { get; set; } | ||
public string OwnerEntityType { get; set; } | ||
} |
38 changes: 38 additions & 0 deletions
38
src/VirtoCommerce.FileExperienceApi.Core/Models/FileUploadError.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
|
||
namespace VirtoCommerce.FileExperienceApi.Core.Models; | ||
|
||
public static class FileUploadError | ||
{ | ||
public static FileUploadResult InvalidContentType(string contentType) | ||
{ | ||
return FileUploadResult.Fail("INVALID_CONTENT_TYPE", $"Expected a multipart request, but got '{contentType}'", contentType); | ||
} | ||
|
||
public static FileUploadResult InvalidContent() | ||
{ | ||
return FileUploadResult.Fail("INVALID_CONTENT", "Cannot read file"); | ||
} | ||
|
||
public static FileUploadResult Exception(Exception ex, string fileName = null) | ||
{ | ||
return FileUploadResult.Fail("EXCEPTION", ex.Message, parameter: null, fileName); | ||
} | ||
|
||
public static FileUploadResult InvalidScope(string scope, string fileName) | ||
{ | ||
return FileUploadResult.Fail("INVALID_SCOPE", $"Unknown scope '{scope}'", scope, fileName); | ||
} | ||
|
||
public static FileUploadResult InvalidExtension(IList<string> allowedExtensions, string fileName) | ||
{ | ||
var joinedExtensions = string.Join(", ", allowedExtensions); | ||
return FileUploadResult.Fail("INVALID_EXTENSION", $"Allowed file extensions: {joinedExtensions}", allowedExtensions, fileName); | ||
} | ||
|
||
public static FileUploadResult InvalidSize(long maxSize, string fileName) | ||
{ | ||
return FileUploadResult.Fail("INVALID_SIZE", $"Maximum allowed file size: {maxSize}", maxSize, fileName); | ||
} | ||
} |
13 changes: 13 additions & 0 deletions
13
src/VirtoCommerce.FileExperienceApi.Core/Models/FileUploadOptions.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
using System.Collections.Generic; | ||
using System.ComponentModel.DataAnnotations; | ||
|
||
namespace VirtoCommerce.FileExperienceApi.Core.Models; | ||
|
||
public class FileUploadOptions | ||
{ | ||
[Required] | ||
public string RootPath { get; set; } = "upload"; | ||
|
||
[Required] | ||
public IList<FileUploadScopeOptions> Scopes { get; set; } = new List<FileUploadScopeOptions>(); | ||
} |
11 changes: 11 additions & 0 deletions
11
src/VirtoCommerce.FileExperienceApi.Core/Models/FileUploadRequest.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
using System.IO; | ||
|
||
namespace VirtoCommerce.FileExperienceApi.Core.Models; | ||
|
||
public class FileUploadRequest | ||
{ | ||
public string Scope { get; set; } | ||
public string UserId { get; set; } | ||
public string FileName { get; set; } | ||
public Stream Stream { get; set; } | ||
} |
37 changes: 37 additions & 0 deletions
37
src/VirtoCommerce.FileExperienceApi.Core/Models/FileUploadResult.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
using VirtoCommerce.Platform.Core.Common; | ||
|
||
namespace VirtoCommerce.FileExperienceApi.Core.Models; | ||
|
||
public class FileUploadResult : File | ||
{ | ||
public bool Succeeded => string.IsNullOrEmpty(ErrorMessage); | ||
public string ErrorCode { get; set; } | ||
public string ErrorMessage { get; set; } | ||
public object ErrorParameter { get; set; } | ||
|
||
public static FileUploadResult Success(File file) | ||
{ | ||
var result = AbstractTypeFactory<FileUploadResult>.TryCreateInstance(); | ||
|
||
result.Scope = file.Scope; | ||
result.Id = file.Id; | ||
result.Name = file.Name; | ||
result.ContentType = file.ContentType; | ||
result.Size = file.Size; | ||
result.Url = file.Url; | ||
|
||
return result; | ||
} | ||
|
||
public static FileUploadResult Fail(string code, string message, object parameter = null, string fileName = null) | ||
{ | ||
var result = AbstractTypeFactory<FileUploadResult>.TryCreateInstance(); | ||
|
||
result.ErrorCode = code; | ||
result.ErrorMessage = message; | ||
result.ErrorParameter = parameter; | ||
result.Name = fileName; | ||
|
||
return result; | ||
} | ||
} |
17 changes: 17 additions & 0 deletions
17
src/VirtoCommerce.FileExperienceApi.Core/Models/FileUploadScopeOptions.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
using System.Collections.Generic; | ||
using System.ComponentModel.DataAnnotations; | ||
|
||
namespace VirtoCommerce.FileExperienceApi.Core.Models | ||
{ | ||
public class FileUploadScopeOptions | ||
{ | ||
[Required] | ||
public string Scope { get; set; } | ||
|
||
[Required] | ||
public long MaxFileSize { get; set; } | ||
|
||
[Required] | ||
public IList<string> AllowedExtensions { get; set; } = new List<string>(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
15 changes: 15 additions & 0 deletions
15
src/VirtoCommerce.FileExperienceApi.Core/Services/IFileUploadService.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
using System.IO; | ||
using System.Threading.Tasks; | ||
using VirtoCommerce.FileExperienceApi.Core.Models; | ||
using VirtoCommerce.Platform.Core.GenericCrud; | ||
using File = VirtoCommerce.FileExperienceApi.Core.Models.File; | ||
|
||
namespace VirtoCommerce.FileExperienceApi.Core.Services | ||
{ | ||
public interface IFileUploadService : ICrudService<File> | ||
{ | ||
Task<FileUploadScopeOptions> GetOptionsAsync(string scope); | ||
Task<FileUploadResult> UploadFileAsync(FileUploadRequest request); | ||
Task<Stream> OpenReadAsync(string id); | ||
} | ||
} |
6 changes: 4 additions & 2 deletions
6
src/VirtoCommerce.FileExperienceApi.Core/VirtoCommerce.FileExperienceApi.Core.csproj
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,14 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
<PropertyGroup> | ||
<TargetFramework>net6.0</TargetFramework> | ||
<TargetFramework>net8.0</TargetFramework> | ||
</PropertyGroup> | ||
<PropertyGroup> | ||
<!-- Project is not a test project --> | ||
<SonarQubeTestProject>false</SonarQubeTestProject> | ||
</PropertyGroup> | ||
<ItemGroup> | ||
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" /> | ||
<PackageReference Include="Microsoft.AspNetCore.Authorization" Version="8.0.0" /> | ||
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="8.0.0" PrivateAssets="All" /> | ||
<PackageReference Include="VirtoCommerce.Platform.Core" Version="3.800.0" /> | ||
</ItemGroup> | ||
</Project> |
41 changes: 41 additions & 0 deletions
41
src/VirtoCommerce.FileExperienceApi.Data/Authorization/FileAuthorizationRequirement.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
using System.Threading.Tasks; | ||
using Microsoft.AspNetCore.Authorization; | ||
using VirtoCommerce.FileExperienceApi.Core.Models; | ||
using VirtoCommerce.Platform.Core; | ||
using VirtoCommerce.Platform.Security.Authorization; | ||
|
||
namespace VirtoCommerce.FileExperienceApi.Data.Authorization; | ||
|
||
public class FileAuthorizationRequirement : PermissionAuthorizationRequirement | ||
{ | ||
public FileAuthorizationRequirement(string permission) | ||
: base(permission) | ||
{ | ||
} | ||
} | ||
|
||
public class FileAuthorizationHandler : PermissionAuthorizationHandlerBase<FileAuthorizationRequirement> | ||
{ | ||
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, FileAuthorizationRequirement requirement) | ||
{ | ||
var authorized = context.User.IsInRole(PlatformConstants.Security.SystemRoles.Administrator); | ||
|
||
if (!authorized && context.Resource is File file) | ||
{ | ||
// Authorize only if the file is not attached to any entity. | ||
// Attached files should be processed by a different handler. | ||
authorized = string.IsNullOrEmpty(file.OwnerEntityId); | ||
} | ||
|
||
if (authorized) | ||
{ | ||
context.Succeed(requirement); | ||
} | ||
else | ||
{ | ||
context.Fail(); | ||
} | ||
|
||
return Task.CompletedTask; | ||
} | ||
} |
32 changes: 32 additions & 0 deletions
32
src/VirtoCommerce.FileExperienceApi.Data/Authorization/FileAuthorizationService.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Security.Claims; | ||
using System.Threading.Tasks; | ||
using Microsoft.AspNetCore.Authorization; | ||
using VirtoCommerce.FileExperienceApi.Core.Authorization; | ||
using VirtoCommerce.FileExperienceApi.Core.Models; | ||
using VirtoCommerce.Platform.Core.Common; | ||
|
||
namespace VirtoCommerce.FileExperienceApi.Data.Authorization; | ||
|
||
public class FileAuthorizationService : IFileAuthorizationService | ||
{ | ||
private readonly IAuthorizationService _authorizationService; | ||
private readonly IEnumerable<IFileAuthorizationRequirementFactory> _requirementFactories; | ||
|
||
public FileAuthorizationService( | ||
IAuthorizationService authorizationService, | ||
IEnumerable<IFileAuthorizationRequirementFactory> requirementFactories) | ||
{ | ||
_authorizationService = authorizationService; | ||
_requirementFactories = requirementFactories; | ||
} | ||
|
||
public Task<AuthorizationResult> AuthorizeAsync(ClaimsPrincipal user, File file, string permission) | ||
{ | ||
var requirementFactory = _requirementFactories.FirstOrDefault(x => x.Scope.EqualsInvariant(file.Scope)); | ||
var requirement = requirementFactory?.Create(file, permission) ?? new FileAuthorizationRequirement(permission); | ||
|
||
return _authorizationService.AuthorizeAsync(user, file, requirement); | ||
} | ||
} |
17 changes: 17 additions & 0 deletions
17
src/VirtoCommerce.FileExperienceApi.Data/Commands/DeleteFileCommand.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
using GraphQL.Types; | ||
using VirtoCommerce.ExperienceApiModule.Core.Infrastructure; | ||
|
||
namespace VirtoCommerce.FileExperienceApi.Data.Commands; | ||
|
||
public class DeleteFileCommand : ICommand<bool> | ||
{ | ||
public string Id { get; set; } | ||
} | ||
|
||
public class DeleteFileCommandType : InputObjectGraphType<DeleteFileCommand> | ||
{ | ||
public DeleteFileCommandType() | ||
{ | ||
Field(x => x.Id); | ||
} | ||
} |
53 changes: 53 additions & 0 deletions
53
src/VirtoCommerce.FileExperienceApi.Data/Commands/DeleteFileCommandBuilder.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
using System.Threading.Tasks; | ||
using GraphQL; | ||
using GraphQL.Types; | ||
using MediatR; | ||
using Microsoft.AspNetCore.Authorization; | ||
using VirtoCommerce.ExperienceApiModule.Core.BaseQueries; | ||
using VirtoCommerce.ExperienceApiModule.Core.Extensions; | ||
using VirtoCommerce.ExperienceApiModule.Core.Infrastructure.Authorization; | ||
using VirtoCommerce.FileExperienceApi.Core.Authorization; | ||
using VirtoCommerce.FileExperienceApi.Core.Services; | ||
using VirtoCommerce.Platform.Core.Common; | ||
using FilePermissions = VirtoCommerce.FileExperienceApi.Core.ModuleConstants.Security.Permissions; | ||
|
||
namespace VirtoCommerce.FileExperienceApi.Data.Commands; | ||
|
||
public class DeleteFileCommandBuilder : CommandBuilder<DeleteFileCommand, bool, DeleteFileCommandType, BooleanGraphType> | ||
{ | ||
protected override string Name => "DeleteFile"; | ||
|
||
private readonly IFileUploadService _fileUploadService; | ||
private readonly IFileAuthorizationService _fileAuthorizationService; | ||
|
||
public DeleteFileCommandBuilder( | ||
IMediator mediator, | ||
IAuthorizationService authorizationService, | ||
IFileUploadService fileUploadService, | ||
IFileAuthorizationService fileAuthorizationService) | ||
: base(mediator, authorizationService) | ||
{ | ||
_fileUploadService = fileUploadService; | ||
_fileAuthorizationService = fileAuthorizationService; | ||
} | ||
|
||
protected override async Task BeforeMediatorSend(IResolveFieldContext<object> context, DeleteFileCommand request) | ||
{ | ||
await base.BeforeMediatorSend(context, request); | ||
|
||
var file = await _fileUploadService.GetNoCloneAsync(request.Id); | ||
if (file is null) | ||
{ | ||
return; | ||
} | ||
|
||
var authorizationResult = await _fileAuthorizationService.AuthorizeAsync(context.GetCurrentPrincipal(), file, FilePermissions.Delete); | ||
|
||
if (!authorizationResult.Succeeded) | ||
{ | ||
throw context.IsAuthenticated() | ||
? AuthorizationError.Forbidden() | ||
: AuthorizationError.AnonymousAccessDenied(); | ||
} | ||
} | ||
} |
23 changes: 23 additions & 0 deletions
23
src/VirtoCommerce.FileExperienceApi.Data/Commands/DeleteFileCommandHandler.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
using MediatR; | ||
using VirtoCommerce.FileExperienceApi.Core.Services; | ||
|
||
namespace VirtoCommerce.FileExperienceApi.Data.Commands; | ||
|
||
public class DeleteFileCommandHandler : IRequestHandler<DeleteFileCommand, bool> | ||
{ | ||
private readonly IFileUploadService _fileUploadService; | ||
|
||
public DeleteFileCommandHandler(IFileUploadService fileUploadService) | ||
{ | ||
_fileUploadService = fileUploadService; | ||
} | ||
|
||
public async Task<bool> Handle(DeleteFileCommand request, CancellationToken cancellationToken) | ||
{ | ||
await _fileUploadService.DeleteAsync(new[] { request.Id }); | ||
|
||
return true; | ||
} | ||
} |
Oops, something went wrong.