Skip to content

Commit 9530d35

Browse files
committed
Add api_key resource
Refactor code
1 parent a15edd2 commit 9530d35

10 files changed

+548
-56
lines changed

client/account.go

+10-8
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,11 @@ package client
33
import (
44
"errors"
55
"fmt"
6-
"strconv"
7-
8-
"github.com/google/martian/log"
96
"github.com/imdario/mergo"
7+
"log"
8+
"strconv"
109
)
1110

12-
1311
type DockerRegistry struct {
1412
Kind string `json:"kind"`
1513
BehindFirewall bool `json:"behindFirewall"`
@@ -120,7 +118,7 @@ type Account struct {
120118
IncreasedAttention bool `json:"increasedAttention,omitempty"`
121119
LocalUserPasswordIDPEnabled bool `json:"localUserPasswordIDPEnabled,omitempty"`
122120
CodefreshEnv string `json:"codefreshEnv,omitempty"`
123-
ID string `json:"_id,omitempty,omitempty"`
121+
ID string `json:"_id,omitempty"`
124122
BadgeToken string `json:"badgeToken,omitempty"`
125123
CreatedAt string `json:"createdAt,omitempty"`
126124
UpdatedAt string `json:"updatedAt,omitempty"`
@@ -129,7 +127,6 @@ type Account struct {
129127
CfcrRepositoryPath string `json:"cfcrRepositoryPath,omitempty"`
130128
Notifications []NotificationEvent `json:"notifications,omitempty"`
131129
RepoPermission string `json:"repoPermission,omitempty"`
132-
__V int `json:"__v,omitempty"`
133130
Limits *Limits `json:"limits,omitempty"`
134131
Features map[string]bool `json:"features,omitempty"`
135132
// Features *Features `json:"features,omitempty"`
@@ -149,7 +146,7 @@ func (account *Account) SetFeatures(m map[string]interface{}) {
149146
value := v.(string)
150147
b, err := strconv.ParseBool(value)
151148
if err != nil {
152-
log.Errorf("[ERROR] Can't parse '%s = %s' as boolean", k, value)
149+
log.Fatalf("[ERROR] Can't parse '%s = %s' as boolean", k, value)
153150
}
154151
res[k] = b
155152
}
@@ -220,7 +217,12 @@ func (client *Client) UpdateAccount(account *Account) (*Account, error) {
220217
}
221218

222219
existingAccount, err := client.GetAccountByID(id)
223-
if err = mergo.Merge(account, existingAccount); err != nil {
220+
if err != nil {
221+
return nil, err
222+
}
223+
224+
err = mergo.Merge(account, existingAccount)
225+
if err != nil {
224226
return nil, err
225227
}
226228

client/api_key.go

+221
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,221 @@
1+
package client
2+
3+
import (
4+
"errors"
5+
"fmt"
6+
"github.com/hashicorp/terraform-plugin-sdk/helper/acctest"
7+
"log"
8+
"net/http"
9+
)
10+
11+
type ApiKeySubject struct {
12+
Type string `json:"type,omitempty"`
13+
Ref string `json:"ref,omitempty"`
14+
}
15+
16+
type ApiKeyScopeSnapshot struct {
17+
Scopes []string `json:"scopes,omitempty"`
18+
ID string `json:"_id,omitempty"`
19+
Date string `json:"date,omitempty"`
20+
V int `json:"__v,omitempty"`
21+
}
22+
23+
type ApiKey struct {
24+
Subject ApiKeySubject `json:"subject,omitempty"`
25+
ID string `json:"_id,omitempty"`
26+
Name string `json:"name"`
27+
Scopes []string `json:"scopes,omitempty"`
28+
TokenPrefix string `json:"tokenPrefix,omitempty"`
29+
ScopeSnapshot ApiKeyScopeSnapshot `json:"scopeSnapshot,omitempty"`
30+
Created string `json:"created,omitempty"`
31+
}
32+
33+
func (client *Client) GetAPIKey(keyID string) (*ApiKey, error) {
34+
35+
opts := RequestOptions{
36+
Path: fmt.Sprintf("/auth/key/%s", keyID),
37+
Method: "GET",
38+
}
39+
40+
resp, err := client.RequestAPI(&opts)
41+
42+
if err != nil {
43+
return nil, err
44+
}
45+
46+
var apiKey ApiKey
47+
48+
err = DecodeResponseInto(resp, &apiKey)
49+
if err != nil {
50+
return nil, err
51+
}
52+
53+
return &apiKey, nil
54+
}
55+
56+
func (client *Client) DeleteAPIKey(keyID string) error {
57+
58+
opts := RequestOptions{
59+
Path: fmt.Sprintf("/auth/key/%s", keyID),
60+
Method: "DELETE",
61+
}
62+
63+
resp, err := client.RequestAPI(&opts)
64+
if err != nil {
65+
fmt.Println(string(resp))
66+
return err
67+
}
68+
69+
return nil
70+
}
71+
72+
func (client *Client) UpdateAPIKey(key *ApiKey) error {
73+
74+
keyID := key.ID
75+
if keyID == "" {
76+
return errors.New("[ERROR] Key ID is empty")
77+
}
78+
79+
body, err := EncodeToJSON(key)
80+
if err != nil {
81+
return err
82+
}
83+
84+
opts := RequestOptions{
85+
Path: fmt.Sprintf("/auth/key/%s", keyID),
86+
Method: "PATCH",
87+
Body: body,
88+
}
89+
90+
resp, err := client.RequestAPI(&opts)
91+
92+
if err != nil {
93+
fmt.Println(string(resp))
94+
return err
95+
}
96+
97+
return nil
98+
}
99+
100+
func (client *Client) CreateApiKey(accountId string, apiKey *ApiKey) (string, error) {
101+
102+
// Check collaborataros
103+
account, err := client.GetAccountByID(accountId)
104+
if err != nil {
105+
return "", err
106+
}
107+
if account.Limits == nil {
108+
log.Fatal("[ERROR] Collaborators are not set")
109+
}
110+
111+
// add user
112+
userPrefix := acctest.RandString(10)
113+
userName := "tfuser" + userPrefix
114+
userEmail := userName + "@codefresh.io"
115+
116+
user, err := client.AddNewUserToAccount(accountId, userName, userEmail)
117+
if err != nil {
118+
return "", err
119+
}
120+
userID := user.ID
121+
122+
// activate
123+
_, err = client.ActivateUser(userID)
124+
if err != nil {
125+
return "", err
126+
}
127+
128+
// set user as account admin
129+
err = client.SetUserAsAccountAdmin(accountId, userID)
130+
if err != nil {
131+
return "", nil
132+
}
133+
134+
// login as user
135+
xAccessToken, err := client.GetXAccessToken(userID)
136+
if err != nil {
137+
return "", err
138+
}
139+
140+
// generate token
141+
apiToken, err := client.GenerateToken(xAccessToken, apiKey)
142+
if err != nil {
143+
return "", err
144+
}
145+
146+
return apiToken, nil
147+
148+
}
149+
150+
func (client *Client) GetXAccessToken(userID string) (string, error) {
151+
152+
url := fmt.Sprintf("%s/admin/user/loginAsUser?userId=%s", client.Host, userID)
153+
request, err := http.NewRequest("GET", url, nil)
154+
if err != nil {
155+
return "", err
156+
}
157+
158+
request.Header.Set("Authorization", client.Token)
159+
request.Header.Set("Content-Type", "application/json; charset=utf-8")
160+
161+
resp, err := client.Client.Do(request)
162+
if err != nil {
163+
return "", err
164+
}
165+
166+
defer resp.Body.Close()
167+
168+
for _, cookie := range resp.Cookies() {
169+
if cookie.Name == "cf-access-token" {
170+
return cookie.Value, nil
171+
}
172+
}
173+
174+
return "", nil
175+
}
176+
177+
func (client *Client) GenerateToken(xToken string, apiKey *ApiKey) (string, error) {
178+
179+
body, err := EncodeToJSON(apiKey)
180+
if err != nil {
181+
return "", err
182+
}
183+
184+
opts := RequestOptions{
185+
Path: "/auth/key",
186+
Method: "POST",
187+
XAccessToken: xToken,
188+
Body: body,
189+
}
190+
191+
resp, err := client.RequestApiXAccessToken(&opts)
192+
193+
if err != nil {
194+
return "", err
195+
}
196+
197+
return string(resp), nil
198+
}
199+
200+
func (client *Client) GetApiKeysList() ([]ApiKey, error) {
201+
fullPath := "/auth/keys"
202+
opts := RequestOptions{
203+
Path: fullPath,
204+
Method: "GET",
205+
}
206+
207+
resp, err := client.RequestAPI(&opts)
208+
209+
if err != nil {
210+
return nil, err
211+
}
212+
213+
var apiKeys []ApiKey
214+
215+
err = DecodeResponseInto(resp, &apiKeys)
216+
if err != nil {
217+
return nil, err
218+
}
219+
220+
return apiKeys, nil
221+
}

client/client.go

+36-4
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,11 @@ type Client struct {
1818

1919
// RequestOptions path, method, etc
2020
type RequestOptions struct {
21-
Path string
22-
Method string
23-
Body []byte
24-
QS map[string]string
21+
Path string
22+
Method string
23+
Body []byte
24+
QS map[string]string
25+
XAccessToken string
2526
}
2627

2728
// NewClient returns a new client configured to communicate on a server with the
@@ -68,6 +69,37 @@ func (client *Client) RequestAPI(opt *RequestOptions) ([]byte, error) {
6869
return body, nil
6970
}
7071

72+
func (client *Client) RequestApiXAccessToken(opt *RequestOptions) ([]byte, error) {
73+
finalURL := fmt.Sprintf("%s%s", client.Host, opt.Path)
74+
if opt.QS != nil {
75+
finalURL += ToQS(opt.QS)
76+
}
77+
request, err := http.NewRequest(opt.Method, finalURL, bytes.NewBuffer(opt.Body))
78+
if err != nil {
79+
return nil, err
80+
}
81+
82+
request.Header.Set("x-access-token", opt.XAccessToken)
83+
request.Header.Set("Content-Type", "application/json; charset=utf-8")
84+
85+
resp, err := client.Client.Do(request)
86+
87+
if err != nil {
88+
return nil, err
89+
}
90+
defer resp.Body.Close()
91+
92+
body, err := ioutil.ReadAll(resp.Body)
93+
if err != nil {
94+
return nil, fmt.Errorf("Failed to read body %v %v", resp.StatusCode, resp.Status)
95+
}
96+
97+
if resp.StatusCode != 200 {
98+
return nil, fmt.Errorf("%v, %s", resp.Status, string(body))
99+
}
100+
return body, nil
101+
}
102+
71103
// ToQS add extra parameters to path
72104
func ToQS(qs map[string]string) string {
73105
var arr = []string{}

client/team.go

+11-11
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ func (client *Client) DeleteTeam(id string) error {
157157

158158
func (client *Client) SynchronizeClientWithGroup(name, ssoType string, notifications bool) error {
159159

160-
fullPath := fmt.Sprintf("/team/group/synchronize/name/%s/type/%s?disableNotifications=%b", name, ssoType, notifications)
160+
fullPath := fmt.Sprintf("/team/group/synchronize/name/%s/type/%s?disableNotifications=%t", name, ssoType, notifications)
161161
opts := RequestOptions{
162162
Path: fullPath,
163163
Method: "GET",
@@ -188,7 +188,7 @@ func (client *Client) AddUserToTeam(teamID, userID string) error {
188188
return nil
189189
}
190190

191-
func (client *Client) DeleteUserFromTeam(teamID, userID string) error {
191+
func (client *Client) DeleteUserFromTeam(teamID, userID string) error {
192192

193193
fullPath := fmt.Sprintf("/team/%s/%s/deleteUserFromTeam", teamID, userID)
194194
opts := RequestOptions{
@@ -237,18 +237,18 @@ func GetUsersDiff(desiredUsers []string, existingUsers []TeamUser) (usersToAdd [
237237
usersToAdd = []string{}
238238
usersToDelete = []string{}
239239

240-
for _, user := range existingUsers{
240+
for _, user := range existingUsers {
241241
existingUsersIDs = append(existingUsersIDs, user.ID)
242242
}
243243

244-
for _, id := range existingUsersIDs{
244+
for _, id := range existingUsersIDs {
245245
ok := find(desiredUsers, id)
246246
if !ok {
247247
usersToDelete = append(usersToDelete, id)
248248
}
249249
}
250250

251-
for _, id := range desiredUsers{
251+
for _, id := range desiredUsers {
252252
ok := find(existingUsersIDs, id)
253253
if !ok {
254254
usersToAdd = append(usersToAdd, id)
@@ -259,10 +259,10 @@ func GetUsersDiff(desiredUsers []string, existingUsers []TeamUser) (usersToAdd [
259259
}
260260

261261
func find(slice []string, val string) bool {
262-
for _, item := range slice {
263-
if item == val {
264-
return true
265-
}
266-
}
267-
return false
262+
for _, item := range slice {
263+
if item == val {
264+
return true
265+
}
266+
}
267+
return false
268268
}

0 commit comments

Comments
 (0)