Пример #1
0
        public async Task <Result <Agent> > Add(UserDescriptionInfo agentRegistration,
                                                string externalIdentity,
                                                string email)
        {
            var(_, isFailure, error) = await Validate(agentRegistration, externalIdentity);

            if (isFailure)
            {
                return(Result.Failure <Agent>(error));
            }

            var createdAgent = new Agent
            {
                Title        = agentRegistration.Title,
                FirstName    = agentRegistration.FirstName,
                LastName     = agentRegistration.LastName,
                Position     = agentRegistration.Position,
                Email        = email,
                IdentityHash = HashGenerator.ComputeSha256(externalIdentity),
                Created      = _dateTimeProvider.UtcNow()
            };

            _context.Agents.Add(createdAgent);
            await _context.SaveChangesAsync();

            return(Result.Success(createdAgent));
        }
Пример #2
0
        public override async Task OnConnectedAsync()
        {
            var identityId = Context.User?.FindFirstValue("sub");

            if (string.IsNullOrEmpty(identityId))
            {
                return;
            }

            var agentId = await _context.Agents
                          .Where(a => a.IdentityHash == HashGenerator.ComputeSha256(identityId))
                          .Select(a => a.Id)
                          .SingleOrDefaultAsync();

            if (agentId == default)
            {
                return;
            }

            // TODO: In the future, we will take this information from the token.
            var agencyId = await _context.AgentAgencyRelations
                           .Where(aar => aar.AgentId == agentId)
                           .Select(aar => aar.AgencyId)
                           .SingleOrDefaultAsync();

            if (agencyId == default)
            {
                return;
            }

            await Groups.AddToGroupAsync(Context.ConnectionId, BuildGroupName(agencyId, agentId));

            await base.OnConnectedAsync();
        }
