예제 #1
0
        public async Task Create_should_add_user()
        {
            var identity = CreateIdentity(found: false);

            var values = new UserValues
            {
                Email = identity.Email
            };

            SetupCreation(identity, 1);

            await sut.CreateAsync(values.Email, values);

            A.CallTo(() => userEvents.OnUserRegistered(A <IUser> .That.Matches(x => x.Identity == identity)))
            .MustHaveHappened();

            A.CallTo(() => userEvents.OnConsentGiven(A <IUser> .That.Matches(x => x.Identity == identity)))
            .MustNotHaveHappened();

            A.CallTo(() => userManager.AddToRoleAsync(identity, A <string> ._))
            .MustNotHaveHappened();

            A.CallTo(() => userManager.AddPasswordAsync(identity, A <string> ._))
            .MustNotHaveHappened();

            A.CallTo(() => userManager.SetLockoutEndDateAsync(identity, A <DateTimeOffset> ._))
            .MustNotHaveHappened();
        }
예제 #2
0
        private static bool HasConsentGiven(UserValues values, IUser?oldUser)
        {
            if (values.Consent == true && oldUser?.Claims.HasConsent() != true)
            {
                return(true);
            }

            return(values.ConsentForEmails == true && oldUser?.Claims.HasConsentForEmails() != true);
        }
예제 #3
0
        public async Task Update_should_throw_exception_if_not_found()
        {
            var update = new UserValues
            {
                Email = "*****@*****.**"
            };

            var identity = CreateIdentity(found: false);

            await Assert.ThrowsAsync <DomainObjectNotFoundException>(() => sut.UpdateAsync(identity.Id, update));
        }
예제 #4
0
        public async Task InitializeAsync(
            CancellationToken ct)
        {
            if (users?.Length > 0)
            {
                await using (var scope = serviceProvider.CreateAsyncScope())
                {
                    var userService = scope.ServiceProvider.GetRequiredService <IUserService>() !;

                    foreach (var user in users)
                    {
                        if (user?.IsConfigured() == true)
                        {
                            try
                            {
                                var existing = await userService.FindByEmailAsync(user.Email, ct);

                                var passwordValues = new UserValues {
                                    Password = user.Password
                                };

                                if (existing == null)
                                {
                                    existing = await userService.CreateAsync(user.Email, passwordValues, ct : ct);
                                }
                                else if (user.PasswordReset)
                                {
                                    await userService.UpdateAsync(existing.Id, passwordValues, ct : ct);
                                }

                                if (!string.IsNullOrWhiteSpace(user.Role))
                                {
                                    var values = new UserValues
                                    {
                                        Roles = new HashSet <string>
                                        {
                                            user.Role
                                        }
                                    };

                                    await userService.UpdateAsync(existing.Id, values, ct : ct);
                                }
                            }
                            catch (Exception ex)
                            {
                                var log = serviceProvider.GetRequiredService <ILogger <UserCreator> >();

                                log.LogError(ex, "Failed to create initial user with email {email}.", user.Email);
                            }
                        }
                    }
                }
            }
        }
예제 #5
0
        public async Task Update_should_do_nothing_for_new_update()
        {
            var update = new UserValues();

            var identity = CreateIdentity(found: true);

            await sut.UpdateAsync(identity.Id, update);

            A.CallTo(() => userEvents.OnUserUpdated(A <IUser> .That.Matches(x => x.Identity == identity)))
            .MustHaveHappened();
        }
예제 #6
0
        public async Task Update_should_add_to_role()
        {
            var update = new UserValues
            {
                Role = "admin"
            };

            var identity = CreateIdentity(found: true);

            await sut.UpdateAsync(identity.Id, update);

            A.CallTo(() => userManager.AddToRoleAsync(identity, "admin"))
            .MustHaveHappened();
        }
예제 #7
0
        public async Task <IUser> UpdateAsync(string id, UserValues values)
        {
            Guard.NotNullOrEmpty(id, nameof(id));
            Guard.NotNull(values, nameof(values));

            var user = await GetUserAsync(id);

            var oldUser = await ResolveAsync(user);

            if (!string.IsNullOrWhiteSpace(values.Email) && values.Email != user.Email)
            {
                await userManager.SetEmailAsync(user, values.Email).Throw(log);

                await userManager.SetUserNameAsync(user, values.Email).Throw(log);
            }

            await userManager.SyncClaims(user, values).Throw(log);

            if (!string.IsNullOrWhiteSpace(values.Password))
            {
                if (await userManager.HasPasswordAsync(user))
                {
                    await userManager.RemovePasswordAsync(user).Throw(log);
                }

                await userManager.AddPasswordAsync(user, values.Password).Throw(log);
            }

            if (!string.IsNullOrWhiteSpace(values.Role) && !await userManager.IsInRoleAsync(user, values.Role))
            {
                await userManager.AddToRoleAsync(user, values.Role).Throw(log);
            }

            var resolved = await ResolveAsync(user);

            foreach (var @events in userEvents)
            {
                @events.OnUserUpdated(resolved);
            }

            if (HasConsentGiven(values, oldUser))
            {
                foreach (var @events in userEvents)
                {
                    @events.OnConsentGiven(resolved);
                }
            }

            return(resolved);
        }
