@@ -11,8 +11,10 @@ import (
11
11
"net/http"
12
12
"net/url"
13
13
"os"
14
+ "os/exec"
14
15
"path"
15
16
"path/filepath"
17
+ "slices"
16
18
"strconv"
17
19
"testing"
18
20
"time"
@@ -31,7 +33,9 @@ import (
31
33
gitea_context "code.gitea.io/gitea/services/context"
32
34
"code.gitea.io/gitea/tests"
33
35
36
+ "github.com/kballard/go-shellquote"
34
37
"github.com/stretchr/testify/assert"
38
+ "github.com/stretchr/testify/require"
35
39
)
36
40
37
41
const (
@@ -105,7 +109,12 @@ func testGitGeneral(t *testing.T, u *url.URL) {
105
109
106
110
// Setup key the user ssh key
107
111
withKeyFile (t , keyname , func (keyFile string ) {
108
- t .Run ("CreateUserKey" , doAPICreateUserKey (sshContext , "test-key" , keyFile ))
112
+ var keyID int64
113
+ t .Run ("CreateUserKey" , doAPICreateUserKey (sshContext , "test-key" , keyFile , func (t * testing.T , key api.PublicKey ) {
114
+ keyID = key .ID
115
+ }))
116
+ assert .NotZero (t , keyID )
117
+ t .Run ("LFSAccessTest" , doSSHLFSAccessTest (sshContext , keyID ))
109
118
110
119
// Setup remote link
111
120
// TODO: get url from api
@@ -136,6 +145,36 @@ func testGitGeneral(t *testing.T, u *url.URL) {
136
145
})
137
146
}
138
147
148
+ func doSSHLFSAccessTest (_ APITestContext , keyID int64 ) func (* testing.T ) {
149
+ return func (t * testing.T ) {
150
+ sshCommand := os .Getenv ("GIT_SSH_COMMAND" ) // it is set in withKeyFile
151
+ sshCmdParts , err := shellquote .Split (sshCommand ) // and parse the ssh command to construct some mocked arguments
152
+ require .NoError (t , err )
153
+
154
+ t .Run ("User2AccessOwned" , func (t * testing.T ) {
155
+ sshCmdUser2Self := append (slices .Clone (sshCmdParts ),
156
+ "-p" , strconv .Itoa (setting .SSH .ListenPort ), "git@" + setting .SSH .ListenHost ,
157
+ "git-lfs-authenticate" , "user2/repo1.git" , "upload" , // accessible to own repo
158
+ )
159
+ cmd := exec .CommandContext (git .DefaultContext , sshCmdUser2Self [0 ], sshCmdUser2Self [1 :]... )
160
+ _ , err := cmd .Output ()
161
+ assert .NoError (t , err ) // accessible, no error
162
+ })
163
+
164
+ t .Run ("User2AccessOther" , func (t * testing.T ) {
165
+ sshCmdUser2Other := append (slices .Clone (sshCmdParts ),
166
+ "-p" , strconv .Itoa (setting .SSH .ListenPort ), "git@" + setting .SSH .ListenHost ,
167
+ "git-lfs-authenticate" , "user5/repo4.git" , "upload" , // inaccessible to other's (user5/repo4)
168
+ )
169
+ cmd := exec .CommandContext (git .DefaultContext , sshCmdUser2Other [0 ], sshCmdUser2Other [1 :]... )
170
+ _ , err := cmd .Output ()
171
+ var errExit * exec.ExitError
172
+ require .ErrorAs (t , err , & errExit ) // inaccessible, error
173
+ assert .Contains (t , string (errExit .Stderr ), fmt .Sprintf ("User: 2:user2 with Key: %d:test-key is not authorized to write to user5/repo4." , keyID ))
174
+ })
175
+ }
176
+ }
177
+
139
178
func ensureAnonymousClone (t * testing.T , u * url.URL ) {
140
179
dstLocalPath := t .TempDir ()
141
180
t .Run ("CloneAnonymous" , doGitClone (dstLocalPath , u ))
0 commit comments