-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathproject.go
102 lines (84 loc) · 2.8 KB
/
project.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
package reflect
import (
"time"
"github.com/pborman/uuid"
jose "gopkg.in/square/go-jose.v2"
"gopkg.in/square/go-jose.v2/jwt"
)
type ProjectClaims struct {
ViewIdentifiers []string `json:"http://reflect.io/s/v3/vid,omitempty"`
Parameters []Parameter `json:"http://reflect.io/s/v3/p,omitempty"`
Attributes map[string]interface{} `json:"http://reflect.io/s/v3/a,omitempty"`
}
type ProjectTokenBuilder struct {
accessKey string
expiration time.Time
claims ProjectClaims
}
// WithExpiration sets the time at which this token will no longer be valid.
// All requests made using an expired token will fail.
func (ptb *ProjectTokenBuilder) WithExpiration(when time.Time) *ProjectTokenBuilder {
ptb.expiration = when
return ptb
}
// WithViewIdentifier restricts the views that can be loaded with this token.
// This method can be called multiple times, and will permit only the specified
// views to be loaded.
func (ptb *ProjectTokenBuilder) WithViewIdentifier(id string) *ProjectTokenBuilder {
ptb.claims.ViewIdentifiers = append(ptb.claims.ViewIdentifiers, id)
return ptb
}
// WithParameter adds a data-filtering parameter to the token. This method can
// be called multiple times to add many parameters.
func (ptb *ProjectTokenBuilder) WithParameter(ps Parameter) *ProjectTokenBuilder {
ptb.claims.Parameters = append(ptb.claims.Parameters, ps)
return ptb
}
// WithAttribute adds the given attribute to the token.
func (ptb *ProjectTokenBuilder) WithAttribute(name string, value interface{}) *ProjectTokenBuilder {
if ptb.claims.Attributes == nil {
ptb.claims.Attributes = make(map[string]interface{})
}
ptb.claims.Attributes[name] = value
return ptb
}
// Build constructs a new encrypted token that encapsulates the secret
// information provided to this builder.
func (ptb *ProjectTokenBuilder) Build(secretKey string) (string, error) {
secret := uuid.Parse(secretKey)
if secret == nil {
return "", ErrInvalidSecretKey
}
jwk := jose.JSONWebKey{
KeyID: ptb.accessKey,
Key: []byte(secret),
}
encrypter, err := jose.NewEncrypter(
jose.A128GCM,
jose.Recipient{Algorithm: jose.DIRECT, Key: jwk},
(&jose.EncrypterOptions{Compression: jose.DEFLATE}).WithType("JWT"),
)
if err != nil {
return "", err
}
t := jwt.NewNumericDate(time.Now())
builder := jwt.Encrypted(encrypter).
Claims(jwt.Claims{
IssuedAt: t,
NotBefore: t,
}).
Claims(ptb.claims)
if !ptb.expiration.IsZero() {
builder = builder.Claims(jwt.Claims{
Expiry: jwt.NewNumericDate(ptb.expiration),
})
}
return builder.CompactSerialize()
}
// NewProjectTokenBuilder creates a new builder that can be configured with
// secret data to be passed to the Reflect API.
func NewProjectTokenBuilder(accessKey string) *ProjectTokenBuilder {
return &ProjectTokenBuilder{
accessKey: accessKey,
}
}