namespace MyOffice.Services.Account; using System.Collections.Generic; using Core; using Core.Extensions; using Data.Models.Accounts; using Domain; public partial class AccountService { public async Task> AccessInviteAsync( Guid userId, Guid accountId, string email, bool isAllowWrite, CancellationToken cancellationToken = default) { if (email == null) throw new ArgumentNullException(nameof(email)); var result = new Exec(AccessInviteStatus.success); var account = await _accountRepository.GetAsync(userId, accountId, cancellationToken); if (account == null) { return result.Set(AccessInviteStatus.account_not_found); } if (!CanManage(account, userId)) { return result.Set(AccessInviteStatus.forbidden); } if (account.AccessRights!.Any(x => x.User!.Email.EqualsIgnoreCase(email))) { return result.Set(AccessInviteStatus.access_exists); } var access = await _accountAccessInviteRepository.GetAsync(userId, email, cancellationToken); if (access != null) { return result.Set(AccessInviteStatus.invite_exists); } var invite = new AccountAccessInvite { Id = Guid.NewGuid(), CreatedOn = DateTime.UtcNow, UserId = userId, AccountId = account.Id, Email = email.SafeTrim()!, IsAllowWrite = isAllowWrite, }; await _accountAccessInviteRepository.AddAsync(invite, cancellationToken); return result.Set(_mapper.Map(invite)); } public async Task> AccessUpdateAsync( Guid userId, Guid accountId, List accesses, CancellationToken cancellationToken = default) { if (accesses == null) throw new ArgumentNullException(nameof(accesses)); var result = new Exec(GeneralExecStatus.success); var account = await _accountRepository.GetAsync(userId, accountId, cancellationToken); if (account == null) { return result.Set(GeneralExecStatus.not_found); } if (!CanManage(account, userId)) { return result.Set(GeneralExecStatus.forbidden); } foreach (var access in account.AccessRights!) { var newAccess = accesses.FirstOrDefault(x => x.UserId == access.UserId); if (newAccess != null && newAccess.IsAllowWrite != access.IsAllowWrite) { access.IsAllowWrite = newAccess.IsAllowWrite; await _accountAccessRepository.UpdateAsync(access, cancellationToken); } } account = await _accountRepository.GetAsync(userId, accountId, cancellationToken); return result.Set(_mapper.Map(account)); } public async Task> AccessDeleteAsync( Guid userId, Guid accountId, Guid accessUserId, CancellationToken cancellationToken = default) { var result = new Exec(GeneralExecStatus.success); var account = await _accountRepository.GetAsync(userId, accountId, cancellationToken); if (account == null || !account.AccessRights!.Any() || account.AccessRights!.Count() == 1) { return result.Set(GeneralExecStatus.not_found); } if (!CanManage(account, userId)) { return result.Set(GeneralExecStatus.forbidden); } var access = account.AccessRights!.FirstOrDefault(x => x.UserId == accessUserId); if (access == null) { return result.Set(GeneralExecStatus.not_found); } if (access.OwnerId == access.UserId) { return result.Set(GeneralExecStatus.not_found); } await _accountAccessRepository.DeleteAsync(access, cancellationToken); account = await _accountRepository.GetAsync(userId, accountId, cancellationToken); return result.Set(_mapper.Map(account)); } public async Task> InvitesGetAsync(string email, CancellationToken cancellationToken = default) { var invites = await _accountAccessInviteRepository.GetActiveAsync(email, cancellationToken); return _mapper.Map>(invites); } public async Task> InviteAcceptAsync( Guid userId, Guid id, string name, CancellationToken cancellationToken = default) { var result = new Exec(InviteAcceptStatus.success); var invite = await _accountAccessInviteRepository.GetAsync(id, cancellationToken); if (invite == null || !invite.Email.EqualsIgnoreCase(_contextProvider.User.Email) || invite.AcceptedOn.HasValue || invite.RejectedOn.HasValue ) { return result.Set(InviteAcceptStatus.invite_not_found); } var account = await _accountRepository.GetAsync(invite.UserId, invite.AccountId, cancellationToken); if (account == null) { return result.Set(InviteAcceptStatus.account_not_found); } if (account.AccessRights!.Any(x => x.UserId == userId)) { result.Set(InviteAcceptStatus.already_accepted); } else { await _accountAccessRepository.AddAsync(new AccountAccess { UserId = userId, AccountId = account.Id, OwnerId = invite.UserId, Name = name, IsAllowRead = true, IsAllowWrite = invite.IsAllowWrite, IsAllowManage = false, Type = AccountAccessTypeEnum.external, }, cancellationToken); } invite.AcceptedOn = DateTime.UtcNow; await _accountAccessInviteRepository.UpdateAsync(invite, cancellationToken); account = await _accountRepository.GetAsync(userId, account.Id, cancellationToken); return result.Set(_mapper.Map(account)); } public async Task> InviteRejectAsync( Guid id, CancellationToken cancellationToken = default) { var result = new Exec(GeneralExecStatus.success); var invite = await _accountAccessInviteRepository.GetAsync(id, cancellationToken); if (invite == null || !invite.Email.EqualsIgnoreCase(_contextProvider.User.Email) || invite.AcceptedOn.HasValue || invite.RejectedOn.HasValue ) { return result.Set(GeneralExecStatus.not_found); } invite.RejectedOn = DateTime.UtcNow; await _accountAccessInviteRepository.UpdateAsync(invite, cancellationToken); return result.Set(_mapper.Map(invite)); } }