Add a migration to remove SSH signatures from release notes

Because the `git` module did not recognize SSH signed tags, those
signatures ended up in the `notes` column of the `release` table. While
future signatures will not end up there, Forgejo should clean up the old
ones.

This migration does just that: finds all releases that have an SSH
signature, and removes those signatures, preserving the rest of the
note (if any).

While this may seem like an expensive operation, it's only done once,
and even on the largest known Forgejo instance as of this
writing (Codeberg), the number of affected rows are just over a hundred,
a tiny amount all things considered.

Signed-off-by: Gergely Nagy <forgejo@gergo.csillger.hu>
This commit is contained in:
Gergely Nagy 2024-02-29 09:14:50 +01:00 committed by oliverpool
parent 26ed995290
commit 8fdffc94ca
5 changed files with 123 additions and 0 deletions

View file

@ -52,6 +52,8 @@ var migrations = []*Migration{
NewMigration("Add wiki_branch to repository", forgejo_v1_22.AddWikiBranchToRepository), NewMigration("Add wiki_branch to repository", forgejo_v1_22.AddWikiBranchToRepository),
// v6 -> v7 // v6 -> v7
NewMigration("Add enable_repo_unit_hints to the user table", forgejo_v1_22.AddUserRepoUnitHintsSetting), NewMigration("Add enable_repo_unit_hints to the user table", forgejo_v1_22.AddUserRepoUnitHintsSetting),
// v7 -> v8
NewMigration("Remove SSH signatures from Release notes", forgejo_v1_22.RemoveSSHSignaturesFromReleaseNotes),
} }
// GetCurrentDBVersion returns the current Forgejo database version. // GetCurrentDBVersion returns the current Forgejo database version.

View file

@ -0,0 +1,14 @@
// Copyright 2024 The Forgejo Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package v1_22 //nolint
import (
"testing"
"code.gitea.io/gitea/models/migrations/base"
)
func TestMain(m *testing.M) {
base.MainTest(m)
}

View file

@ -0,0 +1,51 @@
// Copyright 2024 The Forgejo Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package v1_22 //nolint
import (
"strings"
"xorm.io/xorm"
)
func RemoveSSHSignaturesFromReleaseNotes(x *xorm.Engine) error {
type Release struct {
ID int64 `xorm:"pk autoincr"`
Note string `xorm:"TEXT"`
}
if err := x.Sync(&Release{}); err != nil {
return err
}
var releaseNotes []struct {
ID int64
Note string
}
if err := x.Table("release").Where("note LIKE '%-----BEGIN SSH SIGNATURE-----%'").Find(&releaseNotes); err != nil {
return err
}
sess := x.NewSession()
defer sess.Close()
if err := sess.Begin(); err != nil {
return err
}
for _, release := range releaseNotes {
idx := strings.LastIndex(release.Note, "-----BEGIN SSH SIGNATURE-----")
if idx == -1 {
continue
}
release.Note = release.Note[:idx]
_, err := sess.Exec("UPDATE `release` SET note = ? WHERE id = ?", release.Note, release.ID)
if err != nil {
return err
}
}
return sess.Commit()
}

View file

@ -0,0 +1,34 @@
// Copyright 2024 The Forgejo Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package v1_22 //nolint
import (
"testing"
"code.gitea.io/gitea/models/migrations/base"
"github.com/stretchr/testify/assert"
)
func Test_RemoveSSHSignaturesFromReleaseNotes(t *testing.T) {
// A reduced mock of the `repo_model.Release` struct.
type Release struct {
ID int64 `xorm:"pk autoincr"`
Note string `xorm:"TEXT"`
}
x, deferable := base.PrepareTestEnv(t, 0, new(Release))
defer deferable()
assert.NoError(t, RemoveSSHSignaturesFromReleaseNotes(x))
var releases []Release
err := x.Table("release").OrderBy("id ASC").Find(&releases)
assert.NoError(t, err)
assert.Len(t, releases, 3)
assert.Equal(t, "", releases[0].Note)
assert.Equal(t, "A message.\n", releases[1].Note)
assert.Equal(t, "no signature present here", releases[2].Note)
}

View file

@ -0,0 +1,22 @@
# type Release struct {
# ID int64 `xorm:"pk autoincr"`
# Note string `xorm:"TEXT"`
# }
-
id: 1
note: |
-----BEGIN SSH SIGNATURE-----
some signature
-----END SSH SIGNATURE-----
-
id: 2
note: |
A message.
-----BEGIN SSH SIGNATURE-----
some signature
-----END SSH SIGNATURE-----
-
id: 3
note: "no signature present here"