-
Notifications
You must be signed in to change notification settings - Fork 15
/
credentials.go
147 lines (121 loc) · 4.06 KB
/
credentials.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
package tokens
import (
"context"
"errors"
"fmt"
"strconv"
"time"
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
"github.com/nspcc-dev/neofs-s3-gw/api/cache"
"github.com/nspcc-dev/neofs-s3-gw/creds/accessbox"
cid "github.com/nspcc-dev/neofs-sdk-go/container/id"
oid "github.com/nspcc-dev/neofs-sdk-go/object/id"
"github.com/nspcc-dev/neofs-sdk-go/user"
)
type (
// Credentials is a bearer token get/put interface.
Credentials interface {
GetBox(context.Context, oid.Address) (*accessbox.Box, error)
Put(context.Context, cid.ID, user.ID, *accessbox.AccessBox, uint64, ...*keys.PublicKey) (oid.Address, error)
}
cred struct {
key *keys.PrivateKey
neoFS NeoFS
cache *cache.AccessBoxCache
}
)
// PrmObjectCreate groups parameters of objects created by credential tool.
type PrmObjectCreate struct {
// NeoFS identifier of the object creator.
Creator user.ID
// NeoFS container to store the object.
Container cid.ID
// File path.
Filepath string
// Last NeoFS epoch of the object lifetime.
ExpirationEpoch uint64
// Object payload.
Payload []byte
}
// NeoFS represents virtual connection to NeoFS network.
type NeoFS interface {
// CreateObject creates and saves a parameterized object in the specified
// NeoFS container from a specific user. It sets 'Timestamp' attribute to the current time.
// It returns the ID of the saved object.
//
// It returns exactly one non-nil value. It returns any error encountered which
// prevented the object from being created.
CreateObject(context.Context, PrmObjectCreate) (oid.ID, error)
// ReadObjectPayload reads payload of the object from NeoFS network by address
// into memory.
//
// It returns exactly one non-nil value. It returns any error encountered which
// prevented the object payload from being read.
ReadObjectPayload(context.Context, oid.Address) ([]byte, error)
}
var (
// ErrEmptyPublicKeys is returned when no HCS keys are provided.
ErrEmptyPublicKeys = errors.New("HCS public keys could not be empty")
// ErrEmptyBearerToken is returned when no bearer token is provided.
ErrEmptyBearerToken = errors.New("Bearer token could not be empty")
)
var _ = New
// New creates a new Credentials instance using the given cli and key.
func New(neoFS NeoFS, key *keys.PrivateKey, config *cache.Config) Credentials {
return &cred{neoFS: neoFS, key: key, cache: cache.NewAccessBoxCache(config)}
}
func (c *cred) GetBox(ctx context.Context, addr oid.Address) (*accessbox.Box, error) {
cachedBox := c.cache.Get(addr)
if cachedBox != nil {
return cachedBox, nil
}
box, err := c.getAccessBox(ctx, addr)
if err != nil {
return nil, fmt.Errorf("get access box: %w", err)
}
cachedBox, err = box.GetBox(c.key)
if err != nil {
return nil, fmt.Errorf("get box: %w", err)
}
if err = c.cache.Put(addr, cachedBox); err != nil {
return nil, fmt.Errorf("put box into cache: %w", err)
}
return cachedBox, nil
}
func (c *cred) getAccessBox(ctx context.Context, addr oid.Address) (*accessbox.AccessBox, error) {
data, err := c.neoFS.ReadObjectPayload(ctx, addr)
if err != nil {
return nil, fmt.Errorf("read payload: %w", err)
}
// decode access box
var box accessbox.AccessBox
if err = box.Unmarshal(data); err != nil {
return nil, fmt.Errorf("unmarhal access box: %w", err)
}
return &box, nil
}
func (c *cred) Put(ctx context.Context, idCnr cid.ID, issuer user.ID, box *accessbox.AccessBox, expiration uint64, keys ...*keys.PublicKey) (oid.Address, error) {
if len(keys) == 0 {
return oid.Address{}, ErrEmptyPublicKeys
} else if box == nil {
return oid.Address{}, ErrEmptyBearerToken
}
data, err := box.Marshal()
if err != nil {
return oid.Address{}, fmt.Errorf("marshall box: %w", err)
}
idObj, err := c.neoFS.CreateObject(ctx, PrmObjectCreate{
Creator: issuer,
Container: idCnr,
Filepath: strconv.FormatInt(time.Now().Unix(), 10) + "_access.box",
ExpirationEpoch: expiration,
Payload: data,
})
if err != nil {
return oid.Address{}, fmt.Errorf("create object: %w", err)
}
var addr oid.Address
addr.SetObject(idObj)
addr.SetContainer(idCnr)
return addr, nil
}