Skip to content

Commit 17cfad8

Browse files
committed
fix
1 parent 62c9a05 commit 17cfad8

File tree

3 files changed

+24
-27
lines changed

3 files changed

+24
-27
lines changed

modules/private/serv.go

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,17 +46,16 @@ type ServCommandResults struct {
4646
}
4747

4848
// ServCommand preps for a serv call
49-
func ServCommand(ctx context.Context, keyID int64, ownerName, repoName string, mode perm.AccessMode, verbs ...string) (*ServCommandResults, ResponseExtra) {
49+
func ServCommand(ctx context.Context, keyID int64, ownerName, repoName string, mode perm.AccessMode, verb, lfsVerb string) (*ServCommandResults, ResponseExtra) {
5050
reqURL := setting.LocalURL + fmt.Sprintf("api/internal/serv/command/%d/%s/%s?mode=%d",
5151
keyID,
5252
url.PathEscape(ownerName),
5353
url.PathEscape(repoName),
5454
mode,
5555
)
56-
for _, verb := range verbs {
57-
if verb != "" {
58-
reqURL += "&verb=" + url.QueryEscape(verb)
59-
}
56+
reqURL += "&verb=" + url.QueryEscape(verb)
57+
if lfsVerb != "" {
58+
reqURL += "&lfs_verb=" + url.QueryEscape(lfsVerb)
6059
}
6160
req := newInternalRequestAPI(ctx, reqURL, "GET")
6261
return requestJSONResp(req, &ServCommandResults{})

routers/private/serv.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ func ServCommand(ctx *context.PrivateContext) {
8181
ownerName := ctx.PathParam("owner")
8282
repoName := ctx.PathParam("repo")
8383
mode := perm.AccessMode(ctx.FormInt("mode"))
84-
verb := ctx.FormString("verb") // there should be two verbs, but we only care about the first one
84+
verb := ctx.FormString("verb")
8585

8686
// Set the basic parts of the results to return
8787
results := private.ServCommandResults{
@@ -296,7 +296,10 @@ func ServCommand(ctx *context.PrivateContext) {
296296
return
297297
}
298298
} else {
299-
// Because of the special ref "refs/for" we will need to delay write permission check
299+
// Because of the special ref "refs/for" (AGit) we will need to delay write permission check,
300+
// AGit flow needs to write its own ref when the doer has "reader" permission (allowing to create PR).
301+
// The real permission check is done in HookPreReceive (routers/private/hook_pre_receive.go).
302+
// Here it should relax the permission check for "git push (git-receive-pack)", but not for others like LFS operations.
300303
if git.DefaultFeatures().SupportProcReceive && verb == "git-receive-pack" && unitType == unit.TypeCode {
301304
mode = perm.AccessModeRead
302305
}

tests/integration/git_general_test.go

Lines changed: 15 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
package integration
55

66
import (
7-
"bytes"
87
"encoding/hex"
98
"fmt"
109
"io"
@@ -112,7 +111,7 @@ func testGitGeneral(t *testing.T, u *url.URL) {
112111
t.Run("CreateUserKey", doAPICreateUserKey(sshContext, "test-key", keyFile, func(t *testing.T, key api.PublicKey) {
113112
keyID = key.ID
114113
}))
115-
assert.Greater(t, keyID, int64(0))
114+
assert.NotZero(t, keyID)
116115

117116
// Setup remote link
118117
// TODO: get url from api
@@ -144,26 +143,22 @@ func testGitGeneral(t *testing.T, u *url.URL) {
144143
})
145144
}
146145

147-
func doLFSUploadTest(ctx APITestContext, keyID int64) func(*testing.T) {
146+
func doLFSUploadTest(_ APITestContext, keyID int64) func(*testing.T) {
148147
return func(t *testing.T) {
149-
// This is set in withKeyFile and ensure correctly
150-
sshCommand := os.Getenv("GIT_SSH_COMMAND")
151-
152-
// We really have to split on the arguments and pass them individually.
153-
sshOptions, err := shellquote.Split(sshCommand)
154-
assert.NoError(t, err)
155-
156-
sshOptions = append(sshOptions, "-p "+strconv.Itoa(setting.SSH.ListenPort), "git@"+setting.SSH.ListenHost)
157-
// user2's key upload lfs file to user5/repo4
158-
sshOptions = append(sshOptions, "git-lfs-authenticate", "user5/repo4.git", "upload")
159-
160-
cmd := exec.CommandContext(t.Context(), sshOptions[0], sshOptions[1:]...)
161-
stderr := bytes.Buffer{}
162-
cmd.Stderr = &stderr
163-
err = cmd.Run()
148+
sshCommand := os.Getenv("GIT_SSH_COMMAND") // it is set in withKeyFile and ensure correctly
149+
sshCmdParts, err := shellquote.Split(sshCommand) // and parse the ssh command to construct some mocked arguments
150+
require.NoError(t, err)
164151

165-
assert.ErrorContains(t, err, "exit status 1")
166-
assert.Contains(t, stderr.String(), fmt.Sprintf("User: 2:user2 with Key: %d:test-key is not authorized to write to user5/repo4.", keyID))
152+
t.Run("User2AccessUser5Repo4", func(t *testing.T) {
153+
sshCmdParts = append(sshCmdParts,
154+
"-p", strconv.Itoa(setting.SSH.ListenPort), "git@"+setting.SSH.ListenHost,
155+
"git-lfs-authenticate", "user5/repo4.git", "upload", // user2's key upload lfs file to user5/repo4
156+
)
157+
cmd := exec.CommandContext(t.Context(), sshCmdParts[0], sshCmdParts[1:]...)
158+
out, err := cmd.Output()
159+
assert.ErrorContains(t, err, "exit status 1")
160+
assert.Contains(t, string(out), fmt.Sprintf("User: 2:user2 with Key: %d:test-key is not authorized to write to user5/repo4.", keyID))
161+
})
167162
}
168163
}
169164

0 commit comments

Comments
 (0)