1package tfe 2 3import ( 4 "context" 5 "fmt" 6 "net/url" 7) 8 9// Compile-time proof of interface implementation. 10var _ AdminUsers = (*adminUsers)(nil) 11 12// AdminUsers describes all the admin user related methods that the Terraform 13// Enterprise API supports. 14// It contains endpoints to help site administrators manage their users. 15// 16// TFE API docs: https://www.terraform.io/docs/cloud/api/admin/users.html 17type AdminUsers interface { 18 // List all the users of the given installation. 19 List(ctx context.Context, options AdminUserListOptions) (*AdminUserList, error) 20 21 // Delete a user by its ID. 22 Delete(ctx context.Context, userID string) error 23 24 // Suspend a user by its ID. 25 Suspend(ctx context.Context, userID string) (*AdminUser, error) 26 27 // Unsuspend a user by its ID. 28 Unsuspend(ctx context.Context, userID string) (*AdminUser, error) 29 30 // GrantAdmin grants admin privilages to a user by its ID. 31 GrantAdmin(ctx context.Context, userID string) (*AdminUser, error) 32 33 // RevokeAdmin revokees admin privilages to a user by its ID. 34 RevokeAdmin(ctx context.Context, userID string) (*AdminUser, error) 35 36 // Disable2FA disables a user's two-factor authentication in the situation 37 // where they have lost access to their device and recovery codes. 38 Disable2FA(ctx context.Context, userID string) (*AdminUser, error) 39} 40 41// adminUsers implements the AdminUsers interface. 42type adminUsers struct { 43 client *Client 44} 45 46// AdminUser represents a user as seen by an Admin. 47type AdminUser struct { 48 ID string `jsonapi:"primary,users"` 49 Email string `jsonapi:"attr,email"` 50 Username string `jsonapi:"attr,username"` 51 AvatarURL string `jsonapi:"attr,avatar-url"` 52 TwoFactor *TwoFactor `jsonapi:"attr,two-factor"` 53 IsAdmin bool `jsonapi:"attr,is-admin"` 54 IsSuspended bool `jsonapi:"attr,is-suspended"` 55 IsServiceAccount bool `jsonapi:"attr,is-service-account"` 56 57 // Relations 58 Organizations []*Organization `jsonapi:"relation,organizations"` 59} 60 61// AdminUserList represents a list of users. 62type AdminUserList struct { 63 *Pagination 64 Items []*AdminUser 65} 66 67// AdminUserListOptions represents the options for listing users. 68// https://www.terraform.io/docs/cloud/api/admin/users.html#query-parameters 69type AdminUserListOptions struct { 70 ListOptions 71 72 // A search query string. Users are searchable by username and email address. 73 Query *string `url:"q,omitempty"` 74 75 // Can be "true" or "false" to show only administrators or non-administrators. 76 Administrators *string `url:"filter[admin]"` 77 78 // Can be "true" or "false" to show only suspended users or users who are not suspended. 79 SuspendedUsers *string `url:"filter[suspended]"` 80 81 // A list of relations to include. See available resources 82 // https://www.terraform.io/docs/cloud/api/admin/users.html#available-related-resources 83 Include *string `url:"include"` 84} 85 86// List all user accounts in the Terraform Enterprise installation 87func (a *adminUsers) List(ctx context.Context, options AdminUserListOptions) (*AdminUserList, error) { 88 u := fmt.Sprintf("admin/users") 89 req, err := a.client.newRequest("GET", u, &options) 90 if err != nil { 91 return nil, err 92 } 93 94 aul := &AdminUserList{} 95 err = a.client.do(ctx, req, aul) 96 if err != nil { 97 return nil, err 98 } 99 100 return aul, nil 101} 102 103// Delete a user by its ID. 104func (a *adminUsers) Delete(ctx context.Context, userID string) error { 105 if !validStringID(&userID) { 106 return ErrInvalidUserValue 107 } 108 109 u := fmt.Sprintf("admin/users/%s", url.QueryEscape(userID)) 110 req, err := a.client.newRequest("DELETE", u, nil) 111 if err != nil { 112 return err 113 } 114 115 return a.client.do(ctx, req, nil) 116} 117 118// Suspend a user by its ID. 119func (a *adminUsers) Suspend(ctx context.Context, userID string) (*AdminUser, error) { 120 if !validStringID(&userID) { 121 return nil, ErrInvalidUserValue 122 } 123 124 u := fmt.Sprintf("admin/users/%s/actions/suspend", url.QueryEscape(userID)) 125 req, err := a.client.newRequest("POST", u, nil) 126 if err != nil { 127 return nil, err 128 } 129 130 au := &AdminUser{} 131 err = a.client.do(ctx, req, au) 132 if err != nil { 133 return nil, err 134 } 135 136 return au, nil 137} 138 139// Unsuspend a user by its ID. 140func (a *adminUsers) Unsuspend(ctx context.Context, userID string) (*AdminUser, error) { 141 if !validStringID(&userID) { 142 return nil, ErrInvalidUserValue 143 } 144 145 u := fmt.Sprintf("admin/users/%s/actions/unsuspend", url.QueryEscape(userID)) 146 req, err := a.client.newRequest("POST", u, nil) 147 if err != nil { 148 return nil, err 149 } 150 151 au := &AdminUser{} 152 err = a.client.do(ctx, req, au) 153 if err != nil { 154 return nil, err 155 } 156 157 return au, nil 158} 159 160// GrantAdmin grants admin privilages to a user by its ID. 161func (a *adminUsers) GrantAdmin(ctx context.Context, userID string) (*AdminUser, error) { 162 if !validStringID(&userID) { 163 return nil, ErrInvalidUserValue 164 } 165 166 u := fmt.Sprintf("admin/users/%s/actions/grant_admin", url.QueryEscape(userID)) 167 req, err := a.client.newRequest("POST", u, nil) 168 if err != nil { 169 return nil, err 170 } 171 172 au := &AdminUser{} 173 err = a.client.do(ctx, req, au) 174 if err != nil { 175 return nil, err 176 } 177 178 return au, nil 179} 180 181// RevokeAdmin revokes admin privilages to a user by its ID. 182func (a *adminUsers) RevokeAdmin(ctx context.Context, userID string) (*AdminUser, error) { 183 if !validStringID(&userID) { 184 return nil, ErrInvalidUserValue 185 } 186 187 u := fmt.Sprintf("admin/users/%s/actions/revoke_admin", url.QueryEscape(userID)) 188 req, err := a.client.newRequest("POST", u, nil) 189 if err != nil { 190 return nil, err 191 } 192 193 au := &AdminUser{} 194 err = a.client.do(ctx, req, au) 195 if err != nil { 196 return nil, err 197 } 198 199 return au, nil 200} 201 202// Disable2FA disables a user's two-factor authentication in the situation 203// where they have lost access to their device and recovery codes. 204func (a *adminUsers) Disable2FA(ctx context.Context, userID string) (*AdminUser, error) { 205 if !validStringID(&userID) { 206 return nil, ErrInvalidUserValue 207 } 208 209 u := fmt.Sprintf("admin/users/%s/actions/disable_two_factor", url.QueryEscape(userID)) 210 req, err := a.client.newRequest("POST", u, nil) 211 if err != nil { 212 return nil, err 213 } 214 215 au := &AdminUser{} 216 err = a.client.do(ctx, req, au) 217 if err != nil { 218 return nil, err 219 } 220 221 return au, nil 222} 223