187 lines
4.5 KiB
Go
187 lines
4.5 KiB
Go
package federation
|
|
|
|
import (
|
|
"context"
|
|
"strings"
|
|
"time"
|
|
|
|
"code.gitea.io/gitea/models/db"
|
|
"code.gitea.io/gitea/models/user"
|
|
"code.gitea.io/gitea/modules/log"
|
|
"code.gitea.io/gitea/modules/setting"
|
|
"xorm.io/builder"
|
|
)
|
|
|
|
// 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()
|
|
|
|
}
|
|
|
|
func GetRemoteUsersWithNoLocalFollowers(ctx context.Context, olderThan time.Duration, page int) ([]user.User, error) {
|
|
limit := 40
|
|
offset := page * limit
|
|
var users []user.User
|
|
|
|
err := db.GetEngine(ctx).
|
|
Table("user").
|
|
Where("num_followers = 0").
|
|
And(builder.Lt{"user.created_unix": time.Now().Add(-olderThan).Unix()}).
|
|
Join("inner", "federated_user", "federated_user.user_id = user.id").
|
|
Limit(limit, offset).
|
|
Find(&users)
|
|
|
|
if err != nil {
|
|
log.Trace("Error: GetRemoteUserWithNoLocalFollowers: %w", err)
|
|
return nil, err
|
|
}
|
|
return users, nil
|
|
|
|
}
|