mirror of
https://codeberg.org/forgejo/forgejo.git
synced 2026-05-12 22:10:25 +00:00
ci: prevent usage of live application models & services in migrations (#11872)
Prevent access to "current" application models and services from migrations via `golangci` config: eg: ``` models/forgejo_migrations/v14a_ap-change-fedi-handle-structure.go:18:2: import 'forgejo.org/models/user' is not allowed from list 'migration-isolation': Migrations must not import application models. Application models will be the most recent schema for Forgejo, while migrations will be operating against the database schema that existed when they were authored. (depguard) user_model "forgejo.org/models/user" ^ models/forgejo_migrations/v14a_ap-change-fedi-handle-structure.go:21:2: import 'forgejo.org/services/user' is not allowed from list 'migration-isolation': Migrations must not import application services. Application services will reference application models which will use the most recent schema for Forgejo, while migrations will be operating against the database schema that existed when they were authored. (depguard) user_service "forgejo.org/services/user" ``` Fixes an existing migration issue where it isn't possible to add a new column to the `User` table ([test errors that occur](https://codeberg.org/forgejo/forgejo/actions/runs/148633/jobs/10/attempt/1#jobstep-5-323)), but also guarantees that future migrations don't stumble into the same issue by inadvertently referencing live application code from historical migrations. Originally identified and draft fix by @codecat w/ proposed fix in #11870. ## Checklist The [contributor guide](https://forgejo.org/docs/next/contributor/) contains information that will be helpful to first time contributors. All work and communication must conform to Forgejo's [AI Agreement](https://codeberg.org/forgejo/governance/src/branch/main/AIAgreement.md). There also are a few [conditions for merging Pull Requests in Forgejo repositories](https://codeberg.org/forgejo/governance/src/branch/main/PullRequestsAgreement.md). You are also welcome to join the [Forgejo development chatroom](https://matrix.to/#/#forgejo-development:matrix.org). ### Tests for Go changes - I added test coverage for Go changes... - [ ] in their respective `*_test.go` for unit tests. - [ ] in the `tests/integration` directory if it involves interactions with a live Forgejo server. - I ran... - [x] `make pr-go` before pushing ### Documentation - [ ] I created a pull request [to the documentation](https://codeberg.org/forgejo/docs) to explain to Forgejo users how to use this change. - [x] I did not document these changes and I do not expect someone else to do it. ### Release notes - [ ] This change will be noticed by a Forgejo user or admin (feature, bug fix, performance, etc.). I suggest to include a release note for this change. - [x] This change is not visible to a Forgejo user or admin (refactor, dependency upgrade, etc.). I think there is no need to add a release note for this change. Co-authored-by: Melissa Geels <melissa@nimble.tools> Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11872 Reviewed-by: Andreas Ahlenstorf <aahlenst@noreply.codeberg.org> Reviewed-by: Michael Kriese <michael.kriese@gmx.de> Co-authored-by: Mathieu Fenniak <mathieu@fenniak.net> Co-committed-by: Mathieu Fenniak <mathieu@fenniak.net>
This commit is contained in:
parent
5c13563682
commit
8387974e2e
9 changed files with 172 additions and 65 deletions
|
|
@ -45,6 +45,25 @@ linters:
|
|||
desc: use forgejo.org/modules/git instead, see https://codeberg.org/forgejo/forgejo/pulls/4941
|
||||
- pkg: gopkg.in/yaml.v3
|
||||
desc: use go.yaml.in/yaml instead, see https://codeberg.org/forgejo/forgejo/pulls/8956
|
||||
migration-isolation:
|
||||
list-mode: lax
|
||||
files:
|
||||
- "**/models/forgejo_migrations/**"
|
||||
deny:
|
||||
- pkg: "forgejo.org/models"
|
||||
desc: >
|
||||
Migrations must not import application models. Application models will be the most recent schema for
|
||||
Forgejo, while migrations will be operating against the database schema that existed when they were
|
||||
authored.
|
||||
- pkg: "forgejo.org/services"
|
||||
desc: >
|
||||
Migrations must not import application services. Application services will reference application
|
||||
models which will use the most recent schema for Forgejo, while migrations will be operating against the
|
||||
database schema that existed when they were authored.
|
||||
allow:
|
||||
- "forgejo.org/models/db"
|
||||
- "forgejo.org/models/gitea_migrations/base"
|
||||
- "forgejo.org/models/gitea_migrations/test"
|
||||
gocritic:
|
||||
disabled-checks:
|
||||
- ifElseChain
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ package forgejo_migrations
|
|||
import (
|
||||
"context"
|
||||
|
||||
actions_model "forgejo.org/models/actions"
|
||||
"forgejo.org/models/db"
|
||||
"forgejo.org/modules/log"
|
||||
"forgejo.org/modules/timeutil"
|
||||
|
|
@ -59,6 +58,18 @@ type v14ActionsApprovalAndTrustTrusted struct {
|
|||
}
|
||||
|
||||
func v14ActionsApprovalAndTrustPopulateTableActionUser(x *xorm.Engine) error {
|
||||
type ActionUser struct {
|
||||
ID int64 `xorm:"pk autoincr"`
|
||||
UserID int64 `xorm:"INDEX UNIQUE(action_user_index) REFERENCES(user, id)"`
|
||||
RepoID int64 `xorm:"INDEX UNIQUE(action_user_index) REFERENCES(repository, id)"`
|
||||
TrustedWithPullRequests bool
|
||||
LastAccess timeutil.TimeStamp `xorm:"INDEX"`
|
||||
}
|
||||
insertActionUser := func(ctx context.Context, user *ActionUser) error {
|
||||
user.LastAccess = timeutil.TimeStampNow()
|
||||
return db.Insert(ctx, user)
|
||||
}
|
||||
|
||||
//
|
||||
// Users approved once were trusted before and are trusted now.
|
||||
//
|
||||
|
|
@ -87,7 +98,7 @@ func v14ActionsApprovalAndTrustPopulateTableActionUser(x *xorm.Engine) error {
|
|||
if err := db.WithTx(db.DefaultContext, func(ctx context.Context) error {
|
||||
for _, trusted := range trustedList {
|
||||
log.Debug("v14a_actions-approval-and-trust: repository %d trusts user %d", trusted.RepoID, trusted.UserID)
|
||||
if err := actions_model.InsertActionUser(ctx, &actions_model.ActionUser{
|
||||
if err := insertActionUser(ctx, &ActionUser{
|
||||
RepoID: trusted.RepoID,
|
||||
UserID: trusted.UserID,
|
||||
TrustedWithPullRequests: true,
|
||||
|
|
|
|||
|
|
@ -7,11 +7,8 @@ import (
|
|||
"testing"
|
||||
"time"
|
||||
|
||||
actions_model "forgejo.org/models/actions"
|
||||
"forgejo.org/models/db"
|
||||
migration_tests "forgejo.org/models/gitea_migrations/test"
|
||||
repo_model "forgejo.org/models/repo"
|
||||
user_model "forgejo.org/models/user"
|
||||
"forgejo.org/modules/timeutil"
|
||||
webhook_module "forgejo.org/modules/webhook"
|
||||
|
||||
|
|
@ -20,6 +17,9 @@ import (
|
|||
)
|
||||
|
||||
func Test_v14ActionsApprovalAndTrustPopulateTableActionUser(t *testing.T) {
|
||||
type ConcurrencyMode int
|
||||
type Status int
|
||||
|
||||
type ActionUser struct {
|
||||
ID int64 `xorm:"pk autoincr"`
|
||||
UserID int64 `xorm:"INDEX UNIQUE(action_user_index) REFERENCES(user, id)"`
|
||||
|
|
@ -33,20 +33,17 @@ func Test_v14ActionsApprovalAndTrustPopulateTableActionUser(t *testing.T) {
|
|||
ID int64
|
||||
Title string
|
||||
RepoID int64 `xorm:"index unique(repo_index) index(concurrency)"`
|
||||
Repo *repo_model.Repository `xorm:"-"`
|
||||
OwnerID int64 `xorm:"index"`
|
||||
WorkflowID string `xorm:"index"` // the name of workflow file
|
||||
Index int64 `xorm:"index unique(repo_index)"` // a unique number for each run of a repository
|
||||
TriggerUserID int64 `xorm:"index"`
|
||||
TriggerUser *user_model.User `xorm:"-"`
|
||||
ScheduleID int64
|
||||
Ref string `xorm:"index"` // the commit/tag/… that caused the run
|
||||
IsRefDeleted bool `xorm:"-"`
|
||||
CommitSHA string
|
||||
Event webhook_module.HookEventType // the webhook event that causes the workflow to run
|
||||
EventPayload string `xorm:"LONGTEXT"`
|
||||
TriggerEvent string // the trigger event defined in the `on` configuration of the triggered workflow
|
||||
Status actions_model.Status `xorm:"index"`
|
||||
Status Status `xorm:"index"`
|
||||
Version int `xorm:"version default 0"` // Status could be updated concomitantly, so an optimistic lock is needed
|
||||
// Started and Stopped is used for recording last run time, if rerun happened, they will be reset to 0
|
||||
Started timeutil.TimeStamp
|
||||
|
|
@ -65,7 +62,7 @@ func Test_v14ActionsApprovalAndTrustPopulateTableActionUser(t *testing.T) {
|
|||
ApprovedBy int64 `xorm:"index"`
|
||||
|
||||
ConcurrencyGroup string `xorm:"'concurrency_group' index(concurrency)"`
|
||||
ConcurrencyType actions_model.ConcurrencyMode
|
||||
ConcurrencyType ConcurrencyMode
|
||||
|
||||
PreExecutionError string `xorm:"LONGTEXT"` // used to report errors that blocked execution of a workflow
|
||||
}
|
||||
|
|
@ -83,10 +80,10 @@ func Test_v14ActionsApprovalAndTrustPopulateTableActionUser(t *testing.T) {
|
|||
|
||||
require.NoError(t, v14ActionsApprovalAndTrustPopulateTableActionUser(x))
|
||||
|
||||
var users []*actions_model.ActionUser
|
||||
var users []*ActionUser
|
||||
require.NoError(t, db.GetEngine(t.Context()).Select("`repo_id`, `user_id`").OrderBy("`id`").Find(&users))
|
||||
// See models/gitea_migrations/fixtures/Test_v14ActionsApprovalAndTrustPopulateTableActionUser/action_run.yml
|
||||
assert.Equal(t, []*actions_model.ActionUser{
|
||||
assert.Equal(t, []*ActionUser{
|
||||
{
|
||||
UserID: 3,
|
||||
RepoID: 15,
|
||||
|
|
|
|||
|
|
@ -10,15 +10,14 @@ package forgejo_migrations
|
|||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"forgejo.org/models/db"
|
||||
"forgejo.org/models/forgefed"
|
||||
user_model "forgejo.org/models/user"
|
||||
"forgejo.org/modules/log"
|
||||
"forgejo.org/modules/timeutil"
|
||||
"forgejo.org/modules/validation"
|
||||
user_service "forgejo.org/services/user"
|
||||
|
||||
"xorm.io/xorm"
|
||||
)
|
||||
|
|
@ -31,6 +30,42 @@ func init() {
|
|||
}
|
||||
|
||||
func changeActivityPubUsernameFormat(x *xorm.Engine) error {
|
||||
type FederationHost struct {
|
||||
ID int64 `xorm:"pk autoincr"`
|
||||
HostFqdn string `xorm:"host_fqdn UNIQUE(federation_host) INDEX VARCHAR(255) NOT NULL"`
|
||||
HostPort uint16 `xorm:" UNIQUE(federation_host) INDEX NOT NULL DEFAULT 443"`
|
||||
HostSchema string `xorm:"NOT NULL DEFAULT 'https'"`
|
||||
Created timeutil.TimeStamp `xorm:"created"`
|
||||
Updated timeutil.TimeStamp `xorm:"updated"`
|
||||
}
|
||||
type FederatedUser struct {
|
||||
ID int64 `xorm:"pk autoincr"`
|
||||
UserID int64 `xorm:"NOT NULL INDEX user_id"`
|
||||
ExternalID string `xorm:"UNIQUE(federation_user_mapping) NOT NULL"`
|
||||
FederationHostID int64 `xorm:"UNIQUE(federation_user_mapping) NOT NULL"`
|
||||
KeyID sql.NullString `xorm:"key_id UNIQUE"`
|
||||
PublicKey sql.Null[sql.RawBytes] `xorm:"BLOB"`
|
||||
InboxPath string
|
||||
NormalizedOriginalURL string // This field is just to keep original information. Pls. do not use for search or as ID!
|
||||
}
|
||||
type User struct {
|
||||
ID int64 `xorm:"pk autoincr"`
|
||||
LowerName string `xorm:"UNIQUE NOT NULL"`
|
||||
Name string `xorm:"UNIQUE NOT NULL"`
|
||||
CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"`
|
||||
UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"`
|
||||
}
|
||||
deleteFederatedUser := func(ctx context.Context, userID int64) error {
|
||||
_, err := db.GetEngine(ctx).Delete(&FederatedUser{UserID: userID})
|
||||
return err
|
||||
}
|
||||
userLogString := func(u *User) string {
|
||||
if u == nil {
|
||||
return "<User nil>"
|
||||
}
|
||||
return fmt.Sprintf("<User %d:%s>", u.ID, u.Name)
|
||||
}
|
||||
|
||||
// Normally, the db.WithTx statement ensures that the database transaction (aka. all changes made
|
||||
// by this migration) will only be committed if the SQL operations inside of the iteration
|
||||
// (db.Iterate) don't return an error.
|
||||
|
|
@ -45,9 +80,9 @@ func changeActivityPubUsernameFormat(x *xorm.Engine) error {
|
|||
// migrations at a later point and has been kept as-is.
|
||||
return db.WithTx(db.DefaultContext, func(ctx context.Context) error {
|
||||
// The transaction is committed only if modifying all federated users is possible.
|
||||
return db.Iterate(ctx, nil, func(ctx context.Context, federatedUser *user_model.FederatedUser) error {
|
||||
return db.Iterate(ctx, nil, func(ctx context.Context, federatedUser *FederatedUser) error {
|
||||
// localUser represents the "local" representation of an ActivityPub (federated) user
|
||||
localUser := &user_model.User{}
|
||||
localUser := &User{}
|
||||
has, err := db.GetEngine(ctx).ID(federatedUser.UserID).Get(localUser)
|
||||
if err != nil {
|
||||
log.Warn("Migration[v14a_ap-change-fedi-handle-structure]: Database error occurred while getting local user (ID: %d), ignoring...: %e", federatedUser.UserID, err)
|
||||
|
|
@ -56,7 +91,7 @@ func changeActivityPubUsernameFormat(x *xorm.Engine) error {
|
|||
|
||||
if !has {
|
||||
log.Warn("Migration[v14a_ap-change-fedi-handle-structure]: User missing for federated user: %v", federatedUser)
|
||||
err := user_model.DeleteFederatedUser(ctx, federatedUser.UserID)
|
||||
err := deleteFederatedUser(ctx, federatedUser.UserID)
|
||||
if err != nil {
|
||||
log.Warn("Migration[v14a_ap-change-fedi-handle-structure]: Database error occurred while deleting federated user (%s), ignoring...: %e", federatedUser, err)
|
||||
return nil
|
||||
|
|
@ -68,24 +103,13 @@ func changeActivityPubUsernameFormat(x *xorm.Engine) error {
|
|||
} else {
|
||||
// Copied from models/forgefed/federationhost_repository.go (forgefed.GetFederationHost),
|
||||
// minus some validation code for FederationHost which we do not otherwise manipulate here.
|
||||
federationHost := new(forgefed.FederationHost)
|
||||
federationHost := new(FederationHost)
|
||||
has, err := db.GetEngine(ctx).ID(federatedUser.FederationHostID).Get(federationHost)
|
||||
if err != nil {
|
||||
log.Warn("Migration[v14a_ap-change-fedi-handle-structure]: Database error occurred while looking up federation host info (for %v), ignoring...: %e", federatedUser, err)
|
||||
return nil
|
||||
} else if !has {
|
||||
log.Warn("Migration[v14a_ap-change-fedi-handle-structure]: Federation host for federated user missing, deleting: %v", federatedUser)
|
||||
err := user_model.DeleteFederatedUser(ctx, federatedUser.UserID)
|
||||
if err != nil {
|
||||
log.Warn("Migration[v14a_ap-change-fedi-handle-structure]: Database error occurred while deleting federated user (%v), ignoring...: %e", federatedUser, err)
|
||||
return nil
|
||||
}
|
||||
|
||||
err = user_service.DeleteUser(ctx, localUser, true)
|
||||
if err != nil {
|
||||
log.Warn("Migration[v14a_ap-change-fedi-handle-structure]: Database error occurred while deleting user (%s), ignoring...: %v", localUser.LogString(), err)
|
||||
}
|
||||
|
||||
log.Warn("Migration[v14a_ap-change-fedi-handle-structure]: Federation host for federated user %s is missing", federatedUser)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
@ -117,10 +141,10 @@ func changeActivityPubUsernameFormat(x *xorm.Engine) error {
|
|||
|
||||
// Implicitly assumes that there won't be a lower name unique constraint violation.
|
||||
// Potentially a bit paranoid, but why not?
|
||||
userThatShouldntExist := &user_model.User{}
|
||||
userThatShouldntExist := &User{}
|
||||
lowernameTaken, err := db.GetEngine(ctx).Where("lower_name = ?", strings.ToLower(newUsername)).Table("user").Get(userThatShouldntExist)
|
||||
if err != nil {
|
||||
log.Warn("Migration[v14a_ap-change-fedi-handle-structure]: Database error occurred, skipping migration of %s: %e", localUser.LogString(), err)
|
||||
log.Warn("Migration[v14a_ap-change-fedi-handle-structure]: Database error occurred, skipping migration of %s: %e", userLogString(localUser), err)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
@ -128,23 +152,23 @@ func changeActivityPubUsernameFormat(x *xorm.Engine) error {
|
|||
log.Warn(
|
||||
"Migration[v14a_ap-change-fedi-handle-structure]: New username %s for %s already taken by %s, deleting the former...",
|
||||
newUsername,
|
||||
localUser.LogString(),
|
||||
userThatShouldntExist.LogString(),
|
||||
userLogString(localUser),
|
||||
userLogString(userThatShouldntExist),
|
||||
)
|
||||
err := user_model.DeleteFederatedUser(ctx, localUser.ID)
|
||||
err := deleteFederatedUser(ctx, localUser.ID)
|
||||
if err != nil {
|
||||
log.Warn("Migration[v14a_ap-change-fedi-handle-structure]: Database error occurred while deleting federated user (%s), ignoring...: %e", localUser.LogString(), err)
|
||||
log.Warn("Migration[v14a_ap-change-fedi-handle-structure]: Database error occurred while deleting federated user (%s), ignoring...: %e", userLogString(localUser), err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Safe to assume that the following operations should just work now.
|
||||
log.Info("Migration[v14a_ap-change-fedi-handle-structure]: Updating username of %s to %s", localUser.LogString(), newUsername)
|
||||
if _, err := db.GetEngine(ctx).ID(localUser.ID).Cols("lower_name", "name").Update(&user_model.User{
|
||||
log.Info("Migration[v14a_ap-change-fedi-handle-structure]: Updating username of %s to %s", userLogString(localUser), newUsername)
|
||||
if _, err := db.GetEngine(ctx).ID(localUser.ID).Cols("lower_name", "name").Update(&User{
|
||||
LowerName: strings.ToLower(newUsername),
|
||||
Name: newUsername,
|
||||
}); err != nil {
|
||||
log.Warn("Migration[v14a_ap-change-fedi-handle-structure]: Database error occurred when updating federated user's username (%s), ignoring...: %e", localUser.LogString(), err)
|
||||
log.Warn("Migration[v14a_ap-change-fedi-handle-structure]: Database error occurred when updating federated user's username (%s), ignoring...: %e", userLogString(localUser), err)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ import (
|
|||
"encoding/base64"
|
||||
"fmt"
|
||||
|
||||
admin_model "forgejo.org/models/admin"
|
||||
"forgejo.org/models/db"
|
||||
"forgejo.org/modules/json"
|
||||
"forgejo.org/modules/keying"
|
||||
|
|
@ -17,6 +16,7 @@ import (
|
|||
"forgejo.org/modules/secret"
|
||||
"forgejo.org/modules/setting"
|
||||
"forgejo.org/modules/structs"
|
||||
"forgejo.org/modules/timeutil"
|
||||
|
||||
"xorm.io/builder"
|
||||
"xorm.io/xorm"
|
||||
|
|
@ -30,6 +30,19 @@ func init() {
|
|||
}
|
||||
|
||||
func migrateTaskSecrets(x *xorm.Engine) error {
|
||||
type Task struct {
|
||||
ID int64
|
||||
DoerID int64 `xorm:"index"`
|
||||
OwnerID int64 `xorm:"index"`
|
||||
RepoID int64 `xorm:"index"`
|
||||
PayloadContent string `xorm:"TEXT"`
|
||||
Created timeutil.TimeStamp `xorm:"created"`
|
||||
}
|
||||
taskUpdateCols := func(ctx context.Context, task *Task, cols ...string) error {
|
||||
_, err := db.GetEngine(ctx).ID(task.ID).Cols(cols...).Update(task)
|
||||
return err
|
||||
}
|
||||
|
||||
return db.WithTx(db.DefaultContext, func(ctx context.Context) error {
|
||||
sess := db.GetEngine(ctx)
|
||||
|
||||
|
|
@ -39,7 +52,7 @@ func migrateTaskSecrets(x *xorm.Engine) error {
|
|||
messages := make([]string, 0, 100)
|
||||
ids := make([]int64, 0, 100)
|
||||
|
||||
err := db.Iterate(ctx, builder.Eq{"type": structs.TaskTypeMigrateRepo}, func(ctx context.Context, bean *admin_model.Task) error {
|
||||
err := db.Iterate(ctx, builder.Eq{"type": structs.TaskTypeMigrateRepo}, func(ctx context.Context, bean *Task) error {
|
||||
var opts migration.MigrateOptions
|
||||
err := json.Unmarshal([]byte(bean.PayloadContent), &opts)
|
||||
if err != nil {
|
||||
|
|
@ -96,7 +109,7 @@ func migrateTaskSecrets(x *xorm.Engine) error {
|
|||
}
|
||||
bean.PayloadContent = string(bs)
|
||||
|
||||
return bean.UpdateCols(ctx, "payload_content")
|
||||
return taskUpdateCols(ctx, bean, "payload_content")
|
||||
})
|
||||
|
||||
if err == nil {
|
||||
|
|
@ -106,7 +119,7 @@ func migrateTaskSecrets(x *xorm.Engine) error {
|
|||
log.Error("v14a_migrate_task_secrets: %s", message)
|
||||
}
|
||||
|
||||
_, err = sess.In("id", ids).NoAutoCondition().NoAutoTime().Delete(&admin_model.Task{})
|
||||
_, err = sess.In("id", ids).NoAutoCondition().NoAutoTime().Delete(&Task{})
|
||||
}
|
||||
}
|
||||
return err
|
||||
|
|
|
|||
|
|
@ -8,11 +8,11 @@ import (
|
|||
"fmt"
|
||||
|
||||
"forgejo.org/models/db"
|
||||
webhook_model "forgejo.org/models/webhook"
|
||||
"forgejo.org/modules/keying"
|
||||
"forgejo.org/modules/log"
|
||||
"forgejo.org/modules/secret"
|
||||
"forgejo.org/modules/setting"
|
||||
"forgejo.org/modules/timeutil"
|
||||
|
||||
"xorm.io/xorm"
|
||||
"xorm.io/xorm/schemas"
|
||||
|
|
@ -26,6 +26,16 @@ func init() {
|
|||
}
|
||||
|
||||
func migrateWebhookSecrets(x *xorm.Engine) error {
|
||||
type Webhook struct {
|
||||
ID int64 `xorm:"pk autoincr"`
|
||||
RepoID int64 `xorm:"INDEX"` // An ID of 0 indicates either a default or system webhook
|
||||
OwnerID int64 `xorm:"INDEX"`
|
||||
HeaderAuthorizationEncrypted []byte `xorm:"BLOB"`
|
||||
|
||||
CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"`
|
||||
UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"`
|
||||
}
|
||||
|
||||
return db.WithTx(db.DefaultContext, func(ctx context.Context) error {
|
||||
sess := db.GetEngine(ctx)
|
||||
|
||||
|
|
@ -59,7 +69,7 @@ func migrateWebhookSecrets(x *xorm.Engine) error {
|
|||
messages := make([]string, 0, 100)
|
||||
ids := make([]int64, 0, 100)
|
||||
|
||||
err := db.Iterate(ctx, nil, func(ctx context.Context, bean *webhook_model.Webhook) error {
|
||||
err := db.Iterate(ctx, nil, func(ctx context.Context, bean *Webhook) error {
|
||||
if len(bean.HeaderAuthorizationEncrypted) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
|
@ -83,7 +93,7 @@ func migrateWebhookSecrets(x *xorm.Engine) error {
|
|||
log.Error("migration[v14a_migrate_webhook_authorization]: %s", message)
|
||||
}
|
||||
|
||||
_, err = sess.In("id", ids).NoAutoCondition().NoAutoTime().Delete(&webhook_model.Webhook{})
|
||||
_, err = sess.In("id", ids).NoAutoCondition().NoAutoTime().Delete(&Webhook{})
|
||||
}
|
||||
}
|
||||
return err
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ import (
|
|||
"testing"
|
||||
|
||||
migration_tests "forgejo.org/models/gitea_migrations/test"
|
||||
webhook_model "forgejo.org/models/webhook"
|
||||
"forgejo.org/modules/keying"
|
||||
"forgejo.org/modules/timeutil"
|
||||
webhook_module "forgejo.org/modules/webhook"
|
||||
|
|
@ -17,6 +16,7 @@ import (
|
|||
)
|
||||
|
||||
func Test_MigrateWebhookSecrets(t *testing.T) {
|
||||
type HookContentType int
|
||||
type Webhook struct {
|
||||
ID int64 `xorm:"pk autoincr"`
|
||||
RepoID int64 `xorm:"INDEX"`
|
||||
|
|
@ -24,7 +24,7 @@ func Test_MigrateWebhookSecrets(t *testing.T) {
|
|||
IsSystemWebhook bool
|
||||
URL string `xorm:"url TEXT"`
|
||||
HTTPMethod string `xorm:"http_method"`
|
||||
ContentType webhook_model.HookContentType
|
||||
ContentType HookContentType
|
||||
Secret string `xorm:"TEXT"`
|
||||
Events string `xorm:"TEXT"`
|
||||
IsActive bool `xorm:"INDEX"`
|
||||
|
|
@ -45,7 +45,7 @@ func Test_MigrateWebhookSecrets(t *testing.T) {
|
|||
IsSystemWebhook bool
|
||||
URL string `xorm:"url TEXT"`
|
||||
HTTPMethod string `xorm:"http_method"`
|
||||
ContentType webhook_model.HookContentType
|
||||
ContentType HookContentType
|
||||
Secret string `xorm:"TEXT"`
|
||||
Events string `xorm:"TEXT"`
|
||||
IsActive bool `xorm:"INDEX"`
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@
|
|||
package forgejo_migrations
|
||||
|
||||
import (
|
||||
activities_model "forgejo.org/models/activities"
|
||||
"forgejo.org/modules/setting"
|
||||
|
||||
"xorm.io/xorm"
|
||||
|
|
@ -18,9 +17,10 @@ func init() {
|
|||
}
|
||||
|
||||
func reworkNotification(x *xorm.Engine) error {
|
||||
type NotificationStatus uint8
|
||||
type Notification struct {
|
||||
UserID int64 `xorm:"NOT NULL INDEX(s)"`
|
||||
Status activities_model.NotificationStatus `xorm:"SMALLINT NOT NULL INDEX(s)"`
|
||||
Status NotificationStatus `xorm:"SMALLINT NOT NULL INDEX(s)"`
|
||||
}
|
||||
|
||||
if err := dropIndexIfExists(x, "notification", "IDX_notification_user_id"); err != nil {
|
||||
|
|
|
|||
|
|
@ -5,10 +5,11 @@ package forgejo_migrations
|
|||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"forgejo.org/models/db"
|
||||
user_model "forgejo.org/models/user"
|
||||
"forgejo.org/modules/log"
|
||||
"forgejo.org/modules/timeutil"
|
||||
|
||||
"xorm.io/builder"
|
||||
"xorm.io/xorm"
|
||||
|
|
@ -22,13 +23,45 @@ func init() {
|
|||
}
|
||||
|
||||
func setProhibitLoginActivityPubUser(x *xorm.Engine) error {
|
||||
type UserType int
|
||||
const (
|
||||
UserTypeIndividual UserType = iota // Historic reason to make it starts at 0.
|
||||
UserTypeOrganization // 1
|
||||
UserTypeUserReserved // 2
|
||||
UserTypeOrganizationReserved // 3
|
||||
UserTypeBot // 4
|
||||
UserTypeRemoteUser // 5
|
||||
UserTypeActivityPubUser // 6
|
||||
)
|
||||
type User struct {
|
||||
ID int64 `xorm:"pk autoincr"`
|
||||
Name string `xorm:"UNIQUE NOT NULL"`
|
||||
Passwd string `xorm:"NOT NULL"`
|
||||
PasswdHashAlgo string `xorm:"NOT NULL DEFAULT 'argon2'"`
|
||||
Type UserType
|
||||
Salt string `xorm:"VARCHAR(32)"`
|
||||
CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"`
|
||||
UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"`
|
||||
ProhibitLogin bool `xorm:"NOT NULL DEFAULT false"`
|
||||
}
|
||||
type FederatedUser struct {
|
||||
UserID int64 `xorm:"NOT NULL INDEX user_id"`
|
||||
}
|
||||
|
||||
userLogString := func(u *User) string {
|
||||
if u == nil {
|
||||
return "<User nil>"
|
||||
}
|
||||
return fmt.Sprintf("<User %d:%s>", u.ID, u.Name)
|
||||
}
|
||||
|
||||
return db.WithTx(db.DefaultContext, func(ctx context.Context) error {
|
||||
return db.Iterate(ctx, builder.Eq{"type": 5}, func(ctx context.Context, user *user_model.User) error {
|
||||
log.Info("Checking if user %s is created from ActivityPub", user.LogString())
|
||||
return db.Iterate(ctx, builder.Eq{"type": 5}, func(ctx context.Context, user *User) error {
|
||||
log.Info("Checking if user %s is created from ActivityPub", userLogString(user))
|
||||
|
||||
// Users created from f3 also have the RemoteUser user type. All
|
||||
// FederatedUser should reference exactly one User.
|
||||
has, err := db.GetEngine(ctx).Table("federated_user").Get(&user_model.FederatedUser{UserID: user.ID})
|
||||
has, err := db.GetEngine(ctx).Table("federated_user").Get(&FederatedUser{UserID: user.ID})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -37,9 +70,9 @@ func setProhibitLoginActivityPubUser(x *xorm.Engine) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
log.Info("Updating user %s", user.LogString())
|
||||
_, err = db.GetEngine(ctx).Table("user").ID(user.ID).Cols("type", "prohibit_login", "passwd", "salt", "passwd_hash_algo").Update(&user_model.User{
|
||||
Type: user_model.UserTypeActivityPubUser,
|
||||
log.Info("Updating user %s", userLogString(user))
|
||||
_, err = db.GetEngine(ctx).Table("user").ID(user.ID).Cols("type", "prohibit_login", "passwd", "salt", "passwd_hash_algo").Update(&User{
|
||||
Type: UserTypeActivityPubUser,
|
||||
ProhibitLogin: true,
|
||||
Passwd: "",
|
||||
Salt: "",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue