Skip to content

Commit 9bd5db9

Browse files
committed
Merge branch 'main' into lunny/disable_dl_source_ui
2 parents b06ccad + ff9b6fa commit 9bd5db9

File tree

31 files changed

+1362
-204
lines changed

31 files changed

+1362
-204
lines changed

custom/conf/app.example.ini

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,7 @@ USER = root
313313
;DB_TYPE = sqlite3
314314
;PATH= ; defaults to data/gitea.db
315315
;SQLITE_TIMEOUT = ; Query timeout defaults to: 500
316+
;SQLITE_JOURNAL_MODE = ; defaults to sqlite database default (often DELETE), can be used to enable WAL mode. https://www.sqlite.org/pragma.html#pragma_journal_mode
316317
;;
317318
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
318319
;;

docs/content/doc/advanced/config-cheat-sheet.en-us.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,7 @@ The following configuration set `Content-Type: application/vnd.android.package-a
383383
- `verify-ca`: Enable TLS with verification of the database server certificate against its root certificate.
384384
- `verify-full`: Enable TLS and verify the database server name matches the given certificate in either the `Common Name` or `Subject Alternative Name` fields.
385385
- `SQLITE_TIMEOUT`: **500**: Query timeout for SQLite3 only.
386+
- `SQLITE_JOURNAL_MODE`: **""**: Change journal mode for SQlite3. Can be used to enable [WAL mode](https://www.sqlite.org/wal.html) when high load causes write congestion. See [SQlite3 docs](https://www.sqlite.org/pragma.html#pragma_journal_mode) for possible values. Defaults to the default for the database file, often DELETE.
386387
- `ITERATE_BUFFER_SIZE`: **50**: Internal buffer size for iterating.
387388
- `CHARSET`: **utf8mb4**: For MySQL only, either "utf8" or "utf8mb4". NOTICE: for "utf8mb4" you must use MySQL InnoDB > 5.6. Gitea is unable to check this.
388389
- `PATH`: **data/gitea.db**: For SQLite3 only, the database file path.

integrations/mirror_push_test.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313
"testing"
1414

1515
"code.gitea.io/gitea/models"
16+
"code.gitea.io/gitea/models/db"
1617
repo_model "code.gitea.io/gitea/models/repo"
1718
"code.gitea.io/gitea/models/unittest"
1819
user_model "code.gitea.io/gitea/models/user"
@@ -47,7 +48,7 @@ func testMirrorPush(t *testing.T, u *url.URL) {
4748

4849
doCreatePushMirror(ctx, fmt.Sprintf("%s%s/%s", u.String(), url.PathEscape(ctx.Username), url.PathEscape(mirrorRepo.Name)), user.LowerName, userPassword)(t)
4950

50-
mirrors, err := repo_model.GetPushMirrorsByRepoID(srcRepo.ID)
51+
mirrors, _, err := repo_model.GetPushMirrorsByRepoID(db.DefaultContext, srcRepo.ID, db.ListOptions{})
5152
assert.NoError(t, err)
5253
assert.Len(t, mirrors, 1)
5354

@@ -72,7 +73,7 @@ func testMirrorPush(t *testing.T, u *url.URL) {
7273

7374
// Cleanup
7475
doRemovePushMirror(ctx, fmt.Sprintf("%s%s/%s", u.String(), url.PathEscape(ctx.Username), url.PathEscape(mirrorRepo.Name)), user.LowerName, userPassword, int(mirrors[0].ID))(t)
75-
mirrors, err = repo_model.GetPushMirrorsByRepoID(srcRepo.ID)
76+
mirrors, _, err = repo_model.GetPushMirrorsByRepoID(db.DefaultContext, srcRepo.ID, db.ListOptions{})
7677
assert.NoError(t, err)
7778
assert.Len(t, mirrors, 0)
7879
}

models/auth/webauthn.go

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ package auth
66

77
import (
88
"context"
9-
"encoding/base32"
109
"fmt"
1110
"strings"
1211

@@ -20,14 +19,14 @@ import (
2019
// ErrWebAuthnCredentialNotExist represents a "ErrWebAuthnCRedentialNotExist" kind of error.
2120
type ErrWebAuthnCredentialNotExist struct {
2221
ID int64
23-
CredentialID string
22+
CredentialID []byte
2423
}
2524

2625
func (err ErrWebAuthnCredentialNotExist) Error() string {
27-
if err.CredentialID == "" {
26+
if len(err.CredentialID) == 0 {
2827
return fmt.Sprintf("WebAuthn credential does not exist [id: %d]", err.ID)
2928
}
30-
return fmt.Sprintf("WebAuthn credential does not exist [credential_id: %s]", err.CredentialID)
29+
return fmt.Sprintf("WebAuthn credential does not exist [credential_id: %x]", err.CredentialID)
3130
}
3231

3332
// IsErrWebAuthnCredentialNotExist checks if an error is a ErrWebAuthnCredentialNotExist.
@@ -43,7 +42,7 @@ type WebAuthnCredential struct {
4342
Name string
4443
LowerName string `xorm:"unique(s)"`
4544
UserID int64 `xorm:"INDEX unique(s)"`
46-
CredentialID string `xorm:"INDEX VARCHAR(410)"`
45+
CredentialID []byte `xorm:"INDEX VARBINARY(1024)"`
4746
PublicKey []byte
4847
AttestationType string
4948
AAGUID []byte
@@ -94,9 +93,8 @@ type WebAuthnCredentialList []*WebAuthnCredential
9493
func (list WebAuthnCredentialList) ToCredentials() []webauthn.Credential {
9594
creds := make([]webauthn.Credential, 0, len(list))
9695
for _, cred := range list {
97-
credID, _ := base32.HexEncoding.DecodeString(cred.CredentialID)
9896
creds = append(creds, webauthn.Credential{
99-
ID: credID,
97+
ID: cred.CredentialID,
10098
PublicKey: cred.PublicKey,
10199
AttestationType: cred.AttestationType,
102100
Authenticator: webauthn.Authenticator{
@@ -164,11 +162,11 @@ func HasWebAuthnRegistrationsByUID(uid int64) (bool, error) {
164162
}
165163

166164
// GetWebAuthnCredentialByCredID returns WebAuthn credential by credential ID
167-
func GetWebAuthnCredentialByCredID(userID int64, credID string) (*WebAuthnCredential, error) {
165+
func GetWebAuthnCredentialByCredID(userID int64, credID []byte) (*WebAuthnCredential, error) {
168166
return getWebAuthnCredentialByCredID(db.DefaultContext, userID, credID)
169167
}
170168

171-
func getWebAuthnCredentialByCredID(ctx context.Context, userID int64, credID string) (*WebAuthnCredential, error) {
169+
func getWebAuthnCredentialByCredID(ctx context.Context, userID int64, credID []byte) (*WebAuthnCredential, error) {
172170
cred := new(WebAuthnCredential)
173171
if found, err := db.GetEngine(ctx).Where("user_id = ? AND credential_id = ?", userID, credID).Get(cred); err != nil {
174172
return nil, err
@@ -187,7 +185,7 @@ func createCredential(ctx context.Context, userID int64, name string, cred *weba
187185
c := &WebAuthnCredential{
188186
UserID: userID,
189187
Name: name,
190-
CredentialID: base32.HexEncoding.EncodeToString(cred.ID),
188+
CredentialID: cred.ID,
191189
PublicKey: cred.PublicKey,
192190
AttestationType: cred.AttestationType,
193191
AAGUID: cred.Authenticator.AAGUID,

models/auth/webauthn_test.go

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
package auth
66

77
import (
8-
"encoding/base32"
98
"testing"
109

1110
"code.gitea.io/gitea/models/unittest"
@@ -61,9 +60,7 @@ func TestCreateCredential(t *testing.T) {
6160
res, err := CreateCredential(1, "WebAuthn Created Credential", &webauthn.Credential{ID: []byte("Test")})
6261
assert.NoError(t, err)
6362
assert.Equal(t, "WebAuthn Created Credential", res.Name)
64-
bs, err := base32.HexEncoding.DecodeString(res.CredentialID)
65-
assert.NoError(t, err)
66-
assert.Equal(t, []byte("Test"), bs)
63+
assert.Equal(t, []byte("Test"), res.CredentialID)
6764

6865
unittest.AssertExistsIf(t, true, &WebAuthnCredential{Name: "WebAuthn Created Credential", UserID: 1})
6966
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
-
2+
id: 1
3+
credential_id: "TVHE44TOH7DF7V48SEAIT3EMMJ7TGBOQ289E5AQB34S98LFCUFJ7U2NAVI8RJG6K2F4TC8AQ8KBNO7AGEOQOL9NE43GR63HTEHJSLOG="
4+
-
5+
id: 2
6+
credential_id: "051CLMMKB62S6M9M2A4H54K7MMCQALFJ36G4TGB2S9A47APLTILU6C6744CEBG4EKCGV357N21BSLH8JD33GQMFAR6DQ70S76P34J6FR="
7+
-
8+
id: 4
9+
credential_id: "APU4B1NDTEVTEM60V4T0FRL7SRJMO9KIE2AKFQ8JDGTQ7VHFI41FDEFTDLBVQEAE4ER49QV2GTGVFDNBO31BPOA3OQN6879OT6MTU3G="
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
-
2+
id: 1
3+
lower_name: "u2fkey-correctly-migrated"
4+
name: "u2fkey-correctly-migrated"
5+
user_id: 1
6+
credential_id: "TVHE44TOH7DF7V48SEAIT3EMMJ7TGBOQ289E5AQB34S98LFCUFJ7U2NAVI8RJG6K2F4TC8AQ8KBNO7AGEOQOL9NE43GR63HTEHJSLOG="
7+
public_key: 0x040d0967a2cad045011631187576492a0beb5b377954b4f694c5afc8bdf25270f87f09a9ab6ce9c282f447ba71b2f2bae2105b32b847e0704f310f48644e3eddf2
8+
attestation_type: 'fido-u2f'
9+
sign_count: 1
10+
clone_warning: false
11+
-
12+
id: 2
13+
lower_name: "non-u2f-key"
14+
name: "non-u2f-key"
15+
user_id: 1
16+
credential_id: "051CLMMKB62S6M9M2A4H54K7MMCQALFJ36G4TGB2S9A47APLTILU6C6744CEBG4EKCGV357N21BSLH8JD33GQMFAR6DQ70S76P34J6FR"
17+
public_key: 0x040d0967a2cad045011631187576492a0beb5b377954b4f694c5afc8bdf25270f87f09a9ab6ce9c282f447ba71b2f2bae2105b32b847e0704f310f48644e3eddf2
18+
attestation_type: 'none'
19+
sign_count: 1
20+
clone_warning: false
21+
-
22+
id: 4
23+
lower_name: "packed-key"
24+
name: "packed-key"
25+
user_id: 1
26+
credential_id: "APU4B1NDTEVTEM60V4T0FRL7SRJMO9KIE2AKFQ8JDGTQ7VHFI41FDEFTDLBVQEAE4ER49QV2GTGVFDNBO31BPOA3OQN6879OT6MTU3G="
27+
public_key: 0x040d0967a2cad045011631187576492a0beb5b377954b4f694c5afc8bdf25270f87f09a9ab6ce9c282f447ba71b2f2bae2105b32b847e0704f310f48644e3eddf2
28+
attestation_type: 'fido-u2f'
29+
sign_count: 1
30+
clone_warning: false
31+

models/migrations/migrations.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,12 @@ var migrations = []Migration{
400400
NewMigration("Add sync_on_commit column to push_mirror table", addSyncOnCommitColForPushMirror),
401401
// v220 -> v221
402402
NewMigration("Add container repository property", addContainerRepositoryProperty),
403+
// v221 -> v222
404+
NewMigration("Store WebAuthentication CredentialID as bytes and increase size to at least 1024", storeWebauthnCredentialIDAsBytes),
405+
// v222 -> v223
406+
NewMigration("Drop old CredentialID column", dropOldCredentialIDColumn),
407+
// v223 -> v224
408+
NewMigration("Rename CredentialIDBytes column to CredentialID", renameCredentialIDBytes),
403409
}
404410

405411
// GetCurrentDBVersion returns the current db version

models/migrations/v221.go

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
// Copyright 2022 The Gitea Authors. All rights reserved.
2+
// Use of this source code is governed by a MIT-style
3+
// license that can be found in the LICENSE file.
4+
5+
package migrations
6+
7+
import (
8+
"encoding/base32"
9+
"fmt"
10+
11+
"code.gitea.io/gitea/modules/timeutil"
12+
13+
"xorm.io/xorm"
14+
)
15+
16+
func storeWebauthnCredentialIDAsBytes(x *xorm.Engine) error {
17+
// Create webauthnCredential table
18+
type webauthnCredential struct {
19+
ID int64 `xorm:"pk autoincr"`
20+
Name string
21+
LowerName string `xorm:"unique(s)"`
22+
UserID int64 `xorm:"INDEX unique(s)"`
23+
CredentialID string `xorm:"INDEX VARCHAR(410)"`
24+
// Note the lack of INDEX here - these will be created once the column is renamed in v223.go
25+
CredentialIDBytes []byte `xorm:"VARBINARY(1024)"` // CredentialID is at most 1023 bytes as per spec released 20 July 2022
26+
PublicKey []byte
27+
AttestationType string
28+
AAGUID []byte
29+
SignCount uint32 `xorm:"BIGINT"`
30+
CloneWarning bool
31+
CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"`
32+
UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"`
33+
}
34+
if err := x.Sync2(&webauthnCredential{}); err != nil {
35+
return err
36+
}
37+
38+
var start int
39+
creds := make([]*webauthnCredential, 0, 50)
40+
for {
41+
err := x.Select("id, credential_id").OrderBy("id").Limit(50, start).Find(&creds)
42+
if err != nil {
43+
return err
44+
}
45+
46+
err = func() error {
47+
sess := x.NewSession()
48+
defer sess.Close()
49+
if err := sess.Begin(); err != nil {
50+
return fmt.Errorf("unable to allow start session. Error: %w", err)
51+
}
52+
for _, cred := range creds {
53+
cred.CredentialIDBytes, err = base32.HexEncoding.DecodeString(cred.CredentialID)
54+
if err != nil {
55+
return fmt.Errorf("unable to parse credential id %s for credential[%d]: %w", cred.CredentialID, cred.ID, err)
56+
}
57+
count, err := sess.ID(cred.ID).Cols("credential_id_bytes").Update(cred)
58+
if count != 1 || err != nil {
59+
return fmt.Errorf("unable to update credential id bytes for credential[%d]: %d,%w", cred.ID, count, err)
60+
}
61+
}
62+
return sess.Commit()
63+
}()
64+
if err != nil {
65+
return err
66+
}
67+
68+
if len(creds) < 50 {
69+
break
70+
}
71+
start += 50
72+
creds = creds[:0]
73+
}
74+
return nil
75+
}

