Search Apps Documentation Source Content File Folder Download Copy Actions Download

admin.gno

4.57 Kb · 167 lines
  1package users
  2
  3import (
  4	"chain"
  5	"chain/runtime"
  6
  7	"gno.land/p/moul/addrset"
  8	"gno.land/p/nt/ufmt/v0"
  9
 10	"gno.land/r/gov/dao"
 11)
 12
 13const initControllerPath = "gno.land/r/sys/users/init"
 14
 15var controllers = addrset.Set{} // caller whitelist
 16
 17func init() {
 18	// auto-whitelist the init controller for bootstrapping for testing chain.
 19	if chainID := runtime.ChainID(); chainID == "dev" {
 20		controllers.Add(chain.PackageAddress(initControllerPath))
 21	}
 22}
 23
 24// AddControllerAtGenesis allows adding a controller during chain genesis (height 0).
 25// This is mostly useful for testing.
 26func AddControllerAtGenesis(_ realm, addr address) {
 27	height := runtime.ChainHeight()
 28	if height > 0 {
 29		panic("AddControllerAtGenesis can only be called at genesis (height 0)")
 30	}
 31
 32	if !addr.IsValid() {
 33		panic(ErrInvalidAddress)
 34	}
 35
 36	controllers.Add(addr)
 37}
 38
 39// ProposeNewController allows GovDAO to add a whitelisted caller
 40func ProposeNewController(addr address) dao.ProposalRequest {
 41	if !addr.IsValid() {
 42		panic(ErrInvalidAddress)
 43	}
 44
 45	cb := func(cur realm) error {
 46		return addToWhitelist(addr)
 47	}
 48
 49	desc := "This proposal adds " + addr.String() + " to `sys/users` realm's callers whitelist."
 50	return dao.NewProposalRequest("Add Whitelisted Caller to \"sys/users\" Realm", desc, dao.NewSimpleExecutor(cb, ""))
 51}
 52
 53// ProposeControllerRemoval allows GovDAO to add a whitelisted caller
 54func ProposeControllerRemoval(addr address) dao.ProposalRequest {
 55	if !addr.IsValid() {
 56		panic(ErrInvalidAddress)
 57	}
 58
 59	cb := func(cur realm) error {
 60		return deleteFromWhitelist(addr)
 61	}
 62
 63	desc := "This proposal removes " + addr.String() + " from `sys/users` realm's callers whitelist."
 64	return dao.NewProposalRequest("Remove Whitelisted Caller From \"sys/users\" Realm", desc, dao.NewSimpleExecutor(cb, ""))
 65}
 66
 67// ProposeControllerAdditionAndRemoval allows GovDAO to add a new caller and remove an old caller in the same proposal.
 68func ProposeControllerAdditionAndRemoval(toAdd, toRemove address) dao.ProposalRequest {
 69	if !toAdd.IsValid() || !toRemove.IsValid() {
 70		panic(ErrInvalidAddress)
 71	}
 72
 73	cb := func(cur realm) error {
 74		err := addToWhitelist(toAdd)
 75		if err != nil {
 76			return err
 77		}
 78
 79		return deleteFromWhitelist(toRemove)
 80	}
 81
 82	desc := ufmt.Sprint(
 83		"This proposal adds %s and removes %s from `sys/users` realm's callers whitelist.",
 84		toAdd,
 85		toRemove,
 86	)
 87	return dao.NewProposalRequest("Add and Remove Whitelisted Callers From \"sys/users\" Realm", desc, dao.NewSimpleExecutor(cb, ""))
 88}
 89
 90// ProposeRegisterUser allows GovDAO to register a name without checking controllers
 91func ProposeRegisterUser(name string, addr address) dao.ProposalRequest {
 92	// Validate the name and address now, even though registerUser will validate again
 93	if err := validateName(name); err != nil {
 94		panic(err.Error())
 95	}
 96	if !addr.IsValid() {
 97		panic(ErrInvalidAddress)
 98	}
 99
100	cb := func(cur realm) error {
101		return registerUser(cur, name, addr)
102	}
103
104	desc := "This proposal registers " + name + " with address " + addr.String() + " in `sys/users`."
105	return dao.NewProposalRequest("Register User to \"sys/users\" Realm", desc, dao.NewSimpleExecutor(cb, ""))
106}
107
108// ProposeUpdateName allows GovDAO to update a name with an alias without checking controllers
109func ProposeUpdateName(addr address, newName string) dao.ProposalRequest {
110	if !addr.IsValid() {
111		panic(ErrInvalidAddress)
112	}
113	if err := validateName(newName); err != nil {
114		panic(err.Error())
115	}
116
117	cb := func(cur realm) error {
118		data := ResolveAddress(addr)
119		if data == nil {
120			return ErrUserNotExistOrDeleted
121		}
122		return data.updateName(newName)
123	}
124
125	desc := "This proposal updates address " + addr.String() + " with alias " + newName + " in `sys/users`."
126	return dao.NewProposalRequest("Update Name Alias in \"sys/users\" Realm", desc, dao.NewSimpleExecutor(cb, ""))
127}
128
129// ProposeDeleteUser allows GovDAO to delete a user without checking controllers
130func ProposeDeleteUser(addr address) dao.ProposalRequest {
131	if !addr.IsValid() {
132		panic(ErrInvalidAddress)
133	}
134
135	cb := func(cur realm) error {
136		data := ResolveAddress(addr)
137		if data == nil {
138			return ErrUserNotExistOrDeleted
139		}
140		return data.delete()
141	}
142
143	desc := "This proposal deletes the user with address " + addr.String() + " in `sys/users`."
144	return dao.NewProposalRequest("Delete User in \"sys/users\" Realm", desc, dao.NewSimpleExecutor(cb, ""))
145}
146
147// Helpers
148
149func deleteFromWhitelist(addr address) error {
150	if !controllers.Has(addr) {
151		return NewErrNotWhitelisted()
152	}
153
154	if ok := controllers.Remove(addr); !ok {
155		return ErrWhitelistRemoveFailed
156	}
157
158	return nil
159}
160
161func addToWhitelist(newCaller address) error {
162	if !controllers.Add(newCaller) {
163		return ErrAlreadyWhitelisted
164	}
165
166	return nil
167}