Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: fetch user credentials in sdk #78

Merged
merged 8 commits into from
Jan 8, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions internal/sdk/cloudian/sdk.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,12 @@ func toInternalUser(u User) userInternal {
}
}

// SecurityInfo is the Cloudian API's term for secure credentials
type SecurityInfo struct {
AccessKey Secret `json:"accessKey"`
SecretKey Secret `json:"secretKey"`
}

var ErrNotFound = errors.New("not found")

// WithInsecureTLSVerify skips the TLS validation of the server certificate when `insecure` is true.
Expand Down Expand Up @@ -230,6 +236,43 @@ func (client Client) CreateUser(ctx context.Context, user User) error {
return resp.Body.Close()
}

// GetUserCredentials fetches all the credentials of a user.
func (client Client) GetUserCredentials(ctx context.Context, user User) ([]SecurityInfo, error) {
url := client.baseURL + "/user/credentials/list?userId=" + user.UserID + "&groupId=" + user.GroupID

req, err := client.newRequest(ctx, url, http.MethodGet, nil)
if err != nil {
return nil, fmt.Errorf("error creating credentials request: %w", err)
}

resp, err := client.httpClient.Do(req)
if err != nil {
return nil, fmt.Errorf("error performing credentials request: %w", err)
}

defer resp.Body.Close() // nolint:errcheck

switch resp.StatusCode {
case 200:
body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, fmt.Errorf("error reading credentials response: %w", err)
}

var securityInfo []SecurityInfo
if err := json.Unmarshal(body, &securityInfo); err != nil {
return nil, fmt.Errorf("error parsing credentials response: %w", err)
}

return securityInfo, nil
case 204:
// Cloudian-API returns 204 if no security credentials found
return nil, ErrNotFound
default:
return nil, fmt.Errorf("error: list credentials unexpected status code: %d", resp.StatusCode)
}
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No test of this function?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

None of the cloudian invoking endpoints have tests. We would have to introduce some interfaces and start mocking or stubbing I guess.
I've only tested curl against the cloudian API docs

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should probably add some kind of Go REST module that we can easily stub out. Untested code is no good.


// Delete a group and all its members.
func (client Client) DeleteGroupRecursive(ctx context.Context, groupId string) error {
users, err := client.ListUsers(ctx, groupId, nil)
Expand Down
7 changes: 7 additions & 0 deletions internal/sdk/cloudian/secret.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package cloudian

type Secret string

func (s Secret) String() string {
return "********"
}
24 changes: 24 additions & 0 deletions internal/sdk/cloudian/secret_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package cloudian

import (
"encoding/json"
"testing"
)

func TestSecretUnmarshal(t *testing.T) {
jsonString := `[{"accessKey":"124","secretKey":"x+2","createDate":1735894172440,"active":true}]`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't think we need to test the builtin go marshalling. Suggesting to simply remove the test.

Obfuscating also seems a bit overkill, as the thing running this has access, and we should not print the thing in production.


var secrets []SecurityInfo
err := json.Unmarshal([]byte(jsonString), &secrets)
if err != nil {
t.Errorf("Error deserializing from JSON: %v", err)
}

if string(secrets[0].AccessKey) != "124" {
t.Errorf("Expected string equality to 124, got %v", secrets[0].AccessKey)
}

if secrets[0].AccessKey.String() != "********" {
t.Errorf("Expected obfuscated string, got %v", secrets[0].SecretKey)
}
}
Loading