models/migrations/v221_test.go

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
// Copyright 2022 The Gitea Authors. All rights reserved.
2+
// Use of this source code is governed by a MIT-style
3+
// license that can be found in the LICENSE file.
4+
5+
package migrations
6+
7+
import (
8+
"encoding/base32"
9+
"testing"
10+
11+
"github.com/stretchr/testify/assert"
12+
)
13+
14+
func Test_storeWebauthnCredentialIDAsBytes(t *testing.T) {
15+
// Create webauthnCredential table
16+
type WebauthnCredential struct {
17+
ID int64 `xorm:"pk autoincr"`
18+
Name string
19+
LowerName string `xorm:"unique(s)"`
20+
UserID int64 `xorm:"INDEX unique(s)"`
21+
CredentialID string `xorm:"INDEX VARCHAR(410)"`
22+
PublicKey []byte
23+
AttestationType string
24+
AAGUID []byte
25+
SignCount uint32 `xorm:"BIGINT"`
26+
CloneWarning bool
27+
}
28+
29+
type ExpectedWebauthnCredential struct {
30+
ID int64 `xorm:"pk autoincr"`
31+
CredentialID string // CredentialID is at most 1023 bytes as per spec released 20 July 2022
32+
}
33+
34+
type ConvertedWebauthnCredential struct {
35+
ID int64 `xorm:"pk autoincr"`
36+
CredentialIDBytes []byte `xorm:"VARBINARY(1024)"` // CredentialID is at most 1023 bytes as per spec released 20 July 2022
37+
}
38+
39+
// Prepare and load the testing database
40+
x, deferable := prepareTestEnv(t, 0, new(WebauthnCredential), new(ExpectedWebauthnCredential))
41+
defer deferable()
42+
if x == nil || t.Failed() {
43+
return
44+
}
45+
46+
if err := storeWebauthnCredentialIDAsBytes(x); err != nil {
47+
assert.NoError(t, err)
48+
return
49+
}
50+
51+
expected := []ExpectedWebauthnCredential{}
52+
if err := x.Table("expected_webauthn_credential").Asc("id").Find(&expected); !assert.NoError(t, err) {
53+
return
54+
}
55+
56+
got := []ConvertedWebauthnCredential{}
57+
if err := x.Table("webauthn_credential").Select("id, credential_id_bytes").Asc("id").Find(&got); !assert.NoError(t, err) {
58+
return
59+
}
60+
61+
for i, e := range expected {
62+
credIDBytes, _ := base32.HexEncoding.DecodeString(e.CredentialID)
63+
assert.Equal(t, credIDBytes, got[i].CredentialIDBytes)
64+
}
65+
}

