aboutsummaryrefslogtreecommitdiffstats
path: root/models/lfs_lock.go
diff options
context:
space:
mode:
authorAntoine GIRARD <sapk@users.noreply.github.com>2017-11-28 21:58:37 +0100
committerLauris BH <lauris@nix.lv>2017-11-28 22:58:37 +0200
commitd99f4ab0035631aacc44739af0a936e59daf83b7 (patch)
tree607cde54661ad07cb15f1ee5f4d9e836de6ff034 /models/lfs_lock.go
parent6ad4990a65462af770e15330da4777ea59bcc5ad (diff)
downloadgitea-d99f4ab0035631aacc44739af0a936e59daf83b7.tar.gz
gitea-d99f4ab0035631aacc44739af0a936e59daf83b7.zip
Git LFS lock api (#2938)
* Implement routes * move to api/sdk and create model * Implement add + list * List return 200 empty list no 404 * Add verify lfs lock api * Add delete and start implementing auth control * Revert to code.gitea.io/sdk/gitea vendor * Apply needed check for all lfs locks route * Add simple tests * fix lint * Improve tests * Add delete test + fix * Add lfs ascii header * Various fixes from review + remove useless code + add more corner case testing * Remove repo link since only id is needed. Save a little of memory and cpu time. * Improve tests * Use TEXT column format for path + test * fix mispell * Use NewRequestWithJSON for POST tests * Clean path * Improve DB format * Revert uniquess repoid+path * (Re)-setup uniqueness + max path length * Fixed TEXT in place of VARCHAR * Settle back to maximum VARCHAR(3072) * Let place for repoid in key * Let place for repoid in key * Let place for repoid in key * Revert back
Diffstat (limited to 'models/lfs_lock.go')
-rw-r--r--models/lfs_lock.go146
1 files changed, 146 insertions, 0 deletions
diff --git a/models/lfs_lock.go b/models/lfs_lock.go
new file mode 100644
index 0000000000..83811bc7bd
--- /dev/null
+++ b/models/lfs_lock.go
@@ -0,0 +1,146 @@
+// 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 (
+ "fmt"
+ "path"
+ "strconv"
+ "strings"
+ "time"
+
+ api "code.gitea.io/sdk/gitea"
+)
+
+// LFSLock represents a git lfs lock of repository.
+type LFSLock struct {
+ ID int64 `xorm:"pk autoincr"`
+ RepoID int64 `xorm:"INDEX NOT NULL"`
+ Owner *User `xorm:"-"`
+ OwnerID int64 `xorm:"INDEX NOT NULL"`
+ Path string `xorm:"TEXT"`
+ Created time.Time `xorm:"created"`
+}
+
+// BeforeInsert is invoked from XORM before inserting an object of this type.
+func (l *LFSLock) BeforeInsert() {
+ l.OwnerID = l.Owner.ID
+ l.Path = cleanPath(l.Path)
+}
+
+// AfterLoad is invoked from XORM after setting the values of all fields of this object.
+func (l *LFSLock) AfterLoad() {
+ l.Owner, _ = GetUserByID(l.OwnerID)
+}
+
+func cleanPath(p string) string {
+ return strings.ToLower(path.Clean(p))
+}
+
+// APIFormat convert a Release to lfs.LFSLock
+func (l *LFSLock) APIFormat() *api.LFSLock {
+ return &api.LFSLock{
+ ID: strconv.FormatInt(l.ID, 10),
+ Path: l.Path,
+ LockedAt: l.Created,
+ Owner: &api.LFSLockOwner{
+ Name: l.Owner.DisplayName(),
+ },
+ }
+}
+
+// CreateLFSLock creates a new lock.
+func CreateLFSLock(lock *LFSLock) (*LFSLock, error) {
+ err := CheckLFSAccessForRepo(lock.Owner, lock.RepoID, "create")
+ if err != nil {
+ return nil, err
+ }
+
+ l, err := GetLFSLock(lock.RepoID, lock.Path)
+ if err == nil {
+ return l, ErrLFSLockAlreadyExist{lock.RepoID, lock.Path}
+ }
+ if !IsErrLFSLockNotExist(err) {
+ return nil, err
+ }
+
+ _, err = x.InsertOne(lock)
+ return lock, err
+}
+
+// GetLFSLock returns release by given path.
+func GetLFSLock(repoID int64, path string) (*LFSLock, error) {
+ path = cleanPath(path)
+ rel := &LFSLock{RepoID: repoID, Path: path}
+ has, err := x.Get(rel)
+ if err != nil {
+ return nil, err
+ }
+ if !has {
+ return nil, ErrLFSLockNotExist{0, repoID, path}
+ }
+ return rel, nil
+}
+
+// GetLFSLockByID returns release by given id.
+func GetLFSLockByID(id int64) (*LFSLock, error) {
+ lock := new(LFSLock)
+ has, err := x.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) (locks []*LFSLock, err error) {
+ err = x.Where("repo_id = ?", repoID).Find(&locks)
+ return
+}
+
+// DeleteLFSLockByID deletes a lock by given ID.
+func DeleteLFSLockByID(id int64, u *User, force bool) (*LFSLock, error) {
+ lock, err := GetLFSLockByID(id)
+ if err != nil {
+ return nil, err
+ }
+
+ err = CheckLFSAccessForRepo(u, lock.RepoID, "delete")
+ if 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")
+ }
+
+ _, err = x.ID(id).Delete(new(LFSLock))
+ return lock, err
+}
+
+//CheckLFSAccessForRepo check needed access mode base on action
+func CheckLFSAccessForRepo(u *User, repoID int64, action string) error {
+ if u == nil {
+ return ErrLFSLockUnauthorizedAction{repoID, "undefined", action}
+ }
+ mode := AccessModeRead
+ if action == "create" || action == "delete" || action == "verify" {
+ mode = AccessModeWrite
+ }
+
+ repo, err := GetRepositoryByID(repoID)
+ if err != nil {
+ return err
+ }
+ has, err := HasAccess(u.ID, repo, mode)
+ if err != nil {
+ return err
+ } else if !has {
+ return ErrLFSLockUnauthorizedAction{repo.ID, u.DisplayName(), action}
+ }
+ return nil
+}