Skip to content

Commit f83fee5

Browse files
authored
Merge branch 'main' into feat/publish-ghcr-io
2 parents 34f4c62 + 4ddf94d commit f83fee5

File tree

181 files changed

+2270
-2045
lines changed

Some content is hidden

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

181 files changed

+2270
-2045
lines changed

.gitattributes

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
/assets/*.json linguist-generated
55
/public/assets/img/svg/*.svg linguist-generated
66
/templates/swagger/v1_json.tmpl linguist-generated
7+
/options/fileicon/** linguist-generated
78
/vendor/** -text -eol linguist-vendored
89
/web_src/js/vendor/** -text -eol linguist-vendored
910
Dockerfile.* linguist-language=Dockerfile

cmd/web.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,10 @@ func serveInstalled(ctx *cli.Context) error {
213213
log.Fatal("Can not find APP_DATA_PATH %q", setting.AppDataPath)
214214
}
215215

216+
// the AppDataTempDir is fully managed by us with a safe sub-path
217+
// so it's safe to automatically remove the outdated files
218+
setting.AppDataTempDir("").RemoveOutdated(3 * 24 * time.Hour)
219+
216220
// Override the provided port number within the configuration
217221
if ctx.IsSet("port") {
218222
if err := setPort(ctx.String("port")); err != nil {

custom/conf/app.example.ini

Lines changed: 4 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -197,13 +197,6 @@ RUN_USER = ; git
197197
;; relative paths are made absolute relative to the APP_DATA_PATH
198198
;SSH_SERVER_HOST_KEYS=ssh/gitea.rsa, ssh/gogs.rsa
199199
;;
200-
;; Directory to create temporary files in when testing public keys using ssh-keygen,
201-
;; default is the system temporary directory.
202-
;SSH_KEY_TEST_PATH =
203-
;;
204-
;; Use `ssh-keygen` to parse public SSH keys. The value is passed to the shell. By default, Gitea does the parsing itself.
205-
;SSH_KEYGEN_PATH =
206-
;;
207200
;; Enable SSH Authorized Key Backup when rewriting all keys, default is false
208201
;SSH_AUTHORIZED_KEYS_BACKUP = false
209202
;;
@@ -294,6 +287,9 @@ RUN_USER = ; git
294287
;; Default path for App data
295288
;APP_DATA_PATH = data ; relative paths will be made absolute with _`AppWorkPath`_
296289
;;
290+
;; Base path for App's temp files, leave empty to use the managed tmp directory in APP_DATA_PATH
291+
;APP_TEMP_PATH =
292+
;;
297293
;; Enable gzip compression for runtime-generated content, static resources excluded
298294
;ENABLE_GZIP = false
299295
;;
@@ -1069,15 +1065,6 @@ LEVEL = Info
10691065
;; Separate extensions with a comma. To line wrap files without an extension, just put a comma
10701066
;LINE_WRAP_EXTENSIONS = .txt,.md,.markdown,.mdown,.mkd,.livemd,
10711067

1072-
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1073-
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1074-
;[repository.local]
1075-
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1076-
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1077-
;;
1078-
;; Path for local repository copy. Defaults to `tmp/local-repo` (content gets deleted on gitea restart)
1079-
;LOCAL_COPY_PATH = tmp/local-repo
1080-
10811068
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10821069
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10831070
;[repository.upload]
@@ -1087,9 +1074,6 @@ LEVEL = Info
10871074
;; Whether repository file uploads are enabled. Defaults to `true`
10881075
;ENABLED = true
10891076
;;
1090-
;; Path for uploads. Defaults to `data/tmp/uploads` (content gets deleted on gitea restart)
1091-
;TEMP_PATH = data/tmp/uploads
1092-
;;
10931077
;; Comma-separated list of allowed file extensions (`.zip`), mime types (`text/plain`) or wildcard type (`image/*`, `audio/*`, `video/*`). Empty value or `*/*` allows all types.
10941078
;ALLOWED_TYPES =
10951079
;;
@@ -2473,7 +2457,7 @@ LEVEL = Info
24732457
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
24742458
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
24752459
;; Set the maximum number of characters in a mermaid source. (Set to -1 to disable limits)
2476-
;MERMAID_MAX_SOURCE_CHARACTERS = 5000
2460+
;MERMAID_MAX_SOURCE_CHARACTERS = 50000
24772461

24782462
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
24792463
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -2594,9 +2578,6 @@ LEVEL = Info
25942578
;; Currently, only `minio` and `azureblob` is supported.
25952579
;SERVE_DIRECT = false
25962580
;;
2597-
;; Path for chunked uploads. Defaults to APP_DATA_PATH + `tmp/package-upload`
2598-
;CHUNKED_UPLOAD_PATH = tmp/package-upload
2599-
;;
26002581
;; Maximum count of package versions a single owner can have (`-1` means no limits)
26012582
;LIMIT_TOTAL_OWNER_COUNT = -1
26022583
;; Maximum size of packages a single owner can use (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)

docker/root/etc/s6/openssh/setup

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,16 +31,19 @@ if [ -e /data/ssh/ssh_host_ecdsa_cert ]; then
3131
SSH_ECDSA_CERT=${SSH_ECDSA_CERT:-"/data/ssh/ssh_host_ecdsa_cert"}
3232
fi
3333

34-
if [ -e /data/ssh/ssh_host_ed25519-cert.pub ]; then
35-
SSH_ED25519_CERT=${SSH_ED25519_CERT:-"/data/ssh/ssh_host_ed25519-cert.pub"}
34+
# In case someone wants to sign the `{keyname}.pub` key by `ssh-keygen -s ca -I identity ...` to
35+
# make use of the ssh-key certificate authority feature (see ssh-keygen CERTIFICATES section),
36+
# the generated key file name is `{keyname}-cert.pub`
37+
if [ -e /data/ssh/ssh_host_ed25519_key-cert.pub ]; then
38+
SSH_ED25519_CERT=${SSH_ED25519_CERT:-"/data/ssh/ssh_host_ed25519_key-cert.pub"}
3639
fi
3740

38-
if [ -e /data/ssh/ssh_host_rsa-cert.pub ]; then
39-
SSH_RSA_CERT=${SSH_RSA_CERT:-"/data/ssh/ssh_host_rsa-cert.pub"}
41+
if [ -e /data/ssh/ssh_host_rsa_key-cert.pub ]; then
42+
SSH_RSA_CERT=${SSH_RSA_CERT:-"/data/ssh/ssh_host_rsa_key-cert.pub"}
4043
fi
4144

42-
if [ -e /data/ssh/ssh_host_ecdsa-cert.pub ]; then
43-
SSH_ECDSA_CERT=${SSH_ECDSA_CERT:-"/data/ssh/ssh_host_ecdsa-cert.pub"}
45+
if [ -e /data/ssh/ssh_host_ecdsa_key-cert.pub ]; then
46+
SSH_ECDSA_CERT=${SSH_ECDSA_CERT:-"/data/ssh/ssh_host_ecdsa_key-cert.pub"}
4447
fi
4548

4649
if [ -d /etc/ssh ]; then

models/asymkey/gpg_key.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,3 +240,10 @@ func DeleteGPGKey(ctx context.Context, doer *user_model.User, id int64) (err err
240240

241241
return committer.Commit()
242242
}
243+
244+
func FindGPGKeyWithSubKeys(ctx context.Context, keyID string) ([]*GPGKey, error) {
245+
return db.Find[GPGKey](ctx, FindGPGKeyOptions{
246+
KeyID: keyID,
247+
IncludeSubKeys: true,
248+
})
249+
}

models/asymkey/ssh_key_fingerprint.go

Lines changed: 2 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -6,27 +6,13 @@ package asymkey
66
import (
77
"context"
88
"fmt"
9-
"strings"
109

1110
"code.gitea.io/gitea/models/db"
12-
"code.gitea.io/gitea/modules/log"
13-
"code.gitea.io/gitea/modules/process"
14-
"code.gitea.io/gitea/modules/setting"
15-
"code.gitea.io/gitea/modules/util"
1611

1712
"golang.org/x/crypto/ssh"
1813
"xorm.io/builder"
1914
)
2015

21-
// ___________.__ .__ __
22-
// \_ _____/|__| ____ ____ ________________________|__| _____/ |_
23-
// | __) | |/ \ / ___\_/ __ \_ __ \____ \_ __ \ |/ \ __\
24-
// | \ | | | \/ /_/ > ___/| | \/ |_> > | \/ | | \ |
25-
// \___ / |__|___| /\___ / \___ >__| | __/|__| |__|___| /__|
26-
// \/ \//_____/ \/ |__| \/
27-
//
28-
// This file contains functions for fingerprinting SSH keys
29-
//
3016
// The database is used in checkKeyFingerprint however most of these functions probably belong in a module
3117

3218
// checkKeyFingerprint only checks if key fingerprint has been used as public key,
@@ -41,29 +27,6 @@ func checkKeyFingerprint(ctx context.Context, fingerprint string) error {
4127
return nil
4228
}
4329

44-
func calcFingerprintSSHKeygen(publicKeyContent string) (string, error) {
45-
// Calculate fingerprint.
46-
tmpPath, err := writeTmpKeyFile(publicKeyContent)
47-
if err != nil {
48-
return "", err
49-
}
50-
defer func() {
51-
if err := util.Remove(tmpPath); err != nil {
52-
log.Warn("Unable to remove temporary key file: %s: Error: %v", tmpPath, err)
53-
}
54-
}()
55-
stdout, stderr, err := process.GetManager().Exec("AddPublicKey", "ssh-keygen", "-lf", tmpPath)
56-
if err != nil {
57-
if strings.Contains(stderr, "is not a public key file") {
58-
return "", ErrKeyUnableVerify{stderr}
59-
}
60-
return "", util.NewInvalidArgumentErrorf("'ssh-keygen -lf %s' failed with error '%s': %s", tmpPath, err, stderr)
61-
} else if len(stdout) < 2 {
62-
return "", util.NewInvalidArgumentErrorf("not enough output for calculating fingerprint: %s", stdout)
63-
}
64-
return strings.Split(stdout, " ")[1], nil
65-
}
66-
6730
func calcFingerprintNative(publicKeyContent string) (string, error) {
6831
// Calculate fingerprint.
6932
pk, _, _, _, err := ssh.ParseAuthorizedKey([]byte(publicKeyContent))
@@ -75,15 +38,12 @@ func calcFingerprintNative(publicKeyContent string) (string, error) {
7538

7639
// CalcFingerprint calculate public key's fingerprint
7740
func CalcFingerprint(publicKeyContent string) (string, error) {
78-
// Call the method based on configuration
79-
useNative := setting.SSH.KeygenPath == ""
80-
calcFn := util.Iif(useNative, calcFingerprintNative, calcFingerprintSSHKeygen)
81-
fp, err := calcFn(publicKeyContent)
41+
fp, err := calcFingerprintNative(publicKeyContent)
8242
if err != nil {
8343
if IsErrKeyUnableVerify(err) {
8444
return "", err
8545
}
86-
return "", fmt.Errorf("CalcFingerprint(%s): %w", util.Iif(useNative, "native", "ssh-keygen"), err)
46+
return "", fmt.Errorf("CalcFingerprint: %w", err)
8747
}
8848
return fp, nil
8949
}

models/asymkey/ssh_key_parse.go

Lines changed: 2 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,9 @@ import (
1313
"errors"
1414
"fmt"
1515
"math/big"
16-
"os"
17-
"strconv"
1816
"strings"
1917

2018
"code.gitea.io/gitea/modules/log"
21-
"code.gitea.io/gitea/modules/process"
2219
"code.gitea.io/gitea/modules/setting"
2320
"code.gitea.io/gitea/modules/util"
2421

@@ -175,20 +172,9 @@ func CheckPublicKeyString(content string) (_ string, err error) {
175172
return content, nil
176173
}
177174

178-
var (
179-
fnName string
180-
keyType string
181-
length int
182-
)
183-
if len(setting.SSH.KeygenPath) == 0 {
184-
fnName = "SSHNativeParsePublicKey"
185-
keyType, length, err = SSHNativeParsePublicKey(content)
186-
} else {
187-
fnName = "SSHKeyGenParsePublicKey"
188-
keyType, length, err = SSHKeyGenParsePublicKey(content)
189-
}
175+
keyType, length, err := SSHNativeParsePublicKey(content)
190176
if err != nil {
191-
return "", fmt.Errorf("%s: %w", fnName, err)
177+
return "", fmt.Errorf("SSHNativeParsePublicKey: %w", err)
192178
}
193179
log.Trace("Key info [native: %v]: %s-%d", setting.SSH.StartBuiltinServer, keyType, length)
194180

@@ -258,56 +244,3 @@ func SSHNativeParsePublicKey(keyLine string) (string, int, error) {
258244
}
259245
return "", 0, fmt.Errorf("unsupported key length detection for type: %s", pkey.Type())
260246
}
261-
262-
// writeTmpKeyFile writes key content to a temporary file
263-
// and returns the name of that file, along with any possible errors.
264-
func writeTmpKeyFile(content string) (string, error) {
265-
tmpFile, err := os.CreateTemp(setting.SSH.KeyTestPath, "gitea_keytest")
266-
if err != nil {
267-
return "", fmt.Errorf("TempFile: %w", err)
268-
}
269-
defer tmpFile.Close()
270-
271-
if _, err = tmpFile.WriteString(content); err != nil {
272-
return "", fmt.Errorf("WriteString: %w", err)
273-
}
274-
return tmpFile.Name(), nil
275-
}
276-
277-
// SSHKeyGenParsePublicKey extracts key type and length using ssh-keygen.
278-
func SSHKeyGenParsePublicKey(key string) (string, int, error) {
279-
tmpName, err := writeTmpKeyFile(key)
280-
if err != nil {
281-
return "", 0, fmt.Errorf("writeTmpKeyFile: %w", err)
282-
}
283-
defer func() {
284-
if err := util.Remove(tmpName); err != nil {
285-
log.Warn("Unable to remove temporary key file: %s: Error: %v", tmpName, err)
286-
}
287-
}()
288-
289-
keygenPath := setting.SSH.KeygenPath
290-
if len(keygenPath) == 0 {
291-
keygenPath = "ssh-keygen"
292-
}
293-
294-
stdout, stderr, err := process.GetManager().Exec("SSHKeyGenParsePublicKey", keygenPath, "-lf", tmpName)
295-
if err != nil {
296-
return "", 0, fmt.Errorf("fail to parse public key: %s - %s", err, stderr)
297-
}
298-
if strings.Contains(stdout, "is not a public key file") {
299-
return "", 0, ErrKeyUnableVerify{stdout}
300-
}
301-
302-
fields := strings.Split(stdout, " ")
303-
if len(fields) < 4 {
304-
return "", 0, fmt.Errorf("invalid public key line: %s", stdout)
305-
}
306-
307-
keyType := strings.Trim(fields[len(fields)-1], "()\r\n")
308-
length, err := strconv.ParseInt(fields[0], 10, 32)
309-
if err != nil {
310-
return "", 0, err
311-
}
312-
return strings.ToLower(keyType), int(length), nil
313-
}

models/asymkey/ssh_key_test.go

Lines changed: 0 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ import (
1818

1919
"github.com/42wim/sshsig"
2020
"github.com/stretchr/testify/assert"
21-
"github.com/stretchr/testify/require"
2221
)
2322

2423
func Test_SSHParsePublicKey(t *testing.T) {
@@ -45,27 +44,6 @@ func Test_SSHParsePublicKey(t *testing.T) {
4544
assert.Equal(t, tc.keyType, keyTypeN)
4645
assert.Equal(t, tc.length, lengthN)
4746
})
48-
if tc.skipSSHKeygen {
49-
return
50-
}
51-
t.Run("SSHKeygen", func(t *testing.T) {
52-
keyTypeK, lengthK, err := SSHKeyGenParsePublicKey(tc.content)
53-
if err != nil {
54-
// Some servers do not support ecdsa format.
55-
if !strings.Contains(err.Error(), "line 1 too long:") {
56-
require.NoError(t, err)
57-
}
58-
}
59-
assert.Equal(t, tc.keyType, keyTypeK)
60-
assert.Equal(t, tc.length, lengthK)
61-
})
62-
t.Run("SSHParseKeyNative", func(t *testing.T) {
63-
keyTypeK, lengthK, err := SSHNativeParsePublicKey(tc.content)
64-
require.NoError(t, err)
65-
66-
assert.Equal(t, tc.keyType, keyTypeK)
67-
assert.Equal(t, tc.length, lengthK)
68-
})
6947
})
7048
}
7149
}
@@ -186,14 +164,6 @@ func Test_calcFingerprint(t *testing.T) {
186164
assert.NoError(t, err)
187165
assert.Equal(t, tc.fp, fpN)
188166
})
189-
if tc.skipSSHKeygen {
190-
return
191-
}
192-
t.Run("SSHKeygen", func(t *testing.T) {
193-
fpK, err := calcFingerprintSSHKeygen(tc.content)
194-
assert.NoError(t, err)
195-
assert.Equal(t, tc.fp, fpK)
196-
})
197167
})
198168
}
199169
}

models/git/branch.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,11 @@ func GetDeletedBranchByID(ctx context.Context, repoID, branchID int64) (*Branch,
235235
return &branch, nil
236236
}
237237

238+
func DeleteRepoBranches(ctx context.Context, repoID int64) error {
239+
_, err := db.GetEngine(ctx).Where("repo_id=?", repoID).Delete(new(Branch))
240+
return err
241+
}
242+
238243
func DeleteBranches(ctx context.Context, repoID, doerID int64, branchIDs []int64) error {
239244
return db.WithTx(ctx, func(ctx context.Context) error {
240245
branches := make([]*Branch, 0, len(branchIDs))

models/issues/issue_search.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ import (
2121
"xorm.io/xorm"
2222
)
2323

24+
const ScopeSortPrefix = "scope-"
25+
2426
// IssuesOptions represents options of an issue.
2527
type IssuesOptions struct { //nolint
2628
Paginator *db.ListOptions
@@ -70,6 +72,17 @@ func (o *IssuesOptions) Copy(edit ...func(options *IssuesOptions)) *IssuesOption
7072
// applySorts sort an issues-related session based on the provided
7173
// sortType string
7274
func applySorts(sess *xorm.Session, sortType string, priorityRepoID int64) {
75+
// Since this sortType is dynamically created, it has to be treated specially.
76+
if strings.HasPrefix(sortType, ScopeSortPrefix) {
77+
scope := strings.TrimPrefix(sortType, ScopeSortPrefix)
78+
sess.Join("LEFT", "issue_label", "issue.id = issue_label.issue_id")
79+
// "exclusive_order=0" means "no order is set", so exclude it from the JOIN criteria and then "LEFT JOIN" result is also null
80+
sess.Join("LEFT", "label", "label.id = issue_label.label_id AND label.exclusive_order <> 0 AND label.name LIKE ?", scope+"/%")
81+
// Use COALESCE to make sure we sort NULL last regardless of backend DB (2147483647 == max int)
82+
sess.OrderBy("COALESCE(label.exclusive_order, 2147483647) ASC").Desc("issue.id")
83+
return
84+
}
85+
7386
switch sortType {
7487
case "oldest":
7588
sess.Asc("issue.created_unix").Asc("issue.id")

0 commit comments

Comments
 (0)