Loggest thy stuff
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

278 lines
6.1 KiB

  1. package mysql
  2. import (
  3. "context"
  4. "database/sql"
  5. "encoding/json"
  6. "git.aiterp.net/stufflog3/stufflog3-api/internal/database/mysql/mysqlcore"
  7. "git.aiterp.net/stufflog3/stufflog3-api/internal/models"
  8. "git.aiterp.net/stufflog3/stufflog3-api/internal/slerrors"
  9. "golang.org/x/sync/errgroup"
  10. "sort"
  11. )
  12. type scopeRepository struct {
  13. db *sql.DB
  14. q *mysqlcore.Queries
  15. }
  16. func (r *scopeRepository) Find(ctx context.Context, id int, full bool) (*models.Scope, error) {
  17. scope, err := r.q.GetScope(ctx, id)
  18. if err != nil {
  19. if err == sql.ErrNoRows {
  20. return nil, slerrors.NotFound("Scope")
  21. }
  22. return nil, err
  23. }
  24. res := &models.Scope{
  25. ScopeEntry: models.ScopeEntry{
  26. ID: scope.ID,
  27. Name: scope.Name,
  28. Abbreviation: scope.Abbreviation,
  29. },
  30. Members: []models.ScopeMember{},
  31. Projects: []models.ProjectEntry{},
  32. Stats: []models.Stat{},
  33. StatusLabels: make(map[models.Status]string),
  34. }
  35. eg, ctx := errgroup.WithContext(ctx)
  36. if full {
  37. eg.Go(func() error {
  38. projects, err := r.q.ListProjectEntries(ctx, id)
  39. if err != nil && err != sql.ErrNoRows {
  40. return err
  41. }
  42. for _, project := range projects {
  43. res.Projects = append(res.Projects, models.ProjectEntry{
  44. ID: project.ID,
  45. OwnerID: project.AuthorID,
  46. CreatedTime: project.CreatedTime,
  47. Name: project.Name,
  48. Status: models.Status(project.Status),
  49. })
  50. }
  51. return nil
  52. })
  53. eg.Go(func() error {
  54. stats, err := r.q.ListStats(ctx, id)
  55. if err != nil && err != sql.ErrNoRows {
  56. return err
  57. }
  58. for _, stat := range stats {
  59. var amounts map[string]int
  60. if stat.AllowedAmounts.Valid {
  61. amounts = make(map[string]int)
  62. err := json.Unmarshal(stat.AllowedAmounts.RawMessage, &amounts)
  63. if err != nil {
  64. return err
  65. }
  66. }
  67. res.Stats = append(res.Stats, models.Stat{
  68. StatEntry: models.StatEntry{
  69. ID: stat.ID,
  70. Name: stat.Name,
  71. Weight: stat.Weight,
  72. },
  73. Description: stat.Description,
  74. AllowedAmounts: amounts,
  75. })
  76. }
  77. return nil
  78. })
  79. }
  80. eg.Go(func() error {
  81. members, err := r.q.ListScopeMembers(ctx, id)
  82. if err != nil && err != sql.ErrNoRows {
  83. return err
  84. }
  85. for _, member := range members {
  86. res.Members = append(res.Members, models.ScopeMember{
  87. ID: member.UserID,
  88. Name: member.Name,
  89. Owner: member.Owner,
  90. })
  91. }
  92. return nil
  93. })
  94. err = eg.Wait()
  95. if err != nil {
  96. return nil, err
  97. }
  98. return res, nil
  99. }
  100. func (r *scopeRepository) List(ctx context.Context) ([]models.ScopeEntry, error) {
  101. scopes, err := r.q.ListScopes(ctx)
  102. if err != nil {
  103. return nil, err
  104. }
  105. res := make([]models.ScopeEntry, 0, len(scopes))
  106. for _, scope := range scopes {
  107. res = append(res, models.ScopeEntry{
  108. ID: scope.ID,
  109. Name: scope.Name,
  110. Abbreviation: scope.Abbreviation,
  111. })
  112. }
  113. return res, nil
  114. }
  115. func (r *scopeRepository) ListByUser(ctx context.Context, userID string) ([]models.ScopeEntry, error) {
  116. scopes, err := r.q.ListScopesByUser(ctx, userID)
  117. if err != nil {
  118. return nil, err
  119. }
  120. res := make([]models.ScopeEntry, 0, len(scopes))
  121. for _, scope := range scopes {
  122. res = append(res, models.ScopeEntry{
  123. ID: scope.ID,
  124. Name: scope.Name,
  125. Abbreviation: scope.Abbreviation,
  126. })
  127. }
  128. return res, nil
  129. }
  130. func (r *scopeRepository) Create(ctx context.Context, scope models.ScopeEntry, owner models.ScopeMember) (*models.Scope, error) {
  131. tx, err := r.db.BeginTx(ctx, nil)
  132. if err != nil {
  133. return nil, err
  134. }
  135. defer tx.Rollback()
  136. q := r.q.WithTx(tx)
  137. res, err := q.InsertScope(ctx, mysqlcore.InsertScopeParams(scope))
  138. if err != nil {
  139. return nil, err
  140. }
  141. id, err := res.LastInsertId()
  142. if err != nil {
  143. return nil, err
  144. }
  145. err = q.UpdateScopeMember(ctx, mysqlcore.UpdateScopeMemberParams{
  146. ScopeID: int(id),
  147. UserID: owner.ID,
  148. Name: owner.Name,
  149. Owner: true,
  150. })
  151. err = tx.Commit()
  152. if err != nil {
  153. return nil, err
  154. }
  155. return &models.Scope{
  156. ScopeEntry: models.ScopeEntry{
  157. ID: int(id),
  158. Name: scope.Name,
  159. Abbreviation: scope.Abbreviation,
  160. },
  161. DisplayName: owner.Name,
  162. Members: []models.ScopeMember{
  163. {
  164. ID: owner.ID,
  165. Name: owner.Name,
  166. Owner: true,
  167. },
  168. },
  169. Projects: []models.ProjectEntry{},
  170. Stats: []models.Stat{},
  171. }, nil
  172. }
  173. func (r *scopeRepository) Update(ctx context.Context, scope models.ScopeEntry) error {
  174. return mysqlcore.New(r.db).UpdateScope(ctx, mysqlcore.UpdateScopeParams{
  175. Name: scope.Name,
  176. Abbreviation: scope.Abbreviation,
  177. ID: scope.ID,
  178. })
  179. }
  180. func (r *scopeRepository) Delete(ctx context.Context, scope models.Scope) error {
  181. tx, err := r.db.BeginTx(ctx, nil)
  182. if err != nil {
  183. return err
  184. }
  185. defer tx.Rollback()
  186. q := r.q.WithTx(tx)
  187. err = q.DeleteAllScopeMembers(ctx, scope.ID)
  188. if err != nil {
  189. return err
  190. }
  191. err = q.DeleteScope(ctx, scope.ID)
  192. if err != nil {
  193. return err
  194. }
  195. return tx.Commit()
  196. }
  197. func (r *scopeRepository) UpdateMember(ctx context.Context, scope models.Scope, member models.ScopeMember) (*models.Scope, error) {
  198. err := mysqlcore.New(r.db).UpdateScopeMember(ctx, mysqlcore.UpdateScopeMemberParams{
  199. ScopeID: scope.ID,
  200. UserID: member.ID,
  201. Name: member.Name,
  202. Owner: member.Owner,
  203. })
  204. if err != nil {
  205. return nil, err
  206. }
  207. found := false
  208. scope.Members = append(scope.Members[:0:0], scope.Members...)
  209. for i, member2 := range scope.Members {
  210. if member2.ID == member.ID {
  211. scope.Members[i] = member2
  212. found = true
  213. }
  214. }
  215. if !found {
  216. scope.Members = append(scope.Members, member)
  217. sort.Slice(scope.Members, func(i, j int) bool {
  218. return scope.Members[i].Name < scope.Members[j].Name
  219. })
  220. }
  221. return &scope, nil
  222. }
  223. func (r *scopeRepository) DeleteMember(ctx context.Context, scope models.Scope, userID string) (*models.Scope, error) {
  224. err := mysqlcore.New(r.db).DeleteScopeMember(ctx, mysqlcore.DeleteScopeMemberParams{
  225. ScopeID: scope.ID,
  226. UserID: userID,
  227. })
  228. if err != nil {
  229. return nil, err
  230. }
  231. newMembers := make([]models.ScopeMember, 0, len(scope.Members)-1)
  232. for _, member := range scope.Members {
  233. if member.ID != userID {
  234. newMembers = append(newMembers, member)
  235. }
  236. }
  237. scope.Members = newMembers
  238. return &scope, nil
  239. }