forked from baron/baron-sso
chore: consolidate local integration changes
This commit is contained in:
@@ -9,6 +9,7 @@ import (
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -68,27 +69,76 @@ func NewKratosAdminService() KratosAdminService {
|
||||
|
||||
func (s *kratosAdminService) ListIdentities(ctx context.Context) ([]KratosIdentity, error) {
|
||||
endpoint := strings.TrimRight(s.AdminURL, "/") + "/admin/identities"
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, endpoint, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp, err := s.httpClient().Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode >= 300 {
|
||||
body, _ := io.ReadAll(io.LimitReader(resp.Body, 2048))
|
||||
return nil, fmt.Errorf("kratos admin list identities failed status=%d body=%s", resp.StatusCode, string(body))
|
||||
}
|
||||
|
||||
var identities []KratosIdentity
|
||||
if err := json.NewDecoder(resp.Body).Decode(&identities); err != nil {
|
||||
return nil, err
|
||||
pageToken := ""
|
||||
seenTokens := make(map[string]bool)
|
||||
|
||||
for {
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, endpoint, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
query := req.URL.Query()
|
||||
query.Set("page_size", "250")
|
||||
if pageToken != "" {
|
||||
query.Set("page_token", pageToken)
|
||||
}
|
||||
req.URL.RawQuery = query.Encode()
|
||||
|
||||
resp, err := s.httpClient().Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if resp.StatusCode >= 300 {
|
||||
body, _ := io.ReadAll(io.LimitReader(resp.Body, 2048))
|
||||
_ = resp.Body.Close()
|
||||
return nil, fmt.Errorf("kratos admin list identities failed status=%d body=%s", resp.StatusCode, string(body))
|
||||
}
|
||||
|
||||
var page []KratosIdentity
|
||||
if err := json.NewDecoder(resp.Body).Decode(&page); err != nil {
|
||||
_ = resp.Body.Close()
|
||||
return nil, err
|
||||
}
|
||||
_ = resp.Body.Close()
|
||||
identities = append(identities, page...)
|
||||
|
||||
nextToken := kratosNextPageToken(resp.Header.Values("Link"))
|
||||
if nextToken == "" {
|
||||
return identities, nil
|
||||
}
|
||||
if seenTokens[nextToken] {
|
||||
return nil, fmt.Errorf("kratos admin list identities pagination loop detected page_token=%s", nextToken)
|
||||
}
|
||||
seenTokens[nextToken] = true
|
||||
pageToken = nextToken
|
||||
}
|
||||
return identities, nil
|
||||
}
|
||||
|
||||
func kratosNextPageToken(linkHeaders []string) string {
|
||||
for _, header := range linkHeaders {
|
||||
for _, part := range strings.Split(header, ",") {
|
||||
part = strings.TrimSpace(part)
|
||||
if !strings.Contains(part, `rel="next"`) && !strings.Contains(part, `rel=next`) {
|
||||
continue
|
||||
}
|
||||
start := strings.Index(part, "<")
|
||||
end := strings.Index(part, ">")
|
||||
if start < 0 || end <= start+1 {
|
||||
continue
|
||||
}
|
||||
rawURL := part[start+1 : end]
|
||||
parsed, err := url.Parse(rawURL)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
if token := strings.TrimSpace(parsed.Query().Get("page_token")); token != "" {
|
||||
return token
|
||||
}
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (s *kratosAdminService) FindIdentityIDByIdentifier(ctx context.Context, identifier string) (string, error) {
|
||||
|
||||
Reference in New Issue
Block a user