package sql import ( "context" "golang.org/x/crypto/bcrypt" "gorm.io/gorm" "git.sr.ht/~gabrielgio/img/pkg/database/repository" ) type ( User struct { gorm.Model Username string Name string Password string IsAdmin bool Path string } Users []*User UserRepository struct { db *gorm.DB } ) var _ repository.UserRepository = &UserRepository{} var _ repository.AuthRepository = &UserRepository{} func NewUserRepository(db *gorm.DB) *UserRepository { return &UserRepository{ db: db, } } func (self *User) ToModel() *repository.User { return &repository.User{ ID: self.Model.ID, Name: self.Name, Username: self.Username, Path: self.Path, IsAdmin: self.IsAdmin, } } func (self Users) ToModel() (users []*repository.User) { for _, user := range self { users = append(users, user.ToModel()) } return } // Testing function, will remove later // TODO: remove later func (self *UserRepository) EnsureAdmin(ctx context.Context) { var exists bool self.db. WithContext(ctx). Model(&User{}). Select("count(*) > 0"). Where("username = ?", "admin"). Find(&exists) if !exists { hash, _ := bcrypt.GenerateFromPassword([]byte("admin"), bcrypt.MinCost) self.db.Save(&User{ Username: "admin", Path: "/", IsAdmin: true, Password: string(hash), }) } } func (self *UserRepository) List(ctx context.Context) ([]*repository.User, error) { users := Users{} result := self.db. WithContext(ctx). Find(&users) if result.Error != nil { return nil, result.Error } return users.ToModel(), nil } func (self *UserRepository) Get(ctx context.Context, id uint) (*repository.User, error) { var user = &repository.User{ID: id} result := self.db. WithContext(ctx). First(user) if result.Error != nil { return nil, result.Error } return user, nil } func (self *UserRepository) GetIDByUsername(ctx context.Context, username string) (uint, error) { userID := struct { ID uint }{} result := self.db. WithContext(ctx). Model(&User{}). Where("username = ?", username). First(&userID) if result.Error != nil { return 0, result.Error } return userID.ID, nil } func (self *UserRepository) GetPassword(ctx context.Context, id uint) ([]byte, error) { userPassword := struct { Password []byte }{} result := self.db. WithContext(ctx). Model(&User{}). Where("id = ?", id). First(&userPassword) if result.Error != nil { return nil, result.Error } return userPassword.Password, nil } func (self *UserRepository) Create(ctx context.Context, createUser *repository.CreateUser) (uint, error) { user := &User{ Username: createUser.Username, Name: createUser.Name, Password: string(createUser.Password), } result := self.db. WithContext(ctx). Create(user) if result.Error != nil { return 0, result.Error } return user.Model.ID, nil } func (self *UserRepository) Update(ctx context.Context, id uint, update *repository.UpdateUser) error { user := &User{ Model: gorm.Model{ ID: id, }, Username: update.Username, Name: update.Name, } result := self.db. WithContext(ctx). Save(user) if result.Error != nil { return result.Error } return nil } func (self *UserRepository) Delete(ctx context.Context, id uint) error { userID := struct { ID uint }{ ID: id, } result := self.db. WithContext(ctx). Delete(userID) if result.Error != nil { return result.Error } return nil } func (u *UserRepository) Any(ctx context.Context) (bool, error) { var exists bool result := u.db. WithContext(ctx). Model(&User{}). Select("count(id) > 0"). Find(&exists) if result.Error != nil { return false, result.Error } return exists, nil }