admin.gno
3.61 Kb · 126 lines
1package namereg
2
3import (
4 "gno.land/p/nt/ufmt/v0"
5 "gno.land/r/gov/dao"
6 susers "gno.land/r/sys/users"
7)
8
9var paused = false // XXX: replace with p/moul/authz
10
11//----------------------------------------
12// Privileged mutators.
13
14func setPaused(cur realm, newPausedValue bool) {
15 paused = newPausedValue
16}
17
18func updateUsername(cur realm, userData *susers.UserData, newName string) error {
19 // UpdateName must be called from this realm.
20 return userData.UpdateName(newName)
21}
22
23func deleteUserdata(cur realm, userData *susers.UserData) error {
24 // Delete must be called from this realm.
25 return userData.Delete()
26}
27
28func setRegisterPrice(cur realm, newPrice int64) {
29 registerPrice = newPrice
30}
31
32//----------------------------------------
33// Public API
34
35// NewSetPausedExecutor allows GovDAO to pause or unpause this realm
36func NewSetPausedExecutor(newPausedValue bool) dao.ProposalRequest {
37 cb := func(cur realm) error {
38 setPaused(cur, newPausedValue)
39 return nil
40 }
41
42 e := dao.NewSimpleExecutor(cb, "")
43
44 if newPausedValue {
45 return dao.NewProposalRequest("User Registry V1: Pause", "", e)
46 }
47
48 return dao.NewProposalRequest("User Registry V1: Unpause", "", e)
49}
50
51// ProposeNewName allows GovDAO to propose a new name for an existing user.
52// The associated address and all previous names of a user that changes a
53// name are preserved, and all resolve to the new name.
54//
55// Governance renames bypass the Open Nym Tier `nym-...\d{3}` format intentionally.
56// The DAO is the trust root for this realm; if voters approve a rename to
57// `vitalik` (e.g. for trademark dispute resolution or system reservations),
58// the validation here imposes no further opinion. The new name is still
59// subject to the base shape enforced by `r/sys/users.validateName`
60// (`^[a-z][a-z0-9]*([_-][a-z0-9]+)*$`, max 64 chars), which runs inside
61// the updateUsername callback below.
62func ProposeNewName(addr address, newName string) dao.ProposalRequest {
63 userData := susers.ResolveAddress(addr)
64 if userData == nil {
65 panic(susers.ErrUserNotExistOrDeleted)
66 }
67
68 cb := func(cur realm) error {
69 err := updateUsername(cur, userData, newName)
70 return err
71 }
72
73 e := dao.NewSimpleExecutor(cb, "")
74
75 return dao.NewProposalRequest(
76 ufmt.Sprintf("User Registry V1: Rename user `%s` to `%s`", userData.Name(), newName),
77 "",
78 e,
79 )
80}
81
82// ProposeDeleteUser allows GovDAO to propose deletion of a user
83// This will make the associated address and names unresolvable.
84// WARN: After deletion, the same address WILL NOT be able to register a new name.
85func ProposeDeleteUser(addr address, reason string) dao.ProposalRequest {
86 userData := susers.ResolveAddress(addr)
87 if userData == nil {
88 panic(susers.ErrUserNotExistOrDeleted)
89 }
90
91 cb := func(cur realm) error {
92 return deleteUserdata(cur, userData)
93 }
94
95 e := dao.NewSimpleExecutor(cb, "")
96
97 return dao.NewProposalRequest(
98 ufmt.Sprintf("User Registry V1: Delete user `%s`", userData.Name()),
99 reason,
100 e,
101 )
102}
103
104// ProposeNewRegisterPrice allows GovDAO to update the price of registration.
105// Rejects prices below MinRegisterPrice (currently 0) at proposal-creation
106// time. (audit finding #14: original code only rejected negative values,
107// which would have been arithmetically nonsensical.)
108func ProposeNewRegisterPrice(newPrice int64) dao.ProposalRequest {
109 if newPrice < MinRegisterPrice {
110 panic(ufmt.Sprintf("price below floor: %d ugnot < %d ugnot (MinRegisterPrice)",
111 newPrice, MinRegisterPrice))
112 }
113
114 cb := func(cur realm) error {
115 setRegisterPrice(cur, newPrice)
116 return nil
117 }
118
119 e := dao.NewSimpleExecutor(cb, "")
120
121 return dao.NewProposalRequest(
122 ufmt.Sprintf("User Registry V1: Update registration price to `%d`", newPrice),
123 "",
124 e,
125 )
126}