From ac7c642e278e183d50b9c71525e0a0107953b317 Mon Sep 17 00:00:00 2001 From: Lars Heimdal Date: Tue, 9 Jul 2024 12:19:37 +0200 Subject: [PATCH] feat: Update user profile image (#302) * feat: Update user profile image * Fix typo Co-authored-by: Giannis Katsanos --------- Co-authored-by: Giannis Katsanos --- user/api.go | 5 +++++ user/client.go | 42 ++++++++++++++++++++++++++++++++++++++++++ user/client_test.go | 29 +++++++++++++++++++++++++++++ 3 files changed, 76 insertions(+) diff --git a/user/api.go b/user/api.go index ffc2b289..d07e6552 100644 --- a/user/api.go +++ b/user/api.go @@ -23,6 +23,11 @@ func Update(ctx context.Context, id string, params *UpdateParams) (*clerk.User, return getClient().Update(ctx, id, params) } +// UpdateProfileImage sets or replaces the users's profile image. +func UpdateProfileImage(ctx context.Context, id string, params *UpdateProfileImageParams) (*clerk.User, error) { + return getClient().UpdateProfileImage(ctx, id, params) +} + // UpdateMetadata updates the user's metadata by merging the // provided values with the existing ones. func UpdateMetadata(ctx context.Context, id string, params *UpdateMetadataParams) (*clerk.User, error) { diff --git a/user/client.go b/user/client.go index c48f4f24..76f2219f 100644 --- a/user/client.go +++ b/user/client.go @@ -2,9 +2,12 @@ package user import ( + "bytes" "context" "encoding/json" "fmt" + "io" + "mime/multipart" "net/http" "net/url" "strconv" @@ -112,6 +115,45 @@ func (c *Client) Update(ctx context.Context, id string, params *UpdateParams) (* return resource, err } +type UpdateProfileImageParams struct { + clerk.APIParams + File multipart.File `json:"-"` +} + +func (params *UpdateProfileImageParams) ToMultipart() ([]byte, string, error) { + var buf bytes.Buffer + w := multipart.NewWriter(&buf) + + file, err := w.CreateFormFile("file", "profileImage") + if err != nil { + return nil, "", err + } + defer params.File.Close() + + _, err = io.Copy(file, params.File) + if err != nil { + return nil, "", err + } + err = w.Close() + if err != nil { + return nil, "", err + } + return buf.Bytes(), w.FormDataContentType(), nil +} + +// UpdateProfileImage sets or replaces the user's profile image. +func (c *Client) UpdateProfileImage(ctx context.Context, id string, params *UpdateProfileImageParams) (*clerk.User, error) { + path, err := clerk.JoinPath(path, id, "/profile_image") + if err != nil { + return nil, err + } + req := clerk.NewMultipartAPIRequest(http.MethodPost, path) + req.SetParams(params) + resource := &clerk.User{} + err = c.Backend.Call(ctx, req, resource) + return resource, err +} + type UpdateMetadataParams struct { clerk.APIParams PublicMetadata *json.RawMessage `json:"public_metadata,omitempty"` diff --git a/user/client_test.go b/user/client_test.go index e203d718..be4b15cd 100644 --- a/user/client_test.go +++ b/user/client_test.go @@ -1,6 +1,7 @@ package user import ( + "bytes" "context" "encoding/json" "fmt" @@ -182,6 +183,34 @@ func TestUserClientUpdate(t *testing.T) { require.Equal(t, username, *user.Username) } +type testFile struct { + bytes.Reader +} + +func (_ *testFile) Close() error { + return nil +} + +func TestUserClientUpdateProfileImage(t *testing.T) { + t.Parallel() + userID := "user_123" + config := &clerk.ClientConfig{} + config.HTTPClient = &http.Client{ + Transport: &clerktest.RoundTripper{ + T: t, + Out: json.RawMessage(fmt.Sprintf(`{"id":"%s"}`, userID)), + Method: http.MethodPost, + Path: "/v1/users/" + userID + "/profile_image", + }, + } + client := NewClient(config) + user, err := client.UpdateProfileImage(context.Background(), userID, &UpdateProfileImageParams{ + File: &testFile{Reader: *bytes.NewReader([]byte{})}, + }) + require.NoError(t, err) + require.Equal(t, userID, user.ID) +} + func TestUserClientUpdateMetadata(t *testing.T) { t.Parallel() id := "user_123"