1package tfe
2
3import (
4	"context"
5	"errors"
6	"fmt"
7	"net/url"
8	"time"
9)
10
11// Compile-time proof of interface implementation.
12var _ OAuthTokens = (*oAuthTokens)(nil)
13
14// OAuthTokens describes all the OAuth token related methods that the
15// Terraform Enterprise API supports.
16//
17// TFE API docs:
18// https://www.terraform.io/docs/enterprise/api/oauth-tokens.html
19type OAuthTokens interface {
20	// List all the OAuth tokens for a given organization.
21	List(ctx context.Context, organization string, options OAuthTokenListOptions) (*OAuthTokenList, error)
22	// Read a OAuth token by its ID.
23	Read(ctx context.Context, oAuthTokenID string) (*OAuthToken, error)
24
25	// Update an existing OAuth token.
26	Update(ctx context.Context, oAuthTokenID string, options OAuthTokenUpdateOptions) (*OAuthToken, error)
27
28	// Delete a OAuth token by its ID.
29	Delete(ctx context.Context, oAuthTokenID string) error
30}
31
32// oAuthTokens implements OAuthTokens.
33type oAuthTokens struct {
34	client *Client
35}
36
37// OAuthTokenList represents a list of OAuth tokens.
38type OAuthTokenList struct {
39	*Pagination
40	Items []*OAuthToken
41}
42
43// OAuthToken represents a VCS configuration including the associated
44// OAuth token
45type OAuthToken struct {
46	ID                  string    `jsonapi:"primary,oauth-tokens"`
47	UID                 string    `jsonapi:"attr,uid"`
48	CreatedAt           time.Time `jsonapi:"attr,created-at,iso8601"`
49	HasSSHKey           bool      `jsonapi:"attr,has-ssh-key"`
50	ServiceProviderUser string    `jsonapi:"attr,service-provider-user"`
51
52	// Relations
53	OAuthClient *OAuthClient `jsonapi:"relation,oauth-client"`
54}
55
56// OAuthTokenListOptions represents the options for listing
57// OAuth tokens.
58type OAuthTokenListOptions struct {
59	ListOptions
60}
61
62// List all the OAuth tokens for a given organization.
63func (s *oAuthTokens) List(ctx context.Context, organization string, options OAuthTokenListOptions) (*OAuthTokenList, error) {
64	if !validStringID(&organization) {
65		return nil, errors.New("invalid value for organization")
66	}
67
68	u := fmt.Sprintf("organizations/%s/oauth-tokens", url.QueryEscape(organization))
69	req, err := s.client.newRequest("GET", u, &options)
70	if err != nil {
71		return nil, err
72	}
73
74	otl := &OAuthTokenList{}
75	err = s.client.do(ctx, req, otl)
76	if err != nil {
77		return nil, err
78	}
79
80	return otl, nil
81}
82
83// Read an OAuth token by its ID.
84func (s *oAuthTokens) Read(ctx context.Context, oAuthTokenID string) (*OAuthToken, error) {
85	if !validStringID(&oAuthTokenID) {
86		return nil, errors.New("invalid value for OAuth token ID")
87	}
88
89	u := fmt.Sprintf("oauth-tokens/%s", url.QueryEscape(oAuthTokenID))
90	req, err := s.client.newRequest("GET", u, nil)
91	if err != nil {
92		return nil, err
93	}
94
95	ot := &OAuthToken{}
96	err = s.client.do(ctx, req, ot)
97	if err != nil {
98		return nil, err
99	}
100
101	return ot, err
102}
103
104// OAuthTokenUpdateOptions represents the options for updating an OAuth token.
105type OAuthTokenUpdateOptions struct {
106	// For internal use only!
107	ID string `jsonapi:"primary,oauth-tokens"`
108
109	// A private SSH key to be used for git clone operations.
110	PrivateSSHKey *string `jsonapi:"attr,ssh-key"`
111}
112
113// Update an existing OAuth token.
114func (s *oAuthTokens) Update(ctx context.Context, oAuthTokenID string, options OAuthTokenUpdateOptions) (*OAuthToken, error) {
115	if !validStringID(&oAuthTokenID) {
116		return nil, errors.New("invalid value for OAuth token ID")
117	}
118
119	// Make sure we don't send a user provided ID.
120	options.ID = ""
121
122	u := fmt.Sprintf("oauth-tokens/%s", url.QueryEscape(oAuthTokenID))
123	req, err := s.client.newRequest("PATCH", u, &options)
124	if err != nil {
125		return nil, err
126	}
127
128	ot := &OAuthToken{}
129	err = s.client.do(ctx, req, ot)
130	if err != nil {
131		return nil, err
132	}
133
134	return ot, err
135}
136
137// Delete an OAuth token by its ID.
138func (s *oAuthTokens) Delete(ctx context.Context, oAuthTokenID string) error {
139	if !validStringID(&oAuthTokenID) {
140		return errors.New("invalid value for OAuth token ID")
141	}
142
143	u := fmt.Sprintf("oauth-tokens/%s", url.QueryEscape(oAuthTokenID))
144	req, err := s.client.newRequest("DELETE", u, nil)
145	if err != nil {
146		return err
147	}
148
149	return s.client.do(ctx, req, nil)
150}
151