예제 #1
0
        /// <inheritdoc />
        public async Task <ICollection <User> > CreateUser <TModel, TRegisterModel>(
            ICollection <TRegisterModel> models,
            UpdateOptions options          = null,
            CancellationToken cancellation = default)
            where TModel : User, IOwnerAbstractModel, new()
            where TRegisterModel : IRegistrationModel <TModel>
        {
            await _identityService.RetrieveUserAsync();

            var dbModels = models.Select(m => m.ToModel()).ToList();
            var dbSet    = _dbContext.Set <TModel>();

            var roles   = models.SelectMany(m => m.Groups).ToList();
            var dbRoles = await _dbContext.Roles.Where(r => roles.Contains(r.Name)).ToListAsync(cancellation);


            using (var transaction = _dbContext.Database.BeginTransaction())
            {
                try
                {
                    await MergeReferences(dbModels, options, cancellation);

                    var modelPairs = models.Select(model => (model, model.ToModel())).ToList();

                    // Create each user
                    var createdUsers = new List <User>();
                    foreach (var(registrationModel, model) in modelPairs)
                    {
                        if (model.Id == Guid.Empty)
                        {
                            model.Id = Guid.NewGuid();
                        }

                        foreach (var group in registrationModel.Groups)
                        {
                            var role = dbRoles.First(r => r.Name == group);
                            _dbContext.UserRoles.Add(new IdentityUserRole <Guid> {
                                UserId = model.Id, RoleId = role.Id
                            });
                        }

                        // Validate the password matches the applications password strength
                        var validationTasks = _userManager
                                              .PasswordValidators
                                              .Select(v => v.ValidateAsync(_userManager, model, registrationModel.Password));
                        var validationResults = await Task.WhenAll(validationTasks);

                        var failed = validationResults.Where(r => r.Succeeded == false).ToList();
                        if (failed.Any())
                        {
                            throw new AggregateException(failed
                                                         .SelectMany(f => f.Errors.Select(s => s.Description))
                                                         .Select(s => new InvalidOperationException(s)));
                        }


                        model.UserName         = model.Email;
                        model.PasswordHash     = _userManager.PasswordHasher.HashPassword(model, registrationModel.Password);
                        model.ConcurrencyStamp = await _userManager.GenerateConcurrencyStampAsync(model);

                        model.NormalizedEmail    = _userManager.NormalizeEmail(model.Email);
                        model.NormalizedUserName = _userManager.NormalizeName(model.UserName);
                        model.EmailConfirmed     = true;
                        model.SecurityStamp      = Guid.NewGuid().ToString();
                        dbSet.Update(model);

                        createdUsers.Add(model);
                    }

                    // Ensure that we create all of the base entities instead of updating
                    var addedEntries = _dbContext.ChangeTracker.Entries()
                                       .Where(entry => createdUsers.Contains(entry.Entity));
                    foreach (var entry in addedEntries)
                    {
                        entry.State = EntityState.Added;
                    }

                    var fileModels = _dbContext
                                     .ChangeTracker
                                     .Entries()
                                     .Where(e => e.State == EntityState.Added || e.State == EntityState.Modified)
                                     .Select(e => e.Entity)
                                     .ToList();
                    if (options?.Files != null)
                    {
                        await SaveFiles(fileModels, options.Files, cancellation);
                    }
                    else
                    {
                        ClearFileAttributes(models);
                    }

                    await AssignModelMetaData(_identityService.User, cancellation);

                    ValidateModels(_dbContext.ChangeTracker
                                   .Entries()
                                   .Where(e => e.State == EntityState.Added || e.State == EntityState.Modified)
                                   .Select(e => e.Entity));

                    foreach (var user in createdUsers)
                    {
                        user.Owner = user.Id;
                    }

                    var errors = await _securityService.CheckDbSecurityChanges(_identityService, _dbContext);

                    if (errors.Any())
                    {
                        throw new AggregateException(
                                  errors.Select(error => new InvalidOperationException(error)));
                    }

                    foreach (var entry in _dbContext.ChangeTracker.Entries <IAbstractModel>().ToList())
                    {
                        await entry.Entity.BeforeSave(entry.State, _dbContext, _serviceProvider);
                    }

                    var changes = _dbContext
                                  .ChangeTracker
                                  .Entries <IAbstractModel>()
                                  .Select(e => new ChangeState {
                        State = e.State, Entry = e
                    })
                                  .ToList();
                    await _dbContext.SaveChangesAsync(cancellation);

                    foreach (var change in changes)
                    {
                        await change.Entry.Entity.AfterSave(change.State, _dbContext, _serviceProvider, changes);
                    }

                    transaction.Commit();

                    return(createdUsers);
                }
                catch (Exception e)
                {
                    _logger.LogError("Error completing create user action - {Error}", e.ToString());
                    throw;
                }
            }
        }
예제 #2
0
        /// <inheritdoc />
        public async Task <ICollection <T> > Update <T>(
            ICollection <T> models,
            UpdateOptions options          = null,
            CancellationToken cancellation = default)
            where T : class, IOwnerAbstractModel, new()
        {
            await _identityService.RetrieveUserAsync();

            var dbSet = _dbContext.Set <T>();

            using (var transaction = _dbContext.Database.BeginTransaction())
            {
                try
                {
                    await MergeReferences(models, options, cancellation);

                    foreach (var model in models)
                    {
                        dbSet.Update(model);
                    }

                    var fileModels = _dbContext
                                     .ChangeTracker
                                     .Entries()
                                     .Where(e => e.State == EntityState.Added || e.State == EntityState.Modified)
                                     .Select(e => e.Entity)
                                     .ToList();
                    if (options?.Files != null)
                    {
                        await SaveFiles(fileModels, options.Files, cancellation);
                    }
                    else
                    {
                        ClearFileAttributes(models);
                    }

                    await AssignModelMetaData(_identityService.User, cancellation);

                    ValidateModels(_dbContext.ChangeTracker
                                   .Entries()
                                   .Where(e => e.State == EntityState.Added || e.State == EntityState.Modified)
                                   .Select(e => e.Entity));


                    var errors = await _securityService.CheckDbSecurityChanges(_identityService, _dbContext);

                    if (errors.Any())
                    {
                        throw new AggregateException(
                                  errors.Select(error => new InvalidOperationException(error)));
                    }

                    foreach (var entry in _dbContext.ChangeTracker.Entries <IAbstractModel>().ToList())
                    {
                        await entry.Entity.BeforeSave(entry.State, _dbContext, _serviceProvider);
                    }


                    var changes = _dbContext
                                  .ChangeTracker
                                  .Entries <IAbstractModel>()
                                  .Select(e => new ChangeState {
                        State = e.State, Entry = e
                    })
                                  .ToList();
                    await _dbContext.SaveChangesAsync(cancellation);

                    foreach (var change in changes)
                    {
                        await change.Entry.Entity.AfterSave(change.State, _dbContext, _serviceProvider, changes);
                    }

                    transaction.Commit();

                    return(models);
                }
                catch (Exception e)
                {
                    _logger.LogError("Error completing update action - {Error}", e.ToString());
                    throw;
                }
            }
        }