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.

lfs_lock.go 4.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. // Copyright 2017 The Gitea Authors. All rights reserved.
  2. // Use of this source code is governed by a MIT-style
  3. // license that can be found in the LICENSE file.
  4. package models
  5. import (
  6. "context"
  7. "fmt"
  8. "path"
  9. "strings"
  10. "time"
  11. "code.gitea.io/gitea/models/db"
  12. "code.gitea.io/gitea/models/perm"
  13. access_model "code.gitea.io/gitea/models/perm/access"
  14. repo_model "code.gitea.io/gitea/models/repo"
  15. "code.gitea.io/gitea/models/unit"
  16. user_model "code.gitea.io/gitea/models/user"
  17. "code.gitea.io/gitea/modules/setting"
  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. Path string `xorm:"TEXT"`
  25. Created time.Time `xorm:"created"`
  26. }
  27. func init() {
  28. db.RegisterModel(new(LFSLock))
  29. }
  30. // BeforeInsert is invoked from XORM before inserting an object of this type.
  31. func (l *LFSLock) BeforeInsert() {
  32. l.Path = cleanPath(l.Path)
  33. }
  34. func cleanPath(p string) string {
  35. return path.Clean("/" + p)[1:]
  36. }
  37. // CreateLFSLock creates a new lock.
  38. func CreateLFSLock(repo *repo_model.Repository, lock *LFSLock) (*LFSLock, error) {
  39. dbCtx, committer, err := db.TxContext()
  40. if err != nil {
  41. return nil, err
  42. }
  43. defer committer.Close()
  44. if err := CheckLFSAccessForRepo(dbCtx, lock.OwnerID, repo, perm.AccessModeWrite); err != nil {
  45. return nil, err
  46. }
  47. lock.Path = cleanPath(lock.Path)
  48. lock.RepoID = repo.ID
  49. l, err := GetLFSLock(dbCtx, repo, lock.Path)
  50. if err == nil {
  51. return l, ErrLFSLockAlreadyExist{lock.RepoID, lock.Path}
  52. }
  53. if !IsErrLFSLockNotExist(err) {
  54. return nil, err
  55. }
  56. if err := db.Insert(dbCtx, lock); err != nil {
  57. return nil, err
  58. }
  59. return lock, committer.Commit()
  60. }
  61. // GetLFSLock returns release by given path.
  62. func GetLFSLock(ctx context.Context, repo *repo_model.Repository, path string) (*LFSLock, error) {
  63. path = cleanPath(path)
  64. rel := &LFSLock{RepoID: repo.ID}
  65. has, err := db.GetEngine(ctx).Where("lower(path) = ?", strings.ToLower(path)).Get(rel)
  66. if err != nil {
  67. return nil, err
  68. }
  69. if !has {
  70. return nil, ErrLFSLockNotExist{0, repo.ID, path}
  71. }
  72. return rel, nil
  73. }
  74. // GetLFSLockByID returns release by given id.
  75. func GetLFSLockByID(ctx context.Context, id int64) (*LFSLock, error) {
  76. lock := new(LFSLock)
  77. has, err := db.GetEngine(ctx).ID(id).Get(lock)
  78. if err != nil {
  79. return nil, err
  80. } else if !has {
  81. return nil, ErrLFSLockNotExist{id, 0, ""}
  82. }
  83. return lock, nil
  84. }
  85. // GetLFSLockByRepoID returns a list of locks of repository.
  86. func GetLFSLockByRepoID(repoID int64, page, pageSize int) ([]*LFSLock, error) {
  87. e := db.GetEngine(db.DefaultContext)
  88. if page >= 0 && pageSize > 0 {
  89. start := 0
  90. if page > 0 {
  91. start = (page - 1) * pageSize
  92. }
  93. e.Limit(pageSize, start)
  94. }
  95. lfsLocks := make([]*LFSLock, 0, pageSize)
  96. return lfsLocks, e.Find(&lfsLocks, &LFSLock{RepoID: repoID})
  97. }
  98. // GetTreePathLock returns LSF lock for the treePath
  99. func GetTreePathLock(repoID int64, treePath string) (*LFSLock, error) {
  100. if !setting.LFS.StartServer {
  101. return nil, nil
  102. }
  103. locks, err := GetLFSLockByRepoID(repoID, 0, 0)
  104. if err != nil {
  105. return nil, err
  106. }
  107. for _, lock := range locks {
  108. if lock.Path == treePath {
  109. return lock, nil
  110. }
  111. }
  112. return nil, nil
  113. }
  114. // CountLFSLockByRepoID returns a count of all LFSLocks associated with a repository.
  115. func CountLFSLockByRepoID(repoID int64) (int64, error) {
  116. return db.GetEngine(db.DefaultContext).Count(&LFSLock{RepoID: repoID})
  117. }
  118. // DeleteLFSLockByID deletes a lock by given ID.
  119. func DeleteLFSLockByID(id int64, repo *repo_model.Repository, u *user_model.User, force bool) (*LFSLock, error) {
  120. dbCtx, committer, err := db.TxContext()
  121. if err != nil {
  122. return nil, err
  123. }
  124. defer committer.Close()
  125. lock, err := GetLFSLockByID(dbCtx, id)
  126. if err != nil {
  127. return nil, err
  128. }
  129. if err := CheckLFSAccessForRepo(dbCtx, u.ID, repo, perm.AccessModeWrite); err != nil {
  130. return nil, err
  131. }
  132. if !force && u.ID != lock.OwnerID {
  133. return nil, fmt.Errorf("user doesn't own lock and force flag is not set")
  134. }
  135. if _, err := db.GetEngine(dbCtx).ID(id).Delete(new(LFSLock)); err != nil {
  136. return nil, err
  137. }
  138. return lock, committer.Commit()
  139. }
  140. // CheckLFSAccessForRepo check needed access mode base on action
  141. func CheckLFSAccessForRepo(ctx context.Context, ownerID int64, repo *repo_model.Repository, mode perm.AccessMode) error {
  142. if ownerID == 0 {
  143. return ErrLFSUnauthorizedAction{repo.ID, "undefined", mode}
  144. }
  145. u, err := user_model.GetUserByIDCtx(ctx, ownerID)
  146. if err != nil {
  147. return err
  148. }
  149. perm, err := access_model.GetUserRepoPermission(ctx, repo, u)
  150. if err != nil {
  151. return err
  152. }
  153. if !perm.CanAccess(mode, unit.TypeCode) {
  154. return ErrLFSUnauthorizedAction{repo.ID, u.DisplayName(), mode}
  155. }
  156. return nil
  157. }