namespace MyOffice.Services.Users; using Domain; using Core; using Data.Models.Users; using Data.Repositories.Users; public class UserService { private readonly IUserRepository _userRepository; private readonly IUserExternalRepository _userExternalRepository; private readonly SemaphoreSlim _addExternalLock = new(1, 1); public UserService( IUserRepository userRepository, IUserExternalRepository userExternalRepository ) { _userRepository = userRepository; _userExternalRepository = userExternalRepository; } public async Task Get(Guid id) { return await _userRepository.GetUserAsync(id); } public async Task> GetUserExternals(Guid userId) { return await _userExternalRepository.GetUserExternalsByUserIdAsync(userId); } public async Task GetUserExternal(Guid userId, string provider) { return await _userExternalRepository.GetByUserIdAsync(userId, provider); } public async Task> RemoveUserExternal( Guid userId, string provider, CancellationToken cancellationToken = default) { var result = new Exec(); var userExternal = await _userExternalRepository.GetByUserIdAsync(userId, provider); if (userExternal == null) return result.Set(GeneralExecStatus.not_found); await _userExternalRepository.RemoveUserExternalAsync(userExternal, cancellationToken); return result.Set(userExternal); } public async Task> AddUserExternalAsync( Guid userId, string provider, string externalId, string email, CancellationToken cancellationToken = default ) { var result = new Exec(AddUserExternalStatusEnum.success); var externalLogin = await _userExternalRepository.GetByUserIdAsync(userId, provider); if (externalLogin != null) return result.Set(externalLogin); await _addExternalLock.WaitAsync(cancellationToken); try { externalLogin = await _userExternalRepository.GetByUserIdAsync(userId, provider); if (externalLogin != null) return result.Set(externalLogin); externalLogin = await _userExternalRepository.GetByExternalIdAsync(externalId, provider); if (externalLogin != null) return result.Set(AddUserExternalStatusEnum.externalid_used); var user = await _userRepository.GetByUserUserNameAsync(email); if (user?.Id != userId) return result.Set(AddUserExternalStatusEnum.user_not_valid); externalLogin = new UserExternal { UserId = userId, CreatedOn = DateTime.UtcNow, Provider = provider.ToLower(), ExternalId = externalId, Email = email }; await _userExternalRepository.AddUserExternalAsync(externalLogin, cancellationToken); } finally { _addExternalLock.Release(); } return result; } }