parsav  Diff

Differences From Artifact [39281cf1cf]:

To Artifact [ee3dfa15a8]:


21
22
23
24
25
26
27
28

29
30
31
32
33

34
35
36
37
38
39
40
...
130
131
132
133
134
135
136













137
138
139
140
141
142
143
...
272
273
274
275
276
277
278

279
280
281

282

283
284
285
286

287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
...
392
393
394
395
396
397
398
399























































400
401
402
403

404
405
406
407
408
409
410
411
412
413
414
415
416
417










418
419

420
421
422
423
424
425
426

local ctlcmds = {
	{ 'start', 'start a new instance of the server' };
	{ 'stop', 'stop a running instance' };
	{ 'ls', 'list all running instances' };
	{ 'attach', 'capture log output from a running instance' };
	{ 'db', 'set up and manage the database' };
	{ 'user', 'manage users, privileges, and credentials'};

	{ 'mkroot <handle>', 'establish a new root user with the given handle' };
	{ 'actor <xid> purge-all', 'remove all traces of a user from the database (except local user credentials -- use \27[1mauth all purge\27[m to prevent a user from accessing the instance)' };
	{ 'actor <xid> create', 'instantiate a new actor' };
	{ 'actor <xid> bestow <epithet>', 'bestow an epithet upon an actor' };
	{ 'conf', 'manage the server configuration'};

	{ 'serv dl', 'initiate an update cycle over foreign actors' };
	{ 'tl', 'print the current local timeline to standard out' };
	{ 'be pgsql setup-auth (managed|unmanaged)', '(PGSQL backends) select the authentication strategy to use' };
}

local cmdhelp = function(tbl)
	local str = '\ncommands:\n'
................................................................................
		if acks(i).success then
			lib.report('instance #',num,' reports successful ',rep)
		else
			lib.report('instance #',num,' reports failed ',rep)
		end
	end
end














local emp = lib.ipc.global_emperor
local terra entry_mgtool(argc: int, argv: &rawstring): int
	if argc < 1 then lib.bail('bad invocation!') end

	lib.noise.init(2)
	[lib.init]
................................................................................
				return 1
			end
			if dbmode.arglist.ct < 1 then goto cmderr end

			srv:setup(cnf) 
			if lib.str.cmp(dbmode.arglist(0),'init') == 0 and dbmode.arglist.ct == 2 then
				lib.report('initializing new database structure for domain ', dbmode.arglist(1))

				if dlg:dbsetup() then
					srv:conprep(lib.store.prepmode.conf)
					dlg:conf_set('instance-name', dbmode.arglist(1))

					do var sec: int8[65] gensec(&sec[0])

						dlg:conf_set('server-secret', &sec[0])
					end
					lib.report('database setup complete; use mkroot to create an administrative user')
				else lib.bail('initialization process interrupted') end

			elseif lib.str.cmp(dbmode.arglist(0),'obliterate') == 0 then
				var confirmstrs = array(
					'alpha', 'beta', 'gamma', 'delta', 'epsilon', 'eta', 'nu', 'kappa',
					'emerald', 'carnelian', 'sapphire', 'ruby', 'amethyst'
				)
				var cfmstr: int8[64] cfmstr[0] = 0
				var tdx = lib.osclock.time(nil) / 60
				for i=0,3 do
					if i ~= 0 then lib.str.cat(&cfmstr[0], '-') end
					lib.str.cat(&cfmstr[0], confirmstrs[(tdx ^ (173*i)) % [confirmstrs.type.N]])
				end

				if dbmode.arglist.ct == 1 then
					lib.bail('you are attempting to completely obliterate all data! make sure you have selected your target correctly. if you really want to do this, pass the confirmation string ', &cfmstr[0])
				elseif dbmode.arglist.ct == 2 then
					if lib.str.cmp(dbmode.arglist(1), cfmstr) == 0 then
						lib.warn('completely obliterating all data!')
						dlg:obliterate_everything()
