123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183 |
- // Copyright 2017 The Gitea Authors. All rights reserved.
- // Use of this source code is governed by a MIT-style
- // license that can be found in the LICENSE file.
-
- package models
-
- import (
- "context"
- "fmt"
- "path"
- "strings"
- "time"
-
- "code.gitea.io/gitea/models/db"
- "code.gitea.io/gitea/models/perm"
- access_model "code.gitea.io/gitea/models/perm/access"
- repo_model "code.gitea.io/gitea/models/repo"
- "code.gitea.io/gitea/models/unit"
- user_model "code.gitea.io/gitea/models/user"
- "code.gitea.io/gitea/modules/setting"
- )
-
- // LFSLock represents a git lfs lock of repository.
- type LFSLock struct {
- ID int64 `xorm:"pk autoincr"`
- RepoID int64 `xorm:"INDEX NOT NULL"`
- OwnerID int64 `xorm:"INDEX NOT NULL"`
- Path string `xorm:"TEXT"`
- Created time.Time `xorm:"created"`
- }
-
- func init() {
- db.RegisterModel(new(LFSLock))
- }
-
- // BeforeInsert is invoked from XORM before inserting an object of this type.
- func (l *LFSLock) BeforeInsert() {
- l.Path = cleanPath(l.Path)
- }
-
- func cleanPath(p string) string {
- return path.Clean("/" + p)[1:]
- }
-
- // CreateLFSLock creates a new lock.
- func CreateLFSLock(repo *repo_model.Repository, lock *LFSLock) (*LFSLock, error) {
- dbCtx, committer, err := db.TxContext()
- if err != nil {
- return nil, err
- }
- defer committer.Close()
-
- if err := CheckLFSAccessForRepo(dbCtx, lock.OwnerID, repo, perm.AccessModeWrite); err != nil {
- return nil, err
- }
-
- lock.Path = cleanPath(lock.Path)
- lock.RepoID = repo.ID
-
- l, err := GetLFSLock(dbCtx, repo, lock.Path)
- if err == nil {
- return l, ErrLFSLockAlreadyExist{lock.RepoID, lock.Path}
- }
- if !IsErrLFSLockNotExist(err) {
- return nil, err
- }
-
- if err := db.Insert(dbCtx, lock); err != nil {
- return nil, err
- }
-
- return lock, committer.Commit()
- }
-
- // GetLFSLock returns release by given path.
- func GetLFSLock(ctx context.Context, repo *repo_model.Repository, path string) (*LFSLock, error) {
- path = cleanPath(path)
- rel := &LFSLock{RepoID: repo.ID}
- has, err := db.GetEngine(ctx).Where("lower(path) = ?", strings.ToLower(path)).Get(rel)
- if err != nil {
- return nil, err
- }
- if !has {
- return nil, ErrLFSLockNotExist{0, repo.ID, path}
- }
- return rel, nil
- }
-
- // GetLFSLockByID returns release by given id.
- func GetLFSLockByID(ctx context.Context, id int64) (*LFSLock, error) {
- lock := new(LFSLock)
- has, err := db.GetEngine(ctx).ID(id).Get(lock)
- if err != nil {
- return nil, err
- } else if !has {
- return nil, ErrLFSLockNotExist{id, 0, ""}
- }
- return lock, nil
- }
-
- // GetLFSLockByRepoID returns a list of locks of repository.
- func GetLFSLockByRepoID(repoID int64, page, pageSize int) ([]*LFSLock, error) {
- e := db.GetEngine(db.DefaultContext)
- if page >= 0 && pageSize > 0 {
- start := 0
- if page > 0 {
- start = (page - 1) * pageSize
- }
- e.Limit(pageSize, start)
- }
- lfsLocks := make([]*LFSLock, 0, pageSize)
- return lfsLocks, e.Find(&lfsLocks, &LFSLock{RepoID: repoID})
- }
-
- // GetTreePathLock returns LSF lock for the treePath
- func GetTreePathLock(repoID int64, treePath string) (*LFSLock, error) {
- if !setting.LFS.StartServer {
- return nil, nil
- }
-
- locks, err := GetLFSLockByRepoID(repoID, 0, 0)
- if err != nil {
- return nil, err
- }
- for _, lock := range locks {
- if lock.Path == treePath {
- return lock, nil
- }
- }
- return nil, nil
- }
-
- // CountLFSLockByRepoID returns a count of all LFSLocks associated with a repository.
- func CountLFSLockByRepoID(repoID int64) (int64, error) {
- return db.GetEngine(db.DefaultContext).Count(&LFSLock{RepoID: repoID})
- }
-
- // DeleteLFSLockByID deletes a lock by given ID.
- func DeleteLFSLockByID(id int64, repo *repo_model.Repository, u *user_model.User, force bool) (*LFSLock, error) {
- dbCtx, committer, err := db.TxContext()
- if err != nil {
- return nil, err
- }
- defer committer.Close()
-
- lock, err := GetLFSLockByID(dbCtx, id)
- if err != nil {
- return nil, err
- }
-
- if err := CheckLFSAccessForRepo(dbCtx, u.ID, repo, perm.AccessModeWrite); err != nil {
- return nil, err
- }
-
- if !force && u.ID != lock.OwnerID {
- return nil, fmt.Errorf("user doesn't own lock and force flag is not set")
- }
-
- if _, err := db.GetEngine(dbCtx).ID(id).Delete(new(LFSLock)); err != nil {
- return nil, err
- }
-
- return lock, committer.Commit()
- }
-
- // CheckLFSAccessForRepo check needed access mode base on action
- func CheckLFSAccessForRepo(ctx context.Context, ownerID int64, repo *repo_model.Repository, mode perm.AccessMode) error {
- if ownerID == 0 {
- return ErrLFSUnauthorizedAction{repo.ID, "undefined", mode}
- }
- u, err := user_model.GetUserByIDCtx(ctx, ownerID)
- if err != nil {
- return err
- }
- perm, err := access_model.GetUserRepoPermission(ctx, repo, u)
- if err != nil {
- return err
- }
- if !perm.CanAccess(mode, unit.TypeCode) {
- return ErrLFSUnauthorizedAction{repo.ID, u.DisplayName(), mode}
- }
- return nil
- }
|