Differences From
Artifact [9c53eed84d]:
187 187 select (pg_temp.parsavpg_translate_actor(a)).*,
188 188
189 189 au.restrict,
190 190 array['post' ] <@ au.restrict,
191 191 array['edit' ] <@ au.restrict,
192 192 array['account' ] <@ au.restrict,
193 193 array['upload' ] <@ au.restrict,
194 + array['artifact'] <@ au.restrict,
194 195 array['moderate'] <@ au.restrict,
195 - array['admin' ] <@ au.restrict
196 + array['admin' ] <@ au.restrict,
197 + array['invite' ] <@ au.restrict
196 198
197 199 from parsav_auth au
198 200 left join parsav_actors a on au.uid = a.id
199 201
200 202 where au.aid = $1::bigint and au.blacklist = false and
201 203 (au.netmask is null or au.netmask >> $2::inet) and
202 204 ($3::bigint = 0 or --slightly abusing the epoch time fmt here, but
................................................................................
271 273 update parsav_actors set
272 274 authtime = $2::bigint
273 275 where id = $1::bigint
274 276 ]];
275 277 };
276 278
277 279 auth_create_pw = {
278 - params = {uint64, binblob, int64, pstring}, cmd = true, sql = [[
280 + params = {uint64, binblob, int64, pstring}, sql = [[
279 281 insert into parsav_auth (uid, name, kind, cred, valperiod, comment) values (
280 282 $1::bigint,
281 283 (select handle from parsav_actors where id = $1::bigint),
282 284 'pw-sha256', $2::bytea,
283 285 $3::bigint, $4::text
284 - )
286 + ) on conflict (name,kind,cred) do update set comment = $4::text returning aid
285 287 ]]
286 288 };
289 +
290 + auth_privs_clear = {
291 + params = {uint64}, cmd = true, sql = [[
292 + update parsav_auth set restrict = array[]::text[] where aid = $1::bigint
293 + ]];
294 + };
295 +
296 + auth_priv_install = {
297 + params = {uint64,pstring}, cmd = true, sql = [[
298 + update parsav_auth set restrict = restrict || $2::text where aid = $1::bigint
299 + ]];
300 + };
287 301
288 302 auth_purge_type = {
289 303 params = {rawstring, uint64, rawstring}, cmd = true, sql = [[
290 304 delete from parsav_auth where
291 305 ((uid = 0 and name = $1::text) or uid = $2::bigint) and
292 306 kind like $3::text
293 307 ]]
294 308 };
309 +
310 + auth_purge_aid = {
311 + params = {uint64}, cmd = true, sql = [[
312 + delete from parsav_auth where aid = $1::bigint
313 + ]]
314 + };
295 315
296 316 auth_enum_uid = {
297 317 params = {uint64}, sql = [[
298 318 select aid, kind, comment, netmask, blacklist from parsav_auth where uid = $1::bigint
299 319 ]];
300 320 };
301 321
................................................................................
401 421 params = {uint64, uint64, pstring}, cmd = true, sql = [[
402 422 delete from parsav_acts where
403 423 actor = $1::bigint and
404 424 subject = $2::bigint and
405 425 kind = $3::text
406 426 ]];
407 427 };
428 +
429 + post_react_delete = {
430 + params = {uint64}, cmd = true, sql = [[
431 + delete from parsav_acts where id = $1::bigint
432 + ]];
433 + };
408 434
409 435 post_reacts_fetch_uid = {
410 436 params = {uint64, uint64, pstring}, sql = [[
411 437 select id, actor, subject, kind, body, time from parsav_acts where
412 438 ($1::bigint = 0 or actor = $1::bigint) and
413 439 ($2::bigint = 0 or subject = $2::bigint) and
414 440 ($3::text is null or kind = $3::text )
415 - ]]
441 + ]];
442 + };
443 +
444 + post_act_fetch_notice = {
445 + params = {uint64}, sql = [[
446 + select (pg_temp.parsavpg_translate_act(a)).*
447 + from parsav_acts as a
448 + where id = $1::bigint
449 + ]];
416 450 };
417 451
418 452 post_enum_author_uid = {
419 453 params = {uint64,uint64,uint64,uint64, uint64}, sql = [[
420 454 select (c.post).*
421 455 from pg_temp.parsavpg_known_content as c
422 456
................................................................................
964 998 a.ptr.key = r:bin(row,8)
965 999 end
966 1000 a.ptr.origin = origin
967 1001 if avia.buf ~= nil then avia:free() end
968 1002 return a
969 1003 end
970 1004
971 -local privmap = lib.store.privmap
1005 +local privmap = lib.store.powmap
972 1006
973 1007 local checksha = function(src, hash, origin, username, pw)
974 1008 local validate = function(kind, cred, credlen)
975 1009 return quote
976 1010 var r = queries.actor_auth_pw.exec(
977 1011 [&lib.store.source](src),
978 1012 username,
................................................................................
1015 1049 local privupdate = terra(
1016 1050 src: &lib.store.source,
1017 1051 ac: &lib.store.actor
1018 1052 ): {}
1019 1053 var pdef: lib.store.powerset pdef:clear()
1020 1054 var map = array([privmap])
1021 1055 for i=0, [map.type.N] do
1022 - var d = pdef and map[i].priv
1023 - var u = ac.rights.powers and map[i].priv
1056 + var d = pdef and map[i].val
1057 + var u = ac.rights.powers and map[i].val
1024 1058 queries.actor_power_delete.exec(src, ac.id, map[i].name)
1025 1059 if d:sz() > 0 and u:sz() == 0 then
1026 1060 lib.dbg('blocking power ', {map[i].name.ptr, map[i].name.ct})
1027 1061 queries.actor_power_insert.exec(src, ac.id, map[i].name, 0)
1028 1062 elseif d:sz() == 0 and u:sz() > 0 then
1029 1063 lib.dbg('granting power ', {map[i].name.ptr, map[i].name.ct})
1030 1064 queries.actor_power_insert.exec(src, ac.id, map[i].name, 1)
................................................................................
1041 1075 var r = queries.actor_powers_fetch.exec(src, uid)
1042 1076
1043 1077 for i=0, r.sz do
1044 1078 for j=0, [map.type.N] do
1045 1079 var pn = r:_string(i,0)
1046 1080 if map[j].name:cmp(pn) then
1047 1081 if r:bool(i,1)
1048 - then powers = powers + map[j].priv
1049 - else powers = powers - map[j].priv
1082 + then powers = powers + map[j].val
1083 + else powers = powers - map[j].val
1050 1084 end
1051 1085 end
1052 1086 end
1053 1087 end
1054 1088
1055 1089 return powers
1056 1090 end
................................................................................
1268 1302
1269 1303 var a = row_to_actor(&r, 0)
1270 1304 a.ptr.source = src
1271 1305
1272 1306 var au = [lib.stat(lib.store.auth)] { ok = true }
1273 1307 au.val.aid = aid
1274 1308 au.val.uid = a.ptr.id
1275 - if not r:null(0,13) then -- restricted?
1309 + if not r:null(0,14) then -- restricted?
1276 1310 au.val.privs:clear()
1277 - (au.val.privs.post << r:bool(0,14))
1278 - (au.val.privs.edit << r:bool(0,15))
1279 - (au.val.privs.account << r:bool(0,16))
1280 - (au.val.privs.upload << r:bool(0,17))
1281 - (au.val.privs.moderate<< r:bool(0,18))
1282 - (au.val.privs.admin << r:bool(0,19))
1311 + (au.val.privs.post << r:bool(0,15))
1312 + (au.val.privs.edit << r:bool(0,16))
1313 + (au.val.privs.account << r:bool(0,17))
1314 + (au.val.privs.upload << r:bool(0,18))
1315 + (au.val.privs.artifact<< r:bool(0,19))
1316 + (au.val.privs.moderate<< r:bool(0,20))
1317 + (au.val.privs.admin << r:bool(0,21))
1318 + (au.val.privs.invite << r:bool(0,22))
1283 1319 else au.val.privs:fill() end
1284 1320
1285 1321 return au, a
1286 1322 end
1287 1323
1288 1324 ::fail:: return [lib.stat (lib.store.auth) ] { ok = false },
1289 1325 [lib.mem.ptr(lib.store.actor)] { ptr = nil, ct = 0 }
................................................................................
1321 1357 var r = queries.post_fetch.exec(src, post)
1322 1358 if r.sz == 0 then return [lib.mem.ptr(lib.store.post)].null() end
1323 1359 var p = row_to_post(&r, 0)
1324 1360 p.ptr.source = src
1325 1361 return p
1326 1362 end];
1327 1363
1364 + post_act_cancel = [terra(
1365 + src: &lib.store.source,
1366 + act: uint64
1367 + ): {} queries.post_react_delete.exec(src, act) end];
1368 +
1328 1369 post_retweet = [terra(
1329 1370 src: &lib.store.source,
1330 1371 uid: uint64,
1331 1372 post: uint64,
1332 1373 undo: bool
1333 1374 ): {}
1334 - var time = lib.osclock.time(nil)
1335 1375 if not undo then
1376 + var time = lib.osclock.time(nil)
1336 1377 queries.post_react_simple.exec(src,uid,post,"rt",time)
1337 1378 else
1338 1379 queries.post_react_cancel.exec(src,uid,post,"rt")
1339 1380 end
1340 1381 end];
1341 1382 post_like = [terra(
1342 1383 src: &lib.store.source,
................................................................................
1528 1569
1529 1570 auth_attach_pw = [terra(
1530 1571 src: &lib.store.source,
1531 1572 uid: uint64,
1532 1573 reset: bool,
1533 1574 pw: pstring,
1534 1575 comment: pstring
1535 - ): {}
1576 + ): uint64
1536 1577 var hash: uint8[lib.crypt.algsz.sha256]
1537 1578 if lib.md.mbedtls_md(lib.md.mbedtls_md_info_from_type(lib.crypt.alg.sha256.id),
1538 1579 [&uint8](pw.ptr), pw.ct, &hash[0]) ~= 0 then
1539 1580 lib.bail('cannot hash password')
1540 1581 end
1541 1582 if reset then queries.auth_purge_type.exec(src, nil, uid, 'pw-%') end
1542 - queries.auth_create_pw.exec(src, uid, binblob {ptr = &hash[0], ct = [hash.type.N]}, lib.osclock.time(nil), comment)
1583 + var r = queries.auth_create_pw.exec(src, uid, binblob {ptr = &hash[0], ct = [hash.type.N]}, lib.osclock.time(nil), comment)
1584 + if r.sz == 0 then return 0 end
1585 + var aid = r:int(uint64,0,0)
1586 + r:free()
1587 + return aid
1588 + end];
1589 +
1590 + auth_privs_set = [terra(
1591 + src: &lib.store.source,
1592 + aid: uint64,
1593 + set: lib.store.privset
1594 + ): {}
1595 + var map = array([lib.store.privmap])
1596 + queries.auth_privs_clear.exec(src,aid)
1597 + if set:sz() == 0 then return end
1598 + for i=0, [map.type.N] do
1599 + if (set and map[i].val):sz() > 0 then
1600 + queries.auth_priv_install.exec(src,aid,map[i].name)
1601 + end
1602 + end
1543 1603 end];
1544 1604
1545 1605 auth_purge_pw = [terra(src: &lib.store.source, uid: uint64, handle: rawstring): {}
1546 1606 queries.auth_purge_type.exec(src, handle, uid, 'pw-%')
1547 1607 end];
1548 1608
1549 1609 auth_purge_otp = [terra(src: &lib.store.source, uid: uint64, handle: rawstring): {}
................................................................................
1699 1759 post.id, post.chgcount, post.edited,
1700 1760 post.subject, post.acl, post.body)
1701 1761 end];
1702 1762
1703 1763 post_enum_parent = [terra(
1704 1764 src: &lib.store.source,
1705 1765 post: uint64
1706 - ): lib.mem.ptr(lib.mem.ptr(lib.store.post))
1766 + ): lib.mem.lstptr(lib.store.post)
1707 1767 var r = queries.post_enum_parent.exec(src,post)
1708 1768 if r.sz == 0 then
1709 1769 return [lib.mem.ptr(lib.mem.ptr(lib.store.post))].null()
1710 1770 end
1711 1771 defer r:free()
1712 1772 var lst = lib.mem.heapa([lib.mem.ptr(lib.store.post)], r.sz)
1713 1773
1714 1774 for i=0, r.sz do lst.ptr[i] = row_to_post(&r, i) end
1715 1775
1716 1776 return lst
1717 1777 end];
1778 +
1779 + post_act_fetch_notice = [terra(
1780 + src: &lib.store.source,
1781 + act: uint64
1782 + ): lib.store.notice
1783 + var r = queries.post_act_fetch_notice.exec(src,act)
1784 + if r.sz == 0 then return lib.store.notice { kind = lib.store.noticetype.none } end
1785 + defer r:free()
1786 +
1787 + var n: lib.store.notice
1788 + n.kind = r:int(uint16,0,0)
1789 + n.when = r:int(int64,0,1)
1790 + n.who = r:int(int64,0,2)
1791 + n.what = r:int(uint64,0,3)
1792 + if n.kind == lib.store.noticetype.react then
1793 + var react = r:_string(0,5)
1794 + lib.str.ncpy(n.reaction, react.ptr, lib.math.smallest(react.ct,[(`n.reaction).tree.type.N]))
1795 + end
1796 +
1797 + return n
1798 + end];
1718 1799
1719 1800 thread_latest_arrival_calc = [terra(
1720 1801 src: &lib.store.source,
1721 1802 post: uint64
1722 1803 ): lib.store.timepoint
1723 1804 var r = queries.thread_latest_arrival_calc.exec(src,post)
1724 1805 if r.sz == 0 or r:null(0,0) then return 0 end