|
26 | 26 | ErrGnomeKeyringRequired = fmt.Errorf("gnome-keyring required for secure credential storage: %w", ErrSignedOut) |
27 | 27 | ) |
28 | 28 |
|
| 29 | +type QueryParam func(url.Values) |
| 30 | + |
| 31 | +type QueryParams []QueryParam |
| 32 | + |
| 33 | +func (q QueryParams) Apply(u *url.URL) { |
| 34 | + val := u.Query() |
| 35 | + for _, fn := range q { |
| 36 | + fn(val) |
| 37 | + } |
| 38 | + u.RawQuery = val.Encode() |
| 39 | +} |
| 40 | + |
29 | 41 | // NB: can't call this Client since the name is already taken by an openapi |
30 | 42 | // generated type. It's more like a session anyways, since it caches some |
31 | 43 | // current user info. |
@@ -222,6 +234,34 @@ func (s *Session) FetchCredentials(ctx context.Context, orgSlug, realmSlug strin |
222 | 234 | return creds.Items, nil |
223 | 235 | } |
224 | 236 |
|
| 237 | +func getCredentialsURL(orgSlug, realmSlug string) (*url.URL, error) { |
| 238 | + return url.Parse(fetchCredentialsPath(orgSlug, realmSlug)) |
| 239 | +} |
| 240 | + |
| 241 | +func SubCA(apid string) QueryParam { |
| 242 | + return func(v url.Values) { |
| 243 | + // TODO: v.Set("type", "subca") |
| 244 | + v.Set("subject_uid_param", apid) |
| 245 | + } |
| 246 | +} |
| 247 | + |
| 248 | +func (s *Session) GetCredentials(ctx context.Context, orgSlug, realmSlug string, params ...QueryParam) ([]Credential, error) { |
| 249 | + var creds struct { |
| 250 | + Items []Credential `json:"items,omitempty"` |
| 251 | + } |
| 252 | + |
| 253 | + u, err := getCredentialsURL(orgSlug, realmSlug) |
| 254 | + if err != nil { |
| 255 | + return nil, err |
| 256 | + } |
| 257 | + QueryParams(params).Apply(u) |
| 258 | + |
| 259 | + if err := s.get(ctx, u.RequestURI(), &creds); err != nil { |
| 260 | + return nil, err |
| 261 | + } |
| 262 | + return creds.Items, nil |
| 263 | +} |
| 264 | + |
225 | 265 | func (s *Session) UserInfo(ctx context.Context) (*Root, error) { |
226 | 266 | if s.userInfo != nil { |
227 | 267 | return s.userInfo, nil |
@@ -293,11 +333,14 @@ func (s *Session) GetService(ctx context.Context, orgSlug, serviceSlug string) ( |
293 | 333 | return &svc, nil |
294 | 334 | } |
295 | 335 |
|
296 | | -func (s *Session) get(ctx context.Context, path string, out any) error { |
297 | | - req, err := http.NewRequestWithContext(ctx, "GET", path, nil) |
| 336 | +func (s *Session) get(ctx context.Context, uri string, out any) error { |
| 337 | + req, err := http.NewRequestWithContext(ctx, "GET", uri, nil) |
298 | 338 | if err != nil { |
299 | 339 | return err |
300 | 340 | } |
| 341 | + if req.URL, err = url.Parse(uri); err != nil { |
| 342 | + return err |
| 343 | + } |
301 | 344 | req.Header.Set("Content-Type", "application/json") |
302 | 345 |
|
303 | 346 | res, err := s.Do(req) |
@@ -426,6 +469,7 @@ func (r urlRewriter) RoundTripper(next http.RoundTripper) http.RoundTripper { |
426 | 469 | if err != nil { |
427 | 470 | return nil, err |
428 | 471 | } |
| 472 | + u.RawQuery = req.URL.RawQuery |
429 | 473 | req.URL = u.JoinPath(req.URL.Path) |
430 | 474 |
|
431 | 475 | return next.RoundTrip(req) |
|
0 commit comments