Search Apps Documentation Source Content File Folder Download Copy Actions Download

authz_world.gno

3.34 Kb · 120 lines
  1package chunk
  2
  3import (
  4	"chain"
  5	"strconv"
  6
  7	"gno.land/p/akkadia/v0/accesscontrol"
  8	"gno.land/p/akkadia/v0/rbac"
  9	"gno.land/r/akkadia/v0/admin"
 10)
 11
 12const (
 13	GrantMasterEvent  = "GrantMaster"
 14	RevokeMasterEvent = "RevokeMaster"
 15)
 16
 17var (
 18	worldAuthzRBAC = rbac.NewRBAC(32)
 19)
 20
 21func init() {
 22	initWorldAuthzDefinitions()
 23}
 24
 25func initWorldAuthzDefinitions() {
 26	worldAuthzRBAC = rbac.NewRBAC(32)
 27	worldAuthzRBAC.AddRole(rbac.RoleSpec{Name: "master"})
 28}
 29
 30// ==================== Admin Functions ====================
 31
 32// GrantMaster grants master role to a user for a world (admin only)
 33func GrantMaster(cur realm, worldID uint32, user address) {
 34	assertNotFrozen()
 35	accesscontrol.AssertIsAdmin(0, cur, admin.IsAdmin)
 36	worldStore.AssertExists(worldID)
 37
 38	if IsMaster(worldID, user) {
 39		panic("user " + user.String() + " is already a master for world " + strconv.FormatUint(uint64(worldID), 10))
 40	}
 41
 42	worldAuthzRBAC.AssignRole(formatWorldID(worldID), user, "master")
 43
 44	chain.Emit(
 45		GrantMasterEvent,
 46		"worldID", strconv.FormatUint(uint64(worldID), 10),
 47		"user", user.String(),
 48	)
 49}
 50
 51// RevokeMaster revokes master role from a user for a world (admin only)
 52func RevokeMaster(cur realm, worldID uint32, user address) {
 53	assertNotFrozen()
 54	accesscontrol.AssertIsAdmin(0, cur, admin.IsAdmin)
 55	worldStore.AssertExists(worldID)
 56
 57	if !IsMaster(worldID, user) {
 58		panic("user " + user.String() + " is not a master for world " + strconv.FormatUint(uint64(worldID), 10))
 59	}
 60
 61	worldAuthzRBAC.UnassignRole(formatWorldID(worldID), user, "master")
 62
 63	chain.Emit(
 64		RevokeMasterEvent,
 65		"worldID", strconv.FormatUint(uint64(worldID), 10),
 66		"user", user.String(),
 67	)
 68}
 69
 70// ==================== Query Functions ====================
 71
 72// IsMaster checks if a user is a master for a world
 73func IsMaster(worldID uint32, user address) bool {
 74	assertMigrationStateAvailable()
 75	return worldAuthzRBAC.HasUserRole(formatWorldID(worldID), user, "master")
 76}
 77
 78// HasWorldPermission checks if a user has world-level permission.
 79func HasWorldPermission(worldID uint32, user address, _ string) bool {
 80	assertMigrationStateAvailable()
 81	if admin.IsAdmin(user) {
 82		return true
 83	}
 84	return IsMaster(worldID, user)
 85}
 86
 87// ListWorldMasters returns masters for a world by page.
 88func ListWorldMasters(worldID uint32, page int, count int) []address {
 89	assertMigrationStateAvailable()
 90	assertListPageCount(page, count)
 91	return worldAuthzRBAC.ListRoleUsers(formatWorldID(worldID), "master", page, count)
 92}
 93
 94// GetWorldMasterSize returns the number of masters assigned to a world.
 95func GetWorldMasterSize(worldID uint32) int {
 96	assertMigrationStateAvailable()
 97	return worldAuthzRBAC.RoleUserSize(formatWorldID(worldID), "master")
 98}
 99
100// ListMasterWorlds returns worlds where a user is a master by page.
101func ListMasterWorlds(user address, page int, count int) []uint32 {
102	assertMigrationStateAvailable()
103	assertListPageCount(page, count)
104	result := []uint32{}
105	worlds := worldAuthzRBAC.ListEntitiesByUserRole(user, "master", page, count)
106	for _, worldKey := range worlds {
107		worldID, err := strconv.ParseUint(worldKey, 10, 32)
108		if err != nil {
109			panic("invalid master worldID: " + worldKey)
110		}
111		result = append(result, uint32(worldID))
112	}
113	return result
114}
115
116// GetMasterWorldSize returns the number of worlds where user is a master.
117func GetMasterWorldSize(user address) int {
118	assertMigrationStateAvailable()
119	return worldAuthzRBAC.UserRoleEntitySize(user, "master")
120}