From 3d709643d529b4995dbe21263036310ced460463 Mon Sep 17 00:00:00 2001 From: Silas Davis <silas@monax.io> Date: Mon, 8 Jan 2018 17:08:40 +0000 Subject: [PATCH] Permissions: restructed permissions to make global constants accessible without import cycles. Added some support for building permissions from strings (for genesis). Signed-off-by: Silas Davis <silas@monax.io> --- permission/constants.go | 10 + permission/{types => }/errors.go | 21 +- permission/permissions.go | 190 ++++++++++++++++ permission/snatives.go | 88 ++++++++ permission/types/account_permissions.go | 62 ++++++ permission/types/base_permissions.go | 86 ++++++++ permission/types/permissions.go | 277 ------------------------ permission/types/snatives.go | 120 ---------- permission/{types => }/util.go | 26 ++- permission/util_test.go | 16 ++ 10 files changed, 475 insertions(+), 421 deletions(-) create mode 100644 permission/constants.go rename permission/{types => }/errors.go (61%) create mode 100644 permission/permissions.go create mode 100644 permission/snatives.go create mode 100644 permission/types/account_permissions.go create mode 100644 permission/types/base_permissions.go delete mode 100644 permission/types/permissions.go delete mode 100644 permission/types/snatives.go rename permission/{types => }/util.go (75%) create mode 100644 permission/util_test.go diff --git a/permission/constants.go b/permission/constants.go new file mode 100644 index 00000000..c795fda0 --- /dev/null +++ b/permission/constants.go @@ -0,0 +1,10 @@ +package permission + +import ( + "github.com/hyperledger/burrow/account" + "github.com/hyperledger/burrow/binary" +) + +var ( + GlobalPermissionsAddress = account.Address(binary.Zero160) +) diff --git a/permission/types/errors.go b/permission/errors.go similarity index 61% rename from permission/types/errors.go rename to permission/errors.go index fe023ca8..795b621c 100644 --- a/permission/types/errors.go +++ b/permission/errors.go @@ -12,26 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package types - -import ( - "fmt" -) +package permission //------------------------------------------------------------------------------------------------ // Some errors - -// permission number out of bounds -type ErrInvalidPermission PermFlag - -func (e ErrInvalidPermission) Error() string { - return fmt.Sprintf("invalid permission %d", e) -} - -// set=false. This error should be caught and the global -// value fetched for the permission by the caller -type ErrValueNotSet PermFlag - -func (e ErrValueNotSet) Error() string { - return fmt.Sprintf("the value for permission %d is not set", e) -} diff --git a/permission/permissions.go b/permission/permissions.go new file mode 100644 index 00000000..599be2bf --- /dev/null +++ b/permission/permissions.go @@ -0,0 +1,190 @@ +// Copyright 2017 Monax Industries Limited +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package permission + +import ( + "fmt" + "strings" + + acm "github.com/hyperledger/burrow/account" + "github.com/hyperledger/burrow/permission/types" +) + +//------------------------------------------------------------------------------------------------ + +// Base permission references are like unix (the index is already bit shifted) +const ( + // chain permissions + Root types.PermFlag = 1 << iota // 1 + Send // 2 + Call // 4 + CreateContract // 8 + CreateAccount // 16 + Bond // 32 + Name // 64 + + // moderator permissions + HasBase + SetBase + UnsetBase + SetGlobal + HasRole + AddRole + RemoveRole + + NumPermissions uint = 14 // NOTE Adjust this too. We can support upto 64 + + TopPermFlag types.PermFlag = 1 << (NumPermissions - 1) + AllPermFlags types.PermFlag = TopPermFlag | (TopPermFlag - 1) + DefaultPermFlags types.PermFlag = Send | Call | CreateContract | CreateAccount | Bond | Name | HasBase | HasRole + + RootString string = "root" + SendString = "send" + CallString = "call" + CreateContractString = "createContract" + CreateAccountString = "createAccount" + BondString = "bond" + NameString = "name" + + // moderator permissions + HasBaseString = "hasBase" + SetBaseString = "setBase" + UnsetBaseString = "unsetBase" + SetGlobalString = "setGlobal" + HasRoleString = "hasRole" + AddRoleString = "addRole" + RemoveRoleString = "removeRole" + UnknownString = "#-UNKNOWN-#" + + AllString = "all" +) + +var ( + ZeroBasePermissions = types.BasePermissions{0, 0} + ZeroAccountPermissions = types.AccountPermissions{ + Base: ZeroBasePermissions, + } + DefaultAccountPermissions = types.AccountPermissions{ + Base: types.BasePermissions{ + Perms: DefaultPermFlags, + SetBit: AllPermFlags, + }, + Roles: []string{}, + } + AllAccountPermissions = types.AccountPermissions{ + Base: types.BasePermissions{ + Perms: AllPermFlags, + SetBit: AllPermFlags, + }, + Roles: []string{}, + } +) + +//--------------------------------------------------------------------------------------------- + +//-------------------------------------------------------------------------------- +// string utilities + +// PermFlagToString assumes the permFlag is valid, else returns "#-UNKNOWN-#" +func PermFlagToString(pf types.PermFlag) (perm string) { + switch pf { + case AllPermFlags: + perm = AllString + case Root: + perm = RootString + case Send: + perm = SendString + case Call: + perm = CallString + case CreateContract: + perm = CreateContractString + case CreateAccount: + perm = CreateAccountString + case Bond: + perm = BondString + case Name: + perm = NameString + case HasBase: + perm = HasBaseString + case SetBase: + perm = SetBaseString + case UnsetBase: + perm = UnsetBaseString + case SetGlobal: + perm = SetGlobalString + case HasRole: + perm = HasRoleString + case AddRole: + perm = AddRoleString + case RemoveRole: + perm = RemoveRoleString + default: + perm = UnknownString + } + return +} + +// PermStringToFlag maps camel- and snake case strings to the +// the corresponding permission flag. +func PermStringToFlag(perm string) (pf types.PermFlag, err error) { + switch strings.ToLower(perm) { + case AllString: + pf = AllPermFlags + case RootString: + pf = Root + case SendString: + pf = Send + case CallString: + pf = Call + case CreateContractString, "createcontract", "create_contract": + pf = CreateContract + case CreateAccountString, "createaccount", "create_account": + pf = CreateAccount + case BondString: + pf = Bond + case NameString: + pf = Name + case HasBaseString, "hasbase", "has_base": + pf = HasBase + case SetBaseString, "setbase", "set_base": + pf = SetBase + case UnsetBaseString, "unsetbase", "unset_base": + pf = UnsetBase + case SetGlobalString, "setglobal", "set_global": + pf = SetGlobal + case HasRoleString, "hasrole", "has_role": + pf = HasRole + case AddRoleString, "addrole", "add_role": + pf = AddRole + case RemoveRoleString, "removerole", "rmrole", "rm_role": + pf = RemoveRole + default: + err = fmt.Errorf("unknown permission %s", perm) + } + return +} + +func GlobalPermissionsAccount(state acm.Getter) acm.Account { + acc, err := state.GetAccount(GlobalPermissionsAddress) + if err != nil { + panic("Could not get global permission account, but this must exist") + } + return acc +} + +// Get global permissions from the account at GlobalPermissionsAddress +func GlobalAccountPermissions(state acm.Getter) types.AccountPermissions { + return GlobalPermissionsAccount(state).Permissions() +} diff --git a/permission/snatives.go b/permission/snatives.go new file mode 100644 index 00000000..53fa0eea --- /dev/null +++ b/permission/snatives.go @@ -0,0 +1,88 @@ +// Copyright 2017 Monax Industries Limited +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package permission + +import ( + acm "github.com/hyperledger/burrow/account" + "github.com/hyperledger/burrow/permission/types" +) + +//--------------------------------------------------------------------------------------------------- +// PermissionsTx.PermArgs interface and argument encoding + +type PermArgs struct { + PermFlag types.PermFlag + Address acm.Address `json:",omitempty"` + Permission types.PermFlag `json:",omitempty"` + Role string `json:",omitempty"` + Value bool `json:",omitempty"` +} + +func HasBaseArgs(address acm.Address, permission types.PermFlag) *PermArgs { + return &PermArgs{ + PermFlag: HasBase, + Address: address, + Permission: permission, + } +} + +func SetBaseArgs(address acm.Address, permission types.PermFlag, value bool) *PermArgs { + return &PermArgs{ + PermFlag: SetBase, + Address: address, + Permission: permission, + Value: value, + } +} + +func UnsetBaseArgs(address acm.Address, permission types.PermFlag) *PermArgs { + return &PermArgs{ + PermFlag: UnsetBase, + Address: address, + Permission: permission, + } +} + +func SetGlobalArgs(permission types.PermFlag, value bool) *PermArgs { + return &PermArgs{ + PermFlag: SetGlobal, + Permission: permission, + Value: value, + } +} + +func HasRoleArgs(address acm.Address, role string) *PermArgs { + return &PermArgs{ + PermFlag: HasRole, + Address: address, + Role: role, + } +} + +func AddRoleArgs(address acm.Address, role string) *PermArgs { + return &PermArgs{ + PermFlag: AddRole, + Address: address, + Role: role, + } +} + +func RemoveRoleArgs(address acm.Address, role string) *PermArgs { + return &PermArgs{ + PermFlag: RemoveRole, + Address: address, + Role: role, + } +} diff --git a/permission/types/account_permissions.go b/permission/types/account_permissions.go new file mode 100644 index 00000000..91bee5f8 --- /dev/null +++ b/permission/types/account_permissions.go @@ -0,0 +1,62 @@ +package types + +import "github.com/hyperledger/burrow/binary" + +type AccountPermissions struct { + Base BasePermissions + Roles []string +} + +// Returns true if the role is found +func (ap AccountPermissions) HasRole(role string) bool { + role = string(binary.RightPadBytes([]byte(role), 32)) + for _, r := range ap.Roles { + if r == role { + return true + } + } + return false +} + +// Returns true if the role is added, and false if it already exists +func (ap *AccountPermissions) AddRole(role string) bool { + role = string(binary.RightPadBytes([]byte(role), 32)) + for _, r := range ap.Roles { + if r == role { + return false + } + } + ap.Roles = append(ap.Roles, role) + return true +} + +// Returns true if the role is removed, and false if it is not found +func (ap *AccountPermissions) RmRole(role string) bool { + role = string(binary.RightPadBytes([]byte(role), 32)) + for i, r := range ap.Roles { + if r == role { + post := []string{} + if len(ap.Roles) > i+1 { + post = ap.Roles[i+1:] + } + ap.Roles = append(ap.Roles[:i], post...) + return true + } + } + return false +} + +// Clone clones the account permissions +func (ap *AccountPermissions) Clone() AccountPermissions { + // clone base permissions + basePermissionsClone := ap.Base + // clone roles []string + rolesClone := make([]string, len(ap.Roles)) + // strings are immutable so copy suffices + copy(rolesClone, ap.Roles) + + return AccountPermissions{ + Base: basePermissionsClone, + Roles: rolesClone, + } +} diff --git a/permission/types/base_permissions.go b/permission/types/base_permissions.go new file mode 100644 index 00000000..bc9d7039 --- /dev/null +++ b/permission/types/base_permissions.go @@ -0,0 +1,86 @@ +package types + +import "fmt" + +// A particular permission +type PermFlag uint64 + +// permission number out of bounds +type ErrInvalidPermission PermFlag + +func (e ErrInvalidPermission) Error() string { + return fmt.Sprintf("invalid permission %d", e) +} + +// set=false. This error should be caught and the global +// value fetched for the permission by the caller +type ErrValueNotSet PermFlag + +func (e ErrValueNotSet) Error() string { + return fmt.Sprintf("the value for permission %d is not set", e) +} + +// Base chain permissions struct +type BasePermissions struct { + // bit array with "has"/"doesn't have" for each permission + Perms PermFlag + + // bit array with "set"/"not set" for each permission (not-set should fall back to global) + SetBit PermFlag +} + +// Get a permission value. ty should be a power of 2. +// ErrValueNotSet is returned if the permission's set bit is off, +// and should be caught by caller so the global permission can be fetched +func (p BasePermissions) Get(ty PermFlag) (bool, error) { + if ty == 0 { + return false, ErrInvalidPermission(ty) + } + if p.SetBit&ty == 0 { + return false, ErrValueNotSet(ty) + } + return p.Perms&ty > 0, nil +} + +// Set a permission bit. Will set the permission's set bit to true. +func (p *BasePermissions) Set(ty PermFlag, value bool) error { + if ty == 0 { + return ErrInvalidPermission(ty) + } + p.SetBit |= ty + if value { + p.Perms |= ty + } else { + p.Perms &= ^ty + } + return nil +} + +// Set the permission's set bit to false +func (p *BasePermissions) Unset(ty PermFlag) error { + if ty == 0 { + return ErrInvalidPermission(ty) + } + p.SetBit &= ^ty + return nil +} + +// Check if the permission is set +func (p BasePermissions) IsSet(ty PermFlag) bool { + if ty == 0 { + return false + } + return p.SetBit&ty > 0 +} + +// Returns the Perms PermFlag masked with SetBit bit field to give the resultant +// permissions enabled by this BasePermissions +func (p BasePermissions) ResultantPerms() PermFlag { + return p.Perms & p.SetBit +} + +func (p BasePermissions) String() string { + return fmt.Sprintf("Base: %b; Set: %b", p.Perms, p.SetBit) +} + +//--------------------------------------------------------------------------------------------- diff --git a/permission/types/permissions.go b/permission/types/permissions.go deleted file mode 100644 index c414a85d..00000000 --- a/permission/types/permissions.go +++ /dev/null @@ -1,277 +0,0 @@ -// Copyright 2017 Monax Industries Limited -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package types - -import ( - "fmt" - "strings" - - "github.com/hyperledger/burrow/word256" -) - -//------------------------------------------------------------------------------------------------ - -var ( - GlobalPermissionsAddress = word256.Zero256[:20] - GlobalPermissionsAddress256 = word256.Zero256 -) - -// A particular permission -type PermFlag uint64 - -// Base permission references are like unix (the index is already bit shifted) -const ( - // chain permissions - Root PermFlag = 1 << iota // 1 - Send // 2 - Call // 4 - CreateContract // 8 - CreateAccount // 16 - Bond // 32 - Name // 64 - - // moderator permissions - HasBase - SetBase - UnsetBase - SetGlobal - HasRole - AddRole - RmRole - - NumPermissions uint = 14 // NOTE Adjust this too. We can support upto 64 - - TopPermFlag PermFlag = 1 << (NumPermissions - 1) - AllPermFlags PermFlag = TopPermFlag | (TopPermFlag - 1) - DefaultPermFlags PermFlag = Send | Call | CreateContract | CreateAccount | Bond | Name | HasBase | HasRole -) - -var ( - ZeroBasePermissions = BasePermissions{0, 0} - ZeroAccountPermissions = AccountPermissions{ - Base: ZeroBasePermissions, - } - DefaultAccountPermissions = AccountPermissions{ - Base: BasePermissions{ - Perms: DefaultPermFlags, - SetBit: AllPermFlags, - }, - Roles: []string{}, - } -) - -//--------------------------------------------------------------------------------------------- - -// Base chain permissions struct -type BasePermissions struct { - // bit array with "has"/"doesn't have" for each permission - Perms PermFlag `json:"perms"` - - // bit array with "set"/"not set" for each permission (not-set should fall back to global) - SetBit PermFlag `json:"set"` -} - -// Get a permission value. ty should be a power of 2. -// ErrValueNotSet is returned if the permission's set bit is off, -// and should be caught by caller so the global permission can be fetched -func (p *BasePermissions) Get(ty PermFlag) (bool, error) { - if ty == 0 { - return false, ErrInvalidPermission(ty) - } - if p.SetBit&ty == 0 { - return false, ErrValueNotSet(ty) - } - return p.Perms&ty > 0, nil -} - -// Set a permission bit. Will set the permission's set bit to true. -func (p *BasePermissions) Set(ty PermFlag, value bool) error { - if ty == 0 { - return ErrInvalidPermission(ty) - } - p.SetBit |= ty - if value { - p.Perms |= ty - } else { - p.Perms &= ^ty - } - return nil -} - -// Set the permission's set bit to false -func (p *BasePermissions) Unset(ty PermFlag) error { - if ty == 0 { - return ErrInvalidPermission(ty) - } - p.SetBit &= ^ty - return nil -} - -// Check if the permission is set -func (p *BasePermissions) IsSet(ty PermFlag) bool { - if ty == 0 { - return false - } - return p.SetBit&ty > 0 -} - -// Returns the Perms PermFlag masked with SetBit bit field to give the resultant -// permissions enabled by this BasePermissions -func (p *BasePermissions) ResultantPerms() PermFlag { - return p.Perms & p.SetBit -} - -func (p BasePermissions) String() string { - return fmt.Sprintf("Base: %b; Set: %b", p.Perms, p.SetBit) -} - -//--------------------------------------------------------------------------------------------- - -type AccountPermissions struct { - Base BasePermissions `json:"base"` - Roles []string `json:"roles"` -} - -// Returns true if the role is found -func (aP *AccountPermissions) HasRole(role string) bool { - role = string(word256.RightPadBytes([]byte(role), 32)) - for _, r := range aP.Roles { - if r == role { - return true - } - } - return false -} - -// Returns true if the role is added, and false if it already exists -func (aP *AccountPermissions) AddRole(role string) bool { - role = string(word256.RightPadBytes([]byte(role), 32)) - for _, r := range aP.Roles { - if r == role { - return false - } - } - aP.Roles = append(aP.Roles, role) - return true -} - -// Returns true if the role is removed, and false if it is not found -func (aP *AccountPermissions) RmRole(role string) bool { - role = string(word256.RightPadBytes([]byte(role), 32)) - for i, r := range aP.Roles { - if r == role { - post := []string{} - if len(aP.Roles) > i+1 { - post = aP.Roles[i+1:] - } - aP.Roles = append(aP.Roles[:i], post...) - return true - } - } - return false -} - -// Clone clones the account permissions -func (accountPermissions *AccountPermissions) Clone() AccountPermissions { - // clone base permissions - basePermissionsClone := accountPermissions.Base - // clone roles []string - rolesClone := make([]string, len(accountPermissions.Roles)) - // strings are immutable so copy suffices - copy(rolesClone, accountPermissions.Roles) - - return AccountPermissions{ - Base: basePermissionsClone, - Roles: rolesClone, - } -} - -//-------------------------------------------------------------------------------- -// string utilities - -// PermFlagToString assumes the permFlag is valid, else returns "#-UNKNOWN-#" -func PermFlagToString(pf PermFlag) (perm string) { - switch pf { - case Root: - perm = "root" - case Send: - perm = "send" - case Call: - perm = "call" - case CreateContract: - perm = "create_contract" - case CreateAccount: - perm = "create_account" - case Bond: - perm = "bond" - case Name: - perm = "name" - case HasBase: - perm = "hasBase" - case SetBase: - perm = "setBase" - case UnsetBase: - perm = "unsetBase" - case SetGlobal: - perm = "setGlobal" - case HasRole: - perm = "hasRole" - case AddRole: - perm = "addRole" - case RmRole: - perm = "removeRole" - default: - perm = "#-UNKNOWN-#" - } - return -} - -// PermStringToFlag maps camel- and snake case strings to the -// the corresponding permission flag. -func PermStringToFlag(perm string) (pf PermFlag, err error) { - switch strings.ToLower(perm) { - case "root": - pf = Root - case "send": - pf = Send - case "call": - pf = Call - case "createcontract", "create_contract": - pf = CreateContract - case "createaccount", "create_account": - pf = CreateAccount - case "bond": - pf = Bond - case "name": - pf = Name - case "hasbase", "has_base": - pf = HasBase - case "setbase", "set_base": - pf = SetBase - case "unsetbase", "unset_base": - pf = UnsetBase - case "setglobal", "set_global": - pf = SetGlobal - case "hasrole", "has_role": - pf = HasRole - case "addrole", "add_role": - pf = AddRole - case "removerole", "rmrole", "rm_role": - pf = RmRole - default: - err = fmt.Errorf("Unknown permission %s", perm) - } - return -} diff --git a/permission/types/snatives.go b/permission/types/snatives.go deleted file mode 100644 index f7fe543a..00000000 --- a/permission/types/snatives.go +++ /dev/null @@ -1,120 +0,0 @@ -// Copyright 2017 Monax Industries Limited -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package types - -import ( - "github.com/tendermint/go-wire" -) - -//--------------------------------------------------------------------------------------------------- -// PermissionsTx.PermArgs interface and argument encoding - -// Arguments are a registered interface in the PermissionsTx, -// so binary handles the arguments and each permission function gets a type-byte -// PermFlag() maps the type-byte to the permission -// The account sending the PermissionsTx must have this PermFlag set -type PermArgs interface { - PermFlag() PermFlag -} - -const ( - PermArgsTypeHasBase = byte(0x01) - PermArgsTypeSetBase = byte(0x02) - PermArgsTypeUnsetBase = byte(0x03) - PermArgsTypeSetGlobal = byte(0x04) - PermArgsTypeHasRole = byte(0x05) - PermArgsTypeAddRole = byte(0x06) - PermArgsTypeRmRole = byte(0x07) -) - -// TODO: [ben] this registration needs to be lifted up -// and centralised in core; here it pulls in go-wire dependency -// while it suffices to have the type bytes defined; -// --- -// for wire.readReflect -var _ = wire.RegisterInterface( - struct{ PermArgs }{}, - wire.ConcreteType{&HasBaseArgs{}, PermArgsTypeHasBase}, - wire.ConcreteType{&SetBaseArgs{}, PermArgsTypeSetBase}, - wire.ConcreteType{&UnsetBaseArgs{}, PermArgsTypeUnsetBase}, - wire.ConcreteType{&SetGlobalArgs{}, PermArgsTypeSetGlobal}, - wire.ConcreteType{&HasRoleArgs{}, PermArgsTypeHasRole}, - wire.ConcreteType{&AddRoleArgs{}, PermArgsTypeAddRole}, - wire.ConcreteType{&RmRoleArgs{}, PermArgsTypeRmRole}, -) - -type HasBaseArgs struct { - Address []byte `json:"address"` - Permission PermFlag `json:"permission"` -} - -func (*HasBaseArgs) PermFlag() PermFlag { - return HasBase -} - -type SetBaseArgs struct { - Address []byte `json:"address"` - Permission PermFlag `json:"permission"` - Value bool `json:"value"` -} - -func (*SetBaseArgs) PermFlag() PermFlag { - return SetBase -} - -type UnsetBaseArgs struct { - Address []byte `json:"address"` - Permission PermFlag `json:"permission"` -} - -func (*UnsetBaseArgs) PermFlag() PermFlag { - return UnsetBase -} - -type SetGlobalArgs struct { - Permission PermFlag `json:"permission"` - Value bool `json:"value"` -} - -func (*SetGlobalArgs) PermFlag() PermFlag { - return SetGlobal -} - -type HasRoleArgs struct { - Address []byte `json:"address"` - Role string `json:"role"` -} - -func (*HasRoleArgs) PermFlag() PermFlag { - return HasRole -} - -type AddRoleArgs struct { - Address []byte `json:"address"` - Role string `json:"role"` -} - -func (*AddRoleArgs) PermFlag() PermFlag { - return AddRole -} - -type RmRoleArgs struct { - Address []byte `json:"address"` - Role string `json:"role"` -} - -func (*RmRoleArgs) PermFlag() PermFlag { - return RmRole -} diff --git a/permission/types/util.go b/permission/util.go similarity index 75% rename from permission/types/util.go rename to permission/util.go index c7ceae90..7942eb92 100644 --- a/permission/types/util.go +++ b/permission/util.go @@ -12,16 +12,19 @@ // See the License for the specific language governing permissions and // limitations under the License. -package types +package permission + +import "github.com/hyperledger/burrow/permission/types" // ConvertMapStringIntToPermissions converts a map of string-bool pairs and a slice of // strings for the roles to an AccountPermissions type. If the value in the // permissions map is true for a particular permission string then the permission // will be set in the AccountsPermissions. For all unmentioned permissions the // ZeroBasePermissions is defaulted to. -func ConvertPermissionsMapAndRolesToAccountPermissions(permissions map[string]bool, roles []string) (*AccountPermissions, error) { +func ConvertPermissionsMapAndRolesToAccountPermissions(permissions map[string]bool, + roles []string) (*types.AccountPermissions, error) { var err error - accountPermissions := &AccountPermissions{} + accountPermissions := &types.AccountPermissions{} accountPermissions.Base, err = convertPermissionsMapStringIntToBasePermissions(permissions) if err != nil { return nil, err @@ -32,7 +35,7 @@ func ConvertPermissionsMapAndRolesToAccountPermissions(permissions map[string]bo // convertPermissionsMapStringIntToBasePermissions converts a map of string-bool // pairs to BasePermissions. -func convertPermissionsMapStringIntToBasePermissions(permissions map[string]bool) (BasePermissions, error) { +func convertPermissionsMapStringIntToBasePermissions(permissions map[string]bool) (types.BasePermissions, error) { // initialise basePermissions as ZeroBasePermissions basePermissions := ZeroBasePermissions @@ -47,3 +50,18 @@ func convertPermissionsMapStringIntToBasePermissions(permissions map[string]bool return basePermissions, nil } + +func BasePermissionsFromStringList(permissions []string) (types.BasePermissions, error) { + var permFlag types.PermFlag + for _, perm := range permissions { + flag, err := PermStringToFlag(perm) + if err != nil { + return ZeroBasePermissions, err + } + permFlag |= flag + } + return types.BasePermissions{ + Perms: permFlag, + SetBit: permFlag, + }, nil +} diff --git a/permission/util_test.go b/permission/util_test.go new file mode 100644 index 00000000..54dad954 --- /dev/null +++ b/permission/util_test.go @@ -0,0 +1,16 @@ +package permission + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestBasePermissionsFromStringList(t *testing.T) { + basePerms, err := BasePermissionsFromStringList([]string{HasRoleString, CreateContractString, SendString}) + require.NoError(t, err) + permFlag := HasRole | CreateContract | Send + assert.Equal(t, permFlag, basePerms.Perms) + assert.Equal(t, permFlag, basePerms.SetBit) +} -- GitLab