-
Notifications
You must be signed in to change notification settings - Fork 92
/
auth.go
105 lines (93 loc) · 2.49 KB
/
auth.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
package auth
import (
"encoding/json"
"errors"
"fmt"
"sync"
"github.com/google/uuid"
ds "github.com/ipfs/go-datastore"
"github.com/ipfs/go-datastore/query"
logging "github.com/ipfs/go-log/v2"
"github.com/textileio/powergate/ffs"
)
var (
// ErrNotFound indicates that the auth-token isn't registered.
ErrNotFound = errors.New("auth token not found")
log = logging.Logger("ffs-auth")
)
// Auth contains a mapping between auth-tokens and Api instances.
type Auth struct {
lock sync.Mutex
ds ds.Datastore
}
type entry struct {
Token string
APIID ffs.APIID
// This can be extended to have permissions
}
// New returns a new Auth.
func New(store ds.Datastore) *Auth {
return &Auth{
ds: store,
}
}
// Generate generates a new returned auth-token mapped to the iid.
func (r *Auth) Generate(iid ffs.APIID) (string, error) {
log.Infof("generating auth-token for instance %s", iid)
r.lock.Lock()
defer r.lock.Unlock()
e := entry{
Token: uuid.New().String(),
APIID: iid,
}
buf, err := json.Marshal(&e)
if err != nil {
return "", fmt.Errorf("marshaling new auth token for instance %s: %s", iid, err)
}
if err := r.ds.Put(ds.NewKey(e.Token), buf); err != nil {
return "", fmt.Errorf("saving generated token from %s to datastore: %s", iid, err)
}
return e.Token, nil
}
// Get returns the InstanceID associated with token.
// It returns ErrNotFound if there isn't such.
func (r *Auth) Get(token string) (ffs.APIID, error) {
r.lock.Lock()
defer r.lock.Unlock()
buf, err := r.ds.Get(ds.NewKey(token))
if err != nil && err == ds.ErrNotFound {
return ffs.EmptyInstanceID, ErrNotFound
}
if err != nil {
return ffs.EmptyInstanceID, fmt.Errorf("getting token %s from datastore: %s", token, err)
}
var e entry
if err := json.Unmarshal(buf, &e); err != nil {
return ffs.EmptyInstanceID, fmt.Errorf("unmarshaling %s information from datastore: %s", token, err)
}
return e.APIID, nil
}
// List returns a list of all API instances.
func (r *Auth) List() ([]ffs.APIID, error) {
r.lock.Lock()
defer r.lock.Unlock()
q := query.Query{Prefix: ""}
res, err := r.ds.Query(q)
if err != nil {
return nil, fmt.Errorf("executing query in datastore: %s", err)
}
defer func() {
if err := res.Close(); err != nil {
log.Errorf("closing query result: %s", err)
}
}()
var ret []ffs.APIID
for r := range res.Next() {
var e entry
if err := json.Unmarshal(r.Entry.Value, &e); err != nil {
return nil, fmt.Errorf("unmarshaling query result: %s", err)
}
ret = append(ret, e.APIID)
}
return ret, nil
}