forked from TrueCloudLab/frostfs-contract
[#174] subnet: Add AddUser
method
Signed-off-by: Pavel Karpy <carpawell@nspcc.ru>
This commit is contained in:
parent
cc7d98d45e
commit
9a05e213eb
2 changed files with 82 additions and 3 deletions
|
@ -21,6 +21,8 @@ const (
|
|||
ErrAlreadyExists = "subnet id already exists"
|
||||
// ErrSubNotExist is thrown when id doesn't exist.
|
||||
ErrSubNotExist = "subnet id doesn't exist"
|
||||
// ErrInvalidUser is thrown when user has invalid format.
|
||||
ErrInvalidUser = "invalid user"
|
||||
// ErrInvalidNode is thrown when node has invalid format.
|
||||
ErrInvalidNode = "invalid node key"
|
||||
// ErrNodeAdmNotExist is thrown when node admin is not found.
|
||||
|
@ -34,15 +36,19 @@ const (
|
|||
|
||||
errCheckWitnessFailed = "owner witness check failed"
|
||||
|
||||
ownerPrefix = 'o'
|
||||
nodeAdminPrefix = 'a'
|
||||
infoPrefix = 'i'
|
||||
clientAdminPrefix = 'm'
|
||||
nodePrefix = 'n'
|
||||
user = 'u'
|
||||
infoPrefix = 'i'
|
||||
ownerPrefix = 'o'
|
||||
userPrefix = 'u'
|
||||
notaryDisabledKey = 'z'
|
||||
)
|
||||
|
||||
const (
|
||||
userIDSize = 27
|
||||
)
|
||||
|
||||
// _deploy function sets up initial list of inner ring public keys.
|
||||
func _deploy(data interface{}, isUpdate bool) {
|
||||
if isUpdate {
|
||||
|
@ -391,6 +397,54 @@ func RemoveClientAdmin(subnetID []byte, groupID []byte, adminPublicKey interop.P
|
|||
deleteKeyFromList(ctx, adminPublicKey, stKey)
|
||||
}
|
||||
|
||||
// AddUser adds user to the specified subnetwork and group.
|
||||
// Must be called by the owner or the group's admin only.
|
||||
func AddUser(subnetID []byte, groupID []byte, userID []byte) {
|
||||
if len(userID) != userIDSize {
|
||||
panic("addUser: " + ErrInvalidUser)
|
||||
}
|
||||
|
||||
ctx := storage.GetContext()
|
||||
|
||||
stKey := append([]byte{ownerPrefix}, subnetID...)
|
||||
|
||||
rawOwner := storage.Get(ctx, stKey)
|
||||
if rawOwner == nil {
|
||||
panic("addUser: " + ErrSubNotExist)
|
||||
}
|
||||
|
||||
stKey = append(stKey, groupID...)
|
||||
prefixLen := len(stKey)
|
||||
|
||||
owner := rawOwner.([]byte)
|
||||
if !runtime.CheckWitness(owner) {
|
||||
var hasAccess bool
|
||||
|
||||
stKey[0] = clientAdminPrefix
|
||||
|
||||
iter := storage.Find(ctx, stKey, storage.KeysOnly)
|
||||
for iterator.Next(iter) {
|
||||
key := iterator.Value(iter).([]byte)
|
||||
if runtime.CheckWitness(key[prefixLen:]) {
|
||||
hasAccess = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !hasAccess {
|
||||
panic("addUser: " + ErrAccessDenied)
|
||||
}
|
||||
}
|
||||
|
||||
stKey[0] = userPrefix
|
||||
|
||||
if keyInList(ctx, userID, stKey) {
|
||||
panic("addUser: user has already been added")
|
||||
}
|
||||
|
||||
putKeyInList(ctx, userID, stKey)
|
||||
}
|
||||
|
||||
// Version returns version of the contract.
|
||||
func Version() int {
|
||||
return common.Version
|
||||
|
|
|
@ -233,6 +233,31 @@ func TestSubnet_RemoveClientAdmin(t *testing.T) {
|
|||
cOwn.Invoke(t, stackitem.Null{}, method, id, groupId, admPub)
|
||||
}
|
||||
|
||||
func TestSubnet_AddUser(t *testing.T) {
|
||||
e := newSubnetInvoker(t)
|
||||
|
||||
id, owner := createSubnet(t, e)
|
||||
|
||||
adm := e.NewAccount(t)
|
||||
admPub, ok := vm.ParseSignatureContract(adm.Script())
|
||||
require.True(t, ok)
|
||||
|
||||
user := randomBytes(27)
|
||||
|
||||
groupId := randomBytes(8)
|
||||
|
||||
const method = "addUser"
|
||||
|
||||
cOwn := e.WithSigners(owner)
|
||||
cOwn.InvokeFail(t, method+errSeparator+subnet.ErrSubNotExist, method, []byte{0, 0, 0, 0}, groupId, user)
|
||||
|
||||
cOwn.Invoke(t, stackitem.Null{}, "addClientAdmin", id, groupId, admPub)
|
||||
|
||||
cAdm := e.WithSigners(adm)
|
||||
cAdm.Invoke(t, stackitem.Null{}, method, id, groupId, user)
|
||||
cOwn.InvokeFail(t, method+errSeparator+"user has already been added", method, id, groupId, user)
|
||||
}
|
||||
|
||||
func createSubnet(t *testing.T, e *neotest.ContractInvoker) (id []byte, owner neotest.Signer) {
|
||||
var (
|
||||
ok bool
|
||||
|
|
Loading…
Reference in a new issue