Skip to content

Commit cb37b59

Browse files
committed
Merge branch 'main' into lunny/issue_dev
2 parents abe592c + 1328387 commit cb37b59

File tree

180 files changed

+3197
-853
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

180 files changed

+3197
-853
lines changed

.devcontainer/devcontainer.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
{
22
"name": "Gitea DevContainer",
3-
"image": "mcr.microsoft.com/devcontainers/go:1.22-bullseye",
3+
"image": "mcr.microsoft.com/devcontainers/go:1.23-bookworm",
44
"features": {
55
// installs nodejs into container
66
"ghcr.io/devcontainers/features/node:1": {
77
"version": "20"
88
},
9-
"ghcr.io/devcontainers/features/git-lfs:1.1.0": {},
9+
"ghcr.io/devcontainers/features/git-lfs:1.2.2": {},
1010
"ghcr.io/devcontainers-contrib/features/poetry:2": {},
1111
"ghcr.io/devcontainers/features/python:1": {
1212
"version": "3.12"

.github/labeler.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,10 +70,11 @@ modifies/go:
7070
- any-glob-to-any-file:
7171
- "**/*.go"
7272

73-
modifies/js:
73+
modifies/frontend:
7474
- changed-files:
7575
- any-glob-to-any-file:
7676
- "**/*.js"
77+
- "**/*.ts"
7778
- "**/*.vue"
7879

7980
docs-update-needed:

.github/workflows/pull-db-tests.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,9 @@ jobs:
198198
test-mssql:
199199
if: needs.files-changed.outputs.backend == 'true' || needs.files-changed.outputs.actions == 'true'
200200
needs: files-changed
201-
runs-on: ubuntu-latest
201+
# specifying the version of ubuntu in use as mssql fails on newer kernels
202+
# pending resolution from vendor
203+
runs-on: ubuntu-20.04
202204
services:
203205
mssql:
204206
image: mcr.microsoft.com/mssql/server:2017-latest

Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# Build stage
2-
FROM docker.io/library/golang:1.22-alpine3.20 AS build-env
2+
FROM docker.io/library/golang:1.23-alpine3.20 AS build-env
33

44
ARG GOPROXY
55
ENV GOPROXY=${GOPROXY:-direct}

Dockerfile.rootless

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# Build stage
2-
FROM docker.io/library/golang:1.22-alpine3.20 AS build-env
2+
FROM docker.io/library/golang:1.23-alpine3.20 AS build-env
33

44
ARG GOPROXY
55
ENV GOPROXY=${GOPROXY:-direct}

Makefile

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,12 @@ SHASUM ?= shasum -a 256
2323
HAS_GO := $(shell hash $(GO) > /dev/null 2>&1 && echo yes)
2424
COMMA := ,
2525

26-
XGO_VERSION := go-1.22.x
26+
XGO_VERSION := go-1.23.x
2727

2828
AIR_PACKAGE ?= github.com/air-verse/air@v1
2929
EDITORCONFIG_CHECKER_PACKAGE ?= github.com/editorconfig-checker/editorconfig-checker/cmd/[email protected]
30-
GOFUMPT_PACKAGE ?= mvdan.cc/gofumpt@v0.6.0
31-
GOLANGCI_LINT_PACKAGE ?= github.com/golangci/golangci-lint/cmd/golangci-lint@v1.59.0
30+
GOFUMPT_PACKAGE ?= mvdan.cc/gofumpt@v0.7.0
31+
GOLANGCI_LINT_PACKAGE ?= github.com/golangci/golangci-lint/cmd/golangci-lint@v1.60.3
3232
GXZ_PACKAGE ?= github.com/ulikunitz/xz/cmd/[email protected]
3333
MISSPELL_PACKAGE ?= github.com/golangci/misspell/cmd/[email protected]
3434
SWAGGER_PACKAGE ?= github.com/go-swagger/go-swagger/cmd/[email protected]

assets/go-licenses.json

Lines changed: 72 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

cmd/admin_user_create.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ func runCreateUser(c *cli.Context) error {
158158
IsRestricted: restricted,
159159
}
160160

161-
if err := user_model.CreateUser(ctx, u, overwriteDefault); err != nil {
161+
if err := user_model.CreateUser(ctx, u, &user_model.Meta{}, overwriteDefault); err != nil {
162162
return fmt.Errorf("CreateUser: %w", err)
163163
}
164164

cmd/hook.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -542,14 +542,14 @@ Gitea or set your environment appropriately.`, "")
542542

543543
index := bytes.IndexByte(rs.Data, byte(0))
544544
if index >= len(rs.Data) {
545-
return fail(ctx, "Protocol: format error", "pkt-line: format error "+fmt.Sprint(rs.Data))
545+
return fail(ctx, "Protocol: format error", "pkt-line: format error %s", rs.Data)
546546
}
547547

548548
if index < 0 {
549549
if len(rs.Data) == 10 && rs.Data[9] == '\n' {
550550
index = 9
551551
} else {
552-
return fail(ctx, "Protocol: format error", "pkt-line: format error "+fmt.Sprint(rs.Data))
552+
return fail(ctx, "Protocol: format error", "pkt-line: format error %s", rs.Data)
553553
}
554554
}
555555

cmd/serv.go

Lines changed: 92 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,10 @@ import (
2020
asymkey_model "code.gitea.io/gitea/models/asymkey"
2121
git_model "code.gitea.io/gitea/models/git"
2222
"code.gitea.io/gitea/models/perm"
23+
"code.gitea.io/gitea/modules/container"
2324
"code.gitea.io/gitea/modules/git"
2425
"code.gitea.io/gitea/modules/json"
26+
"code.gitea.io/gitea/modules/lfstransfer"
2527
"code.gitea.io/gitea/modules/log"
2628
"code.gitea.io/gitea/modules/pprof"
2729
"code.gitea.io/gitea/modules/private"
@@ -36,7 +38,11 @@ import (
3638
)
3739

3840
const (
39-
lfsAuthenticateVerb = "git-lfs-authenticate"
41+
verbUploadPack = "git-upload-pack"
42+
verbUploadArchive = "git-upload-archive"
43+
verbReceivePack = "git-receive-pack"
44+
verbLfsAuthenticate = "git-lfs-authenticate"
45+
verbLfsTransfer = "git-lfs-transfer"
4046
)
4147

4248
// CmdServ represents the available serv sub-command.
@@ -73,12 +79,18 @@ func setup(ctx context.Context, debug bool) {
7379
}
7480

7581
var (
76-
allowedCommands = map[string]perm.AccessMode{
77-
"git-upload-pack": perm.AccessModeRead,
78-
"git-upload-archive": perm.AccessModeRead,
79-
"git-receive-pack": perm.AccessModeWrite,
80-
lfsAuthenticateVerb: perm.AccessModeNone,
81-
}
82+
// keep getAccessMode() in sync
83+
allowedCommands = container.SetOf(
84+
verbUploadPack,
85+
verbUploadArchive,
86+
verbReceivePack,
87+
verbLfsAuthenticate,
88+
verbLfsTransfer,
89+
)
90+
allowedCommandsLfs = container.SetOf(
91+
verbLfsAuthenticate,
92+
verbLfsTransfer,
93+
)
8294
alphaDashDotPattern = regexp.MustCompile(`[^\w-\.]`)
8395
)
8496

@@ -124,6 +136,45 @@ func handleCliResponseExtra(extra private.ResponseExtra) error {
124136
return nil
125137
}
126138

139+
func getAccessMode(verb, lfsVerb string) perm.AccessMode {
140+
switch verb {
141+
case verbUploadPack, verbUploadArchive:
142+
return perm.AccessModeRead
143+
case verbReceivePack:
144+
return perm.AccessModeWrite
145+
case verbLfsAuthenticate, verbLfsTransfer:
146+
switch lfsVerb {
147+
case "upload":
148+
return perm.AccessModeWrite
149+
case "download":
150+
return perm.AccessModeRead
151+
}
152+
}
153+
// should be unreachable
154+
return perm.AccessModeNone
155+
}
156+
157+
func getLFSAuthToken(ctx context.Context, lfsVerb string, results *private.ServCommandResults) (string, error) {
158+
now := time.Now()
159+
claims := lfs.Claims{
160+
RegisteredClaims: jwt.RegisteredClaims{
161+
ExpiresAt: jwt.NewNumericDate(now.Add(setting.LFS.HTTPAuthExpiry)),
162+
NotBefore: jwt.NewNumericDate(now),
163+
},
164+
RepoID: results.RepoID,
165+
Op: lfsVerb,
166+
UserID: results.UserID,
167+
}
168+
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
169+
170+
// Sign and get the complete encoded token as a string using the secret
171+
tokenString, err := token.SignedString(setting.LFS.JWTSecretBytes)
172+
if err != nil {
173+
return "", fail(ctx, "Failed to sign JWT Token", "Failed to sign JWT token: %v", err)
174+
}
175+
return fmt.Sprintf("Bearer %s", tokenString), nil
176+
}
177+
127178
func runServ(c *cli.Context) error {
128179
ctx, cancel := installSignals()
129180
defer cancel()
@@ -143,6 +194,12 @@ func runServ(c *cli.Context) error {
143194
return nil
144195
}
145196

197+
defer func() {
198+
if err := recover(); err != nil {
199+
_ = fail(ctx, "Internal Server Error", "Panic: %v\n%s", err, log.Stack(2))
200+
}
201+
}()
202+
146203
keys := strings.Split(c.Args().First(), "-")
147204
if len(keys) != 2 || keys[0] != "key" {
148205
return fail(ctx, "Key ID format error", "Invalid key argument: %s", c.Args().First())
@@ -189,21 +246,9 @@ func runServ(c *cli.Context) error {
189246
}
190247

191248
verb := words[0]
192-
repoPath := words[1]
193-
if repoPath[0] == '/' {
194-
repoPath = repoPath[1:]
195-
}
249+
repoPath := strings.TrimPrefix(words[1], "/")
196250

197251
var lfsVerb string
198-
if verb == lfsAuthenticateVerb {
199-
if !setting.LFS.StartServer {
200-
return fail(ctx, "Unknown git command", "LFS authentication request over SSH denied, LFS support is disabled")
201-
}
202-
203-
if len(words) > 2 {
204-
lfsVerb = words[2]
205-
}
206-
}
207252

208253
rr := strings.SplitN(repoPath, "/", 2)
209254
if len(rr) != 2 {
@@ -240,53 +285,52 @@ func runServ(c *cli.Context) error {
240285
}()
241286
}
242287

243-
requestedMode, has := allowedCommands[verb]
244-
if !has {
288+
if allowedCommands.Contains(verb) {
289+
if allowedCommandsLfs.Contains(verb) {
290+
if !setting.LFS.StartServer {
291+
return fail(ctx, "Unknown git command", "LFS authentication request over SSH denied, LFS support is disabled")
292+
}
293+
if verb == verbLfsTransfer && !setting.LFS.AllowPureSSH {
294+
return fail(ctx, "Unknown git command", "LFS SSH transfer connection denied, pure SSH protocol is disabled")
295+
}
296+
if len(words) > 2 {
297+
lfsVerb = words[2]
298+
}
299+
}
300+
} else {
245301
return fail(ctx, "Unknown git command", "Unknown git command %s", verb)
246302
}
247303

248-
if verb == lfsAuthenticateVerb {
249-
if lfsVerb == "upload" {
250-
requestedMode = perm.AccessModeWrite
251-
} else if lfsVerb == "download" {
252-
requestedMode = perm.AccessModeRead
253-
} else {
254-
return fail(ctx, "Unknown LFS verb", "Unknown lfs verb %s", lfsVerb)
255-
}
256-
}
304+
requestedMode := getAccessMode(verb, lfsVerb)
257305

258306
results, extra := private.ServCommand(ctx, keyID, username, reponame, requestedMode, verb, lfsVerb)
259307
if extra.HasError() {
260308
return fail(ctx, extra.UserMsg, "ServCommand failed: %s", extra.Error)
261309
}
262310

311+
// LFS SSH protocol
312+
if verb == verbLfsTransfer {
313+
token, err := getLFSAuthToken(ctx, lfsVerb, results)
314+
if err != nil {
315+
return err
316+
}
317+
return lfstransfer.Main(ctx, repoPath, lfsVerb, token)
318+
}
319+
263320
// LFS token authentication
264-
if verb == lfsAuthenticateVerb {
321+
if verb == verbLfsAuthenticate {
265322
url := fmt.Sprintf("%s%s/%s.git/info/lfs", setting.AppURL, url.PathEscape(results.OwnerName), url.PathEscape(results.RepoName))
266323

267-
now := time.Now()
268-
claims := lfs.Claims{
269-
RegisteredClaims: jwt.RegisteredClaims{
270-
ExpiresAt: jwt.NewNumericDate(now.Add(setting.LFS.HTTPAuthExpiry)),
271-
NotBefore: jwt.NewNumericDate(now),
272-
},
273-
RepoID: results.RepoID,
274-
Op: lfsVerb,
275-
UserID: results.UserID,
276-
}
277-
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
278-
279-
// Sign and get the complete encoded token as a string using the secret
280-
tokenString, err := token.SignedString(setting.LFS.JWTSecretBytes)
324+
token, err := getLFSAuthToken(ctx, lfsVerb, results)
281325
if err != nil {
282-
return fail(ctx, "Failed to sign JWT Token", "Failed to sign JWT token: %v", err)
326+
return err
283327
}
284328

285329
tokenAuthentication := &git_model.LFSTokenResponse{
286330
Header: make(map[string]string),
287331
Href: url,
288332
}
289-
tokenAuthentication.Header["Authorization"] = fmt.Sprintf("Bearer %s", tokenString)
333+
tokenAuthentication.Header["Authorization"] = token
290334

291335
enc := json.NewEncoder(os.Stdout)
292336
err = enc.Encode(tokenAuthentication)

0 commit comments

Comments
 (0)