Files
goalfylearning-admin/internal/services/sso_admin_service.go

171 lines
4.7 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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
}