admins.gno
1.93 Kb · 64 lines
1// Package admins lets a fixed set of addresses change a realm's gnotif
2// triggers. The realm passes the handle gnotif.Open returned straight to New,
3// keeps the *Admins unexported, and on each call gives its gnotif identity,
4// minted in the crossing function the admin called.
5package admins
6
7import (
8 "chain/runtime"
9
10 "gno.land/p/g13rqvks880v0hmlfepcj0kkudq0js38d3pc5k6a/gnotif/trigger/v0"
11)
12
13// Handle is the method set of the registry's *Handle.
14type Handle interface {
15 Set(cur realm, name string, t trigger.Trigger) string
16 Remove(cur realm, name string)
17}
18
19// Admins holds a realm's handle and the addresses allowed to use it.
20type Admins struct {
21 h Handle
22 admins map[address]bool
23}
24
25// New returns an Admins over the handle h. It panics with no admin.
26func New(h Handle, addrs ...address) *Admins {
27 if len(addrs) == 0 {
28 panic("at least one admin")
29 }
30 a := &Admins{h: h, admins: make(map[address]bool, len(addrs))}
31 for _, addr := range addrs {
32 if !addr.IsValid() {
33 panic("invalid admin address " + addr.String())
34 }
35 a.admins[addr] = true
36 }
37 return a
38}
39
40// Set stores t under name and returns its id, when the realm's caller is an
41// admin. me is the realm's gnotif identity, cur.Sub(gnotif.Subpath), and its
42// Previous is the caller.
43func (a *Admins) Set(_ int, me realm, name string, t trigger.Trigger) string {
44 a.mustAdmin(0, me)
45 return a.h.Set(cross(me), name, t)
46}
47
48// Remove removes the trigger under name, when the realm's caller is an admin.
49func (a *Admins) Remove(_ int, me realm, name string) {
50 a.mustAdmin(0, me)
51 a.h.Remove(cross(me), name)
52}
53
54func (a *Admins) mustAdmin(_ int, me realm) {
55 if !me.IsCurrent() {
56 panic("me is not current: mint it in the crossing function the admin called")
57 }
58 if _, _, _, isSession := runtime.GetSessionInfo(); isSession {
59 panic("sign with your own key, not a session key")
60 }
61 if caller := me.Previous().Address(); !a.admins[caller] {
62 panic(caller.String() + " is not an admin")
63 }
64}