user.go 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283
  1. package store
  2. import (
  3. "context"
  4. "strings"
  5. )
  6. // Role is the type of a role.
  7. type Role string
  8. const (
  9. // RoleHost is the HOST role.
  10. RoleHost Role = "HOST"
  11. // RoleAdmin is the ADMIN role.
  12. RoleAdmin Role = "ADMIN"
  13. // RoleUser is the USER role.
  14. RoleUser Role = "USER"
  15. )
  16. func (e Role) String() string {
  17. switch e {
  18. case RoleHost:
  19. return "HOST"
  20. case RoleAdmin:
  21. return "ADMIN"
  22. case RoleUser:
  23. return "USER"
  24. }
  25. return "USER"
  26. }
  27. type User struct {
  28. ID int
  29. // Standard fields
  30. RowStatus RowStatus
  31. CreatedTs int64
  32. UpdatedTs int64
  33. // Domain specific fields
  34. Username string
  35. Role Role
  36. Email string
  37. Nickname string
  38. PasswordHash string
  39. OpenID string
  40. AvatarURL string
  41. }
  42. type UpdateUser struct {
  43. ID int
  44. UpdatedTs *int64
  45. RowStatus *RowStatus
  46. Username *string `json:"username"`
  47. Email *string `json:"email"`
  48. Nickname *string `json:"nickname"`
  49. Password *string `json:"password"`
  50. ResetOpenID *bool `json:"resetOpenId"`
  51. AvatarURL *string `json:"avatarUrl"`
  52. PasswordHash *string
  53. OpenID *string
  54. }
  55. type FindUser struct {
  56. ID *int
  57. RowStatus *RowStatus
  58. Username *string
  59. Role *Role
  60. Email *string
  61. Nickname *string
  62. OpenID *string
  63. }
  64. type DeleteUser struct {
  65. ID int
  66. }
  67. func (s *Store) CreateUser(ctx context.Context, create *User) (*User, error) {
  68. stmt := `
  69. INSERT INTO user (
  70. username,
  71. role,
  72. email,
  73. nickname,
  74. password_hash,
  75. open_id
  76. )
  77. VALUES (?, ?, ?, ?, ?, ?)
  78. RETURNING id, avatar_url, created_ts, updated_ts, row_status
  79. `
  80. if err := s.db.QueryRowContext(
  81. ctx,
  82. stmt,
  83. create.Username,
  84. create.Role,
  85. create.Email,
  86. create.Nickname,
  87. create.PasswordHash,
  88. create.OpenID,
  89. ).Scan(
  90. &create.ID,
  91. &create.AvatarURL,
  92. &create.CreatedTs,
  93. &create.UpdatedTs,
  94. &create.RowStatus,
  95. ); err != nil {
  96. return nil, err
  97. }
  98. user := create
  99. s.userCache.Store(user.ID, user)
  100. return user, nil
  101. }
  102. func (s *Store) UpdateUser(ctx context.Context, update *UpdateUser) (*User, error) {
  103. set, args := []string{}, []any{}
  104. if v := update.UpdatedTs; v != nil {
  105. set, args = append(set, "updated_ts = ?"), append(args, *v)
  106. }
  107. if v := update.RowStatus; v != nil {
  108. set, args = append(set, "row_status = ?"), append(args, *v)
  109. }
  110. if v := update.Username; v != nil {
  111. set, args = append(set, "username = ?"), append(args, *v)
  112. }
  113. if v := update.Email; v != nil {
  114. set, args = append(set, "email = ?"), append(args, *v)
  115. }
  116. if v := update.Nickname; v != nil {
  117. set, args = append(set, "nickname = ?"), append(args, *v)
  118. }
  119. if v := update.AvatarURL; v != nil {
  120. set, args = append(set, "avatar_url = ?"), append(args, *v)
  121. }
  122. if v := update.PasswordHash; v != nil {
  123. set, args = append(set, "password_hash = ?"), append(args, *v)
  124. }
  125. if v := update.OpenID; v != nil {
  126. set, args = append(set, "open_id = ?"), append(args, *v)
  127. }
  128. args = append(args, update.ID)
  129. query := `
  130. UPDATE user
  131. SET ` + strings.Join(set, ", ") + `
  132. WHERE id = ?
  133. RETURNING id, username, role, email, nickname, password_hash, open_id, avatar_url, created_ts, updated_ts, row_status
  134. `
  135. user := &User{}
  136. if err := s.db.QueryRowContext(ctx, query, args...).Scan(
  137. &user.ID,
  138. &user.Username,
  139. &user.Role,
  140. &user.Email,
  141. &user.Nickname,
  142. &user.PasswordHash,
  143. &user.OpenID,
  144. &user.AvatarURL,
  145. &user.CreatedTs,
  146. &user.UpdatedTs,
  147. &user.RowStatus,
  148. ); err != nil {
  149. return nil, err
  150. }
  151. s.userCache.Store(user.ID, user)
  152. return user, nil
  153. }
  154. func (s *Store) ListUsers(ctx context.Context, find *FindUser) ([]*User, error) {
  155. where, args := []string{"1 = 1"}, []any{}
  156. if v := find.ID; v != nil {
  157. where, args = append(where, "id = ?"), append(args, *v)
  158. }
  159. if v := find.Username; v != nil {
  160. where, args = append(where, "username = ?"), append(args, *v)
  161. }
  162. if v := find.Role; v != nil {
  163. where, args = append(where, "role = ?"), append(args, *v)
  164. }
  165. if v := find.Email; v != nil {
  166. where, args = append(where, "email = ?"), append(args, *v)
  167. }
  168. if v := find.Nickname; v != nil {
  169. where, args = append(where, "nickname = ?"), append(args, *v)
  170. }
  171. if v := find.OpenID; v != nil {
  172. where, args = append(where, "open_id = ?"), append(args, *v)
  173. }
  174. query := `
  175. SELECT
  176. id,
  177. username,
  178. role,
  179. email,
  180. nickname,
  181. password_hash,
  182. open_id,
  183. avatar_url,
  184. created_ts,
  185. updated_ts,
  186. row_status
  187. FROM user
  188. WHERE ` + strings.Join(where, " AND ") + `
  189. ORDER BY created_ts DESC, row_status DESC
  190. `
  191. rows, err := s.db.QueryContext(ctx, query, args...)
  192. if err != nil {
  193. return nil, err
  194. }
  195. defer rows.Close()
  196. list := make([]*User, 0)
  197. for rows.Next() {
  198. var user User
  199. if err := rows.Scan(
  200. &user.ID,
  201. &user.Username,
  202. &user.Role,
  203. &user.Email,
  204. &user.Nickname,
  205. &user.PasswordHash,
  206. &user.OpenID,
  207. &user.AvatarURL,
  208. &user.CreatedTs,
  209. &user.UpdatedTs,
  210. &user.RowStatus,
  211. ); err != nil {
  212. return nil, err
  213. }
  214. list = append(list, &user)
  215. }
  216. if err := rows.Err(); err != nil {
  217. return nil, err
  218. }
  219. for _, user := range list {
  220. s.userCache.Store(user.ID, user)
  221. }
  222. return list, nil
  223. }
  224. func (s *Store) GetUser(ctx context.Context, find *FindUser) (*User, error) {
  225. if find.ID != nil {
  226. if cache, ok := s.userCache.Load(*find.ID); ok {
  227. return cache.(*User), nil
  228. }
  229. }
  230. list, err := s.ListUsers(ctx, find)
  231. if err != nil {
  232. return nil, err
  233. }
  234. if len(list) == 0 {
  235. return nil, nil
  236. }
  237. user := list[0]
  238. s.userCache.Store(user.ID, user)
  239. return user, nil
  240. }
  241. func (s *Store) DeleteUser(ctx context.Context, delete *DeleteUser) error {
  242. result, err := s.db.ExecContext(ctx, `
  243. DELETE FROM user WHERE id = ?
  244. `, delete.ID)
  245. if err != nil {
  246. return err
  247. }
  248. if _, err := result.RowsAffected(); err != nil {
  249. return err
  250. }
  251. if err := s.Vacuum(ctx); err != nil {
  252. // Prevent linter warning.
  253. return err
  254. }
  255. s.userCache.Delete(delete.ID)
  256. return nil
  257. }