gitea源码

lfs_lock.go 5.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. // Copyright 2017 The Gitea Authors. All rights reserved.
  2. // SPDX-License-Identifier: MIT
  3. package git
  4. import (
  5. "context"
  6. "errors"
  7. "fmt"
  8. "strings"
  9. "time"
  10. "code.gitea.io/gitea/models/db"
  11. "code.gitea.io/gitea/models/perm"
  12. access_model "code.gitea.io/gitea/models/perm/access"
  13. repo_model "code.gitea.io/gitea/models/repo"
  14. "code.gitea.io/gitea/models/unit"
  15. user_model "code.gitea.io/gitea/models/user"
  16. "code.gitea.io/gitea/modules/setting"
  17. "code.gitea.io/gitea/modules/util"
  18. )
  19. // LFSLock represents a git lfs lock of repository.
  20. type LFSLock struct {
  21. ID int64 `xorm:"pk autoincr"`
  22. RepoID int64 `xorm:"INDEX NOT NULL"`
  23. OwnerID int64 `xorm:"INDEX NOT NULL"`
  24. Owner *user_model.User `xorm:"-"`
  25. Path string `xorm:"TEXT"`
  26. Created time.Time `xorm:"created"`
  27. }
  28. func init() {
  29. db.RegisterModel(new(LFSLock))
  30. }
  31. // BeforeInsert is invoked from XORM before inserting an object of this type.
  32. func (l *LFSLock) BeforeInsert() {
  33. l.Path = util.PathJoinRel(l.Path)
  34. }
  35. // LoadAttributes loads attributes of the lock.
  36. func (l *LFSLock) LoadAttributes(ctx context.Context) error {
  37. // Load owner
  38. if err := l.LoadOwner(ctx); err != nil {
  39. return fmt.Errorf("load owner: %w", err)
  40. }
  41. return nil
  42. }
  43. // LoadOwner loads owner of the lock.
  44. func (l *LFSLock) LoadOwner(ctx context.Context) error {
  45. if l.Owner != nil {
  46. return nil
  47. }
  48. owner, err := user_model.GetUserByID(ctx, l.OwnerID)
  49. if err != nil {
  50. if user_model.IsErrUserNotExist(err) {
  51. l.Owner = user_model.NewGhostUser()
  52. return nil
  53. }
  54. return err
  55. }
  56. l.Owner = owner
  57. return nil
  58. }
  59. // CreateLFSLock creates a new lock.
  60. func CreateLFSLock(ctx context.Context, repo *repo_model.Repository, lock *LFSLock) (*LFSLock, error) {
  61. return db.WithTx2(ctx, func(ctx context.Context) (*LFSLock, error) {
  62. if err := CheckLFSAccessForRepo(ctx, lock.OwnerID, repo, perm.AccessModeWrite); err != nil {
  63. return nil, err
  64. }
  65. lock.Path = util.PathJoinRel(lock.Path)
  66. lock.RepoID = repo.ID
  67. l, err := GetLFSLock(ctx, repo, lock.Path)
  68. if err == nil {
  69. return l, ErrLFSLockAlreadyExist{lock.RepoID, lock.Path}
  70. }
  71. if !IsErrLFSLockNotExist(err) {
  72. return nil, err
  73. }
  74. if err := db.Insert(ctx, lock); err != nil {
  75. return nil, err
  76. }
  77. return lock, nil
  78. })
  79. }
  80. // GetLFSLock returns release by given path.
  81. func GetLFSLock(ctx context.Context, repo *repo_model.Repository, path string) (*LFSLock, error) {
  82. path = util.PathJoinRel(path)
  83. rel := &LFSLock{RepoID: repo.ID}
  84. has, err := db.GetEngine(ctx).Where("lower(path) = ?", strings.ToLower(path)).Get(rel)
  85. if err != nil {
  86. return nil, err
  87. }
  88. if !has {
  89. return nil, ErrLFSLockNotExist{0, repo.ID, path}
  90. }
  91. return rel, nil
  92. }
  93. // GetLFSLockByID returns release by given id.
  94. func GetLFSLockByID(ctx context.Context, id int64) (*LFSLock, error) {
  95. lock := new(LFSLock)
  96. has, err := db.GetEngine(ctx).ID(id).Get(lock)
  97. if err != nil {
  98. return nil, err
  99. } else if !has {
  100. return nil, ErrLFSLockNotExist{id, 0, ""}
  101. }
  102. return lock, nil
  103. }
  104. // GetLFSLockByRepoID returns a list of locks of repository.
  105. func GetLFSLockByRepoID(ctx context.Context, repoID int64, page, pageSize int) (LFSLockList, error) {
  106. e := db.GetEngine(ctx)
  107. if page >= 0 && pageSize > 0 {
  108. start := 0
  109. if page > 0 {
  110. start = (page - 1) * pageSize
  111. }
  112. e.Limit(pageSize, start)
  113. }
  114. lfsLocks := make(LFSLockList, 0, pageSize)
  115. return lfsLocks, e.Find(&lfsLocks, &LFSLock{RepoID: repoID})
  116. }
  117. // GetTreePathLock returns LSF lock for the treePath
  118. func GetTreePathLock(ctx context.Context, repoID int64, treePath string) (*LFSLock, error) {
  119. if !setting.LFS.StartServer {
  120. return nil, nil
  121. }
  122. locks, err := GetLFSLockByRepoID(ctx, repoID, 0, 0)
  123. if err != nil {
  124. return nil, err
  125. }
  126. for _, lock := range locks {
  127. if lock.Path == treePath {
  128. return lock, nil
  129. }
  130. }
  131. return nil, nil
  132. }
  133. // CountLFSLockByRepoID returns a count of all LFSLocks associated with a repository.
  134. func CountLFSLockByRepoID(ctx context.Context, repoID int64) (int64, error) {
  135. return db.GetEngine(ctx).Count(&LFSLock{RepoID: repoID})
  136. }
  137. // DeleteLFSLockByID deletes a lock by given ID.
  138. func DeleteLFSLockByID(ctx context.Context, id int64, repo *repo_model.Repository, u *user_model.User, force bool) (*LFSLock, error) {
  139. return db.WithTx2(ctx, func(ctx context.Context) (*LFSLock, error) {
  140. lock, err := GetLFSLockByID(ctx, id)
  141. if err != nil {
  142. return nil, err
  143. }
  144. if err := CheckLFSAccessForRepo(ctx, u.ID, repo, perm.AccessModeWrite); err != nil {
  145. return nil, err
  146. }
  147. if !force && u.ID != lock.OwnerID {
  148. return nil, errors.New("user doesn't own lock and force flag is not set")
  149. }
  150. if _, err := db.GetEngine(ctx).ID(id).Delete(new(LFSLock)); err != nil {
  151. return nil, err
  152. }
  153. return lock, nil
  154. })
  155. }
  156. // CheckLFSAccessForRepo check needed access mode base on action
  157. func CheckLFSAccessForRepo(ctx context.Context, ownerID int64, repo *repo_model.Repository, mode perm.AccessMode) error {
  158. if ownerID == 0 {
  159. return ErrLFSUnauthorizedAction{repo.ID, "undefined", mode}
  160. }
  161. u, err := user_model.GetUserByID(ctx, ownerID)
  162. if err != nil {
  163. return err
  164. }
  165. perm, err := access_model.GetUserRepoPermission(ctx, repo, u)
  166. if err != nil {
  167. return err
  168. }
  169. if !perm.CanAccess(mode, unit.TypeCode) {
  170. return ErrLFSUnauthorizedAction{repo.ID, u.DisplayName(), mode}
  171. }
  172. return nil
  173. }