Пример #3
0
        public async Task <Result> Accept(string invitationCode, string identity, string email)
        {
            return(await GetActiveInvitation()
                   .Ensure(IsIdentityPresent, "User should have identity")
                   .Ensure(IsInvitationTypeCorrect, "Incorrect invitation type")
                   .Ensure(IsEmailUnique, "Administrator with same mail is already registered")
                   .BindWithTransaction(_context, invitation => Result.Success(invitation)
                                        .Tap(SaveAccepted)
                                        .Bind(CreateAdmin)
                                        .Tap(WriteAuditLog)));


            Task <Result <UserInvitation> > GetActiveInvitation()
            => _invitationRecordService.GetActiveInvitationByCode(invitationCode);


            bool IsIdentityPresent(UserInvitation _)
            => !string.IsNullOrWhiteSpace(identity);


            bool IsInvitationTypeCorrect(UserInvitation invitation)
            => invitation.InvitationType == UserInvitationTypes.Administrator;


            async Task <bool> IsEmailUnique(UserInvitation _)
            => !await _context.Administrators.AnyAsync(a => a.Email == email);


            Task SaveAccepted(UserInvitation _)
            => _invitationRecordService.SetAccepted(invitationCode);


            async Task <Result <Administrator> > CreateAdmin(UserInvitation invitation)
            {
                var now            = _dateTimeProvider.UtcNow();
                var invitationData = _invitationRecordService.GetInvitationData(invitation);

                var administrator = new Administrator
                {
                    Email                = email,
                    FirstName            = invitationData.UserRegistrationInfo.FirstName,
                    LastName             = invitationData.UserRegistrationInfo.LastName,
                    IdentityHash         = HashGenerator.ComputeSha256(identity),
                    Position             = invitationData.UserRegistrationInfo.Position,
                    AdministratorRoleIds = invitationData.RoleIds,
                    Created              = now,
                    Updated              = now
                };

                _context.Administrators.Add(administrator);
                await _context.SaveChangesAsync();

                return(administrator);
            }

            Task WriteAuditLog(Administrator administrator)
            => _managementAuditService.Write(ManagementEventType.AdministratorRegistration,
                                             new AdministrationRegistrationEvent(administrator.Email, administrator.Id, invitationCode));
        }
        public Task <Result <string> > Create(UserInvitationData prefilledData, UserInvitationTypes invitationType,
                                              int inviterUserId, int?inviterAgencyId = null)
        {
            var invitationCode = GenerateRandomCode();
            var now            = _dateTimeProvider.UtcNow();

            return(Result.Success()
                   .Ensure(AllProvidedRolesExist, "All roles should exist")
                   .Bind(SaveInvitation)
                   .Tap(LogInvitationCreated)
                   .Map(_ => invitationCode));


            string GenerateRandomCode()
            {
                using var provider = new RNGCryptoServiceProvider();

                var byteArray = new byte[64];

                provider.GetBytes(byteArray);

                return(Base64UrlEncoder.Encode(byteArray));
            }

            async Task <bool> AllProvidedRolesExist()
            {
                var allRoleIds = await _context.AgentRoles.Select(r => r.Id).ToListAsync();

                return(prefilledData.RoleIds.All(x => allRoleIds.Contains(x)));
            }

            async Task <Result <UserInvitation> > SaveInvitation()
            {
                var newInvitation = new UserInvitation
                {
                    CodeHash         = HashGenerator.ComputeSha256(invitationCode),
                    Email            = prefilledData.UserRegistrationInfo.Email,
                    Created          = now,
                    InviterUserId    = inviterUserId,
                    InviterAgencyId  = inviterAgencyId,
                    InvitationType   = invitationType,
                    InvitationStatus = UserInvitationStatuses.Active,
                    Data             = JsonConvert.SerializeObject(prefilledData)
                };

                _context.UserInvitations.Add(newInvitation);

                await _context.SaveChangesAsync();

                return(newInvitation);
            }

            void LogInvitationCreated()
            => _logger.LogInvitationCreated(invitationType, prefilledData.UserRegistrationInfo.Email);
        }
        public Task <Result> Set(int agencyId, int agentId, ApiClientData clientData)
        {
            return(Validate()
                   .BindWithTransaction(_context, () => SetClient()
                                        .Bind(WriteAuditLog)));


            async Task <Result> Validate()
            {
                var doesAgencyExist = await _context.AgentAgencyRelations
                                      .AnyAsync(r => r.AgencyId == agencyId && r.AgentId == agentId);

                return(doesAgencyExist
                    ? Result.Success()
                    : Result.Failure("Could not find agent and agency"));
            }

            async Task <Result> SetClient()
            {
                var existingClient = await _context.ApiClients
                                     .SingleOrDefaultAsync(a => a.AgentId == agentId && a.AgencyId == agencyId);

                if (existingClient is null)
                {
                    var doesSameNameClientExist = await _context.ApiClients.AnyAsync(a => a.Name == clientData.Name);

                    if (doesSameNameClientExist)
                    {
                        return(Result.Failure("Client with same name already exists"));
                    }

                    _context.ApiClients.Add(new ApiClient
                    {
                        AgentId      = agentId,
                        AgencyId     = agencyId,
                        Name         = clientData.Name,
                        PasswordHash = HashGenerator.ComputeSha256(clientData.Password)
                    });
                }
                else
                {
                    existingClient.Name         = clientData.Name;
                    existingClient.PasswordHash = HashGenerator.ComputeSha256(clientData.Password);
                    _context.Update(existingClient);
                }

                await _context.SaveChangesAsync();

                return(Result.Success());
            }

            Task <Result> WriteAuditLog()
            => _managementAuditService.Write(ManagementEventType.AgentApiClientCreateOrEdit, new AgentApiClientEventData(agentId, agencyId));
        }