................................................................................
					dlg:conf_set('master',root.handle)
					lib.report('created new administrator')
					if mg then
						var tmppw: int8[33]
						pwset(dlg, &tmppw, ruid, false)
						lib.report('temporary root pw: ', {&tmppw[0], 32})
					end
				else goto cmderr end























































			elseif lib.str.cmp(mode.arglist(0),'user') == 0 then
				var umode: pbasic umode:parse(mode.arglist.ct, &mode.arglist(0))
				if umode.help then
					[ lib.emit(false, 1, 'usage: ', `argv[0], ' user ', umode.type.helptxt.flags, ' <handle> <cmd> [<args>…]', umode.type.helptxt.opts, cmdhelp {

						{ 'user <handle> auth <type> new', '(where applicable, managed auth only) create a new authentication token of the given type for a user' };
						{ 'user <handle> auth <type> reset', '(where applicable, managed auth only) delete all of a user\'s authentication tokens of the given type and issue a new one' };
						{ 'user <handle> auth (<type>|all) purge', 'delete all credentials that would allow this user to log in (where possible)' };
						{ 'user <handle> (grant|revoke) (<priv>|all)', 'grant or revoke a specific power to or from a user' };
						{ 'user <handle> emasculate', 'strip all administrative powers from a user' };
						{ 'user <handle> forgive', 'restore all default powers to a user' };
						{ 'user <handle> suspend [<timespec>]', '(e.g. \27[1muser jokester suspend 5d 6h 7m 3s\27[m to suspend "jokester" for five days, six hours, seven minutes, and three seconds) suspend a user'};
					}) ]
					return 1
				end
				if umode.arglist.ct >= 3 then
					var grant = lib.str.cmp(umode.arglist(1),'grant') == 0
					var handle = umode.arglist(0)
					var usr = dlg:actor_fetch_xid(pstr {ptr=handle, ct=lib.str.sz(handle)})










					if grant or lib.str.cmp(umode.arglist(1),'revoke') == 0 then
						if not usr then lib.bail('unknown handle') end

						var newprivs = usr.ptr.rights.powers
						var map = array([lib.store.privmap])
						if umode.arglist.ct == 3 and lib.str.cmp(umode.arglist(2),'all') == 0 then
							if grant
								then newprivs:fill()
								else newprivs:clear()
							end







|
>

<
<
<

>







 







>
>
>
>
>
>
>
>
>
>
>
>
>







 







>



>

>




>

<
<
<
<
|
<
<
<
<
<







 








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>




>




|





<
<
|
|
>
>
>
>
>
>
>
>
>
>
|
|
>







21
22
23
24
25
26
27
28
29
30



31
32
33
34
35
36
37
38
39
...
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
...
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303




304





305
306
307
308
309
310
311
...
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476


477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498

local ctlcmds = {
	{ 'start', 'start a new instance of the server' };
	{ 'stop', 'stop a running instance' };
	{ 'ls', 'list all running instances' };
	{ 'attach', 'capture log output from a running instance' };
	{ 'db', 'set up and manage the database' };
	{ 'user', 'create and manage users, privileges, and credentials'};
	{ 'actor', 'manage and purge actors, epithets, and ranks'};
	{ 'mkroot <handle>', 'establish a new root user with the given handle' };



	{ 'conf', 'manage the server configuration'};
	{ 'grow <count> [<acl>]', 'grant a new round of invites to all users, or those who match the given ACL' };
	{ 'serv dl', 'initiate an update cycle over foreign actors' };
	{ 'tl', 'print the current local timeline to standard out' };
	{ 'be pgsql setup-auth (managed|unmanaged)', '(PGSQL backends) select the authentication strategy to use' };
}

local cmdhelp = function(tbl)
	local str = '\ncommands:\n'
................................................................................
		if acks(i).success then
			lib.report('instance #',num,' reports successful ',rep)
		else
			lib.report('instance #',num,' reports failed ',rep)
		end
	end
end

local terra gen_cfstr(cfmstr: rawstring, seed: intptr)
	var confirmstrs = array(
		'alpha', 'beta', 'gamma', 'delta', 'epsilon', 'eta', 'nu', 'kappa',
		'emerald', 'carnelian', 'sapphire', 'ruby', 'amethyst'
	)
	var tdx = lib.osclock.time(nil) / 60
	cfmstr[0] = 0
	for i=0,3 do
		if i ~= 0 then lib.str.cat(cfmstr, '-') end
		lib.str.cat(cfmstr, confirmstrs[(seed ^ tdx ^ (173*i)) % [confirmstrs.type.N]])
	end
end

local emp = lib.ipc.global_emperor
local terra entry_mgtool(argc: int, argv: &rawstring): int
	if argc < 1 then lib.bail('bad invocation!') end

	lib.noise.init(2)
	[lib.init]
................................................................................
				return 1
			end
			if dbmode.arglist.ct < 1 then goto cmderr end

			srv:setup(cnf) 
			if lib.str.cmp(dbmode.arglist(0),'init') == 0 and dbmode.arglist.ct == 2 then
				lib.report('initializing new database structure for domain ', dbmode.arglist(1))
				dlg:tx_enter()
				if dlg:dbsetup() then
					srv:conprep(lib.store.prepmode.conf)
					dlg:conf_set('instance-name', dbmode.arglist(1))
					dlg:conf_set('domain', dbmode.arglist(1))
					do var sec: int8[65] gensec(&sec[0])
						dlg:conf_set('server-secret', &sec[0])
						dlg:conf_set('server-secret', &sec[0])
					end
					lib.report('database setup complete; use mkroot to create an administrative user')
				else lib.bail('initialization process interrupted') end
				dlg:tx_complete()
			elseif lib.str.cmp(dbmode.arglist(0),'obliterate') == 0 then




				var cfmstr: int8[64] gen_cfstr(&cfmstr[0],0)






				if dbmode.arglist.ct == 1 then
					lib.bail('you are attempting to completely obliterate all data! make sure you have selected your target correctly. if you really want to do this, pass the confirmation string ', &cfmstr[0])
				elseif dbmode.arglist.ct == 2 then
					if lib.str.cmp(dbmode.arglist(1), cfmstr) == 0 then
						lib.warn('completely obliterating all data!')
						dlg:obliterate_everything()
................................................................................
					dlg:conf_set('master',root.handle)
					lib.report('created new administrator')
					if mg then
						var tmppw: int8[33]
						pwset(dlg, &tmppw, ruid, false)
						lib.report('temporary root pw: ', {&tmppw[0], 32})
					end
				else goto cmderr end
			elseif lib.str.cmp(mode.arglist(0),'actor') == 0 then
				var umode: pbasic umode:parse(mode.arglist.ct, &mode.arglist(0))
				if umode.help then
					[ lib.emit(false, 1, 'usage: ', `argv[0], ' actor ', umode.type.helptxt.flags, ' <xid> <cmd> [<args>…]', umode.type.helptxt.opts, cmdhelp {
						{ 'actor <xid> rank <value>', 'set an actor\'s rank to <value> (remote actors cannot exercise rank-related powers, but benefit from rank immunities)' };
						{ 'actor <xid> degrade', 'alias for `actor <xid> rank 0`' };
						{ 'actor <xid> bestow <epithet>', 'bestow an epithet upon an actor' };
						{ 'actor <xid> instantiate', 'instantiate a remote actor, retrieving their profile and posts even if no one follows them' };
						{ 'actor <xid> proscribe', 'globally ban an actor from interacting with your server' };
						{ 'actor <xid> rehabilitate', 'lift a proscription on an actor' };
						{ 'actor <xid> purge-all <confirm-str>', 'remove all traces of a user from the database (except local user credentials -- use \27[1mauth all purge\27[m to prevent a user from accessing the instance)' };
					}) ]
					return 1
				end
				if umode.arglist.ct >= 2 then
					var degrade = lib.str.cmp(umode.arglist(1),'degrade') == 0
					var xid = umode.arglist(0)
					var usr = dlg:actor_fetch_xid(pstr {ptr=xid, ct=lib.str.sz(xid)})
					if not usr then lib.bail('no such actor') end
					if degrade or lib.str.cmp(umode.arglist(1),'rank') == 0 then
						var rank: uint16
						if degrade and umode.arglist.ct == 2 then
							rank = 0
						elseif (not degrade) and umode.arglist.ct == 3 then
							var r, ok = lib.math.decparse(pstr {
								ptr = umode.arglist(2);
								ct = lib.str.sz(umode.arglist(2));
							})
							if not ok then goto cmderr end
							rank = r
						else goto cmderr end
						usr.ptr.rights.rank = rank
						dlg:actor_save(usr.ptr)
						lib.report('set user rank')
					elseif umode.arglist.ct == 3 and lib.str.cmp(umode.arglist(1),'bestow') == 0 then
						if umode.arglist(2)[0] == 0
							then usr.ptr.epithet = nil
							else usr.ptr.epithet = umode.arglist(2)
						end
						dlg:actor_save(usr.ptr)
						lib.report('bestowed a new epithet on ', usr.ptr.xid)
					elseif lib.str.cmp(umode.arglist(1),'purge-all') == 0 then
						var cfmstr: int8[64] gen_cfstr(&cfmstr[0],usr.ptr.id)
						if umode.arglist.ct == 2 then
							lib.bail('you are attempting to completely purge the actor ', usr.ptr.xid, ' and all related content from the database! if you really want to do this, pass the confirmation string ', &cfmstr[0])
						elseif umode.arglist.ct == 3 then
							if lib.str.ncmp(&cfmstr[0],umode.arglist(2),64) ~= 0 then
								lib.bail('you have supplied an invalid confirmation string; if you really want to purge this actor, pass ', &cfmstr[0])
							end
							lib.warn('completely purging actor ', usr.ptr.xid, ' and all related content from database')
							dlg:actor_purge_uid(usr.ptr.id)
							lib.report('actor purged')
						else goto cmderr end
					else goto cmderr end
				else goto cmderr end
			elseif lib.str.cmp(mode.arglist(0),'user') == 0 then
				var umode: pbasic umode:parse(mode.arglist.ct, &mode.arglist(0))
				if umode.help then
					[ lib.emit(false, 1, 'usage: ', `argv[0], ' user ', umode.type.helptxt.flags, ' <handle> <cmd> [<args>…]', umode.type.helptxt.opts, cmdhelp {
						{ 'user <handle> create', 'add a new user' };
						{ 'user <handle> auth <type> new', '(where applicable, managed auth only) create a new authentication token of the given type for a user' };
						{ 'user <handle> auth <type> reset', '(where applicable, managed auth only) delete all of a user\'s authentication tokens of the given type and issue a new one' };
						{ 'user <handle> auth (<type>|all) purge', 'delete all credentials that would allow this user to log in (where possible)' };
						{ 'user <handle> (grant|revoke) (<priv>|all)', 'grant or revoke a specific power to or from a user' };
						{ 'user <handle> emasculate', 'strip all administrative powers and rank from a user' };
						{ 'user <handle> forgive', 'restore all default powers to a user' };
						{ 'user <handle> suspend [<timespec>]', '(e.g. \27[1muser jokester suspend 5d 6h 7m 3s\27[m to suspend "jokester" for five days, six hours, seven minutes, and three seconds) suspend a user'};
					}) ]
					return 1
				end


				var handle = umode.arglist(0)
				var usr = dlg:actor_fetch_xid(pstr {ptr=handle, ct=lib.str.sz(handle)})
				if umode.arglist.ct == 2 and lib.str.cmp(umode.arglist(1),'create')==0 then
					if usr:ref() then lib.bail('that user already exists') end
					if not lib.store.actor.handle_validate(handle) then
						lib.bail('invalid user handle') end
					var kbuf: uint8[lib.crypt.const.maxdersz]
					var na = lib.store.actor.mk(&kbuf[0])
					na.handle = handle
					dlg:actor_create(&na)
					lib.report('created new user @',na.handle,'; assign credentials to enable login')
				elseif umode.arglist.ct >= 3 then
					var grant = lib.str.cmp(umode.arglist(1),'grant') == 0
					if not usr then lib.bail('no such user') end
					if grant or lib.str.cmp(umode.arglist(1),'revoke') == 0 then
						var newprivs = usr.ptr.rights.powers
						var map = array([lib.store.privmap])
						if umode.arglist.ct == 3 and lib.str.cmp(umode.arglist(2),'all') == 0 then
							if grant
								then newprivs:fill()
								else newprivs:clear()
							end