Beispiel #1
0
        public async Task <ActionResult <UserDTO> > CreateUser([FromBody] UserLoginRequestDTO dto, CancellationToken ct)
        {
            if (dto == null)
            {
                return(BadRequest());
            }

            if (!await _userSvc.CheckUsernameAvailableAsync(dto.Username, ct))
            {
                var modelErrors = new ModelStateDictionary();
                modelErrors.AddModelError("details", "That username is already in use.");
                return(Conflict(modelErrors));
            }

            if (Validators.CheckForbiddenName(dto.Username))
            {
                var modelErrors = new ModelStateDictionary();
                modelErrors.AddModelError("details", "That username is forbidden or reserved for system use.");
                return(Conflict(modelErrors));
            }

            var obj = _mapper.Map <User>(dto);

            obj.Id   = Guid.NewGuid();
            obj.Salt = PasswordUtils.GenerateSalt();
            obj.Hash = PasswordUtils.GenerateHash(dto.Password, obj.Salt);
            obj      = await _userSvc.AddUserAsync(obj, ct);

            return(CreatedAtAction(nameof(GetUser), new { id = obj.Id }, _mapper.Map <UserDTO>(obj)));
        }
Beispiel #2
0
 /// <summary>
 /// Check if the provided password matches the current User object's password.
 /// </summary>
 /// <param name="password">Password string to test</param>
 /// <returns>True if hash matches, false otherwise</returns>
 public bool CheckPassword(string password)
 {
     if (Salt != null && Hash != null)
     {
         return(Hash.Equals(PasswordUtils.GenerateHash(password, Salt), StringComparison.InvariantCulture));
     }
     else
     {
         return(false);
     }
 }
Beispiel #3
0
        public async Task <ActionResult <UserDTO> > UpdateUser(Guid id, [FromBody] UserUpdateDTO dto, CancellationToken ct)
        {
            var obj = await _userSvc.GetUserAsync(id, ct : ct);

            if (obj == null)
            {
                return(NotFound());
            }
            obj.Salt = PasswordUtils.GenerateSalt();
            obj.Hash = PasswordUtils.GenerateHash(dto.Password, obj.Salt);
            obj      = await _userSvc.UpdateUserAsync(obj, ct);

            return(Ok(_mapper.Map <UserDTO>(obj)));
        }
Beispiel #4
0
        protected override void OnModelCreating(ModelBuilder model)
        {
            #region Model configuration
            // Set certain columns to be *case insensitive*
            model.Entity <User>()
            .Property(u => u.Username)
            .HasColumnType("TEXT COLLATE NOCASE");
            model.Entity <SettingsEntry>()
            .Property(s => s.Key)
            .HasColumnType("TEXT COLLATE NOCASE");

            // Set default values
            model.Entity <Slide>()
            .Property(s => s.Order)
            .ValueGeneratedNever()
            .HasDefaultValue(999);

            model.Entity <Slide>()
            .Property(s => s.DisplaySeconds)
            .ValueGeneratedNever()
            .HasDefaultValue(20);
            #endregion

            #region Settings seeding
            #endregion

            #region Users seeding
            // Generate an admin user with a default known password.
            var adminUserSalt = PasswordUtils.GenerateSalt();
            model.Entity <User>().HasData(
                new User()
            {
                Id       = Guid.NewGuid(),
                Username = "******",
                Salt     = adminUserSalt,
                Hash     = PasswordUtils.GenerateHash("letmeslaps", adminUserSalt)
            });
            #endregion

            #region DateTimeOffset converter
            if (Database.ProviderName == "Microsoft.EntityFrameworkCore.Sqlite")
            {
                // NB: Taken from https://blog.dangl.me/archive/handling-datetimeoffset-in-sqlite-with-entity-framework-core/

                // SQLite does not have proper support for DateTimeOffset via Entity Framework Core, see the limitations
                // here: https://docs.microsoft.com/en-us/ef/core/providers/sqlite/limitations#query-limitations
                // To work around this, when the Sqlite database provider is used, all model properties of type DateTimeOffset
                // use the DateTimeOffsetToBinaryConverter
                // Based on: https://github.com/aspnet/EntityFrameworkCore/issues/10784#issuecomment-415769754
                // This only supports millisecond precision, but should be sufficient for most use cases.
                foreach (var entityType in model.Model.GetEntityTypes())
                {
                    var properties = entityType.ClrType.GetProperties().Where(p => p.PropertyType == typeof(DateTimeOffset) ||
                                                                              p.PropertyType == typeof(DateTimeOffset?));
                    foreach (var property in properties)
                    {
                        model.Entity(entityType.Name)
                        .Property(property.Name)
                        .HasConversion(new DateTimeOffsetToBinaryConverter());
                    }
                }
            }
            #endregion
        }