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}