Differences From
Artifact [e7b33e5534]:
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