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.

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