diff --git a/models/federation/federation.go b/models/federation/federation.go new file mode 100644 index 000000000..6b867e8ea --- /dev/null +++ b/models/federation/federation.go @@ -0,0 +1,163 @@ +package federation + +import ( + "context" + "strings" + + "code.gitea.io/gitea/models/db" + "code.gitea.io/gitea/models/user" + "code.gitea.io/gitea/modules/setting" +) + +// HookTask represents a hook task. +// exact copy of models/webhook/hooktask.go when this migration was created +// - xorm:"-" fields deleted +type FederatedHost struct { + ID int64 `xorm:"pk autoincr"` + isBlocked bool + HostFqdn string `xorm:"UNIQUE(s) INDEX"` +} + +func GetFederatdHost(ctx context.Context, hostFqdn string) (*FederatedHost, error) { + rec := new(FederatedHost) + _, err := db.GetEngine(ctx). + Table("federated_host").Where("host_fqdn = ?", hostFqdn).Get(rec) + if err != nil { + return nil, err + } + return rec, nil +} + +func FederatedHostExists(ctx context.Context, hostFqdn string) (bool, error) { + rec := new(FederatedHost) + exists, err := db.GetEngine(ctx). + Table("federated_host").Where("host_fqdn = ?", hostFqdn).Get(rec) + if err != nil { + return false, err + } + return exists, nil +} + +func (host *FederatedHost) Save(ctx context.Context) error { + _, err := db.GetEngine(ctx). + Insert(host) + return err +} + +type FederatedUser struct { + ID int64 `xorm:"pk autoincr"` + UserID int64 `xorm:"INDEX"` + ExternalID string `xorm:"UNIQUE(s) INDEX"` + FederationHostID int64 `xorm:"INDEX"` +} + +func CreateFederatedUser(ctx context.Context, u *user.User, host *FederatedHost) error { + engine := db.GetEngine(ctx) + // _, err := engine. + // Insert(u) + // if err != nil { + // return err + // } + + federatedUser := new(FederatedUser) + federatedUser.ExternalID = u.Name + federatedUser.UserID = u.ID + federatedUser.FederationHostID = host.ID + _, err := engine.Insert(federatedUser) + return err +} + +func CreatUser(ctx context.Context, u *user.User) error { + // set system defaults + u.Visibility = setting.Service.DefaultUserVisibilityMode + u.AllowCreateOrganization = setting.Service.DefaultAllowCreateOrganization && !setting.Admin.DisableRegularOrgCreation + u.EmailNotificationsPreference = setting.Admin.DefaultEmailNotification + u.MaxRepoCreation = -1 + u.Theme = setting.UI.DefaultTheme + u.IsRestricted = setting.Service.DefaultUserIsRestricted + u.IsActive = !(setting.Service.RegisterEmailConfirm || setting.Service.RegisterManualConfirm) + + // Ensure consistency of the dates. + if u.UpdatedUnix < u.CreatedUnix { + u.UpdatedUnix = u.CreatedUnix + } + + // validate data + if err := user.ValidateUser(u); err != nil { + return err + } + + if err := user.ValidateEmail(u.Email); err != nil { + return err + } + + ctx, committer, err := db.TxContext(ctx) + if err != nil { + return err + } + defer committer.Close() + + isExist, err := user.IsUserExist(ctx, 0, u.Name) + if err != nil { + return err + } else if isExist { + return user.ErrUserAlreadyExist{u.Name} + } + + isExist, err = user.IsEmailUsed(ctx, u.Email) + if err != nil { + return err + } else if isExist { + return user.ErrEmailAlreadyUsed{ + Email: u.Email, + } + } + + // prepare for database + + u.LowerName = strings.ToLower(u.Name) + u.AvatarEmail = u.Email + if u.Rands, err = user.GetUserSalt(); err != nil { + return err + } + if u.Passwd != "" { + if err = u.SetPassword(u.Passwd); err != nil { + return err + } + } else { + u.Salt = "" + u.PasswdHashAlgo = "" + } + + // save changes to database + + if err = user.DeleteUserRedirect(ctx, u.Name); err != nil { + return err + } + + if u.CreatedUnix == 0 { + // Caller expects auto-time for creation & update timestamps. + err = db.Insert(ctx, u) + } else { + // Caller sets the timestamps themselves. They are responsible for ensuring + // both `CreatedUnix` and `UpdatedUnix` are set appropriately. + _, err = db.GetEngine(ctx).NoAutoTime().Insert(u) + } + if err != nil { + return err + } + + // insert email address + if err := db.Insert(ctx, &user.EmailAddress{ + UID: u.ID, + Email: u.Email, + LowerEmail: strings.ToLower(u.Email), + IsActivated: u.IsActive, + IsPrimary: true, + }); err != nil { + return err + } + + return committer.Commit() + +} diff --git a/models/forgejo_migrations/migrate.go b/models/forgejo_migrations/migrate.go index da417cc08..a0f336074 100644 --- a/models/forgejo_migrations/migrate.go +++ b/models/forgejo_migrations/migrate.go @@ -50,6 +50,10 @@ var migrations = []*Migration{ NewMigration("create the forgejo_repo_flag table", forgejo_v1_22.CreateRepoFlagTable), // v5 -> v6 NewMigration("Add wiki_branch to repository", forgejo_v1_22.AddWikiBranchToRepository), + // v6 -> v7 + NewMigration("create federated_host table", forgejo_v1_22.AddFederatedHost), + // v7 -> v8 + NewMigration("create federated_user table", forgejo_v1_22.AddFederatedUser), } // GetCurrentDBVersion returns the current Forgejo database version. @@ -118,6 +122,7 @@ func Migrate(x *xorm.Engine) error { } v := currentVersion.Version + log.Info("Current version: %d", v) // Downgrading Forgejo's database version not supported if v > ExpectedVersion() { @@ -156,5 +161,6 @@ func Migrate(x *xorm.Engine) error { return fmt.Errorf("sync: %w", err) } + // panic("fn end") return semver.SetVersionStringWithEngine(x, setting.ForgejoVersion) } diff --git a/models/forgejo_migrations/v1_22/v7.go b/models/forgejo_migrations/v1_22/v7.go new file mode 100644 index 000000000..b3eab7b58 --- /dev/null +++ b/models/forgejo_migrations/v1_22/v7.go @@ -0,0 +1,26 @@ +// Copyright 2024 The Forgejo Authors +// SPDX-License-Identifier: AGPL-3.0-or-later + +package v1_22 //nolint + +import ( + "code.gitea.io/gitea/models/federation" + "code.gitea.io/gitea/modules/log" + "xorm.io/xorm" +) + +//// HookTask represents a hook task. +//// exact copy of models/webhook/hooktask.go when this migration was created +//// - xorm:"-" fields deleted +//type FederatedHost struct { +// ID int64 `xorm:"pk autoincr"` +// isBlocked bool +// HostFqdn string `xorm:"UNIQUE(s) INDEX"` +//} + +func AddFederatedHost(x *xorm.Engine) error { + + // panic("add host") + log.Info("Running Add host migration") + return x.Sync(new(federation.FederatedHost)) +} diff --git a/models/forgejo_migrations/v1_22/v8.go b/models/forgejo_migrations/v1_22/v8.go new file mode 100644 index 000000000..5548d7415 --- /dev/null +++ b/models/forgejo_migrations/v1_22/v8.go @@ -0,0 +1,25 @@ +// Copyright 2024 The Forgejo Authors +// SPDX-License-Identifier: AGPL-3.0-or-later + +package v1_22 //nolint + +import ( + "code.gitea.io/gitea/models/federation" + "code.gitea.io/gitea/modules/log" + "xorm.io/xorm" +) + +// HookTask represents a hook task. +// exact copy of models/webhook/hooktask.go when this migration was created +// - xorm:"-" fields deleted +//type FederatedUser struct { +// ID int64 `xorm:"pk autoincr"` +// UserID int64 `xorm:"INDEX"` +// ExternalID string `xorm:"UNIQUE(s) INDEX"` +// FederationHostID int64 `xorm:"INDEX"` +//} + +func AddFederatedUser(x *xorm.Engine) error { + log.Info("Running Add user migration") + return x.Sync(new(federation.FederatedUser)) +}