Skip to content

Commit aacec86

Browse files
committed
Added AddSSHKey function and unit tests
1 parent 31687dc commit aacec86

File tree

4 files changed

+150
-1
lines changed

4 files changed

+150
-1
lines changed

accounts.go

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -453,6 +453,25 @@ func (s *AccountsService) GetSSHKey(ctx context.Context, accountID, sshKeyID str
453453
return v, resp, err
454454
}
455455

456+
// AddSSHKey adds an SSH key to a user's account.
457+
// Gerrit API docs: https://gerrit-review.googlesource.com/Documentation/rest-api-accounts.html#add-ssh-key
458+
func (s *AccountsService) AddSSHKey(ctx context.Context, accountID string, sshKey string) (*SSHKeyInfo, *Response, error) {
459+
u := fmt.Sprintf("accounts/%s/sshkeys", accountID)
460+
461+
req, err := s.client.NewRawPostRequest(ctx, u, sshKey)
462+
if err != nil {
463+
return nil, nil, err
464+
}
465+
466+
var keyInfo SSHKeyInfo
467+
resp, err := s.client.Do(req, &keyInfo)
468+
if err != nil {
469+
return nil, resp, err
470+
}
471+
472+
return &keyInfo, resp, err
473+
}
474+
456475
// ListGPGKeys returns the GPG keys of an account.
457476
//
458477
// Gerrit API docs: https://gerrit-review.googlesource.com/Documentation/rest-api-accounts.html#list-gpg-keys
@@ -957,6 +976,5 @@ func (s *AccountsService) UnstarChange(ctx context.Context, accountID, changeID
957976

958977
/*
959978
Missing Account Endpoints:
960-
Add SSH Key
961979
Get Avatar
962980
*/

accounts_test.go

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
package gerrit_test
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"io"
7+
"net/http"
8+
"strings"
9+
"testing"
10+
)
11+
12+
// TestAddSSHKey tests the addition of an SSH key to an account.
13+
func TestAddSSHKey(t *testing.T) {
14+
setup()
15+
defer teardown()
16+
17+
testMux.HandleFunc("/accounts/self/sshkeys", func(w http.ResponseWriter, r *http.Request) {
18+
// Ensure the request method is POST
19+
if r.Method != http.MethodPost {
20+
t.Errorf("Expected POST request, got %s", r.Method)
21+
}
22+
23+
// Ensure Content-Type is text/plain
24+
if r.Header.Get("Content-Type") != "text/plain" {
25+
t.Errorf("Expected Content-Type 'text/plain', got %s", r.Header.Get("Content-Type"))
26+
}
27+
28+
// Read body and validate SSH key
29+
expectedSSHKey := "ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA0T...YImydZAw== john.doe@example.com"
30+
body, _ := io.ReadAll(r.Body)
31+
receivedSSHKey := strings.TrimSpace(string(body))
32+
33+
if receivedSSHKey != expectedSSHKey {
34+
t.Errorf("Expected SSH key '%s', but received '%s'", expectedSSHKey, receivedSSHKey)
35+
}
36+
37+
// Mock successful JSON response
38+
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
39+
w.WriteHeader(http.StatusOK)
40+
fmt.Fprint(w, `{
41+
"seq": 2,
42+
"ssh_public_key": "ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA0T...YImydZAw== john.doe@example.com",
43+
"encoded_key": "AAAAB3NzaC1yc2EAAAABIwAAAQEA0T...YImydZAw==",
44+
"algorithm": "ssh-rsa",
45+
"comment": "john.doe@example.com",
46+
"valid": true
47+
}`)
48+
})
49+
50+
ctx := context.Background()
51+
sshKey := "ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA0T...YImydZAw== john.doe@example.com"
52+
53+
// Use testClient.Accounts instead of undefined Accounts variable
54+
keyInfo, _, err := testClient.Accounts.AddSSHKey(ctx, "self", sshKey)
55+
if err != nil {
56+
t.Fatalf("AddSSHKey returned error: %v", err)
57+
}
58+
59+
// Verify SSH key information in the response
60+
if keyInfo.SSHPublicKey != sshKey {
61+
t.Errorf("Expected SSH key '%s', got '%s'", sshKey, keyInfo.SSHPublicKey)
62+
}
63+
64+
if keyInfo.Valid != true {
65+
t.Errorf("Expected key validity to be true, got false")
66+
}
67+
68+
if keyInfo.Comment != "john.doe@example.com" {
69+
t.Errorf("Expected comment 'john.doe@example.com', got '%s'", keyInfo.Comment)
70+
}
71+
}

gerrit.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,34 @@ func (c *Client) NewRawPutRequest(ctx context.Context, urlStr string, body strin
289289
return req, nil
290290
}
291291

292+
// NewRawPostRequest creates a raw POST request and makes no attempt to encode
293+
// or marshal the body. Just passes it straight through.
294+
func (c *Client) NewRawPostRequest(ctx context.Context, urlStr string, body string) (*http.Request, error) {
295+
// Build URL for request
296+
u, err := c.buildURLForRequest(urlStr)
297+
if err != nil {
298+
return nil, err
299+
}
300+
301+
buf := bytes.NewBuffer([]byte(body))
302+
req, err := http.NewRequestWithContext(ctx, "POST", u, buf)
303+
if err != nil {
304+
return nil, err
305+
}
306+
307+
// Apply Authentication
308+
if err := c.addAuthentication(ctx, req); err != nil {
309+
return nil, err
310+
}
311+
312+
// Request compact JSON
313+
// See https://gerrit-review.googlesource.com/Documentation/rest-api.html#output
314+
req.Header.Add("Accept", "application/json")
315+
req.Header.Add("Content-Type", "text/plain")
316+
317+
return req, nil
318+
}
319+
292320
// Call is a combine function for Client.NewRequest and Client.Do.
293321
//
294322
// Most API methods are quite the same.

gerrit_test.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -437,6 +437,38 @@ func TestNewRawPutRequest(t *testing.T) {
437437
}
438438
}
439439

440+
func TestNewRawPostRequest(t *testing.T) {
441+
ctx := context.Background()
442+
c, err := gerrit.NewClient(ctx, testGerritInstanceURL, nil)
443+
if err != nil {
444+
t.Errorf("An error occured. Expected nil. Got %+v.", err)
445+
}
446+
447+
inURL, outURL := "/foo", testGerritInstanceURL+"foo"
448+
req, _ := c.NewRawPostRequest(ctx, inURL, "test raw POST contents")
449+
450+
// Test that relative URL was expanded
451+
if got, want := req.URL.String(), outURL; got != want {
452+
t.Errorf("NewRequest(%q) URL is %v, want %v", inURL, got, want)
453+
}
454+
455+
// Test that HTTP method is POST
456+
if got, want := req.Method, http.MethodPost; got != want {
457+
t.Errorf("NewRawPostRequest method is %v, want %v", got, want)
458+
}
459+
460+
// Test that request body is passed correctly
461+
body, _ := io.ReadAll(req.Body)
462+
if got, want := string(body), "test raw POST contents"; got != want {
463+
t.Errorf("NewRequest Body is %v, want %v", got, want)
464+
}
465+
466+
// Test that Content-Type is set correctly
467+
if got, want := req.Header.Get("Content-Type"), "text/plain"; got != want {
468+
t.Errorf("NewRawPostRequest Content-Type is %v, want %v", got, want)
469+
}
470+
}
471+
440472
func testURLParseError(t *testing.T, err error) {
441473
if err == nil {
442474
t.Errorf("Expected error to be returned")

0 commit comments

Comments
 (0)