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