| package service
|
|
|
| import (
|
| "bytes"
|
| "encoding/json"
|
| "fmt"
|
| "io"
|
| "math/rand"
|
| "net/http"
|
| "time"
|
| )
|
|
|
| const (
|
| CredentialGenerateURL = "https://fe.zencoder.ai/frontegg/identity/resources/users/api-tokens/v1"
|
| )
|
|
|
| type CredentialGenerateRequest struct {
|
| Description string `json:"description"`
|
| ExpiresInMinutes int `json:"expiresInMinutes"`
|
| }
|
|
|
| type CredentialGenerateResponse struct {
|
| ClientID string `json:"clientId"`
|
| Description string `json:"description"`
|
| CreatedAt string `json:"createdAt"`
|
| Secret string `json:"secret"`
|
| Expires string `json:"expires"`
|
| RefreshToken string `json:"refreshToken,omitempty"`
|
| }
|
|
|
|
|
| func GenerateRandomDescription() string {
|
| const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
|
| rng := rand.New(rand.NewSource(time.Now().UnixNano()))
|
| b := make([]byte, 5)
|
| for i := range b {
|
| b[i] = charset[rng.Intn(len(charset))]
|
| }
|
| return string(b)
|
| }
|
|
|
|
|
| func GenerateCredential(token string) (*CredentialGenerateResponse, error) {
|
| reqBody := CredentialGenerateRequest{
|
| Description: GenerateRandomDescription(),
|
| ExpiresInMinutes: 525600,
|
| }
|
|
|
| bodyBytes, err := json.Marshal(reqBody)
|
| if err != nil {
|
| return nil, fmt.Errorf("failed to marshal request: %w", err)
|
| }
|
|
|
| req, err := http.NewRequest("POST", CredentialGenerateURL, bytes.NewReader(bodyBytes))
|
| if err != nil {
|
| return nil, fmt.Errorf("failed to create request: %w", err)
|
| }
|
|
|
|
|
| req.Header.Set("Accept-Encoding", "gzip, deflate, br")
|
| req.Header.Set("Connection", "keep-alive")
|
| req.Header.Set("accept", "*/*")
|
| req.Header.Set("accept-language", "zh-CN,zh;q=0.9,en;q=0.8,zh-TW;q=0.7,ja;q=0.6")
|
| req.Header.Set("authorization", "Bearer "+token)
|
| req.Header.Set("cache-control", "no-cache")
|
| req.Header.Set("content-type", "application/json")
|
| req.Header.Set("frontegg-source", "admin-portal")
|
| req.Header.Set("origin", "https://auth.zencoder.ai")
|
| req.Header.Set("pragma", "no-cache")
|
| req.Header.Set("priority", "u=1, i")
|
| req.Header.Set("referer", "https://auth.zencoder.ai/")
|
| req.Header.Set("sec-ch-ua", `"Google Chrome";v="143", "Chromium";v="143", "Not A(Brand";v="24"`)
|
| req.Header.Set("sec-ch-ua-mobile", "?0")
|
| req.Header.Set("sec-ch-ua-platform", `"Windows"`)
|
| req.Header.Set("sec-fetch-dest", "empty")
|
| req.Header.Set("sec-fetch-mode", "cors")
|
| req.Header.Set("sec-fetch-site", "same-site")
|
| req.Header.Set("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36")
|
| req.Header.Set("x-frontegg-framework", "next@15.3.8")
|
| req.Header.Set("x-frontegg-sdk", "@frontegg/nextjs@9.2.10")
|
|
|
| client := &http.Client{Timeout: 30 * time.Second}
|
| resp, err := client.Do(req)
|
| if err != nil {
|
| return nil, fmt.Errorf("failed to send request: %w", err)
|
| }
|
| defer resp.Body.Close()
|
|
|
| if resp.StatusCode != http.StatusOK && resp.StatusCode != http.StatusCreated {
|
| body, _ := io.ReadAll(resp.Body)
|
| return nil, fmt.Errorf("API returned status %d: %s", resp.StatusCode, string(body))
|
| }
|
|
|
| var result CredentialGenerateResponse
|
| if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
|
| return nil, fmt.Errorf("failed to decode response: %w", err)
|
| }
|
|
|
| return &result, nil
|
| }
|
|
|
|
|
| func BatchGenerateCredentials(token string, count int) ([]*CredentialGenerateResponse, []error) {
|
| var results []*CredentialGenerateResponse
|
| var errors []error
|
|
|
| for i := 0; i < count; i++ {
|
| cred, err := GenerateCredential(token)
|
| if err != nil {
|
| errors = append(errors, fmt.Errorf("credential %d: %w", i+1, err))
|
| continue
|
| }
|
| results = append(results, cred)
|
|
|
|
|
| if i < count-1 {
|
| time.Sleep(500 * time.Millisecond)
|
| }
|
| }
|
|
|
| return results, errors
|
| }
|
|
|