parsav  Diff

Differences From Artifact [e7b33e5534]:

To Artifact [da1c9184b0]:


    22     22   		'pw', 'otp', 'challenge', 'trust'
    23     23   	};
    24     24   	privset = lib.set {
    25     25   		'post', 'edit', 'acct', 'upload', 'censor', 'admin', 'invite'
    26     26   	};
    27     27   	powerset = lib.set {
    28     28   		-- user powers -- default on
    29         -		'login', 'visible', 'post', 'shout',
    30         -		'propagate', 'upload', 'acct', 'edit';
           29  +		'login', -- not locked out
           30  +		'visible', -- account & posts can be seen by others
           31  +		'post', -- can do poasts
           32  +		'shout', -- posts show up on local timeline
           33  +		'propagate', -- posts are sent to other instances
           34  +		'artifact', -- upload, claim, and manage artifacts
           35  +		'acct', -- configure own account
           36  +		'edit'; -- edit own poasts
    31     37   
    32     38   		-- admin powers -- default off
    33         -		'purge', 'config', 'censor', 'suspend',
    34         -		'cred', 'elevate', 'demote', 'rebrand', -- modify site's brand identity
    35         -		'herald', -- grant serverwide epithets
           39  +		'purge', -- permanently delete users
           40  +		'config', -- change daemon policy & config UI
           41  +		'censor', -- dispose of badthink
           42  +		'discipline', -- enforced timeouts, stripping badges and epithets, punitive actions that do not permanently deprive of powers; can remove own injunctions but not others'
           43  +		'vacate', -- can remove others' injunctions, but not apply them
           44  +		'cred', -- alter credentials
           45  +		'elevate', 'demote', -- change user rank, give and take powers, including the ability to log in
           46  +		'rebrand', -- modify site's brand identity
           47  +		'herald', -- grant serverwide epithets and badges
    36     48   		'invite' -- *unlimited* invites
    37     49   	};
    38     50   	prepmode = lib.enum {
    39     51   		'full','conf','admin'
    40     52   	}
    41     53   }
    42     54   
