From 8d6e23fd7c4810322575caf7c02f179b781f5abe Mon Sep 17 00:00:00 2001 From: Jiahui <4543bxy@gmail.com> Date: Wed, 27 Mar 2024 14:24:09 +0800 Subject: [PATCH] add init job (#4629) * fix init job * fix init job * fix init job * fix init job * fix --- controllers/account/api/v1/debt_webhook.go | 7 +-- .../account/controllers/debt_controller.go | 2 +- .../job/init/internal/util/database/types.go | 10 +++-- .../job/init/internal/util/database/user.go | 19 +++++++- .../pkg/database/cockroach/accountv2.go | 32 ++++++++++--- controllers/pkg/database/interface.go | 2 +- controllers/pkg/types/global.go | 45 +++++++++++++++++-- 7 files changed, 96 insertions(+), 21 deletions(-) diff --git a/controllers/account/api/v1/debt_webhook.go b/controllers/account/api/v1/debt_webhook.go index 1a777c44a..85519c937 100644 --- a/controllers/account/api/v1/debt_webhook.go +++ b/controllers/account/api/v1/debt_webhook.go @@ -148,15 +148,10 @@ func (d *DebtValidate) checkOption(ctx context.Context, logger logr.Logger, c cl return admission.ValidationResponse(false, fmt.Sprintf("this namespace is not user namespace %s,or have not create", ns.Name)) } logger.V(1).Info("check user namespace", "ns", ns.Name, "user", user) - accountList := AccountList{} - if err := c.List(ctx, &accountList, client.MatchingFields{Name: user}); err != nil { - logger.Error(err, "get account error", "user", user) - return admission.ValidationResponse(true, err.Error()) - } account, err := d.AccountV2.GetAccount(&pkgtype.UserQueryOpts{Owner: user}) if err != nil { logger.Error(err, "get account error", "user", user) - return admission.ValidationResponse(false, err.Error()) + return admission.ValidationResponse(true, err.Error()) } if account.Balance < account.DeductionBalance { return admission.ValidationResponse(false, fmt.Sprintf(code.MessageFormat, code.InsufficientBalance, fmt.Sprintf("account balance less than 0,now account is %.2f¥. Please recharge the user %s.", GetAccountDebtBalance(*account), user))) diff --git a/controllers/account/controllers/debt_controller.go b/controllers/account/controllers/debt_controller.go index c8d8cd81c..2feb9e176 100644 --- a/controllers/account/controllers/debt_controller.go +++ b/controllers/account/controllers/debt_controller.go @@ -124,7 +124,7 @@ func (r *DebtReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl. } } r.Logger.Error(fmt.Errorf("account %s not exist", owner), "account not exist") - return ctrl.Result{RequeueAfter: 60 * time.Minute}, nil + return ctrl.Result{RequeueAfter: 10 * time.Minute}, nil } // In a multi-region scenario, select the region where the account is created for SMS notification smsEnable := account.CreateRegionID == r.LocalRegionID diff --git a/controllers/job/init/internal/util/database/types.go b/controllers/job/init/internal/util/database/types.go index 4e86a54a5..4b652843a 100644 --- a/controllers/job/init/internal/util/database/types.go +++ b/controllers/job/init/internal/util/database/types.go @@ -24,11 +24,13 @@ const ( ) const ( - EnvAdminUserName = "ADMIN_USER_NAME" - EnvAdminPassword = "ADMIN_PASSWORD" + EnvAdminUserName = "ADMIN_USER_NAME" + EnvAdminPassword = "ADMIN_PASSWORD" + EnvWorkspacePrefix = "WORKSPACE_PREFIX" ) var ( - adminPassword = hashPassword(env.GetEnvWithDefault(EnvAdminPassword, DefaultAdminPassword)) - adminUserName = env.GetEnvWithDefault(EnvAdminUserName, DefaultAdminUserName) + adminPassword = hashPassword(env.GetEnvWithDefault(EnvAdminPassword, DefaultAdminPassword)) + adminUserName = env.GetEnvWithDefault(EnvAdminUserName, DefaultAdminUserName) + workspacePrefix = env.GetEnvWithDefault(EnvWorkspacePrefix, "ns-") ) diff --git a/controllers/job/init/internal/util/database/user.go b/controllers/job/init/internal/util/database/user.go index 9a4af7f28..bbf49238c 100644 --- a/controllers/job/init/internal/util/database/user.go +++ b/controllers/job/init/internal/util/database/user.go @@ -67,14 +67,15 @@ func PresetAdminUser() error { Domain: domain, DisplayName: domain, Location: domain, + Description: domain, }); err != nil { return fmt.Errorf("failed to create region: %v", err) } - userNanoID, err := gonanoid.New(10) if err != nil { return fmt.Errorf("failed to generate nano id: %v", err) } + genUserCrUID, genWorkspaceUID := uuid.New(), uuid.New() if err = v2Account.CreateUser(&types.OauthProvider{ UserUID: common.AdminUID(), ProviderType: types.OauthProviderTypePassword, @@ -83,6 +84,7 @@ func PresetAdminUser() error { CreatedAt: time.Now(), UpdatedAt: time.Now(), }, &types.RegionUserCr{ + UID: genUserCrUID, CrName: adminUserName, UserUID: common.AdminUID(), CreatedAt: time.Now(), @@ -94,6 +96,21 @@ func PresetAdminUser() error { Nickname: userNanoID, CreatedAt: time.Now(), UpdatedAt: time.Now(), + }, &types.Workspace{ + UID: genWorkspaceUID, + ID: workspacePrefix + adminUserName, + DisplayName: "private team", + CreatedAt: time.Now(), + UpdatedAt: time.Now(), + }, &types.UserWorkspace{ + WorkspaceUID: genWorkspaceUID, + UserCrUID: genUserCrUID, + Role: types.RoleOwner, + Status: types.JoinStatusInWorkspace, + IsPrivate: true, + CreatedAt: time.Now(), + UpdatedAt: time.Now(), + JoinAt: time.Now(), }); err != nil { return fmt.Errorf("failed to create user: %v", err) } diff --git a/controllers/pkg/database/cockroach/accountv2.go b/controllers/pkg/database/cockroach/accountv2.go index 0654d31d3..9f0d6446c 100644 --- a/controllers/pkg/database/cockroach/accountv2.go +++ b/controllers/pkg/database/cockroach/accountv2.go @@ -51,18 +51,40 @@ const ( EnvBaseBalance = "BASE_BALANCE" ) -func (g *Cockroach) CreateUser(oAuth *types.OauthProvider, regionUserCr *types.RegionUserCr, user *types.User) error { - if g.Localdb.Where(&types.RegionUserCr{CrName: regionUserCr.CrName}).First(&types.RegionUserCr{}).Error == gorm.ErrRecordNotFound { - if err := g.DB.Where(&types.User{Name: user.Name}).FirstOrCreate(user).Error; err != nil { +func (g *Cockroach) CreateUser(oAuth *types.OauthProvider, regionUserCr *types.RegionUserCr, user *types.User, workspace *types.Workspace, userWorkspace *types.UserWorkspace) error { + findUser, findRegionUserCr, findUserWorkspace := &types.User{}, &types.RegionUserCr{}, &types.UserWorkspace{} + if g.DB.Where(&types.User{Name: user.Name}).First(findUser).Error == gorm.ErrRecordNotFound { + findUser = user + if err := g.DB.Save(user).Error; err != nil { return fmt.Errorf("failed to create user: %w", err) } - if err := g.DB.Where(types.OauthProvider{ProviderID: oAuth.ProviderID}).FirstOrCreate(oAuth).Error; err != nil { + } + if g.DB.Where(types.OauthProvider{UserUID: findUser.UID}).First(&types.OauthProvider{}).Error == gorm.ErrRecordNotFound { + oAuth.UserUID = findUser.UID + if err := g.DB.Save(oAuth).Error; err != nil { return fmt.Errorf("failed to create user oauth provider: %w", err) } - if err := g.Localdb.Where(types.RegionUserCr{CrName: regionUserCr.CrName}).FirstOrCreate(®ionUserCr).Error; err != nil { + } + if g.Localdb.Where(&types.RegionUserCr{CrName: regionUserCr.CrName}).First(findRegionUserCr).Error == gorm.ErrRecordNotFound { + regionUserCr.UserUID = findUser.UID + findRegionUserCr = regionUserCr + if err := g.Localdb.Save(regionUserCr).Error; err != nil { return fmt.Errorf("failed to create user region cr: %w", err) } } + if g.Localdb.Where(types.UserWorkspace{UserCrUID: findRegionUserCr.UID}).First(findUserWorkspace).Error == gorm.ErrRecordNotFound { + userWorkspace.UserCrUID = findRegionUserCr.UID + findUserWorkspace = userWorkspace + if err := g.Localdb.Save(userWorkspace).Error; err != nil { + return fmt.Errorf("failed to create user workspace: %w", err) + } + } + if g.Localdb.Where(types.Workspace{UID: findUserWorkspace.WorkspaceUID}).First(&types.Workspace{}).Error == gorm.ErrRecordNotFound { + workspace.UID = findUserWorkspace.WorkspaceUID + if err := g.Localdb.Save(workspace).Error; err != nil { + return fmt.Errorf("failed to create workspace: %w", err) + } + } return nil } diff --git a/controllers/pkg/database/interface.go b/controllers/pkg/database/interface.go index 872b99c89..113ff2999 100644 --- a/controllers/pkg/database/interface.go +++ b/controllers/pkg/database/interface.go @@ -81,7 +81,7 @@ type Traffic interface { type AccountV2 interface { Close() error GetUserCr(user *types.UserQueryOpts) (*types.RegionUserCr, error) - CreateUser(oAuth *types.OauthProvider, regionUserCr *types.RegionUserCr, user *types.User) error + CreateUser(oAuth *types.OauthProvider, regionUserCr *types.RegionUserCr, user *types.User, workspace *types.Workspace, userWorkspace *types.UserWorkspace) error GetAccount(user *types.UserQueryOpts) (*types.Account, error) GetUserOauthProvider(ops *types.UserQueryOpts) (*types.OauthProvider, error) AddBalance(user *types.UserQueryOpts, balance int64) error diff --git a/controllers/pkg/types/global.go b/controllers/pkg/types/global.go index 1d3efbbcc..e28e5c7e4 100644 --- a/controllers/pkg/types/global.go +++ b/controllers/pkg/types/global.go @@ -89,15 +89,54 @@ func (User) TableName() string { return "User" } -type OauthProviderType string +type Workspace struct { + UID uuid.UUID `gorm:"type:uuid;default:gen_random_uuid();primary_key"` + ID string `gorm:"type:text;not null;unique"` + DisplayName string `gorm:"column:displayName;type:text;not null"` + CreatedAt time.Time `gorm:"column:createdAt;type:timestamp(3) with time zone;default:current_timestamp()"` + UpdatedAt time.Time `gorm:"column:updatedAt;type:timestamp(3) with time zone;default:current_timestamp()"` +} + +type UserWorkspace struct { + UID uuid.UUID `gorm:"type:uuid;default:gen_random_uuid();primary_key"` + CreatedAt time.Time `gorm:"column:createdAt;type:timestamp(3) with time zone;default:current_timestamp()"` + UpdatedAt time.Time `gorm:"column:updatedAt;type:timestamp(3) with time zone;default:current_timestamp()"` + WorkspaceUID uuid.UUID `gorm:"column:workspaceUid;type:uuid;not null"` + UserCrUID uuid.UUID `gorm:"column:userCrUid;type:uuid;not null"` + HandlerUID uuid.UUID `gorm:"column:handlerUid;type:uuid"` + Role Role `gorm:"type:Role;default:'DEVELOPER'::defaultdb.public.'Role';not null"` + Status JoinStatus + IsPrivate bool `gorm:"column:isPrivate;type:boolean;not null"` + JoinAt time.Time `gorm:"column:joinAt;type:timestamp(3) with time zone"` +} + +type ( + Role string + JoinStatus string + OauthProviderType string +) const ( OauthProviderTypePhone OauthProviderType = "PHONE" - OauthProviderTypeGithub OauthProviderType = "GITHUB" - OauthProviderTypeWechat OauthProviderType = "WECHAT" OauthProviderTypePassword OauthProviderType = "PASSWORD" + //OauthProviderTypeGithub OauthProviderType = "GITHUB" + //OauthProviderTypeWechat OauthProviderType = "WECHAT" + + RoleOwner Role = "OWNER" + //RoleDeveloper Role = "DEVELOPER" + //RoleManager Role = "MANAGER" + + JoinStatusInWorkspace JoinStatus = "IN_WORKSPACE" ) +func (UserWorkspace) TableName() string { + return "UserWorkspace" +} + +func (Workspace) TableName() string { + return "Workspace" +} + func (OauthProvider) TableName() string { return "OauthProvider" }