Компетенции и аватар
This commit is contained in:
@@ -158,3 +158,5 @@ src/Modules/Collaboration/Tests/obj/
|
|||||||
src/Modules/Reputation/Tests/obj/
|
src/Modules/Reputation/Tests/obj/
|
||||||
|
|
||||||
src/Modules/Reputation/Tests/bin/
|
src/Modules/Reputation/Tests/bin/
|
||||||
|
|
||||||
|
uploads/
|
||||||
|
|||||||
@@ -20,6 +20,8 @@ RUN dotnet publish "Nashel.Host.csproj" -c Release -o /app/publish /p:UseAppHost
|
|||||||
FROM mcr.microsoft.com/dotnet/aspnet:10.0-preview AS final
|
FROM mcr.microsoft.com/dotnet/aspnet:10.0-preview AS final
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
COPY --from=build /app/publish .
|
COPY --from=build /app/publish .
|
||||||
|
# Copy wwwroot folder for static files (uploads)
|
||||||
|
COPY src/Host/wwwroot /app/wwwroot
|
||||||
ENV ASPNETCORE_URLS=http://+:8080
|
ENV ASPNETCORE_URLS=http://+:8080
|
||||||
EXPOSE 8080
|
EXPOSE 8080
|
||||||
ENTRYPOINT ["dotnet", "Nashel.Host.dll"]
|
ENTRYPOINT ["dotnet", "Nashel.Host.dll"]
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ services:
|
|||||||
container_name: nashel-backend
|
container_name: nashel-backend
|
||||||
ports:
|
ports:
|
||||||
- "5000:8080"
|
- "5000:8080"
|
||||||
|
volumes:
|
||||||
|
- ./uploads:/app/wwwroot/uploads
|
||||||
environment:
|
environment:
|
||||||
- ASPNETCORE_ENVIRONMENT=Development
|
- ASPNETCORE_ENVIRONMENT=Development
|
||||||
- ConnectionStrings__DefaultConnection=Host=db;Port=5432;Database=nashel;Username=postgres;Password=postgres
|
- ConnectionStrings__DefaultConnection=Host=db;Port=5432;Database=nashel;Username=postgres;Password=postgres
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
using MediatR;
|
using MediatR;
|
||||||
|
using Nashel.BuildingBlocks.Application.Abstractions;
|
||||||
|
using Nashel.Modules.Identity.Domain.Repositories;
|
||||||
|
|
||||||
namespace Nashel.Modules.Identity.Application.Commands;
|
namespace Nashel.Modules.Identity.Application.Commands;
|
||||||
|
|
||||||
@@ -7,6 +9,17 @@ public class UploadAvatarCommandHandler : IRequestHandler<UploadAvatarCommand, s
|
|||||||
private const long MaxFileSize = 5 * 1024 * 1024; // 5MB
|
private const long MaxFileSize = 5 * 1024 * 1024; // 5MB
|
||||||
private static readonly string[] AllowedExtensions = { ".jpg", ".jpeg", ".png" };
|
private static readonly string[] AllowedExtensions = { ".jpg", ".jpeg", ".png" };
|
||||||
|
|
||||||
|
private readonly IAccountRepository _accountRepository;
|
||||||
|
private readonly ICurrentUserService _currentUserService;
|
||||||
|
|
||||||
|
public UploadAvatarCommandHandler(
|
||||||
|
IAccountRepository accountRepository,
|
||||||
|
ICurrentUserService currentUserService)
|
||||||
|
{
|
||||||
|
_accountRepository = accountRepository;
|
||||||
|
_currentUserService = currentUserService;
|
||||||
|
}
|
||||||
|
|
||||||
public async Task<string> Handle(UploadAvatarCommand request, CancellationToken cancellationToken)
|
public async Task<string> Handle(UploadAvatarCommand request, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var file = request.File;
|
var file = request.File;
|
||||||
@@ -35,7 +48,30 @@ public class UploadAvatarCommandHandler : IRequestHandler<UploadAvatarCommand, s
|
|||||||
await file.CopyToAsync(stream, cancellationToken);
|
await file.CopyToAsync(stream, cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Возвращаем URL
|
// Получаем текущего пользователя
|
||||||
return $"/uploads/{fileName}";
|
var userId = _currentUserService.UserId;
|
||||||
|
if (userId == null)
|
||||||
|
{
|
||||||
|
throw new UnauthorizedAccessException();
|
||||||
|
}
|
||||||
|
|
||||||
|
var account = await _accountRepository.GetByIdAsync(userId.Value, cancellationToken);
|
||||||
|
if (account == null)
|
||||||
|
{
|
||||||
|
throw new Exception("Account not found");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (account.Profile == null)
|
||||||
|
{
|
||||||
|
throw new Exception("Profile not found");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Обновляем аватар в базе данных
|
||||||
|
var avatarUrl = $"/uploads/{fileName}";
|
||||||
|
account.Profile.UpdateAvatar(avatarUrl);
|
||||||
|
|
||||||
|
await _accountRepository.UpdateAsync(account, cancellationToken);
|
||||||
|
|
||||||
|
return avatarUrl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,6 @@ public class Competency
|
|||||||
if (string.IsNullOrWhiteSpace(name))
|
if (string.IsNullOrWhiteSpace(name))
|
||||||
throw new ArgumentException("Название компетенции не может быть пустым", nameof(name));
|
throw new ArgumentException("Название компетенции не может быть пустым", nameof(name));
|
||||||
|
|
||||||
return new Competency { Id = Guid.NewGuid(), Name = name.Trim() };
|
return new Competency { Id = Guid.NewGuid(), Name = name.Trim().ToLower() };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
using Nashel.Modules.Identity.Domain.Entities;
|
||||||
|
|
||||||
|
namespace Nashel.Modules.Identity.Domain.Repositories;
|
||||||
|
|
||||||
|
public interface ICompetencyRepository
|
||||||
|
{
|
||||||
|
Task<Competency?> GetByNameAsync(string name, CancellationToken cancellationToken);
|
||||||
|
Task AddAsync(Competency competency, CancellationToken cancellationToken);
|
||||||
|
}
|
||||||
@@ -7,6 +7,7 @@ using Nashel.BuildingBlocks.Application.Behaviors;
|
|||||||
using Nashel.Modules.Identity.Application.Commands;
|
using Nashel.Modules.Identity.Application.Commands;
|
||||||
using Nashel.Modules.Identity.Domain.Repositories;
|
using Nashel.Modules.Identity.Domain.Repositories;
|
||||||
using Nashel.Modules.Identity.Domain.Services;
|
using Nashel.Modules.Identity.Domain.Services;
|
||||||
|
using Nashel.Modules.Identity.Infrastructure.CommandHandlers;
|
||||||
using Nashel.Modules.Identity.Infrastructure.Persistence;
|
using Nashel.Modules.Identity.Infrastructure.Persistence;
|
||||||
using Nashel.Modules.Identity.Infrastructure.Repositories;
|
using Nashel.Modules.Identity.Infrastructure.Repositories;
|
||||||
using Nashel.Modules.Identity.Infrastructure.Services;
|
using Nashel.Modules.Identity.Infrastructure.Services;
|
||||||
@@ -26,6 +27,7 @@ public static class DependencyInjection
|
|||||||
services.AddMediatR(cfg =>
|
services.AddMediatR(cfg =>
|
||||||
{
|
{
|
||||||
cfg.RegisterServicesFromAssembly(typeof(RegisterUserCommand).Assembly);
|
cfg.RegisterServicesFromAssembly(typeof(RegisterUserCommand).Assembly);
|
||||||
|
cfg.RegisterServicesFromAssembly(typeof(UpdateProfileCompetenciesCommandHandler).Assembly);
|
||||||
cfg.AddBehavior(typeof(IPipelineBehavior<,>), typeof(ValidationBehavior<,>));
|
cfg.AddBehavior(typeof(IPipelineBehavior<,>), typeof(ValidationBehavior<,>));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user