forked from Onyx-Protocol/Onyx
/
access_tokens.go
104 lines (88 loc) · 2.41 KB
/
access_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
package core
import (
"context"
"encoding/json"
"chain/core/accesstoken"
"chain/errors"
"chain/log"
"chain/net/http/authz"
"chain/net/http/httpjson"
)
var errCurrentToken = errors.New("token cannot delete itself")
func (a *API) createAccessToken(ctx context.Context, x struct{ ID, Type string }) (*accesstoken.Token, error) {
token, err := a.accessTokens.Create(ctx, x.ID, x.Type)
if err != nil {
return nil, errors.Wrap(err)
}
if x.Type == "" {
return token, nil
}
data := map[string]interface{}{
"id": token.ID,
}
guardData, err := json.Marshal(data)
if err != nil {
return nil, errors.Wrap(err)
}
var grant *authz.Grant
// Type is deprecated; however, for backward compatibility, using the
// Type field will create a grant associated with this new token.
switch x.Type {
case "client":
grant = &authz.Grant{
GuardType: "access_token",
GuardData: guardData,
Policy: "client-readwrite",
}
case "network":
grant = &authz.Grant{
GuardType: "access_token",
GuardData: guardData,
Policy: "crosscore",
}
default:
// We've already returned if x.Type wasn't specified, so this must be a bad type.
return nil, accesstoken.ErrBadType
}
err = a.sdb.Exec(ctx, a.grants.Save(ctx, grant))
if err != nil {
return nil, errors.Wrap(err)
}
token.Type = x.Type // deprecated
return token, nil
}
func (a *API) listAccessTokens(ctx context.Context, x requestQuery) (*page, error) {
limit := x.PageSize
if limit == 0 {
limit = defGenericPageSize
}
tokens, next, err := a.accessTokens.List(ctx, x.Type, x.After, limit)
if err != nil {
return nil, err
}
outQuery := x
outQuery.After = next
return &page{
Items: httpjson.Array(tokens),
LastPage: len(tokens) < limit,
Next: outQuery,
}, nil
}
func (a *API) deleteAccessToken(ctx context.Context, x struct{ ID string }) error {
currentID, _, _ := httpjson.Request(ctx).BasicAuth()
if currentID == x.ID {
return errCurrentToken
}
err := a.accessTokens.Delete(ctx, x.ID)
if err != nil {
return err
}
err = a.sdb.Exec(ctx, a.deleteGrantsByAccessToken(x.ID))
if err != nil {
// well, technically we did delete the access token, so don't return the error
// TODO(tessr): make this whole operation atomic, such that we either delete
// both the access token and its grants, or we return a failure.
log.Printkv(ctx, log.KeyError, err, "at", "revoking grants for access token", "token", x.ID)
}
return nil
}