lens @ 2a986064a2657c9091a31a941ce0d004191b8453

  1package sql
  2
  3import (
  4	"context"
  5
  6	"golang.org/x/crypto/bcrypt"
  7	"gorm.io/gorm"
  8
  9	"git.sr.ht/~gabrielgio/img/pkg/database/repository"
 10)
 11
 12type (
 13	User struct {
 14		gorm.Model
 15		Username string
 16		Name     string
 17		Password string
 18		IsAdmin  bool
 19		Path     string
 20	}
 21
 22	Users []*User
 23
 24	UserRepository struct {
 25		db *gorm.DB
 26	}
 27)
 28
 29var _ repository.UserRepository = &UserRepository{}
 30
 31var _ repository.AuthRepository = &UserRepository{}
 32
 33func NewUserRepository(db *gorm.DB) *UserRepository {
 34	return &UserRepository{
 35		db: db,
 36	}
 37}
 38
 39func (self *User) ToModel() *repository.User {
 40	return &repository.User{
 41		ID:       self.Model.ID,
 42		Name:     self.Name,
 43		Username: self.Username,
 44		Path:     self.Path,
 45		IsAdmin:  self.IsAdmin,
 46	}
 47}
 48
 49func (self Users) ToModel() (users []*repository.User) {
 50	for _, user := range self {
 51		users = append(users, user.ToModel())
 52	}
 53	return
 54}
 55
 56// Testing function, will remove later
 57// TODO: remove later
 58func (self *UserRepository) EnsureAdmin(ctx context.Context) {
 59	var exists bool
 60	self.db.
 61		WithContext(ctx).
 62		Model(&User{}).
 63		Select("count(*) > 0").
 64		Where("username = ?", "admin").
 65		Find(&exists)
 66
 67	if !exists {
 68		hash, _ := bcrypt.GenerateFromPassword([]byte("admin"), bcrypt.MinCost)
 69		self.db.Save(&User{
 70			Username: "admin",
 71			Path:     "/",
 72			IsAdmin:  true,
 73			Password: string(hash),
 74		})
 75	}
 76}
 77
 78func (self *UserRepository) List(ctx context.Context) ([]*repository.User, error) {
 79	users := Users{}
 80	result := self.db.
 81		WithContext(ctx).
 82		Find(&users)
 83
 84	if result.Error != nil {
 85		return nil, result.Error
 86	}
 87
 88	return users.ToModel(), nil
 89}
 90
 91func (self *UserRepository) Get(ctx context.Context, id uint) (*repository.User, error) {
 92	var user = &repository.User{ID: id}
 93	result := self.db.
 94		WithContext(ctx).
 95		First(user)
 96
 97	if result.Error != nil {
 98		return nil, result.Error
 99	}
100
101	return user, nil
102}
103
104func (self *UserRepository) GetIDByUsername(ctx context.Context, username string) (uint, error) {
105	userID := struct {
106		ID uint
107	}{}
108
109	result := self.db.
110		WithContext(ctx).
111		Model(&User{}).
112		Where("username = ?", username).
113		First(&userID)
114
115	if result.Error != nil {
116		return 0, result.Error
117	}
118
119	return userID.ID, nil
120}
121
122func (self *UserRepository) GetPassword(ctx context.Context, id uint) ([]byte, error) {
123	userPassword := struct {
124		Password []byte
125	}{}
126
127	result := self.db.
128		WithContext(ctx).
129		Model(&User{}).
130		Where("id = ?", id).
131		First(&userPassword)
132
133	if result.Error != nil {
134		return nil, result.Error
135	}
136
137	return userPassword.Password, nil
138}
139
140func (self *UserRepository) Create(ctx context.Context, createUser *repository.CreateUser) (uint, error) {
141	user := &User{
142		Username: createUser.Username,
143		Name:     createUser.Name,
144		Path:     createUser.Path,
145		IsAdmin:  createUser.IsAdmin,
146		Password: string(createUser.Password),
147	}
148
149	result := self.db.
150		WithContext(ctx).
151		Create(user)
152	if result.Error != nil {
153		return 0, result.Error
154	}
155
156	return user.Model.ID, nil
157}
158
159func (self *UserRepository) Update(ctx context.Context, id uint, update *repository.UpdateUser) error {
160	user := &User{
161		Model: gorm.Model{
162			ID: id,
163		},
164		Username: update.Username,
165		Name:     update.Name,
166		IsAdmin:  update.IsAdmin,
167		Path:     update.Path,
168	}
169
170	result := self.db.
171		WithContext(ctx).
172		Omit("password").
173		Updates(user)
174	if result.Error != nil {
175		return result.Error
176	}
177
178	return nil
179}
180
181func (self *UserRepository) Delete(ctx context.Context, id uint) error {
182	user := &User{
183		Model: gorm.Model{
184			ID: id,
185		},
186	}
187
188	result := self.db.
189		WithContext(ctx).
190		Delete(user)
191	if result.Error != nil {
192		return result.Error
193	}
194	return nil
195}
196
197func (u *UserRepository) Any(ctx context.Context) (bool, error) {
198	var exists bool
199	result := u.db.
200		WithContext(ctx).
201		Model(&User{}).
202		Select("count(id) > 0").
203		Find(&exists)
204
205	if result.Error != nil {
206		return false, result.Error
207	}
208
209	return exists, nil
210}
211
212func (u *UserRepository) GetPathFromUserID(ctx context.Context, id uint) (string, error) {
213	var userPath string
214
215	result := u.db.
216		WithContext(ctx).
217		Model(&User{}).
218		Select("path").
219		Where("id = ?", id).
220		First(&userPath)
221
222	if result.Error != nil {
223		return "", result.Error
224	}
225
226	return userPath, nil
227}
228
229func (u *UserRepository) UpdatePassword(ctx context.Context, id uint, password []byte) error {
230	result := u.db.
231		WithContext(ctx).
232		Model(&User{}).
233		Where("id = ?", id).
234		Update("password", password)
235
236	return result.Error
237}