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

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
.gitignore vendored
View File

@@ -158,3 +158,5 @@ src/Modules/Collaboration/Tests/obj/
src/Modules/Reputation/Tests/obj/
src/Modules/Reputation/Tests/bin/
uploads/

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
WORKDIR /app
COPY --from=build /app/publish .
# Copy wwwroot folder for static files (uploads)
COPY src/Host/wwwroot /app/wwwroot
ENV ASPNETCORE_URLS=http://+:8080
EXPOSE 8080
ENTRYPOINT ["dotnet", "Nashel.Host.dll"]

View File

@@ -6,6 +6,8 @@ services:
container_name: nashel-backend
ports:
- "5000:8080"
volumes:
- ./uploads:/app/wwwroot/uploads
environment:
- ASPNETCORE_ENVIRONMENT=Development
- ConnectionStrings__DefaultConnection=Host=db;Port=5432;Database=nashel;Username=postgres;Password=postgres

View File

@@ -1,4 +1,6 @@
using MediatR;
using Nashel.BuildingBlocks.Application.Abstractions;
using Nashel.Modules.Identity.Domain.Repositories;
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 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)
{
var file = request.File;
@@ -35,7 +48,30 @@ public class UploadAvatarCommandHandler : IRequestHandler<UploadAvatarCommand, s
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;
}
}

View File

@@ -19,6 +19,6 @@ public class Competency
if (string.IsNullOrWhiteSpace(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() };
}
}

View File

@@ -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);
}

View File

@@ -7,6 +7,7 @@ using Nashel.BuildingBlocks.Application.Behaviors;
using Nashel.Modules.Identity.Application.Commands;
using Nashel.Modules.Identity.Domain.Repositories;
using Nashel.Modules.Identity.Domain.Services;
using Nashel.Modules.Identity.Infrastructure.CommandHandlers;
using Nashel.Modules.Identity.Infrastructure.Persistence;
using Nashel.Modules.Identity.Infrastructure.Repositories;
using Nashel.Modules.Identity.Infrastructure.Services;
@@ -26,6 +27,7 @@ public static class DependencyInjection
services.AddMediatR(cfg =>
{
cfg.RegisterServicesFromAssembly(typeof(RegisterUserCommand).Assembly);
cfg.RegisterServicesFromAssembly(typeof(UpdateProfileCompetenciesCommandHandler).Assembly);
cfg.AddBehavior(typeof(IPipelineBehavior<,>), typeof(ValidationBehavior<,>));
});