models/migrations/v222.go

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
// Copyright 2022 The Gitea Authors. All rights reserved.
2+
// Use of this source code is governed by a MIT-style
3+
// license that can be found in the LICENSE file.
4+
5+
package migrations
6+
7+
import (
8+
"context"
9+
"fmt"
10+
11+
"code.gitea.io/gitea/modules/timeutil"
12+
13+
"xorm.io/xorm"
14+
)
15+
16+
func dropOldCredentialIDColumn(x *xorm.Engine) error {
17+
// This migration maybe rerun so that we should check if it has been run
18+
credentialIDExist, err := x.Dialect().IsColumnExist(x.DB(), context.Background(), "webauthn_credential", "credential_id")
19+
if err != nil {
20+
return err
21+
}
22+
if !credentialIDExist {
23+
// Column is already non-extant
24+
return nil
25+
}
26+
credentialIDBytesExists, err := x.Dialect().IsColumnExist(x.DB(), context.Background(), "webauthn_credential", "credential_id_bytes")
27+
if err != nil {
28+
return err
29+
}
30+
if !credentialIDBytesExists {
31+
// looks like 221 hasn't properly run
32+
return fmt.Errorf("webauthn_credential does not have a credential_id_bytes column... it is not safe to run this migration")
33+
}
34+
35+
// Create webauthnCredential table
36+
type webauthnCredential struct {
37+
ID int64 `xorm:"pk autoincr"`
38+
Name string
39+
LowerName string `xorm:"unique(s)"`
40+
UserID int64 `xorm:"INDEX unique(s)"`
41+
CredentialID string `xorm:"INDEX VARCHAR(410)"`
42+
// Note the lack of the INDEX on CredentialIDBytes - we will add this in v223.go
43+
CredentialIDBytes []byte `xorm:"VARBINARY(1024)"` // CredentialID is at most 1023 bytes as per spec released 20 July 2022
44+
PublicKey []byte
45+
AttestationType string
46+
AAGUID []byte
47+
SignCount uint32 `xorm:"BIGINT"`
48+
CloneWarning bool
49+
CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"`
50+
UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"`
51+
}
52+
if err := x.Sync2(&webauthnCredential{}); err != nil {
53+
return err
54+
}
55+
56+
// Drop the old credential ID
57+
sess := x.NewSession()
58+
defer sess.Close()
59+
60+
if err := dropTableColumns(sess, "webauthn_credential", "credential_id"); err != nil {
61+
return fmt.Errorf("unable to drop old credentialID column: %w", err)
62+
}
63+
return sess.Commit()
64+
}

0 commit comments

Comments
 (0)