forked from Scalingo/go-scalingo
-
Notifications
You must be signed in to change notification settings - Fork 0
/
tokens.go
158 lines (129 loc) · 3.48 KB
/
tokens.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
package scalingo
import (
"encoding/json"
"errors"
"strconv"
"time"
"github.com/Scalingo/go-scalingo/http"
errgo "gopkg.in/errgo.v1"
)
type TokensService interface {
TokensList() (Tokens, error)
TokenCreate(TokenCreateParams) (Token, error)
TokenExchange(token string) (string, error)
TokenShow(id int) (Token, error)
}
var _ TokensService = (*Client)(nil)
var ErrOTPRequired = errors.New("OTP Required")
// IsOTPRequired tests if the authentication backend return an OTP Required error
func IsOTPRequired(err error) bool {
rerr, ok := err.(*http.RequestFailedError)
if !ok {
return false
}
if rerr.Message == "OTP Required" {
return true
}
return false
}
type Token struct {
ID int `json:"int"`
Name string `json:"name"`
CreatedAt time.Time `json:"created_at"`
Token string `json:"token"`
}
type LoginParams struct {
Identifier string `json:"identifier"`
Password string `json:"password"`
OTP string `json:"otp"`
JWT string `json:"jwt"`
}
type TokenCreateParams struct {
Name string `json:"name"`
}
type Tokens []*Token
type TokensRes struct {
Tokens Tokens `json:"tokens"`
}
type BearerTokenRes struct {
Token string `json:"token"`
}
type TokenRes struct {
Token Token `json:"token"`
}
func (c *Client) TokensList() (Tokens, error) {
var tokensRes TokensRes
err := c.AuthAPI().ResourceList("tokens", nil, &tokensRes)
if err != nil {
return nil, errgo.Notef(err, "fail to get tokens")
}
return tokensRes.Tokens, nil
}
func (c *Client) TokenExchange(token string) (string, error) {
req := &http.APIRequest{
NoAuth: true,
Method: "POST",
Endpoint: "/tokens/exchange",
Password: token,
}
res, err := c.AuthAPI().Do(req)
if err != nil {
return "", errgo.Notef(err, "fail to make request POST /v1/tokens/exchange")
}
defer res.Body.Close()
var btRes BearerTokenRes
err = json.NewDecoder(res.Body).Decode(&btRes)
if err != nil {
return "", errgo.Notef(err, "invalid response from authentication service")
}
return btRes.Token, nil
}
func (c *Client) TokenCreateWithLogin(params TokenCreateParams, login LoginParams) (Token, error) {
req := &http.APIRequest{
NoAuth: true,
Method: "POST",
Endpoint: "/tokens",
Expected: http.Statuses{201},
Username: login.Identifier,
Password: login.Password,
OTP: login.OTP,
Token: login.JWT,
Params: map[string]interface{}{"token": params},
}
resp, err := c.AuthAPI().Do(req)
if err != nil {
if IsOTPRequired(err) {
return Token{}, ErrOTPRequired
}
return Token{}, errgo.Notef(err, "request failed")
}
defer resp.Body.Close()
var tokenRes TokenRes
err = json.NewDecoder(resp.Body).Decode(&tokenRes)
if err != nil {
return Token{}, errgo.NoteMask(err, "invalid response from authentication service", errgo.Any)
}
return tokenRes.Token, nil
}
func (c *Client) TokenCreate(params TokenCreateParams) (Token, error) {
var tokenRes TokenRes
payload := map[string]TokenCreateParams{
"token": params,
}
err := c.AuthAPI().ResourceAdd("tokens", payload, &tokenRes)
if err != nil {
return Token{}, errgo.Notef(err, "fail to create token")
}
return tokenRes.Token, nil
}
func (c *Client) TokenShow(id int) (Token, error) {
var tokenRes TokenRes
err := c.AuthAPI().ResourceGet("tokens", strconv.Itoa(id), nil, &tokenRes)
if err != nil {
return Token{}, errgo.Notef(err, "fail to get token")
}
return tokenRes.Token, nil
}
func (c *Client) GetAccessToken() (string, error) {
return c.ScalingoAPI().TokenGenerator().GetAccessToken()
}