예제 #8
0
        public async Task Create_should_raise_event_if_consent_given()
        {
            var identity = CreateIdentity(found: false);

            var values = new UserValues
            {
                Consent = true,
            };

            SetupCreation(identity, 1);

            await sut.CreateAsync(identity.Email, values);

            A.CallTo(() => userEvents.OnConsentGiven(A <IUser> .That.Matches(x => x.Identity == identity)))
            .MustHaveHappened();
        }
예제 #9
0
        public async Task Create_should_set_admin_if_first_user()
        {
            var identity = CreateIdentity(found: false);

            var values = new UserValues
            {
                Consent = true,
            };

            SetupCreation(identity, 0);

            await sut.CreateAsync(identity.Email, values);

            A.CallTo(() => userManager.AddToRoleAsync(identity, NotifoRoles.AppAdmin))
            .MustHaveHappened();
        }
예제 #10
0
        public async Task Create_should_add_password()
        {
            var identity = CreateIdentity(found: false);

            var values = new UserValues
            {
                Password = "******"
            };

            SetupCreation(identity, 1);

            await sut.CreateAsync(identity.Email, values, false);

            A.CallTo(() => userManager.AddPasswordAsync(identity, values.Password))
            .MustHaveHappened();
        }
예제 #11
0
        public async Task Create_should_lock_second_user()
        {
            var identity = CreateIdentity(found: false);

            var values = new UserValues
            {
                Consent = true,
            };

            SetupCreation(identity, 1);

            await sut.CreateAsync(identity.Email, values, true);

            A.CallTo(() => userManager.SetLockoutEndDateAsync(identity, InFuture()))
            .MustHaveHappened();
        }
예제 #12
0
        public async Task Create_should_not_lock_first_user()
        {
            var identity = CreateIdentity(found: false);

            var values = new UserValues
            {
                Consent = true,
            };

            SetupCreation(identity, 0);

            await sut.CreateAsync(identity.Email, values, true);

            A.CallTo(() => userManager.SetLockoutEndDateAsync(identity, A <DateTimeOffset> ._))
            .MustNotHaveHappened();
        }
예제 #13
0
        public async Task Update_should_set_claim_if_email_consent_given()
        {
            var update = new UserValues
            {
                ConsentForEmails = true
            };

            var identity = CreateIdentity(found: true);

            await sut.UpdateAsync(identity.Id, update);

            A.CallTo <Task <IdentityResult> >(() => userManager.AddClaimsAsync(identity, HasClaim(NotifoClaimTypes.ConsentForEmails)))
            .MustHaveHappened();

            A.CallTo(() => userEvents.OnConsentGiven(A <IUser> .That.Matches(x => x.Identity == identity)))
            .MustHaveHappened();
        }
예제 #14
0
        public async Task Update_should_change_email_if_changed()
        {
            var update = new UserValues
            {
                Email = "*****@*****.**"
            };

            var identity = CreateIdentity(found: true);

            await sut.UpdateAsync(identity.Id, update);

            A.CallTo(() => userManager.SetEmailAsync(identity, update.Email))
            .MustHaveHappened();

            A.CallTo(() => userManager.SetUserNameAsync(identity, update.Email))
            .MustHaveHappened();
        }
예제 #15
0
        public async Task InitializeAsync(CancellationToken cancellationToken)
        {
            if (users != null && users.Length > 0)
            {
                using (var scope = serviceProvider.CreateScope())
                {
                    var userService = scope.ServiceProvider.GetRequiredService <IUserService>() !;

                    foreach (var user in users)
                    {
                        if (user?.IsConfigured() == true)
                        {
                            try
                            {
                                var existing = await userService.FindByEmailAsync(user.Email);

                                var passwordValues = new UserValues {
                                    Password = user.Password
                                };

                                if (existing == null)
                                {
                                    existing = await userService.CreateAsync(user.Email, passwordValues);
                                }
                                else if (user.PasswordReset)
                                {
                                    await userService.UpdateAsync(existing.Id, passwordValues);
                                }

                                if (!string.IsNullOrWhiteSpace(user.Role))
                                {
                                    await userService.UpdateAsync(existing.Id, new UserValues { Role = user.Role });
                                }
                            }
                            catch (Exception ex)
                            {
                                log.LogError(ex, w => w
                                             .WriteProperty("action", "CreateUser")
                                             .WriteProperty("status", "Failed")
                                             .WriteProperty("email", user.Email));
                            }
                        }
                    }
                }
            }
        }
