forked from TrueCloudLab/frostfs-s3-gw
129 lines
3 KiB
Go
129 lines
3 KiB
Go
|
package frostfsid
|
||
|
|
||
|
import (
|
||
|
"encoding/hex"
|
||
|
"errors"
|
||
|
"strconv"
|
||
|
"strings"
|
||
|
|
||
|
"git.frostfs.info/TrueCloudLab/frostfs-contract/frostfsid/client"
|
||
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api"
|
||
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/cache"
|
||
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/handler"
|
||
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/internal/frostfs/frostfsid/contract"
|
||
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/internal/logs"
|
||
|
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||
|
"github.com/nspcc-dev/neo-go/pkg/util"
|
||
|
"go.uber.org/zap"
|
||
|
)
|
||
|
|
||
|
type FrostFSID struct {
|
||
|
frostfsid *contract.FrostFSID
|
||
|
cache *cache.FrostfsIDCache
|
||
|
log *zap.Logger
|
||
|
}
|
||
|
|
||
|
type Config struct {
|
||
|
Cache *cache.FrostfsIDCache
|
||
|
FrostFSID *contract.FrostFSID
|
||
|
Logger *zap.Logger
|
||
|
}
|
||
|
|
||
|
var (
|
||
|
_ api.FrostFSID = (*FrostFSID)(nil)
|
||
|
_ handler.FrostFSID = (*FrostFSID)(nil)
|
||
|
)
|
||
|
|
||
|
// NewFrostFSID creates new FrostfsID wrapper.
|
||
|
func NewFrostFSID(cfg Config) (*FrostFSID, error) {
|
||
|
switch {
|
||
|
case cfg.FrostFSID == nil:
|
||
|
return nil, errors.New("missing frostfsid client")
|
||
|
case cfg.Cache == nil:
|
||
|
return nil, errors.New("missing frostfsid cache")
|
||
|
case cfg.Logger == nil:
|
||
|
return nil, errors.New("missing frostfsid logger")
|
||
|
}
|
||
|
|
||
|
return &FrostFSID{
|
||
|
frostfsid: cfg.FrostFSID,
|
||
|
cache: cfg.Cache,
|
||
|
log: cfg.Logger,
|
||
|
}, nil
|
||
|
}
|
||
|
|
||
|
func (f *FrostFSID) ValidatePublicKey(key *keys.PublicKey) error {
|
||
|
_, err := f.getSubject(key.GetScriptHash())
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
func (f *FrostFSID) GetUserGroupIDs(userHash util.Uint160) ([]string, error) {
|
||
|
subj, err := f.getSubject(userHash)
|
||
|
if err != nil {
|
||
|
if strings.Contains(err.Error(), "not found") {
|
||
|
f.log.Debug(logs.UserGroupsListIsEmpty, zap.Error(err))
|
||
|
return nil, nil
|
||
|
}
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
res := make([]string, len(subj.Groups))
|
||
|
for i, group := range subj.Groups {
|
||
|
res[i] = strconv.FormatInt(group.ID, 10)
|
||
|
}
|
||
|
|
||
|
return res, nil
|
||
|
}
|
||
|
|
||
|
func (f *FrostFSID) getSubject(addr util.Uint160) (*client.SubjectExtended, error) {
|
||
|
if subj := f.cache.GetSubject(addr); subj != nil {
|
||
|
return subj, nil
|
||
|
}
|
||
|
|
||
|
subj, err := f.frostfsid.GetSubjectExtended(addr)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
if err = f.cache.PutSubject(addr, subj); err != nil {
|
||
|
f.log.Warn(logs.CouldntCacheSubject, zap.Error(err))
|
||
|
}
|
||
|
|
||
|
return subj, nil
|
||
|
}
|
||
|
|
||
|
func (f *FrostFSID) GetUserAddress(namespace, name string) (string, error) {
|
||
|
userKey, err := f.getUserKey(namespace, name)
|
||
|
if err != nil {
|
||
|
return "", err
|
||
|
}
|
||
|
|
||
|
return userKey.Address(), nil
|
||
|
}
|
||
|
|
||
|
func (f *FrostFSID) GetUserKey(namespace, name string) (string, error) {
|
||
|
userKey, err := f.getUserKey(namespace, name)
|
||
|
if err != nil {
|
||
|
return "", err
|
||
|
}
|
||
|
|
||
|
return hex.EncodeToString(userKey.Bytes()), nil
|
||
|
}
|
||
|
|
||
|
func (f *FrostFSID) getUserKey(namespace, name string) (*keys.PublicKey, error) {
|
||
|
if userKey := f.cache.GetUserKey(namespace, name); userKey != nil {
|
||
|
return userKey, nil
|
||
|
}
|
||
|
|
||
|
userKey, err := f.frostfsid.GetSubjectKeyByName(namespace, name)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
if err = f.cache.PutUserKey(namespace, name, userKey); err != nil {
|
||
|
f.log.Warn(logs.CouldntCacheUserKey, zap.Error(err))
|
||
|
}
|
||
|
|
||
|
return userKey, nil
|
||
|
}
|