................................................................................
    46     58   	m.privmap[#m.privmap + 1] = quote
    47     59   		var ps: m.powerset ps:clear()
    48     60   		(ps.[v] << true)
    49     61   	in pt {name = lib.str.plit(v), priv = ps} end
    50     62   end end
    51     63   
    52     64   terra m.powerset:affect_users()
    53         -	return self.purge() or self.censor() or self.suspend() or
           65  +	return self.purge() or self.discipline() or self.herald() or
    54     66   	       self.elevate() or self.demote() or self.cred()
    55     67   end
    56     68   
    57     69   local str = rawstring
    58     70   local pstr = lib.mem.ptr(int8)
    59     71   
    60     72   struct m.source
................................................................................
    64     76   	-- creating staff automatically assigns rank immediately below you
    65     77   	quota: uint32 -- # of allowed tweets per day; 0 = no limit
    66     78   	invites: uint32 -- # of people left this user can invite
    67     79   	
    68     80   	powers: m.powerset
    69     81   }
    70     82   
    71         -terra m.rights_default()
           83  +terra m.rights_default() -- TODO make configurable
    72     84   	var pow: m.powerset pow:clear()
    73     85   	(pow.login     << true)
    74     86   	(pow.visible   << true)
    75     87   	(pow.post      << true)
    76     88   	(pow.shout     << true)
    77     89   	(pow.propagate << true)
    78         -	(pow.upload    << true)
           90  +	(pow.artifact  << true)
    79     91   	(pow.acct      << true)
    80     92   	(pow.edit      << true)
    81     93   	return m.rights { rank = 0, quota = 1000, invites = 0, powers = pow; }
    82     94   end
    83     95   
    84     96   struct m.actor {
    85     97   	id: uint64
................................................................................
    94    106   	rights: m.rights
    95    107   	key: lib.mem.ptr(uint8)
    96    108   
    97    109   -- ephemera
    98    110   	xid: str
    99    111   	source: &m.source
   100    112   }
          113  +
          114  +terra m.actor:outranks(other: &m.actor)
          115  + -- this predicate determines where two users stand relative to
          116  + -- each other in the formal staff hierarchy. it is used in
          117  + -- authority calculations, but this function should only be
          118  + -- used directly in rendering code and by other predicates.
          119  + -- do not use it in authority calculation, as there are special
          120  + -- cases where formal rank does not fully determine a user's
          121  + -- capabilities (e.g. roots have the same rank, but can
          122  + -- exercise power over each other, unlike lower ranks)
          123  +	if self.rights.rank == 0 then
          124  +	 -- peons never outrank anybody
          125  +		return false
          126  +	end
          127  +	if other.rights.rank == 0 then
          128  +	 -- everybody outranks peons
          129  +		return true
          130  +	end
          131  +	return self.rights.rank < other.rights.rank
          132  +	-- rank 1 is the highest possible, rank 2 is second-highest, and so on
          133  +end
          134  +
          135  +terra m.actor:overpowers(other: &m.actor)
          136  + -- this predicate determines whether one user may exercise their
          137  + -- powers over another user. it does not affect what those powers
          138  + -- actually are (for instance, you cannot revoke a power you do
          139  + -- not have, no matter how much you outrank someone)
          140  +	if self.rights.rank == 1 and other.rights.rank == 1 then
          141  +	 -- special case: root users always overpower each other
          142  +	 -- otherwise, nobody could reset their passwords
          143  +	 -- (also dissuades people from giving root lightly)
          144  +		return true
          145  +	end
          146  +	return self:outranks(other)
          147  +end
          148  +
          149  +terra m.actor.methods.handle_validate(hnd: rawstring)
          150  +	if hnd[0] == 0 then
          151  +		return false
          152  +	end
          153  +	-- TODO validate fully
          154  +	return true
          155  +end
   101    156   
   102    157   terra m.actor.methods.mk(kbuf: &uint8)
   103    158   	var newkp = lib.crypt.genkp()
   104    159   	var privsz = lib.crypt.der(false,&newkp,kbuf)
   105    160   	return m.actor {
   106    161   		id = 0; nym = nil; handle = nil;
   107    162   		origin = 0; bio = nil; avatar = nil;
................................................................................
   280    335   	conf_get: {&m.source, rawstring} -> lib.mem.ptr(int8)
   281    336   	conf_set: {&m.source, rawstring, rawstring} -> {}
   282    337   	conf_reset: {&m.source, rawstring} -> {}
   283    338   
   284    339   	actor_create: {&m.source, &m.actor} -> uint64
   285    340   	actor_save: {&m.source, &m.actor} -> {}
   286    341   	actor_save_privs: {&m.source, &m.actor} -> {}
          342  +	actor_purge_uid: {&m.source, uint64} -> {}
   287    343   	actor_fetch_xid: {&m.source, lib.mem.ptr(int8)} -> lib.mem.ptr(m.actor)
   288    344   	actor_fetch_uid: {&m.source, uint64} -> lib.mem.ptr(m.actor)
   289    345   	actor_notif_fetch_uid: {&m.source, uint64} -> lib.mem.ptr(m.notif)
   290         -	actor_enum: {&m.source} -> lib.mem.ptr(&m.actor)
   291         -	actor_enum_local: {&m.source} -> lib.mem.ptr(&m.actor)
          346  +	actor_enum: {&m.source} -> lib.mem.lstptr(m.actor)
          347  +	actor_enum_local: {&m.source} -> lib.mem.lstptr(m.actor)
   292    348   	actor_stats: {&m.source, uint64} -> m.actor_stats
   293    349   	actor_rel: {&m.source, uint64, uint64} -> m.relationship
   294    350   
   295    351   	actor_auth_how: {&m.source, m.inet, rawstring} -> {m.credset, bool}
   296    352   		-- returns a set of auth method categories that are available for a
   297    353   		-- given user from a certain origin
   298    354   			-- origin: inet
................................................................................
   326    382   			-- cookie issue time: m.timepoint
   327    383   	actor_auth_register_uid: {&m.source, uint64, uint64} -> {}
   328    384   		-- notifies the backend module of the UID that has been assigned for
   329    385   		-- an authentication ID
   330    386   			-- aid: uint64
   331    387   			-- uid: uint64
   332    388   
   333         -	auth_enum_uid:    {&m.source, uint64}    -> lib.mem.ptr(lib.mem.ptr(m.auth))
   334         -	auth_enum_handle: {&m.source, rawstring} -> lib.mem.ptr(lib.mem.ptr(m.auth))
          389  +	auth_enum_uid:    {&m.source, uint64}    -> lib.mem.lstptr(m.auth)
          390  +	auth_enum_handle: {&m.source, rawstring} -> lib.mem.lstptr(m.auth)
   335    391   	auth_attach_pw: {&m.source, uint64, bool, pstr, pstr} -> {}
   336    392   		-- uid: uint64
   337    393   		-- reset: bool (delete other passwords?)
   338    394   		-- pw: pstring
   339    395   		-- comment: pstring
   340    396   	auth_purge_pw: {&m.source, uint64, rawstring} -> {}
   341    397   	auth_purge_otp: {&m.source, uint64, rawstring} -> {}
................................................................................
   350    406   			-- uid: uint64
   351    407   			-- timestamp: timepoint
   352    408   
   353    409   	post_save: {&m.source, &m.post} -> {}
   354    410   	post_create: {&m.source, &m.post} -> uint64
   355    411   	post_destroy: {&m.source, uint64} -> {}
   356    412   	post_fetch: {&m.source, uint64} -> lib.mem.ptr(m.post)
   357         -	post_enum_author_uid: {&m.source, uint64, m.range} -> lib.mem.ptr(lib.mem.ptr(m.post))
   358         -	post_enum_parent: {&m.source, uint64} -> lib.mem.ptr(lib.mem.ptr(m.post))
          413  +	post_enum_author_uid: {&m.source, uint64, m.range} -> lib.mem.lstptr(m.post)
          414  +	post_enum_parent: {&m.source, uint64} -> lib.mem.lstptr(m.post)
   359    415   	post_attach_ctl: {&m.source, uint64, uint64, bool} -> {}
   360    416   		-- attaches or detaches an existing database artifact
   361    417   			-- post id: uint64
   362    418   			-- artifact id: uint64
   363    419   			-- detach: bool
   364    420   
   365    421   	thread_latest_arrival_calc: {&m.source, uint64} -> m.timepoint
................................................................................
   402    458   			-- proto: kompromat (null for all records, or a prototype describing the records to return)
   403    459   	nkvd_sanction_issue:  {&m.source, &m.sanction} -> uint64
   404    460   	nkvd_sanction_vacate: {&m.source, uint64} -> {}
   405    461   	nkvd_sanction_enum_target: {&m.source, uint64} -> {}
   406    462   	nkvd_sanction_enum_issuer: {&m.source, uint64} -> {}
   407    463   	nkvd_sanction_review: {&m.source, m.timepoint} -> {}
   408    464   
   409         -	timeline_actor_fetch_uid: {&m.source, uint64, m.range} -> lib.mem.ptr(lib.mem.ptr(m.post))
   410         -	timeline_instance_fetch: {&m.source, m.range} -> lib.mem.ptr(lib.mem.ptr(m.post))
          465  +	timeline_actor_fetch_uid: {&m.source, uint64, m.range} -> lib.mem.lstptr(m.post)
          466  +	timeline_instance_fetch: {&m.source, m.range} -> lib.mem.lstptr(m.post)
   411    467   }
   412    468   
   413    469   m.user_conf_funcs(m.backend, 'str', rawstring, lib.mem.ptr(int8))
   414    470   m.user_conf_funcs(m.backend, 'int', intptr, intptr, bool)
   415    471   
   416    472   struct m.source {
   417    473   	backend: &m.backend