171 lines
4.7 KiB
Go
171 lines
4.7 KiB
Go
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
|
||
}
|