예제 #16
0
        public async Task Update_should_remove_from_role()
        {
            var update = new UserValues
            {
                Roles = new HashSet <string>()
            };

            var identity = CreateIdentity(found: true);

            A.CallTo(() => userManager.GetRolesAsync(identity))
            .Returns(new List <string> {
                "admin"
            });

            await sut.UpdateAsync(identity.Id, update, ct : ct);

            A.CallTo(() => userManager.RemoveFromRoleAsync(identity, "admin"))
            .MustHaveHappened();
        }
예제 #17
0
        public async Task Update_should_change_password_if_changed()
        {
            var update = new UserValues
            {
                Password = "******"
            };

            var identity = CreateIdentity(found: true);

            A.CallTo(() => userManager.HasPasswordAsync(identity))
            .Returns(true);

            await sut.UpdateAsync(identity.Id, update);

            A.CallTo(() => userManager.RemovePasswordAsync(identity))
            .MustHaveHappened();

            A.CallTo(() => userManager.AddPasswordAsync(identity, update.Password))
            .MustHaveHappened();
        }
예제 #18
0
        public static async Task <IdentityResult> SyncClaims(this UserManager <IdentityUser> userManager, IdentityUser user, UserValues values)
        {
            var current = await userManager.GetClaimsAsync(user);

            var claimsToRemove = new List <Claim>();
            var claimsToAdd    = new List <Claim>();

            void RemoveClaims(Func <Claim, bool> predicate)
            {
                claimsToAdd.RemoveAll(x => predicate(x));
                claimsToRemove.AddRange(current.Where(predicate));
            }

            void AddClaim(string type, string value)
            {
                claimsToAdd.Add(new Claim(type, value));
            }

            void SyncBoolean(string type, bool?value)
            {
                if (value != null)
                {
                    RemoveClaims(x => x.Type == type);

                    if (value == true)
                    {
                        AddClaim(type, value.ToString() !);
                    }
                }
            }

            SyncBoolean(NotifoClaimTypes.Consent, values.Consent);
            SyncBoolean(NotifoClaimTypes.ConsentForEmails, values.ConsentForEmails);
            SyncBoolean(NotifoClaimTypes.Invited, values.Invited);

            if (claimsToRemove.Count > 0)
            {
                var result = await userManager.RemoveClaimsAsync(user, claimsToRemove);

                if (!result.Succeeded)
                {
                    return(result);
                }
            }

            if (claimsToAdd.Count > 0)
            {
                return(await userManager.AddClaimsAsync(user, claimsToAdd));
            }

            return(IdentityResult.Success);
        }
예제 #19
0
        public async Task <IUser> UpdateAsync(string id, UserValues values, bool silent = false,
                                              CancellationToken ct = default)
        {
            Guard.NotNullOrEmpty(id);
            Guard.NotNull(values);

            var user = await GetUserAsync(id);

            if (!string.IsNullOrWhiteSpace(values.Email) && values.Email != user.Email)
            {
                await userManager.SetEmailAsync(user, values.Email).Throw(log);

                await userManager.SetUserNameAsync(user, values.Email).Throw(log);
            }

            await userManager.SyncClaims(user, values).Throw(log);

            if (!string.IsNullOrWhiteSpace(values.Password))
            {
                if (await userManager.HasPasswordAsync(user))
                {
                    await userManager.RemovePasswordAsync(user).Throw(log);
                }

                await userManager.AddPasswordAsync(user, values.Password).Throw(log);
            }

            var oldUser = await ResolveAsync(user);

            if (values.Roles != null)
            {
                foreach (var role in values.Roles.Where(x => !oldUser.Roles.Contains(x)))
                {
                    await userManager.AddToRoleAsync(user, role).Throw(log);
                }

                foreach (var role in oldUser.Roles.Where(x => !values.Roles.Contains(x)))
                {
                    await userManager.RemoveFromRoleAsync(user, role).Throw(log);
                }
            }

            var resolved = await ResolveAsync(user);

            if (!silent)
            {
                foreach (var @events in userEvents)
                {
                    await @events.OnUserUpdatedAsync(resolved, oldUser);
                }

                if (HasConsentGiven(values, oldUser))
                {
                    foreach (var @events in userEvents)
                    {
                        await @events.OnConsentGivenAsync(resolved);
                    }
                }
            }

            return(resolved);
        }