mirror of
https://github.com/go-gitea/gitea.git
synced 2026-05-11 04:55:34 +02:00
lfs: relax lfs checks allowing AGit+LFS
This commit is contained in:
parent
49e6d5f6d6
commit
380d95b0d2
@ -333,8 +333,9 @@ func ServCommand(ctx *context.PrivateContext) {
|
||||
// Because of the special ref "refs/for" (AGit) we will need to delay write permission check,
|
||||
// AGit flow needs to write its own ref when the doer has "reader" permission (allowing to create PR).
|
||||
// The real permission check is done in HookPreReceive (routers/private/hook_pre_receive.go).
|
||||
// Here it should relax the permission check for "git push (git-receive-pack)", but not for others like LFS operations.
|
||||
if git.DefaultFeatures().SupportProcReceive && unitType == unit.TypeCode && verb == git.CmdVerbReceivePack {
|
||||
// Here it should relax the permission check for "git push (git-receive-pack)" and LFS upload operations.
|
||||
if git.DefaultFeatures().SupportProcReceive && unitType == unit.TypeCode &&
|
||||
(verb == git.CmdVerbReceivePack || verb == git.CmdVerbLfsAuthenticate || verb == git.CmdVerbLfsTransfer) {
|
||||
mode = perm.AccessModeRead
|
||||
}
|
||||
|
||||
|
||||
@ -26,6 +26,7 @@ import (
|
||||
"code.gitea.io/gitea/models/unit"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
"code.gitea.io/gitea/modules/auth/httpauth"
|
||||
"code.gitea.io/gitea/modules/git"
|
||||
"code.gitea.io/gitea/modules/httplib"
|
||||
"code.gitea.io/gitea/modules/json"
|
||||
lfs_module "code.gitea.io/gitea/modules/lfs"
|
||||
@ -537,7 +538,7 @@ func writeStatusMessage(ctx *context.Context, status int, message string) {
|
||||
// to proceed. This server assumes an HTTP Basic auth format.
|
||||
func authenticate(ctx *context.Context, repository *repo_model.Repository, authorization string, requireSigned, requireWrite bool) bool {
|
||||
accessMode := perm_model.AccessModeRead
|
||||
if requireWrite {
|
||||
if requireWrite && !git.DefaultFeatures().SupportProcReceive {
|
||||
accessMode = perm_model.AccessModeWrite
|
||||
}
|
||||
|
||||
|
||||
119
tests/integration/agit_lfs_test.go
Normal file
119
tests/integration/agit_lfs_test.go
Normal file
@ -0,0 +1,119 @@
|
||||
// Copyright 2024 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package integration
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
auth_model "code.gitea.io/gitea/models/auth"
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
"code.gitea.io/gitea/modules/git"
|
||||
"code.gitea.io/gitea/modules/git/gitcmd"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
api "code.gitea.io/gitea/modules/structs"
|
||||
"code.gitea.io/gitea/tests"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func testAPISaveUserPublicKey(t *testing.T, session *TestSession, username, keyname, content string) {
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteUser)
|
||||
req := NewRequestWithJSON(t, "POST", "/api/v1/user/keys", &api.CreateKeyOption{
|
||||
Title: keyname,
|
||||
Key: content,
|
||||
}).AddTokenAuth(token)
|
||||
MakeRequest(t, req, http.StatusCreated)
|
||||
}
|
||||
|
||||
func TestAgitLFS(t *testing.T) {
|
||||
onGiteaRun(t, func(t *testing.T, u *url.URL) {
|
||||
// Enable LFS
|
||||
defer tests.PrepareTestEnv(t)()
|
||||
setting.LFS.StartServer = true
|
||||
setting.LFS.Storage.Path = filepath.Join(setting.AppDataPath, "lfs")
|
||||
|
||||
t.Run("HTTP", func(t *testing.T) {
|
||||
dstPath := t.TempDir()
|
||||
|
||||
// user4 has read access to repo1 (owned by user2)
|
||||
u.Path = "user2/repo1.git"
|
||||
u.User = url.UserPassword("user4", userPassword)
|
||||
|
||||
doGitClone(dstPath, u)(t)
|
||||
|
||||
// Setup LFS in the repo
|
||||
_, _, err := gitcmd.NewCommand("lfs", "install").WithDir(dstPath).RunStdString(t.Context())
|
||||
assert.NoError(t, err)
|
||||
|
||||
_, _, err = gitcmd.NewCommand("lfs", "track", "*.bin").WithDir(dstPath).RunStdString(t.Context())
|
||||
assert.NoError(t, err)
|
||||
|
||||
assert.NoError(t, os.WriteFile(filepath.Join(dstPath, "large.bin"), []byte("this is a large file"), 0o644))
|
||||
assert.NoError(t, git.AddChanges(t.Context(), dstPath, true))
|
||||
|
||||
signature := git.Signature{
|
||||
Email: "user4@example.com",
|
||||
Name: "user4",
|
||||
}
|
||||
assert.NoError(t, git.CommitChanges(t.Context(), dstPath, git.CommitChangesOptions{
|
||||
Committer: &signature,
|
||||
Author: &signature,
|
||||
Message: "Add LFS file",
|
||||
}))
|
||||
|
||||
// push to create an agit pull request
|
||||
assert.NoError(t, gitcmd.NewCommand("push", "origin", "HEAD:refs/for/master/test-agit-lfs-http").
|
||||
WithDir(dstPath).
|
||||
Run(t.Context()))
|
||||
})
|
||||
|
||||
t.Run("SSH", func(t *testing.T) {
|
||||
dstPath := t.TempDir()
|
||||
|
||||
// user4 has read access to repo1 (owned by user2)
|
||||
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{OwnerName: "user2", Name: "repo1"})
|
||||
sshURL := createSSHUrl(repo.FullName()+".git", u)
|
||||
|
||||
withKeyFile(t, "id_rsa", func(keyFile string) {
|
||||
t.Run("AddKey", func(t *testing.T) {
|
||||
session := loginUser(t, "user4")
|
||||
content, _ := os.ReadFile(keyFile + ".pub")
|
||||
testAPISaveUserPublicKey(t, session, "user4", "user4-agit-lfs", string(content))
|
||||
})
|
||||
|
||||
doGitClone(dstPath, sshURL)(t)
|
||||
|
||||
// Setup LFS in the repo
|
||||
_, _, err := gitcmd.NewCommand("lfs", "install").WithDir(dstPath).RunStdString(t.Context())
|
||||
assert.NoError(t, err)
|
||||
|
||||
_, _, err = gitcmd.NewCommand("lfs", "track", "*.bin").WithDir(dstPath).RunStdString(t.Context())
|
||||
assert.NoError(t, err)
|
||||
|
||||
assert.NoError(t, os.WriteFile(filepath.Join(dstPath, "large-ssh.bin"), []byte("this is a large file via ssh"), 0o644))
|
||||
assert.NoError(t, git.AddChanges(t.Context(), dstPath, true))
|
||||
|
||||
signature := git.Signature{
|
||||
Email: "user4@example.com",
|
||||
Name: "user4",
|
||||
}
|
||||
assert.NoError(t, git.CommitChanges(t.Context(), dstPath, git.CommitChangesOptions{
|
||||
Committer: &signature,
|
||||
Author: &signature,
|
||||
Message: "Add LFS file via SSH",
|
||||
}))
|
||||
|
||||
// push to create an agit pull request
|
||||
assert.NoError(t, gitcmd.NewCommand("push", "origin", "HEAD:refs/for/master/test-agit-lfs-ssh").
|
||||
WithDir(dstPath).
|
||||
Run(t.Context()))
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user