Пример #6
0
        public Task <Result <string> > Create(UserInvitationData prefilledData, int inviterUserId)
        {
            if (prefilledData.RoleIds is null || !prefilledData.RoleIds.Any())
            {
                return(Task.FromResult(Result.Failure <string>("Invitation should have role ids")));
            }

            var invitationCode   = GenerateRandomCode();
            var now              = _dateTimeProvider.UtcNow();
            var registrationInfo = prefilledData.UserRegistrationInfo;

            return(SaveInvitation()
                   .Tap(LogInvitationCreated)
                   .Map(_ => invitationCode));


            string GenerateRandomCode()
            {
                using var provider = new RNGCryptoServiceProvider();

                var byteArray = new byte[64];

                provider.GetBytes(byteArray);

                return(Base64UrlEncoder.Encode(byteArray));
            }

            async Task <Result <UserInvitation> > SaveInvitation()
            {
                var newInvitation = new UserInvitation
                {
                    CodeHash         = HashGenerator.ComputeSha256(invitationCode),
                    Email            = registrationInfo.Email,
                    Created          = now,
                    InviterUserId    = inviterUserId,
                    InvitationType   = UserInvitationTypes.Administrator,
                    InvitationStatus = UserInvitationStatuses.Active,
                    Data             = JsonConvert.SerializeObject(prefilledData)
                };

                _context.UserInvitations.Add(newInvitation);

                await _context.SaveChangesAsync();

                return(newInvitation);
            }

            void LogInvitationCreated()
            => _logger.LogInvitationCreated(UserInvitationTypes.Administrator, registrationInfo.Email);
        }
Пример #7
0
        public async Task <Result <Administrator> > GetCurrent()
        {
            var identity = _tokenInfoAccessor.GetIdentity();

            if (string.IsNullOrWhiteSpace(identity))
            {
                return(Result.Failure <Administrator>("Identity is empty"));
            }

            var identityHash  = HashGenerator.ComputeSha256(identity);
            var administrator = await _context.Administrators
                                .SingleOrDefaultAsync(c => c.IdentityHash == identityHash);

            if (administrator != default)
            {
                return(Result.Success(administrator));
            }

            return(Result.Failure <Administrator>("Could not get administrator"));
        }
Пример #8
0
        public override async Task OnConnectedAsync()
        {
            var identityId = Context.User?.FindFirstValue("sub");

            if (string.IsNullOrEmpty(identityId))
            {
                return;
            }

            var adminId = await _context.Administrators
                          .Where(a => a.IdentityHash == HashGenerator.ComputeSha256(identityId) && a.IsActive)
                          .Select(a => a.Id)
                          .SingleOrDefaultAsync();

            if (adminId == default)
            {
                return;
            }

            await Groups.AddToGroupAsync(Context.ConnectionId, BuildGroupName(adminId));

            await base.OnConnectedAsync();
        }
Пример #9
0
        public async Task <Result> RegisterByInvitation(string invitationCode, string identity)
        {
            return(await _invitationService.GetPendingInvitation(invitationCode)
                   .BindWithTransaction(_context, invitation => Result.Success(invitation)
                                        .Map(CreateAdministrator)
                                        .Tap(AcceptInvitation)
                                        .Bind(WriteAuditLog)));


            async Task <Administrator> CreateAdministrator(AdministratorInvitationInfo info)
            {
                var now           = _dateTimeProvider.UtcNow();
                var administrator = new Administrator
                {
                    Email        = info.Email,
                    FirstName    = info.FirstName,
                    LastName     = info.LastName,
                    IdentityHash = HashGenerator.ComputeSha256(identity),
                    Position     = info.Position,
                    Created      = now,
                    Updated      = now
                };

                _context.Administrators.Add(administrator);
                await _context.SaveChangesAsync();

                return(administrator);
            }

            Task <Result> WriteAuditLog(Administrator administrator)
            => _managementAuditService.Write(ManagementEventType.AdministratorRegistration,
                                             new AdministrationRegistrationEvent(administrator.Email, administrator.Id, invitationCode));


            Task AcceptInvitation() => _invitationService.AcceptInvitation(invitationCode);
        }
Пример #10
0
 private async Task <Result> CheckIdentityIsUnique(string identity)
 {
     return(await _context.Agents.AnyAsync(a => a.IdentityHash == HashGenerator.ComputeSha256(identity))
         ? Result.Failure("User is already registered")
         : Result.Success());
 }
Пример #11
0
 public Task <Result <UserInvitation> > GetActiveInvitationByCode(string code)
 => GetActiveInvitationByHash(HashGenerator.ComputeSha256(code));