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/components/auth"
10 user "git.sr.ht/~gabrielgio/img/pkg/components/auth"
11)
12
13type (
14 User struct {
15 gorm.Model
16 Username string
17 Name string
18 Password string
19 }
20
21 Users []*User
22
23 UserRepository struct {
24 db *gorm.DB
25 }
26)
27
28var _ auth.Repository = &UserRepository{}
29
30func NewUserRepository(db *gorm.DB) *UserRepository {
31 return &UserRepository{
32 db: db,
33 }
34}
35
36func (self *User) ToModel() *user.User {
37 return &user.User{
38 ID: self.Model.ID,
39 Name: self.Name,
40 Username: self.Username,
41 }
42}
43
44func (self Users) ToModel() (users []*user.User) {
45 for _, user := range self {
46 users = append(users, user.ToModel())
47 }
48 return
49}
50
51// Testing function, will remove later
52// TODO: remove later
53func (self *UserRepository) EnsureAdmin(ctx context.Context) {
54 var exists bool
55 self.db.
56 WithContext(ctx).
57 Model(&User{}).
58 Select("count(*) > 0").
59 Where("username = ?", "admin").
60 Find(&exists)
61
62 if !exists {
63 hash, _ := bcrypt.GenerateFromPassword([]byte("admin"), bcrypt.MinCost)
64 self.db.Save(&User{
65 Username: "admin",
66 Password: string(hash),
67 })
68 }
69}
70
71func (self *UserRepository) List(ctx context.Context) ([]*user.User, error) {
72 users := Users{}
73 result := self.db.
74 WithContext(ctx).
75 Find(&users)
76
77 if result.Error != nil {
78 return nil, result.Error
79 }
80
81 return users.ToModel(), nil
82}
83
84func (self *UserRepository) Get(ctx context.Context, id uint) (*user.User, error) {
85 var user = &user.User{ID: id}
86 result := self.db.
87 WithContext(ctx).
88 First(user)
89
90 if result.Error != nil {
91 return nil, result.Error
92 }
93
94 return user, nil
95}
96
97func (self *UserRepository) GetIDByUsername(ctx context.Context, username string) (uint, error) {
98 userID := struct {
99 ID uint
100 }{}
101
102 result := self.db.
103 WithContext(ctx).
104 Model(&User{}).
105 Where("username = ?", username).
106 First(&userID)
107
108 if result.Error != nil {
109 return 0, result.Error
110 }
111
112 return userID.ID, nil
113}
114
115func (self *UserRepository) GetPassword(ctx context.Context, id uint) ([]byte, error) {
116 userPassword := struct {
117 Password []byte
118 }{}
119
120 result := self.db.
121 WithContext(ctx).
122 Model(&User{}).
123 Where("id = ?", id).
124 First(&userPassword)
125
126 if result.Error != nil {
127 return nil, result.Error
128 }
129
130 return userPassword.Password, nil
131}
132
133func (self *UserRepository) Create(ctx context.Context, createUser *user.CreateUser) (uint, error) {
134 user := &User{
135 Username: createUser.Username,
136 Name: createUser.Name,
137 Password: string(createUser.Password),
138 }
139
140 result := self.db.
141 WithContext(ctx).
142 Create(user)
143 if result.Error != nil {
144 return 0, result.Error
145 }
146
147 return user.Model.ID, nil
148}
149
150func (self *UserRepository) Update(ctx context.Context, id uint, update *user.UpdateUser) error {
151 user := &User{
152 Model: gorm.Model{
153 ID: id,
154 },
155 Username: update.Username,
156 Name: update.Name,
157 }
158
159 result := self.db.
160 WithContext(ctx).
161 Save(user)
162 if result.Error != nil {
163 return result.Error
164 }
165
166 return nil
167}
168
169func (self *UserRepository) Delete(ctx context.Context, id uint) error {
170 userID := struct {
171 ID uint
172 }{
173 ID: id,
174 }
175 result := self.db.
176 WithContext(ctx).
177 Delete(userID)
178 if result.Error != nil {
179 return result.Error
180 }
181 return nil
182}