You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

238 lines
5.3 KiB

10 years ago
10 years ago
  1. package types
  2. import (
  3. "fmt"
  4. . "github.com/tendermint/tendermint/common"
  5. )
  6. //------------------------------------------------------------------------------------------------
  7. var (
  8. GlobalPermissionsAddress = Zero256[:20]
  9. GlobalPermissionsAddress256 = Zero256
  10. )
  11. // A particular permission
  12. type PermFlag uint64
  13. // Base permission references are like unix (the index is already bit shifted)
  14. const (
  15. // chain permissions
  16. Root PermFlag = 1 << iota // 1
  17. Send // 2
  18. Call // 4
  19. CreateContract // 8
  20. CreateAccount // 16
  21. Bond // 32
  22. Name // 64
  23. // moderator permissions
  24. HasBase
  25. SetBase
  26. UnsetBase
  27. SetGlobal
  28. HasRole
  29. AddRole
  30. RmRole
  31. NumPermissions uint = 14 // NOTE Adjust this too. We can support upto 64
  32. TopPermFlag PermFlag = 1 << (NumPermissions - 1)
  33. AllPermFlags PermFlag = TopPermFlag | (TopPermFlag - 1)
  34. DefaultPermFlags PermFlag = Send | Call | CreateContract | CreateAccount | Bond | Name | HasBase | HasRole
  35. )
  36. var (
  37. ZeroBasePermissions = BasePermissions{0, 0}
  38. ZeroAccountPermissions = AccountPermissions{
  39. Base: ZeroBasePermissions,
  40. }
  41. DefaultAccountPermissions = AccountPermissions{
  42. Base: BasePermissions{
  43. Perms: DefaultPermFlags,
  44. SetBit: AllPermFlags,
  45. },
  46. Roles: []string{},
  47. }
  48. )
  49. //---------------------------------------------------------------------------------------------
  50. // Base chain permissions struct
  51. type BasePermissions struct {
  52. // bit array with "has"/"doesn't have" for each permission
  53. Perms PermFlag `json:"perms"`
  54. // bit array with "set"/"not set" for each permission (not-set should fall back to global)
  55. SetBit PermFlag `json:"set"`
  56. }
  57. // Get a permission value. ty should be a power of 2.
  58. // ErrValueNotSet is returned if the permission's set bit is off,
  59. // and should be caught by caller so the global permission can be fetched
  60. func (p *BasePermissions) Get(ty PermFlag) (bool, error) {
  61. if ty == 0 {
  62. return false, ErrInvalidPermission(ty)
  63. }
  64. if p.SetBit&ty == 0 {
  65. return false, ErrValueNotSet(ty)
  66. }
  67. return p.Perms&ty > 0, nil
  68. }
  69. // Set a permission bit. Will set the permission's set bit to true.
  70. func (p *BasePermissions) Set(ty PermFlag, value bool) error {
  71. if ty == 0 {
  72. return ErrInvalidPermission(ty)
  73. }
  74. p.SetBit |= ty
  75. if value {
  76. p.Perms |= ty
  77. } else {
  78. p.Perms &= ^ty
  79. }
  80. return nil
  81. }
  82. // Set the permission's set bit to false
  83. func (p *BasePermissions) Unset(ty PermFlag) error {
  84. if ty == 0 {
  85. return ErrInvalidPermission(ty)
  86. }
  87. p.SetBit &= ^ty
  88. return nil
  89. }
  90. // Check if the permission is set
  91. func (p *BasePermissions) IsSet(ty PermFlag) bool {
  92. if ty == 0 {
  93. return false
  94. }
  95. return p.SetBit&ty > 0
  96. }
  97. func (p BasePermissions) String() string {
  98. return fmt.Sprintf("Base: %b; Set: %b", p.Perms, p.SetBit)
  99. }
  100. //---------------------------------------------------------------------------------------------
  101. type AccountPermissions struct {
  102. Base BasePermissions `json:"base"`
  103. Roles []string `json:"roles"`
  104. }
  105. // Returns true if the role is found
  106. func (aP *AccountPermissions) HasRole(role string) bool {
  107. role = string(LeftPadBytes([]byte(role), 32))
  108. for _, r := range aP.Roles {
  109. if r == role {
  110. return true
  111. }
  112. }
  113. return false
  114. }
  115. // Returns true if the role is added, and false if it already exists
  116. func (aP *AccountPermissions) AddRole(role string) bool {
  117. role = string(LeftPadBytes([]byte(role), 32))
  118. for _, r := range aP.Roles {
  119. if r == role {
  120. return false
  121. }
  122. }
  123. aP.Roles = append(aP.Roles, role)
  124. return true
  125. }
  126. // Returns true if the role is removed, and false if it is not found
  127. func (aP *AccountPermissions) RmRole(role string) bool {
  128. role = string(LeftPadBytes([]byte(role), 32))
  129. for i, r := range aP.Roles {
  130. if r == role {
  131. post := []string{}
  132. if len(aP.Roles) > i+1 {
  133. post = aP.Roles[i+1:]
  134. }
  135. aP.Roles = append(aP.Roles[:i], post...)
  136. return true
  137. }
  138. }
  139. return false
  140. }
  141. //--------------------------------------------------------------------------------
  142. // string utilities
  143. // PermFlagToString assumes the permFlag is valid, else returns "#-UNKNOWN-#"
  144. func PermFlagToString(pf PermFlag) (perm string) {
  145. switch pf {
  146. case Root:
  147. perm = "root"
  148. case Send:
  149. perm = "send"
  150. case Call:
  151. perm = "call"
  152. case CreateContract:
  153. perm = "create_contract"
  154. case CreateAccount:
  155. perm = "create_account"
  156. case Bond:
  157. perm = "bond"
  158. case Name:
  159. perm = "name"
  160. case HasBase:
  161. perm = "has_base"
  162. case SetBase:
  163. perm = "set_base"
  164. case UnsetBase:
  165. perm = "unset_base"
  166. case SetGlobal:
  167. perm = "set_global"
  168. case HasRole:
  169. perm = "has_role"
  170. case AddRole:
  171. perm = "add_role"
  172. case RmRole:
  173. perm = "rm_role"
  174. default:
  175. perm = "#-UNKNOWN-#"
  176. }
  177. return
  178. }
  179. func PermStringToFlag(perm string) (pf PermFlag, err error) {
  180. switch perm {
  181. case "root":
  182. pf = Root
  183. case "send":
  184. pf = Send
  185. case "call":
  186. pf = Call
  187. case "create_contract":
  188. pf = CreateContract
  189. case "create_account":
  190. pf = CreateAccount
  191. case "bond":
  192. pf = Bond
  193. case "name":
  194. pf = Name
  195. case "has_base":
  196. pf = HasBase
  197. case "set_base":
  198. pf = SetBase
  199. case "unset_base":
  200. pf = UnsetBase
  201. case "set_global":
  202. pf = SetGlobal
  203. case "has_role":
  204. pf = HasRole
  205. case "add_role":
  206. pf = AddRole
  207. case "rm_role":
  208. pf = RmRole
  209. default:
  210. err = fmt.Errorf("Unknown permission %s", perm)
  211. }
  212. return
  213. }