Компетенции и аватар

This commit is contained in:
Халимов Рустам
2026-02-13 22:37:07 +03:00
parent 1e72d006c4
commit cc73945ae2
7 changed files with 56 additions and 3 deletions
+2
View File
@@ -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/
+2
View File
@@ -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"]
+2
View File
@@ -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<,>));
}); });