Search Apps Documentation Source Content File Folder Download Copy Actions Download

authz_master.gno

2.77 Kb ยท 116 lines
  1package chunk
  2
  3import (
  4	"chain"
  5	"chain/runtime"
  6	"strconv"
  7
  8	"gno.land/p/demo/tokens/grc721"
  9	"gno.land/p/nt/ufmt"
 10)
 11
 12const (
 13	GrantMasterEvent  = "GrantMaster"
 14	RevokeMasterEvent = "RevokeMaster"
 15)
 16
 17var (
 18	// World masters: worldID -> address -> bool
 19	worldMasters = make(map[uint32]map[address]bool)
 20)
 21
 22// ==================== Admin Functions ====================
 23
 24// GrantMaster grants master role to a user for a world (admin only)
 25func GrantMaster(cur realm, worldID uint32, user address) {
 26	caller := runtime.PreviousRealm().Address()
 27	assertIsAdmin(caller)
 28	mustGetWorld(worldID)
 29
 30	if _, found := worldMasters[worldID]; !found {
 31		worldMasters[worldID] = make(map[address]bool)
 32	}
 33
 34	if worldMasters[worldID][user] {
 35		panic("user " + user.String() + " is already a master for world " + ufmt.Sprintf("%d", worldID))
 36	}
 37
 38	worldMasters[worldID][user] = true
 39
 40	chain.Emit(
 41		GrantMasterEvent,
 42		"worldID", ufmt.Sprintf("%d", worldID),
 43		"user", user.String(),
 44	)
 45}
 46
 47// RevokeMaster revokes master role from a user for a world (admin only)
 48func RevokeMaster(cur realm, worldID uint32, user address) {
 49	caller := runtime.PreviousRealm().Address()
 50	assertIsAdmin(caller)
 51
 52	if _, found := worldMasters[worldID]; !found {
 53		panic("user " + user.String() + " is not a master for world " + ufmt.Sprintf("%d", worldID))
 54	}
 55
 56	if !worldMasters[worldID][user] {
 57		panic("user " + user.String() + " is not a master for world " + ufmt.Sprintf("%d", worldID))
 58	}
 59
 60	delete(worldMasters[worldID], user)
 61
 62	// Clean up empty map
 63	if len(worldMasters[worldID]) == 0 {
 64		delete(worldMasters, worldID)
 65	}
 66
 67	chain.Emit(
 68		RevokeMasterEvent,
 69		"worldID", ufmt.Sprintf("%d", worldID),
 70		"user", user.String(),
 71	)
 72}
 73
 74// ==================== Query Functions ====================
 75
 76// IsMaster checks if a user is a master for a world
 77func IsMaster(worldID uint32, user address) bool {
 78	if _, found := worldMasters[worldID]; !found {
 79		return false
 80	}
 81	return worldMasters[worldID][user]
 82}
 83
 84// ListWorldMasters returns all masters for a world
 85func ListWorldMasters(worldID uint32) []address {
 86	result := []address{}
 87	if masters, found := worldMasters[worldID]; found {
 88		for addr := range masters {
 89			result = append(result, addr)
 90		}
 91	}
 92	return result
 93}
 94
 95// ListMasterWorlds returns all worlds where a user is a master
 96func ListMasterWorlds(user address) []uint32 {
 97	result := []uint32{}
 98	for worldID, masters := range worldMasters {
 99		if masters[user] {
100			result = append(result, worldID)
101		}
102	}
103	return result
104}
105
106// ==================== Helper Functions ====================
107
108// getWorldIDFromTokenID extracts worldID from tokenID
109func getWorldIDFromTokenID(tid grc721.TokenID) uint32 {
110	worldIDStr, _ := parseTokenID(tid)
111	worldID, err := strconv.Atoi(worldIDStr)
112	if err != nil {
113		panic("invalid worldID: " + worldIDStr)
114	}
115	return uint32(worldID)
116}