package service import ( "context" "fmt" "strings" "oci-portal/internal/model" "oci-portal/internal/oci" ) // homeRegionOf 返回配置的 home region 名称;本地表查不到时退回默认区域。 // 用户管理等 IAM 写操作必须发往 home region。 func homeRegionOf(cfg *model.OciConfig) string { if info, ok := oci.RegionByKey(cfg.HomeRegionKey); ok { return info.Name } return cfg.Region } // credentialsAndHomeRegion 一次取回凭据与 home region。 func (s *OciConfigService) credentialsAndHomeRegion(ctx context.Context, id uint) (oci.Credentials, string, error) { cfg, err := s.Get(ctx, id) if err != nil { return oci.Credentials{}, "", err } cred, err := s.credentialsOf(cfg) if err != nil { return oci.Credentials{}, "", err } return cred, homeRegionOf(cfg), nil } // TenantUsers 列出租户 IAM 用户。 func (s *OciConfigService) TenantUsers(ctx context.Context, id uint) ([]oci.TenantUser, error) { cred, err := s.credentialsByID(ctx, id) if err != nil { return nil, err } return s.client.ListTenantUsers(ctx, cred) } // TenantUserDetail 查用户的域档案与管理员状态(编辑表单预填充用)。 func (s *OciConfigService) TenantUserDetail(ctx context.Context, id uint, userID string) (oci.TenantUserDetail, error) { cred, homeRegion, err := s.credentialsAndHomeRegion(ctx, id) if err != nil { return oci.TenantUserDetail{}, err } return s.client.GetTenantUserDetail(ctx, cred, homeRegion, userID) } // CreateTenantUser 新增用户;名字与姓氏必填(域用户档案要求), // 描述缺省用「名 姓」。 func (s *OciConfigService) CreateTenantUser(ctx context.Context, id uint, in oci.CreateTenantUserInput) (oci.TenantUser, error) { if strings.TrimSpace(in.Name) == "" { return oci.TenantUser{}, fmt.Errorf("create tenant user: name is required") } if strings.TrimSpace(in.GivenName) == "" || strings.TrimSpace(in.FamilyName) == "" { return oci.TenantUser{}, fmt.Errorf("create tenant user: givenName and familyName are required") } if in.Description == "" { in.Description = strings.TrimSpace(in.GivenName + " " + in.FamilyName) } cred, homeRegion, err := s.credentialsAndHomeRegion(ctx, id) if err != nil { return oci.TenantUser{}, err } return s.client.CreateTenantUser(ctx, cred, homeRegion, in) } // UpdateTenantUser 编辑用户资料;nil 字段不修改,全 nil 报错。 func (s *OciConfigService) UpdateTenantUser(ctx context.Context, id uint, userID string, in oci.UpdateTenantUserInput) (oci.TenantUser, error) { hasField := in.Description != nil || in.Email != nil || in.GivenName != nil || in.FamilyName != nil hasAdmin := in.GrantDomainAdmin != nil || in.AddToAdminGroup != nil if !hasField && !hasAdmin { return oci.TenantUser{}, fmt.Errorf("update tenant user: nothing to update") } cred, homeRegion, err := s.credentialsAndHomeRegion(ctx, id) if err != nil { return oci.TenantUser{}, err } return s.client.UpdateTenantUser(ctx, cred, homeRegion, userID, in) } // IdentitySetting 读取域身份设置(当前只透出主邮箱必填开关)。 func (s *OciConfigService) IdentitySetting(ctx context.Context, id uint) (oci.IdentitySettingInfo, error) { cred, homeRegion, err := s.credentialsAndHomeRegion(ctx, id) if err != nil { return oci.IdentitySettingInfo{}, err } return s.client.GetIdentitySetting(ctx, cred, homeRegion) } // UpdateIdentitySetting 修改「用户需要提供主电子邮件地址」开关。 func (s *OciConfigService) UpdateIdentitySetting(ctx context.Context, id uint, primaryEmailRequired bool) (oci.IdentitySettingInfo, error) { cred, homeRegion, err := s.credentialsAndHomeRegion(ctx, id) if err != nil { return oci.IdentitySettingInfo{}, err } return s.client.UpdateIdentitySetting(ctx, cred, homeRegion, primaryEmailRequired) } // DeleteTenantUser 删除 IAM 用户;拒绝删除当前配置正在使用的用户。 func (s *OciConfigService) DeleteTenantUser(ctx context.Context, id uint, userID string) error { cred, homeRegion, err := s.credentialsAndHomeRegion(ctx, id) if err != nil { return err } if userID == cred.UserOCID { return fmt.Errorf("delete tenant user: refusing to delete the user this config signs requests with") } return s.client.DeleteTenantUser(ctx, cred, homeRegion, userID) } // ResetTenantUserPassword 重置用户控制台密码,返回一次性新密码。 func (s *OciConfigService) ResetTenantUserPassword(ctx context.Context, id uint, userID string) (string, error) { cred, homeRegion, err := s.credentialsAndHomeRegion(ctx, id) if err != nil { return "", err } return s.client.ResetTenantUserPassword(ctx, cred, homeRegion, userID) } // DeleteTenantUserMfa 清除用户全部 MFA,返回删除的经典 TOTP 设备数。 func (s *OciConfigService) DeleteTenantUserMfa(ctx context.Context, id uint, userID string) (int, error) { cred, homeRegion, err := s.credentialsAndHomeRegion(ctx, id) if err != nil { return 0, err } return s.client.DeleteTenantUserMfaDevices(ctx, cred, homeRegion, userID) } // DeleteTenantUserApiKeys 删除用户的 API Key;默认保留当前配置使用的指纹。 func (s *OciConfigService) DeleteTenantUserApiKeys(ctx context.Context, id uint, userID string, includeCurrent bool) (int, error) { cred, homeRegion, err := s.credentialsAndHomeRegion(ctx, id) if err != nil { return 0, err } return s.client.DeleteTenantUserApiKeys(ctx, cred, homeRegion, userID, includeCurrent) } // NotificationRecipients 查询域通知收件人设置。 func (s *OciConfigService) NotificationRecipients(ctx context.Context, id uint) (oci.NotificationRecipients, error) { cred, homeRegion, err := s.credentialsAndHomeRegion(ctx, id) if err != nil { return oci.NotificationRecipients{}, err } return s.client.GetNotificationRecipients(ctx, cred, homeRegion) } // UpdateNotificationRecipients 把域通知改为只发给指定收件人; // 收件人为空表示关闭 test mode 恢复默认发送。 func (s *OciConfigService) UpdateNotificationRecipients(ctx context.Context, id uint, emails []string) (oci.NotificationRecipients, error) { if err := validateEmails(emails); err != nil { return oci.NotificationRecipients{}, err } cred, homeRegion, err := s.credentialsAndHomeRegion(ctx, id) if err != nil { return oci.NotificationRecipients{}, err } return s.client.UpdateNotificationRecipients(ctx, cred, homeRegion, emails) } func validateEmails(emails []string) error { for _, email := range emails { if !strings.Contains(email, "@") || strings.ContainsAny(email, " \t") { return fmt.Errorf("update notification recipients: invalid email %q", email) } } return nil } // PasswordPolicies 列出域密码策略。 func (s *OciConfigService) PasswordPolicies(ctx context.Context, id uint) ([]oci.PasswordPolicyInfo, error) { cred, homeRegion, err := s.credentialsAndHomeRegion(ctx, id) if err != nil { return nil, err } return s.client.ListPasswordPolicies(ctx, cred, homeRegion) } // UpdatePasswordPolicy 修改域密码策略的过期天数或最小长度。 func (s *OciConfigService) UpdatePasswordPolicy(ctx context.Context, id uint, policyID string, in oci.UpdatePasswordPolicyInput) (oci.PasswordPolicyInfo, error) { if in.PasswordExpiresAfter == nil && in.MinLength == nil { return oci.PasswordPolicyInfo{}, fmt.Errorf("update password policy: nothing to update") } cred, homeRegion, err := s.credentialsAndHomeRegion(ctx, id) if err != nil { return oci.PasswordPolicyInfo{}, err } return s.client.UpdatePasswordPolicy(ctx, cred, homeRegion, policyID, in) }