1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
|
-- vim: ft=terra
local pstr = lib.mem.ptr(int8)
local pref = lib.mem.ref(int8)
local terra cs(s: rawstring)
return pstr { ptr = s, ct = lib.str.sz(s) }
end
local terra
render_conf_users(co: &lib.srv.convo, path: lib.mem.ptr(pref)): pstr
if path.ct == 2 then
var uid, ok = lib.math.shorthand.parse(path(1).ptr,path(1).ct)
var user = co.srv:actor_fetch_uid(uid)
if not user then goto e404 end
var islinkct = false
var cinp: lib.str.acc
var clnk: lib.str.acc clnk:compose('<hr>')
var cinpp = cinp:finalize() defer cinpp:free()
var clnkp: pstr
if islinkct then clnkp = clnk:finalize() else
clnk:free()
clnkp = pstr { ptr='', ct=0 }
end
var pg = data.view.conf_user_ctl {
name = cs(user(0).handle);
inputcontent = cinpp;
linkcontent = clnkp;
}
var ret = pg:tostr()
if islinkct then clnkp:free() end
return ret
else
end
do return pstr.null() end
::e404:: co:complain(404, 'not found', 'there is no user or resource by that identifier on this server')
do return pstr.null() end
end
return render_conf_users
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
<
>
>
<
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
|
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
|
-- vim: ft=terra
local pstr = lib.mem.ptr(int8)
local pref = lib.mem.ref(int8)
local P = lib.str.plit
local terra cs(s: rawstring)
return pstr { ptr = s, ct = lib.str.sz(s) }
end
local terra
regalia(acc: &lib.str.acc, rank: uint16)
switch rank do -- TODO customizability
case [uint16](1) then acc:lpush('๐') end
case [uint16](2) then acc:lpush('๐ฑ') end
case [uint16](3) then acc:lpush('โ๏ธ') end
case [uint16](4) then acc:lpush('๐ก') end
case [uint16](5) then acc:lpush('๐') end
else acc:lpush('๐ด')
end
end
local num_field = macro(function(acc,name,lbl,min,max,value)
name = name:asvalue()
lbl = lbl:asvalue()
return quote
var decbuf: int8[21]
in acc:lpush([string.format('<div class="elem small"><label for="%s">%s</label><input type="number" id="%s" name="%s" min="', name, lbl, name, name)])
:push(lib.math.decstr(min, &decbuf[20]),0)
:lpush('" max="'):push(lib.math.decstr(max, &decbuf[20]),0)
:lpush('" value="'):push(lib.math.decstr(value, &decbuf[20]),0):lpush('"></div>')
end
end)
local terra
push_checkbox(acc: &lib.str.acc, name: pstr, lbl: pstr, on: bool, enabled: bool)
acc:lpush('<label><input type="checkbox" name="'):ppush(name):lpush('"')
if on then acc:lpush(' checked') end
if not enabled then acc:lpush(' disabled') end
acc:lpush('> '):ppush(lbl):lpush('</label>')
end
local mode_local, mode_remote, mode_staff, mode_peers, mode_peons, mode_all = 0,1,2,3,4,5
local terra
render_conf_users(co: &lib.srv.convo, path: lib.mem.ptr(pref)): pstr
if path.ct == 3 then
var uid, ok = lib.math.shorthand.parse(path(2).ptr,path(2).ct)
if not ok then goto e404 end
var user = co.srv:actor_fetch_uid(uid)
-- FIXME allow xids as well, for manual queries
if not user then goto e404 end
defer user:free()
if not co.who:overpowers(user.ptr) then goto e403 end
var islinkct = false
var cinp: lib.str.acc cinp:init(128)
var clnk: lib.str.acc clnk:compose('<hr>')
cinp:lpush('<div class="elem-group">')
if co.who.rights.powers.herald() then
var sanitized: pstr
if user.ptr.epithet == nil
then sanitized = pstr {ptr='', ct=0}
else sanitized = lib.html.sanitize(cs(user.ptr.epithet),true)
end
cinp:lpush('<div class="elem"><label for="epithet">epithet</label><input type="text" id="epithet" name="epithet" value="'):ppush(sanitized):lpush('"></div>')
if user.ptr.epithet ~= nil then sanitized:free() end
end
if user.ptr.rights.rank > 0 and (co.who.rights.powers.elevate() or co.who.rights.powers.demote()) then
var max = co.who.rights.rank
if not co.who.rights.powers.elevate() then max = user.ptr.rights.rank end
var min = co.srv.cfg.nranks
if not co.who.rights.powers.demote() then min = user.ptr.rights.rank end
num_field(cinp, 'rank', 'rank', max, min, user.ptr.rights.rank)
end
if co.who.rights.powers.invite() or co.who.rights.powers.discipline() then
var min = 0
if not (co.who.rights.powers.discipline() or
co.who.rights.powers.demote() and co.who.rights.powers.invite())
then min = user.ptr.rights.invites end
var max = co.srv.cfg.maxinvites
if not co.who.rights.powers.invite() then max = user.ptr.rights.invites end
num_field(cinp, 'invites', 'invites', min, max, user.ptr.rights.invites)
end
cinp:lpush('</div><div class="check-panel">')
if (user.ptr.rights.rank == 0 and co.who.rights.powers.elevate()) or
(user.ptr.rights.rank > 0 and co.who.rights.powers.demote()) then
push_checkbox(&cinp, 'staff', 'site staff member', user.ptr.rights.rank > 0, true)
end
cinp:lpush('</div>')
if co.who.rights.powers.elevate() or
co.who.rights.powers.demote() then
var map = array([lib.store.privmap])
cinp:lpush('<label>powers</label><div class="check-panel">')
for i=0, [map.type.N] do
if (co.who.rights.powers and map[i].priv) == map[i].priv then
var name: int8[64]
var on = (user.ptr.rights.powers and map[i].priv) == map[i].priv
var enabled = (on and co.who.rights.powers.demote()) or
((not on) and co.who.rights.powers.elevate())
lib.str.cpy(&name[0], 'allow-')
lib.str.ncpy(&name[6], map[i].name.ptr, map[i].name.ct)
push_checkbox(&cinp, pstr{ptr=&name[0],ct=map[i].name.ct+6},
map[i].name, on, enabled)
end
end
cinp:lpush('</div>')
end
-- TODO black mark system? e.g. resolution option for badthink reports
-- adds a black mark to the offending user; they can be automatically banned
-- or brought up for review after a certain number of offenses; possibly lower
-- set of default privs for marked users
var cinpp = cinp:finalize() defer cinpp:free()
var clnkp: pstr
if islinkct then clnkp = clnk:finalize() else
clnk:free()
clnkp = pstr { ptr='', ct=0 }
end
var unym: lib.str.acc unym:init(64)
unym:lpush('<a href="/')
if user(0).origin ~= 0 then unym:lpush('@') end
do var sanxid = lib.html.sanitize(user(0).xid, true)
unym:ppush(sanxid)
sanxid:free() end
unym:lpush('" class="id">')
lib.render.nym(user.ptr,0,&unym)
unym:lpush('</a>')
var pg = data.view.conf_user_ctl {
name = unym:finalize();
inputcontent = cinpp;
linkcontent = clnkp;
}
var ret = pg:tostr()
pg.name:free()
if islinkct then clnkp:free() end
return ret
else
var modes = array(P'local', P'remote', P'staff', P'titled', P'peons', P'all')
var idbuf: int8[lib.math.shorthand.maxlen]
var ulst: lib.str.acc ulst:init(256)
var mode: uint8 = mode_local
var modestr = co:pgetv('show')
ulst:lpush('<div style="text-align: right"><em>showing ')
for i=0,[modes.type.N] do
if modestr:ref() and modes[i]:cmp(modestr) then mode = i end
end
for i=0,[modes.type.N] do
if i > 0 then ulst:lpush(' ยท ') end
if mode == i then
ulst:lpush('<strong>'):ppush(modes[i]):lpush('</strong>')
else
ulst:lpush('<a href="?show='):ppush(modes[i]):lpush('">')
:ppush(modes[i]):lpush('</a>')
end
end
var users: lib.mem.lstptr(lib.store.actor)
if mode == mode_local then
users = co.srv:actor_enum_local()
else
users = co.srv:actor_enum()
end
ulst:lpush('</em></div>')
ulst:lpush('<ul class="user-list">')
for i=0,users.ct do var usr = users(i).ptr
if mode == mode_staff and usr.rights.rank == 0 then goto skip
elseif mode == mode_peons and usr.rights.rank ~= 0 then goto skip
elseif mode == mode_remote and usr.origin == 0 then goto skip
elseif mode == mode_peers and usr.epithet == nil then goto skip end
var idlen = lib.math.shorthand.gen(usr.id, &idbuf[0])
ulst:lpush('<li>')
if usr.rights.rank ~= 0 then
ulst:lpush('<span class="regalia">')
regalia(&ulst, usr.rights.rank)
ulst:lpush('</span>')
end
if co.who:overpowers(usr) then
ulst:lpush('<a class="id" href="users/'):push(&idbuf[0],idlen):lpush('">')
lib.render.nym(usr, 0, &ulst)
ulst:lpush('</a></li>')
else
ulst:lpush('<span class="id">')
lib.render.nym(usr, 0, &ulst)
ulst:lpush('</span></li>')
end
::skip::end
ulst:lpush('</ul>')
return ulst:finalize()
end
do return pstr.null() end
::e404:: co:complain(404, 'not found', 'there is no user or resource by that identifier on this server') goto quit
::e403:: co:complain(403, 'forbidden', 'you do not have sufficient authority to control that resource')
::quit:: return pstr.null()
end
return render_conf_users
|