package services import ( "bytes" "context" "encoding/json" "fmt" "io" "net/http" "time" "goalfymax-admin/internal/config" ) // SSOAdminUserCreateRequest SSO创建用户请求 type SSOAdminUserCreateRequest struct { Username string `json:"username"` Email string `json:"email"` Phone string `json:"phone"` Password string `json:"password"` } // SSOAdminUserCreateResponse SSO创建用户响应 type SSOAdminUserCreateResponse struct { ID int `json:"id"` Username string `json:"username"` Email string `json:"email"` Phone string `json:"phone"` Message string `json:"message,omitempty"` } // SSOAdminUserRoleAssignRequest SSO用户角色分配请求 type SSOAdminUserRoleAssignRequest struct { UserID int `json:"user_id"` RoleID int `json:"role_id"` } // SSOAdminUserRoleAssignResponse SSO用户角色分配响应 type SSOAdminUserRoleAssignResponse struct { Success bool `json:"success"` Message string `json:"message,omitempty"` } // SSOAdminService SSO管理服务接口 type SSOAdminService interface { CreateUser(ctx context.Context, req *SSOAdminUserCreateRequest) (*SSOAdminUserCreateResponse, error) SetSystemRole(ctx context.Context, userID int, systemRole string) error } // ssoAdminService SSO管理服务实现 type ssoAdminService struct { baseURL string adminToken string timeout time.Duration client *http.Client } // NewSSOAdminService 创建SSO管理服务实例 func NewSSOAdminService() SSOAdminService { cfg := config.GetConfig() client := &http.Client{ Timeout: cfg.SSO.Timeout, } return &ssoAdminService{ baseURL: cfg.SSO.SSOServerURL, adminToken: cfg.SSO.AdminToken, timeout: cfg.SSO.Timeout, client: client, } } // CreateUser 创建SSO用户 func (s *ssoAdminService) CreateUser(ctx context.Context, req *SSOAdminUserCreateRequest) (*SSOAdminUserCreateResponse, error) { url := fmt.Sprintf("%s/api/admin/users", s.baseURL) // 构造请求体 reqBody, err := json.Marshal(req) if err != nil { return nil, fmt.Errorf("序列化请求体失败: %w", err) } // 创建HTTP请求 httpReq, err := http.NewRequestWithContext(ctx, "POST", url, bytes.NewBuffer(reqBody)) if err != nil { return nil, fmt.Errorf("创建HTTP请求失败: %w", err) } // 设置请求头 httpReq.Header.Set("Content-Type", "application/json") httpReq.Header.Set("Authorization", fmt.Sprintf("Bearer %s", s.adminToken)) httpReq.Header.Set("Accept", "*/*") httpReq.Header.Set("Accept-Language", "zh-CN,zh;q=0.9") httpReq.Header.Set("Cache-Control", "no-cache") httpReq.Header.Set("Pragma", "no-cache") // 发送请求 resp, err := s.client.Do(httpReq) if err != nil { return nil, fmt.Errorf("发送HTTP请求失败: %w", err) } defer resp.Body.Close() // 读取响应体 respBody, err := io.ReadAll(resp.Body) if err != nil { return nil, fmt.Errorf("读取响应体失败: %w", err) } // 检查HTTP状态码 if resp.StatusCode != http.StatusOK && resp.StatusCode != http.StatusCreated { return nil, fmt.Errorf("SSO API返回错误状态码 %d: %s", resp.StatusCode, string(respBody)) } // 解析响应 var response SSOAdminUserCreateResponse if err := json.Unmarshal(respBody, &response); err != nil { return nil, fmt.Errorf("解析SSO响应失败: %w", err) } return &response, nil } // SetSystemRole 设置系统角色(custom/sys_admin) func (s *ssoAdminService) SetSystemRole(ctx context.Context, userID int, systemRole string) error { url := fmt.Sprintf("%s/api/admin/users/%d/role", s.baseURL, userID) // 构造请求体 reqBodyBytes, err := json.Marshal(map[string]string{ "system_role": systemRole, }) if err != nil { return fmt.Errorf("序列化请求体失败: %w", err) } // 创建HTTP请求 httpReq, err := http.NewRequestWithContext(ctx, "POST", url, bytes.NewBuffer(reqBodyBytes)) if err != nil { return fmt.Errorf("创建HTTP请求失败: %w", err) } // 设置请求头 httpReq.Header.Set("Content-Type", "application/json") httpReq.Header.Set("Authorization", fmt.Sprintf("Bearer %s", s.adminToken)) httpReq.Header.Set("Accept", "*/*") httpReq.Header.Set("Accept-Language", "zh-CN,zh;q=0.9") httpReq.Header.Set("Cache-Control", "no-cache") httpReq.Header.Set("Pragma", "no-cache") // 发送请求 resp, err := s.client.Do(httpReq) if err != nil { return fmt.Errorf("发送HTTP请求失败: %w", err) } defer resp.Body.Close() // 读取响应体 respBody, err := io.ReadAll(resp.Body) if err != nil { return fmt.Errorf("读取响应体失败: %w", err) } if resp.StatusCode != http.StatusOK && resp.StatusCode != http.StatusCreated { return fmt.Errorf("SSO系统角色API返回错误状态码 %d: %s", resp.StatusCode, string(respBody)) } // 允许无 success 包装的简易响应,这里不做进一步结构校验 return nil }