Skip to content

Commit 21aaf94

Browse files
committed
Merge remote-tracking branch 'giteaofficial/main'
* giteaofficial/main: [skip ci] Updated translations via Crowdin Remove unnecessary double quotes on language file (go-gitea#30977) Always load or generate oauth2 jwt secret (go-gitea#30942) Filter out duplicate action(activity) items for a repository (go-gitea#30957)
2 parents f35d360 + db57843 commit 21aaf94

23 files changed

+133
-87
lines changed

models/activities/action.go

+10-1
Original file line numberDiff line numberDiff line change
@@ -524,7 +524,12 @@ func activityQueryCondition(ctx context.Context, opts GetFeedsOptions) (builder.
524524
}
525525

526526
if opts.RequestedRepo != nil {
527-
cond = cond.And(builder.Eq{"repo_id": opts.RequestedRepo.ID})
527+
// repo's actions could have duplicate items, see the comment of NotifyWatchers
528+
// so here we only filter the "original items", aka: user_id == act_user_id
529+
cond = cond.And(
530+
builder.Eq{"`action`.repo_id": opts.RequestedRepo.ID},
531+
builder.Expr("`action`.user_id = `action`.act_user_id"),
532+
)
528533
}
529534

530535
if opts.RequestedTeam != nil {
@@ -577,6 +582,10 @@ func DeleteOldActions(ctx context.Context, olderThan time.Duration) (err error)
577582
}
578583

579584
// NotifyWatchers creates batch of actions for every watcher.
585+
// It could insert duplicate actions for a repository action, like this:
586+
// * Original action: UserID=1 (the real actor), ActUserID=1
587+
// * Organization action: UserID=100 (the repo's org), ActUserID=1
588+
// * Watcher action: UserID=20 (a user who is watching a repo), ActUserID=1
580589
func NotifyWatchers(ctx context.Context, actions ...*Action) error {
581590
var watchers []*repo_model.Watch
582591
var repo *repo_model.Repository

models/activities/action_test.go

+21
Original file line numberDiff line numberDiff line change
@@ -318,3 +318,24 @@ func TestDeleteIssueActions(t *testing.T) {
318318
assert.NoError(t, activities_model.DeleteIssueActions(db.DefaultContext, issue.RepoID, issue.ID, issue.Index))
319319
unittest.AssertCount(t, &activities_model.Action{}, 0)
320320
}
321+
322+
func TestRepoActions(t *testing.T) {
323+
assert.NoError(t, unittest.PrepareTestDatabase())
324+
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
325+
_ = db.TruncateBeans(db.DefaultContext, &activities_model.Action{})
326+
for i := 0; i < 3; i++ {
327+
_ = db.Insert(db.DefaultContext, &activities_model.Action{
328+
UserID: 2 + int64(i),
329+
ActUserID: 2,
330+
RepoID: repo.ID,
331+
OpType: activities_model.ActionCommentIssue,
332+
})
333+
}
334+
count, _ := db.Count[activities_model.Action](db.DefaultContext, &db.ListOptions{})
335+
assert.EqualValues(t, 3, count)
336+
actions, _, err := activities_model.GetFeeds(db.DefaultContext, activities_model.GetFeedsOptions{
337+
RequestedRepo: repo,
338+
})
339+
assert.NoError(t, err)
340+
assert.Len(t, actions, 1)
341+
}

modules/setting/oauth2.go

+6-11
Original file line numberDiff line numberDiff line change
@@ -126,16 +126,15 @@ func loadOAuth2From(rootCfg ConfigProvider) {
126126
OAuth2.Enabled = sec.Key("ENABLE").MustBool(OAuth2.Enabled)
127127
}
128128

129-
if !OAuth2.Enabled {
130-
return
131-
}
132-
133-
jwtSecretBase64 := loadSecret(sec, "JWT_SECRET_URI", "JWT_SECRET")
134-
135129
if !filepath.IsAbs(OAuth2.JWTSigningPrivateKeyFile) {
136130
OAuth2.JWTSigningPrivateKeyFile = filepath.Join(AppDataPath, OAuth2.JWTSigningPrivateKeyFile)
137131
}
138132

133+
// FIXME: at the moment, no matter oauth2 is enabled or not, it must generate a "oauth2 JWT_SECRET"
134+
// Because this secret is also used as GeneralTokenSigningSecret (as a quick not-that-breaking fix for some legacy problems).
135+
// Including: CSRF token, account validation token, etc ...
136+
// In main branch, the signing token should be refactored (eg: one unique for LFS/OAuth2/etc ...)
137+
jwtSecretBase64 := loadSecret(sec, "JWT_SECRET_URI", "JWT_SECRET")
139138
if InstallLock {
140139
jwtSecretBytes, err := generate.DecodeJwtSecretBase64(jwtSecretBase64)
141140
if err != nil {
@@ -157,20 +156,16 @@ func loadOAuth2From(rootCfg ConfigProvider) {
157156
}
158157
}
159158

160-
// generalSigningSecret is used as container for a []byte value
161-
// instead of an additional mutex, we use CompareAndSwap func to change the value thread save
162159
var generalSigningSecret atomic.Pointer[[]byte]
163160

164161
func GetGeneralTokenSigningSecret() []byte {
165162
old := generalSigningSecret.Load()
166163
if old == nil || len(*old) == 0 {
167164
jwtSecret, _, err := generate.NewJwtSecretWithBase64()
168165
if err != nil {
169-
log.Fatal("Unable to generate general JWT secret: %s", err.Error())
166+
log.Fatal("Unable to generate general JWT secret: %v", err)
170167
}
171168
if generalSigningSecret.CompareAndSwap(old, &jwtSecret) {
172-
// FIXME: in main branch, the signing token should be refactored (eg: one unique for LFS/OAuth2/etc ...)
173-
LogStartupProblem(1, log.WARN, "OAuth2 is not enabled, unable to use a persistent signing secret, a new one is generated, which is not persistent between restarts and cluster nodes")
174169
return jwtSecret
175170
}
176171
return *generalSigningSecret.Load()

modules/setting/oauth2_test.go

+27-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
package setting
55

66
import (
7+
"os"
78
"testing"
89

910
"code.gitea.io/gitea/modules/generate"
@@ -14,7 +15,7 @@ import (
1415

1516
func TestGetGeneralSigningSecret(t *testing.T) {
1617
// when there is no general signing secret, it should be generated, and keep the same value
17-
assert.Nil(t, generalSigningSecret.Load())
18+
generalSigningSecret.Store(nil)
1819
s1 := GetGeneralTokenSigningSecret()
1920
assert.NotNil(t, s1)
2021
s2 := GetGeneralTokenSigningSecret()
@@ -33,6 +34,31 @@ JWT_SECRET = BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
3334
assert.EqualValues(t, expected, actual)
3435
}
3536

37+
func TestGetGeneralSigningSecretSave(t *testing.T) {
38+
defer test.MockVariableValue(&InstallLock, true)()
39+
40+
old := GetGeneralTokenSigningSecret()
41+
assert.Len(t, old, 32)
42+
43+
tmpFile := t.TempDir() + "/app.ini"
44+
_ = os.WriteFile(tmpFile, nil, 0o644)
45+
cfg, _ := NewConfigProviderFromFile(tmpFile)
46+
loadOAuth2From(cfg)
47+
generated := GetGeneralTokenSigningSecret()
48+
assert.Len(t, generated, 32)
49+
assert.NotEqual(t, old, generated)
50+
51+
generalSigningSecret.Store(nil)
52+
cfg, _ = NewConfigProviderFromFile(tmpFile)
53+
loadOAuth2From(cfg)
54+
again := GetGeneralTokenSigningSecret()
55+
assert.Equal(t, generated, again)
56+
57+
iniContent, err := os.ReadFile(tmpFile)
58+
assert.NoError(t, err)
59+
assert.Contains(t, string(iniContent), "JWT_SECRET = ")
60+
}
61+
3662
func TestOauth2DefaultApplications(t *testing.T) {
3763
cfg, _ := NewConfigProviderFromData(``)
3864
loadOAuth2From(cfg)

options/locale/locale_cs-CZ.ini

-1
Original file line numberDiff line numberDiff line change
@@ -3320,7 +3320,6 @@ mirror_sync_create=synchronizoval/a novou referenci <a href="%[2]s">%[3]s</a> do
33203320
mirror_sync_delete=synchronizoval/a a smazal/a referenci <code>%[2]s</code> v <a href="%[1]s">%[3]s</a> ze zrcadla
33213321
approve_pull_request=`schválil/a <a href="%[1]s">%[3]s#%[2]s</a>`
33223322
reject_pull_request=`navrhl/a změny pro <a href="%[1]s">%[3]s#%[2]s</a>`
3323-
publish_release=`vydal/a <a href="%[2]s"> "%[4]s" </a> v <a href="%[1]s">%[3]s</a>`
33243323
review_dismissed=`zamítl/a posouzení z <b>%[4]s</b> pro <a href="%[1]s">%[3]s#%[2]s</a>`
33253324
review_dismissed_reason=Důvod:
33263325
create_branch=vytvořil/a větev <a href="%[2]s">%[3]s</a> v <a href="%[1]s">%[4]s</a>

options/locale/locale_de-DE.ini

-1
Original file line numberDiff line numberDiff line change
@@ -3329,7 +3329,6 @@ mirror_sync_create=neue Referenz <a href="%[2]s">%[3]s</a> bei <a href="%[1]s">%
33293329
mirror_sync_delete=hat die Referenz des Mirrors <code>%[2]s</code> in <a href="%[1]s">%[3]s</a> synchronisiert und gelöscht
33303330
approve_pull_request=`hat <a href="%[1]s">%[3]s#%[2]s</a> approved`
33313331
reject_pull_request=`schlug Änderungen für <a href="%[1]s">%[3]s#%[2]s</a> vor`
3332-
publish_release=`veröffentlichte Release <a href="%[2]s"> "%[4]s" </a> in <a href="%[1]s">%[3]s</a>`
33333332
review_dismissed=`verwarf das Review von <b>%[4]s</b> in <a href="%[1]s">%[3]s#%[2]s</a>`
33343333
review_dismissed_reason=Grund:
33353334
create_branch=legte den Branch <a href="%[2]s">%[3]s</a> in <a href="%[1]s">%[4]s</a> an

options/locale/locale_el-GR.ini

-1
Original file line numberDiff line numberDiff line change
@@ -3210,7 +3210,6 @@ mirror_sync_create=συγχρονίστηκε η νέα αναφορά <a href="
32103210
mirror_sync_delete=συγχρόνισε και διάγραψε την αναφορά <code>%[2]s</code> σε <a href="%[1]s">%[3]s</a> από το είδωλο
32113211
approve_pull_request=`ενέκρινε το <a href="%[1]s">%[3]s#%[2]s</a>`
32123212
reject_pull_request=`πρότεινε αλλαγές για το <a href="%[1]s">%[3]s#%[2]s</a>`
3213-
publish_release=`έκδωσε τη <a href="%[2]s"> "%[4]s" </a> στο <a href="%[1]s">%[3]s</a>`
32143213
review_dismissed=`ακύρωσε την εξέταση από <b>%[4]s</b> for <a href="%[1]s">%[3]s#%[2]s</a>`
32153214
review_dismissed_reason=Αιτία:
32163215
create_branch=δημιούργησε το κλαδο <a href="%[2]s">%[3]s</a> στο <a href="%[1]s">%[4]s</a>

options/locale/locale_en-US.ini

+1-1
Original file line numberDiff line numberDiff line change
@@ -3348,7 +3348,7 @@ mirror_sync_create = synced new reference <a href="%[2]s">%[3]s</a> to <a href="
33483348
mirror_sync_delete = synced and deleted reference <code>%[2]s</code> at <a href="%[1]s">%[3]s</a> from mirror
33493349
approve_pull_request = `approved <a href="%[1]s">%[3]s#%[2]s</a>`
33503350
reject_pull_request = `suggested changes for <a href="%[1]s">%[3]s#%[2]s</a>`
3351-
publish_release = `released <a href="%[2]s"> "%[4]s" </a> at <a href="%[1]s">%[3]s</a>`
3351+
publish_release = `released <a href="%[2]s">%[4]s</a> at <a href="%[1]s">%[3]s</a>`
33523352
review_dismissed = `dismissed review from <b>%[4]s</b> for <a href="%[1]s">%[3]s#%[2]s</a>`
33533353
review_dismissed_reason = Reason:
33543354
create_branch = created branch <a href="%[2]s">%[3]s</a> in <a href="%[1]s">%[4]s</a>

options/locale/locale_es-ES.ini

-1
Original file line numberDiff line numberDiff line change
@@ -3193,7 +3193,6 @@ mirror_sync_create=sincronizó la nueva referencia <a href="%[2]s">%[3]s</a> a <
31933193
mirror_sync_delete=sincronizada y eliminada referencia <code>%[2]s</code> en <a href="%[1]s">%[3]s</a> desde réplica
31943194
approve_pull_request=`aprobó <a href="%[1]s">%[3]s#%[2]s</a>`
31953195
reject_pull_request=`sugirió cambios para <a href="%[1]s">%[3]s#%[2]s</a>`
3196-
publish_release=`se lanzó <a href="%[2]s"> "%[4]s" </a> en <a href="%[1]s">%[3]s</a>`
31973196
review_dismissed=`descartó la revisión de <b>%[4]s</b> para <a href="%[1]s">%[3]s#%[2]s</a>`
31983197
review_dismissed_reason=Motivo:
31993198
create_branch=creó rama <a href="%[2]s">%[3]s</a> en <a href="%[1]s">%[4]s</a>

options/locale/locale_fa-IR.ini

-1
Original file line numberDiff line numberDiff line change
@@ -2508,7 +2508,6 @@ mirror_sync_create=مرجع جدید <a href="%[2]s">%[3]s</a> با <a href="%[1
25082508
mirror_sync_delete=از مرجع <code>%[2]s</code> در<a href="%[1]s">%[3]s</a> حذف شده و از قرینه همگام شده
25092509
approve_pull_request=`تأیید <a href="%[1]s">%[3]s#%[2]s</a>`
25102510
reject_pull_request=`تغییرات پیشنهادی برای <a href="%[1]s">%[3]s#%[2]s</a>`
2511-
publish_release=`<a href="%[2]s"> "%[4]s" </a> در <a href="%[1]s">%[3]s</a> منتشر شد`
25122511
review_dismissed=`بازبینی از <b>%[4]s</b> برای <a href="%[1]s">%[3]s#%[2]s</a> رد شد`
25132512
review_dismissed_reason=دلیل:
25142513
create_branch=شاخه <a href="%[2]s">%[3]s</a> در <a href="%[1]s">%[4]s</a> ایجاد کرد

options/locale/locale_fr-FR.ini

-1
Original file line numberDiff line numberDiff line change
@@ -3249,7 +3249,6 @@ mirror_sync_create=a synchronisé la nouvelle référence <a href="%[2]s">%[3]s<
32493249
mirror_sync_delete=a synchronisé puis supprimé la nouvelle référence <code>%[2]s</code> vers <a href="%[1]s">%[3]s</a> depuis le miroir
32503250
approve_pull_request=`a approuvé <a href="%[1]s">%[3]s#%[2]s</a>`
32513251
reject_pull_request=`a suggérés des changements pour <a href="%[1]s">%[3]s#%[2]s</a>`
3252-
publish_release=`a publié <a href="%[2]s"> "%[4]s" </a> dans <a href="%[1]s">%[3]s</a>`
32533252
review_dismissed=`a révoqué l’évaluation de <b>%[4]s</b> dans <a href="%[1]s">%[3]s#%[2]s</a>`
32543253
review_dismissed_reason=Raison :
32553254
create_branch=a créé la branche <a href="%[2]s">%[3]s</a> dans <a href="%[1]s">%[4]s</a>

options/locale/locale_it-IT.ini

-1
Original file line numberDiff line numberDiff line change
@@ -2707,7 +2707,6 @@ mirror_sync_create=ha sincronizzato un nuovo riferimento <a href="%[2]s">%[3]s</
27072707
mirror_sync_delete=riferimento sincronizzato ed eliminato <code>%[2]s</code> a <a href="%[1]s">%[3]s</a> dal mirror
27082708
approve_pull_request=`ha approvato <a href="%[1]s">%[3]s#%[2]s</a>`
27092709
reject_pull_request=`ha suggerito modifiche per <a href="%[1]s">%[3]s#%[2]s</a>`
2710-
publish_release=`ha rilasciato <a href="%[2]s"> "%[4]s" </a> su <a href="%[1]s">%[3]s</a>`
27112710
review_dismissed=`respinta la recensione da <b>%[4]s</b> per <a href="%[1]s">%[3]s#%[2]s</a>`
27122711
review_dismissed_reason=Motivo:
27132712
create_branch=ha creato il ramo <a href="%[2]s">%[3]s</a> in <a href="%[1]s">%[4]s</a>

options/locale/locale_ja-JP.ini

-1
Original file line numberDiff line numberDiff line change
@@ -3344,7 +3344,6 @@ mirror_sync_create=が <a href="%[1]s">%[4]s</a> の新しい参照 <a href="%[2
33443344
mirror_sync_delete=が <a href="%[1]s">%[3]s</a> の参照 <code>%[2]s</code> をミラーから反映し、削除しました
33453345
approve_pull_request=`が <a href="%[1]s">%[3]s#%[2]s</a> を承認しました`
33463346
reject_pull_request=`が <a href="%[1]s">%[3]s#%[2]s</a>について変更を提案しました`
3347-
publish_release=`が <a href="%[1]s">%[3]s</a> の <a href="%[2]s"> "%[4]s" </a> をリリースしました`
33483347
review_dismissed=`が <b>%[4]s</b> の <a href="%[1]s">%[3]s#%[2]s</a> へのレビューを棄却しました`
33493348
review_dismissed_reason=理由:
33503349
create_branch=がブランチ <a href="%[2]s">%[3]s</a> を <a href="%[1]s">%[4]s</a> に作成しました

0 commit comments

Comments
 (0)