parsav  Diff

Differences From Artifact [0f343f8c98]:

To Artifact [41f55e0682]:


   103    103   		if punct ~= nil then a:push(punct, 1) end
   104    104   		a:ipush(rnd(uint16,0,65535))
   105    105   	end
   106    106   
   107    107   	if xXx then a:lpush('_xXx') end
   108    108   
   109    109   end
          110  +
          111  +local terra 
          112  +suggest_domain(a: &lib.str.acc)
          113  +	var tlds = array('tld','club','town','space','xxx')
          114  +end
   110    115   
   111    116   local push_num_field = macro(function(acc,name,lbl,min,max,value,disable)
   112    117   	name = name:asvalue()
   113    118   	lbl = lbl:asvalue()
   114    119   	local start = '<div class="elem small">'
   115    120   	local enabled = start .. string.format('<label for="%s">%s</label><input type="number" id="%s" name="%s" min="', name, lbl, name, name)
   116    121   	local disabled = start .. string.format('<label>%s</label><div class="txtbox">', lbl)
................................................................................
   154    159   local push_checkbox = input_pusher('checkbox',true,false)
   155    160   local push_pickbox = input_pusher('checkbox',false,false)
   156    161   local push_radio = input_pusher('radio',false,true)
   157    162   
   158    163   local mode_local, mode_remote, mode_staff, mode_peers, mode_peons, mode_all = 0,1,2,3,4,5
   159    164   local terra 
   160    165   render_conf_users(co: &lib.srv.convo, path: lib.mem.ptr(pref)): pstr
   161         -	if path.ct == 3 then
          166  +	if path.ct >= 3 then
   162    167   		var uid, ok = lib.math.shorthand.parse(path(2).ptr,path(2).ct)
   163    168   		if not ok then goto e404 end
   164    169   		var user = co.srv:actor_fetch_uid(uid)
   165    170   		-- FIXME allow xids as well, for manual queries
   166    171   		if not user then goto e404 end
   167    172   		defer user:free()
   168    173   		if not co.who:overpowers(user.ptr) then goto e403 end
   169    174   
   170         -		var cinp: lib.str.acc cinp:init(256)
   171         -		var clnk: lib.str.acc clnk:init(512)
   172         -		cinp:lpush('<div class="elem-group">')
   173         -		if user.ptr.rights.rank > 0 and (co.who.rights.powers.elevate() or co.who.rights.powers.demote()) then
   174         -			var max = co.who.rights.rank
   175         -			if not co.who.rights.powers.elevate() then max = user.ptr.rights.rank end
   176         -			var min = co.srv.cfg.nranks
   177         -			if not co.who.rights.powers.demote() then min = user.ptr.rights.rank end
   178         -
   179         -			push_num_field(cinp, 'rank', 'rank', max, min, user.ptr.rights.rank, user.ptr.id == co.who.id)
   180         -		end
   181         -		if co.who.rights.powers.herald() then
   182         -			var sanitized: pstr
   183         -			if user.ptr.epithet == nil
   184         -				then sanitized = pstr {ptr='', ct=0}
   185         -				else sanitized = lib.html.sanitize(cs(user.ptr.epithet),true)
          175  +		if path.ct == 4 then
          176  +			if path(3):cmp(lib.str.lit'cred') then
          177  +				var pg: lib.str.acc pg:init(1024)
          178  +				pg:lpush('<div class="context">editing credentials for user <a href="/conf/users/'):rpush(path(2)):lpush('">'):push(user(0).xid,0):lpush('</a></div>')
          179  +				var credmgr = lib.render.conf.sec(co, uid)
          180  +				pg:ppush(credmgr)
          181  +				credmgr:free()
          182  +				return pg:finalize()
          183  +			else goto e404 end
          184  +		elseif path.ct == 3 then
          185  +			var cinp: lib.str.acc cinp:init(256)
          186  +			cinp:lpush('<div class="elem-group">')
          187  +			if user.ptr.rights.rank > 0 and (co.who.rights.powers.elevate() or co.who.rights.powers.demote()) then
          188  +				var max = co.who.rights.rank
          189  +				if not co.who.rights.powers.elevate() then max = user.ptr.rights.rank end
          190  +				var min = co.srv.cfg.nranks
          191  +				if not co.who.rights.powers.demote() then min = user.ptr.rights.rank end
          192  +
          193  +				push_num_field(cinp, 'rank', 'rank', max, min, user.ptr.rights.rank, user.ptr.id == co.who.id)
          194  +			end
          195  +			if co.who.rights.powers.herald() then
          196  +				var sanitized: pstr
          197  +				if user.ptr.epithet == nil
          198  +					then sanitized = pstr {ptr='', ct=0}
          199  +					else sanitized = lib.html.sanitize(cs(user.ptr.epithet),true)
          200  +				end
          201  +				cinp:lpush('<div class="elem"><label for="epithet">epithet</label><input type="text" id="epithet" name="epithet" value="'):ppush(sanitized):lpush('"></div>')
          202  +				if user.ptr.epithet ~= nil then sanitized:free() end
          203  +			end
          204  +			if co.who.rights.powers.invite() or co.who.rights.powers.discipline() then
          205  +				var min: uint32 = 0
          206  +				if not (co.who.rights.powers.discipline() or
          207  +					co.who.rights.powers.demote() and co.who.rights.powers.invite())
          208  +						then min = user.ptr.rights.invites end
          209  +				var max: uint32 = co.srv.cfg.maxinvites
          210  +				if not co.who.rights.powers.invite() then max = user.ptr.rights.invites end
          211  +
          212  +				push_num_field(cinp, 'invites', 'invites', min, max, user.ptr.rights.invites, false)
          213  +			end
          214  +			if co.who.rights.powers.elevate() or co.who.rights.powers.demote() then
          215  +				var max: uint32 = 5000
          216  +				if not co.who.rights.powers.elevate() then max = user.ptr.rights.quota end
          217  +				var min: uint32 = 0
          218  +				if not co.who.rights.powers.demote() then min = user.ptr.rights.quota end
          219  +
          220  +				push_num_field(cinp, 'quota', 'quota', min, max, user.ptr.rights.quota, user.ptr.id == co.who.id and co.who.rights.rank ~= 1)
   186    221   			end
   187         -			cinp:lpush('<div class="elem"><label for="epithet">epithet</label><input type="text" id="epithet" name="epithet" value="'):ppush(sanitized):lpush('"></div>')
   188         -			if user.ptr.epithet ~= nil then sanitized:free() end
   189         -		end
   190         -		if co.who.rights.powers.invite() or co.who.rights.powers.discipline() then
   191         -			var min: uint32 = 0
   192         -			if not (co.who.rights.powers.discipline() or
   193         -				co.who.rights.powers.demote() and co.who.rights.powers.invite())
   194         -					then min = user.ptr.rights.invites end
   195         -			var max: uint32 = co.srv.cfg.maxinvites
   196         -			if not co.who.rights.powers.invite() then max = user.ptr.rights.invites end
          222  +			cinp:lpush('</div><div class="elem"><div class="check-panel">')
          223  +
          224  +			if user.ptr.id ~= co.who.id and
          225  +			   ((user.ptr.rights.rank == 0 and co.who.rights.powers.elevate()) or
          226  +				(user.ptr.rights.rank >  0 and co.who.rights.powers.demote())) then
          227  +				push_checkbox(&cinp, 'staff', pstr.null(), 'site staff member', user.ptr.rights.rank > 0, true, pstr.null())
          228  +			end
   197    229   
   198         -			push_num_field(cinp, 'invites', 'invites', min, max, user.ptr.rights.invites, false)
   199         -		end
   200         -		if co.who.rights.powers.elevate() or co.who.rights.powers.demote() then
   201         -			var max: uint32 = 5000
   202         -			if not co.who.rights.powers.elevate() then max = user.ptr.rights.quota end
   203         -			var min: uint32 = 0
   204         -			if not co.who.rights.powers.demote() then min = user.ptr.rights.quota end
          230  +			cinp:lpush('</div></div>')
   205    231   
   206         -			push_num_field(cinp, 'quota', 'quota', min, max, user.ptr.rights.quota, user.ptr.id == co.who.id and co.who.rights.rank ~= 1)
   207         -		end
   208         -		cinp:lpush('</div><div class="elem"><div class="check-panel">')
   209         -
   210         -		if user.ptr.id ~= co.who.id and
   211         -		   ((user.ptr.rights.rank == 0 and co.who.rights.powers.elevate()) or
   212         -		    (user.ptr.rights.rank >  0 and co.who.rights.powers.demote())) then
   213         -			push_checkbox(&cinp, 'staff', pstr.null(), 'site staff member', user.ptr.rights.rank > 0, true, pstr.null())
   214         -		end
   215         -
   216         -		cinp:lpush('</div></div>')
   217         -
   218         -		if (co.who.rights.powers.elevate() or
   219         -		   co.who.rights.powers.demote()) and user.ptr.id ~= co.who.id then
   220         -			var map = array([lib.store.privmap])
   221         -			cinp:lpush('<details><summary>powers</summary><div class="pick-list">')
   222         -				for i=0, [map.type.N] do
   223         -					if (co.who.rights.powers and map[i].priv):sz() > 0 then
   224         -						var on = (user.ptr.rights.powers and map[i].priv):sz() > 0
   225         -						var enabled = (     on  and co.who.rights.powers.demote() ) or
   226         -									  ((not on) and co.who.rights.powers.elevate())
   227         -						var namea: lib.str.acc namea:compose('power-', map[i].name)
   228         -						var name = namea:finalize()
   229         -						push_pickbox(&cinp, name, pstr.null(), map[i].name, on, enabled, pstr.null())
   230         -						name:free()
          232  +			if (co.who.rights.powers.elevate() or
          233  +			   co.who.rights.powers.demote()) and user.ptr.id ~= co.who.id then
          234  +				var map = array([lib.store.privmap])
          235  +				cinp:lpush('<details><summary>powers</summary><div class="pick-list">')
          236  +					for i=0, [map.type.N] do
          237  +						if (co.who.rights.powers and map[i].priv):sz() > 0 then
          238  +							var on = (user.ptr.rights.powers and map[i].priv):sz() > 0
          239  +							var enabled = (     on  and co.who.rights.powers.demote() ) or
          240  +										  ((not on) and co.who.rights.powers.elevate())
          241  +							var namea: lib.str.acc namea:compose('power-', map[i].name)
          242  +							var name = namea:finalize()
          243  +							push_pickbox(&cinp, name, pstr.null(), map[i].name, on, enabled, pstr.null())
          244  +							name:free()
          245  +						end
   231    246   					end
          247  +				cinp:lpush('</div></details>')
          248  +			end
          249  +
          250  +			if co.who.id ~= uid and co.who.rights.powers.purge() then
          251  +				var purgeconf: lib.str.acc purgeconf:init(48)
          252  +				var purgestrs = array(
          253  +					'alpha', 'beta', 'gamma', 'delta', 'epsilon', 'eta', 'nu', 'kappa',
          254  +					'emerald', 'carnelian', 'sapphire', 'ruby', 'amethyst', 'glory',
          255  +					'hope', 'grace', 'pearl', 'carnation', 'rose', 'peony', 'poppy'
          256  +				)
          257  +				for i=0,3 do
          258  +					purgeconf:push(purgestrs[lib.crypt.random(intptr,0,[purgestrs.type.N])],0)
          259  +					if i ~= 2 then purgeconf:lpush('-') end
   232    260   				end
   233         -			cinp:lpush('</div></details>')
   234         -		end
          261  +				cinp:lpush('<details><summary>purge account</summary><p>you have the authority to destroy this account and all its associated content irreversibly and irretrievably. if you really wish to apply such an extreme sanction, enter the confirmation string <strong style="user-select:none">'):push(purgeconf.buf,purgeconf.sz):lpush('</strong> below and press the “alter” button to begin the process.</p><div class="elem"><label for="purge">purge confirmation string</label><input type="text" id="purge" name="purgekey"></div><input type="hidden" name="purgestr" value="'):push(purgeconf.buf,purgeconf.sz):lpush('"></details>')
          262  +				purgeconf:free()
          263  +			end
          264  +
          265  +			-- TODO black mark system? e.g. resolution option for badthink reports
          266  +			-- adds a black mark to the offending user; they can be automatically banned
          267  +			-- or brought up for review after a certain number of offenses; possibly lower
          268  +			-- set of default privs for marked users
   235    269   
   236         -		-- TODO black mark system? e.g. resolution option for badthink reports
   237         -		-- adds a black mark to the offending user; they can be automatically banned
   238         -		-- or brought up for review after a certain number of offenses; possibly lower
   239         -		-- set of default privs for marked users
          270  +			var cinpp = cinp:finalize() defer cinpp:free()
          271  +			var unym: lib.str.acc unym:init(64)
          272  +			unym:lpush('<a href="/')
          273  +			if user(0).origin ~= 0 then unym:lpush('@') end
          274  +			do var sanxid = lib.html.sanitize(user(0).xid, true)
          275  +				unym:ppush(sanxid)
          276  +				sanxid:free() end
          277  +			unym:lpush('" class="id">')
          278  +			lib.render.nym(user.ptr,0,&unym,false)
          279  +			unym:lpush('</a>')
          280  +			var ctlbox = data.view.conf_user_ctl {
          281  +				name = unym:finalize();
          282  +				inputcontent = cinpp;
          283  +				btns = pstr{'',0};
          284  +			}
          285  +			if co.who.id ~= uid and co.who.rights.powers.cred() then
          286  +				ctlbox.btns = lib.str.acc{}:compose('<a class="button" href="/conf/users/',path(2),'/cred">security &amp; credentials</a>'):finalize()
          287  +			end
          288  +			var pg: lib.str.acc pg:init(512)
          289  +			ctlbox:append(&pg)
          290  +			ctlbox.name:free()
          291  +			if ctlbox.btns.ct > 0 then ctlbox.btns:free() end
   240    292   
   241         -		var cinpp = cinp:finalize() defer cinpp:free()
   242         -		var clnkp: pstr
   243         -		if clnk.sz > 0 then clnkp = clnk:finalize() else
   244         -			clnk:free()
   245         -			clnkp = pstr { ptr='', ct=0 }
          293  +			return pg:finalize()
   246    294   		end
   247         -		var unym: lib.str.acc unym:init(64)
   248         -		unym:lpush('<a href="/')
   249         -		if user(0).origin ~= 0 then unym:lpush('@') end
   250         -		do var sanxid = lib.html.sanitize(user(0).xid, true)
   251         -			unym:ppush(sanxid)
   252         -			sanxid:free() end
   253         -		unym:lpush('" class="id">')
   254         -		lib.render.nym(user.ptr,0,&unym,false)
   255         -		unym:lpush('</a>')
   256         -		var pg = data.view.conf_user_ctl {
   257         -			name = unym:finalize();
   258         -			inputcontent = cinpp;
   259         -			linkcontent = clnkp;
   260         -		}
   261         -		var ret = pg:tostr()
   262         -		pg.name:free()
   263         -		if clnkp.ct > 0 then clnkp:free() end
   264         -		return ret
   265    295   	else
   266    296   		var modes = array(P'local', P'remote', P'staff', P'titled', P'peons', P'all')
   267    297   		var idbuf: int8[lib.math.shorthand.maxlen]
   268    298   		var ulst: lib.str.acc ulst:init(256)
   269    299   		var mode: uint8 = mode_local
   270    300   		var modestr = co:pgetv('show')
   271    301   		ulst:lpush('<div style="text-align: right"><em>showing ')