Differences From
Artifact [35848d4bf0]:
254 254 update parsav_actors set
255 255 authtime = to_timestamp($2::bigint)
256 256 where id = $1::bigint
257 257 ]];
258 258 };
259 259
260 260 auth_create_pw = {
261 - params = {uint64, lib.mem.ptr(uint8)}, cmd = true, sql = [[
262 - insert into parsav_auth (uid, name, kind, cred) values (
261 + params = {uint64, binblob, pstring}, cmd = true, sql = [[
262 + insert into parsav_auth (uid, name, kind, cred, comment) values (
263 263 $1::bigint,
264 264 (select handle from parsav_actors where id = $1::bigint),
265 - 'pw-sha256', $2::bytea
265 + 'pw-sha256', $2::bytea,
266 + $3::text
266 267 )
267 268 ]]
268 269 };
269 270
270 271 auth_purge_type = {
271 272 params = {rawstring, uint64, rawstring}, cmd = true, sql = [[
272 273 delete from parsav_auth where
273 274 ((uid = 0 and name = $1::text) or uid = $2::bigint) and
274 275 kind like $3::text
275 276 ]]
276 277 };
278 +
279 + auth_enum_uid = {
280 + params = {uint64}, sql = [[
281 + select aid, kind, comment, netmask, blacklist from parsav_auth where uid = $1::bigint
282 + ]];
283 + };
284 +
285 + auth_enum_handle = {
286 + params = {rawstring}, sql = [[
287 + select aid, kind, comment, netmask, blacklist from parsav_auth where name = $1::text
288 + ]];
289 + };
277 290
278 291 post_save = {
279 292 params = {
280 293 uint64, uint32, int64;
281 294 rawstring, rawstring, rawstring;
282 295 }, cmd = true, sql = [[
283 296 update parsav_posts set
................................................................................
287 300 chgcount = $2::integer,
288 301 edited = to_timestamp($3::bigint)
289 302 where id = $1::bigint
290 303 ]]
291 304 };
292 305
293 306 post_create = {
294 - params = {uint64, rawstring, rawstring, rawstring}, sql = [[
307 + params = {
308 + uint64, rawstring, rawstring, rawstring,
309 + uint64, uint64, rawstring
310 + }, sql = [[
295 311 insert into parsav_posts (
296 312 author, subject, acl, body,
297 - posted, discovered,
298 - circles, mentions
313 + parent, posted, discovered,
314 + circles, mentions, convoheaduri
299 315 ) values (
300 316 $1::bigint, case when $2::text = '' then null else $2::text end,
301 317 $3::text, $4::text,
302 - now(), now(), array[]::bigint[], array[]::bigint[]
318 + $5::bigint, to_timestamp($6::bigint), now(),
319 + array[]::bigint[], array[]::bigint[], $7::text
303 320 ) returning id
304 321 ]]; -- TODO array handling
305 322 };
306 323
307 324 post_destroy_prepare = {
308 325 params = {uint64}, cmd = true, sql = [[
309 326 update parsav_posts set
................................................................................
321 338 post_fetch = {
322 339 params = {uint64}, sql = [[
323 340 select a.origin is null,
324 341 p.id, p.author, p.subject, p.acl, p.body,
325 342 extract(epoch from p.posted )::bigint,
326 343 extract(epoch from p.discovered)::bigint,
327 344 extract(epoch from p.edited )::bigint,
328 - p.parent, p.convoheaduri, p.chgcount
345 + p.parent, p.convoheaduri, p.chgcount,
346 + coalesce(c.value, -1)::smallint
347 +
329 348 from parsav_posts as p
330 - inner join parsav_actors as a on p.author = a.id
349 + inner join parsav_actors as a on p.author = a.id
350 + left join parsav_actor_conf_ints as c on c.uid = a.id and c.key = 'ui-accent'
331 351 where p.id = $1::bigint
332 352 ]];
333 353 };
354 +
355 + post_enum_parent = {
356 + params = {uint64}, sql = [[
357 + select a.origin is null,
358 + p.id, p.author, p.subject, p.acl, p.body,
359 + extract(epoch from p.posted )::bigint,
360 + extract(epoch from p.discovered)::bigint,
361 + extract(epoch from p.edited )::bigint,
362 + p.parent, p.convoheaduri, p.chgcount,
363 + coalesce(c.value, -1)::smallint
364 +
365 + from parsav_posts as p
366 + inner join parsav_actors as a on a.id = p.author
367 + left join parsav_actor_conf_ints as c on c.uid = a.id and c.key = 'ui-accent'
368 + where p.parent = $1::bigint
369 + order by p.posted, p.discovered asc
370 + ]]
371 + };
372 +
373 + thread_latest_arrival_calc = {
374 + params = {uint64}, sql = [[
375 + with recursive posts(id) as (
376 + select id from parsav_posts where parent = $1::bigint
377 + union
378 + select p.id from parsav_posts as p
379 + inner join posts on posts.id = p.parent
380 + ),
381 +
382 + maxes as (
383 + select unnest(array[max(p.posted), max(p.discovered), max(p.edited)]) as m
384 + from posts
385 + inner join parsav_posts as p
386 + on p.id = posts.id
387 + )
388 +
389 + select extract(epoch from max(m))::bigint from maxes
390 + ]];
391 + };
334 392
335 393 post_enum_author_uid = {
336 394 params = {uint64,uint64,uint64,uint64, uint64}, sql = [[
337 395 select a.origin is null,
338 396 p.id, p.author, p.subject, p.acl, p.body,
339 397 extract(epoch from p.posted )::bigint,
340 398 extract(epoch from p.discovered)::bigint,
341 399 extract(epoch from p.edited )::bigint,
342 - p.parent, p.convoheaduri, p.chgcount
400 + p.parent, p.convoheaduri, p.chgcount,
401 + coalesce((select value from parsav_actor_conf_ints as c where
402 + c.uid = $1::bigint and c.key = 'ui-accent'),-1)::smallint
403 +
343 404 from parsav_posts as p
344 405 inner join parsav_actors as a on p.author = a.id
345 406 where p.author = $5::bigint and
346 407 ($1::bigint = 0 or p.posted <= to_timestamp($1::bigint)) and
347 408 ($2::bigint = 0 or to_timestamp($2::bigint) < p.posted)
348 409 order by (p.posted, p.discovered) desc
349 410 limit case when $3::bigint = 0 then null
................................................................................
357 418 timeline_instance_fetch = {
358 419 params = {uint64, uint64, uint64, uint64}, sql = [[
359 420 select true,
360 421 p.id, p.author, p.subject, p.acl, p.body,
361 422 extract(epoch from p.posted )::bigint,
362 423 extract(epoch from p.discovered)::bigint,
363 424 extract(epoch from p.edited )::bigint,
364 - p.parent, null::text, p.chgcount
425 + p.parent, null::text, p.chgcount,
426 + coalesce(c.value, -1)::smallint
427 +
365 428 from parsav_posts as p
366 - inner join parsav_actors as a on p.author = a.id
429 + inner join parsav_actors as a on p.author = a.id
430 + left join parsav_actor_conf_ints as c on c.uid = a.id and c.key = 'ui-accent'
367 431 where
368 432 ($1::bigint = 0 or p.posted <= to_timestamp($1::bigint)) and
369 433 ($2::bigint = 0 or to_timestamp($2::bigint) < p.posted) and
370 434 (a.origin is null)
371 435 order by (p.posted, p.discovered) desc
372 436 limit case when $3::bigint = 0 then null
373 437 else $3::bigint end
................................................................................
430 494 ]];
431 495 };
432 496 post_attach_ctl_ins = {
433 497 params = {uint64, uint64}, cmd=true, sql = [[
434 498 update parsav_posts set
435 499 artifacts = artifacts || $2::bigint
436 500 where id = $1::bigint and not
437 - artifacts @> array[$2::bigint]
501 + artifacts @> array[$2::bigint] -- prevent duplication
438 502 ]];
439 503 };
440 504 post_attach_ctl_del = {
441 505 params = {uint64, uint64}, cmd=true, sql = [[
442 506 update parsav_posts set
443 507 artifacts = array_remove(artifacts, $2::bigint)
444 508 where id = $1::bigint and
445 509 artifacts @> array[$2::bigint]
446 510 ]];
447 511 };
512 +
513 + actor_conf_str_get = {
514 + params = {uint64, rawstring}, sql = [[
515 + select value from parsav_actor_conf_strs where
516 + uid = $1::bigint and
517 + key = $2::text
518 + limit 1
519 + ]];
520 + };
521 + actor_conf_str_set = {
522 + params = {uint64, rawstring, rawstring}, cmd = true, sql = [[
523 + insert into parsav_actor_conf_strs (uid,key,value)
524 + values ($1::bigint, $2::text, $3::text)
525 + on conflict (uid,key) do update set value = $3::text
526 + ]];
527 + };
528 + actor_conf_str_enum = {
529 + params = {uint64}, sql = [[
530 + select value from parsav_actor_conf_strs where uid = $1::bigint
531 + ]];
532 + };
533 + actor_conf_str_reset = {
534 + params = {uint64, rawstring}, cmd = true, sql = [[
535 + delete from parsav_actor_conf_strs where
536 + uid = $1::bigint and ($2::text is null or key = $2::text)
537 + ]]
538 + };
539 +
540 + actor_conf_int_get = {
541 + params = {uint64, rawstring}, sql = [[
542 + select value from parsav_actor_conf_ints where
543 + uid = $1::bigint and
544 + key = $2::text
545 + limit 1
546 + ]];
547 + };
548 + actor_conf_int_set = {
549 + params = {uint64, rawstring, uint64}, cmd = true, sql = [[
550 + insert into parsav_actor_conf_ints (uid,key,value)
551 + values ($1::bigint, $2::text, $3::bigint)
552 + on conflict (uid,key) do update set value = $3::bigint
553 + ]];
554 + };
555 + actor_conf_int_enum = {
556 + params = {uint64}, sql = [[
557 + select value from parsav_actor_conf_ints where uid = $1::bigint
558 + ]];
559 + };
560 + actor_conf_int_reset = {
561 + params = {uint64, rawstring}, cmd = true, sql = [[
562 + delete from parsav_actor_conf_ints where
563 + uid = $1::bigint and ($2::text is null or key = $2::text)
564 + ]]
565 + };
448 566 }
449 567
450 568 local struct pqr {
451 569 sz: intptr
452 570 res: &lib.pq.PGresult
453 571 }
454 572 terra pqr:free() if self.sz > 0 then lib.pq.PQclear(self.res) end end
................................................................................
651 769 then p.ptr.parent = 0
652 770 else p.ptr.parent = r:int(uint64,row,9)
653 771 end
654 772 if r:null(row,11)
655 773 then p.ptr.chgcount = 0
656 774 else p.ptr.chgcount = r:int(uint32,row,11)
657 775 end
776 + p.ptr.accent = r:int(int16,row,12)
658 777 p.ptr.localpost = r:bool(row,0)
659 778
660 779 return p
661 780 end
662 781 local terra row_to_actor(r: &pqr, row: intptr): lib.mem.ptr(lib.store.actor)
663 782 var a: lib.mem.ptr(lib.store.actor)
664 783 var av: rawstring, avlen: intptr
................................................................................
1025 1144 [lib.mem.ptr(lib.store.actor)] { ptr = nil, ct = 0 }
1026 1145 end];
1027 1146
1028 1147 post_create = [terra(
1029 1148 src: &lib.store.source,
1030 1149 post: &lib.store.post
1031 1150 ): uint64
1032 - var r = queries.post_create.exec(src,post.author,post.subject,post.acl,post.body)
1151 + var r = queries.post_create.exec(src,
1152 + post.author,post.subject,post.acl,post.body,
1153 + post.parent,post.posted,post.convoheaduri
1154 + )
1033 1155 if r.sz == 0 then return 0 end
1034 1156 defer r:free()
1035 1157 var id = r:int(uint64,0,0)
1158 + post.source = src
1036 1159 return id
1037 1160 end];
1038 1161
1039 1162 post_destroy = [terra(
1040 1163 src: &lib.store.source,
1041 1164 post: uint64
1042 1165 ): {}
................................................................................
1114 1237 lib.dbg('created new actor, establishing powers')
1115 1238 privupdate(src,ac)
1116 1239
1117 1240 lib.dbg('powers established')
1118 1241 return ac.id
1119 1242 end];
1120 1243
1121 - auth_create_pw = [terra(
1244 + auth_enum_uid = [terra(
1245 + src: &lib.store.source,
1246 + uid: uint64
1247 + ): lib.mem.ptr(lib.mem.ptr(lib.store.auth))
1248 + var r = queries.auth_enum_uid.exec(src,uid)
1249 + if r.sz == 0 then return [lib.mem.ptr(lib.mem.ptr(lib.store.auth))].null() end
1250 + var ret = lib.mem.heapa([lib.mem.ptr(lib.store.auth)], r.sz)
1251 + for i=0, r.sz do
1252 + var kind = r:_string(i, 1)
1253 + var comment = r:_string(i, 2)
1254 + var a = [ lib.str.encapsulate(lib.store.auth, {
1255 + kind = {`kind.ptr, `kind.ct};
1256 + comment = {`comment.ptr, `comment.ct};
1257 + }) ]
1258 + a.ptr.aid = r:int(uint64, i, 0)
1259 + a.ptr.netmask = r:cidr(i, 3)
1260 + a.ptr.blacklist = r:bool(i, 4)
1261 + ret.ptr[i] = a
1262 + end
1263 + return ret
1264 + end];
1265 +
1266 + auth_attach_pw = [terra(
1122 1267 src: &lib.store.source,
1123 1268 uid: uint64,
1124 1269 reset: bool,
1125 - pw: lib.mem.ptr(int8)
1270 + pw: pstring,
1271 + comment: pstring
1126 1272 ): {}
1127 1273 var hash: uint8[lib.crypt.algsz.sha256]
1128 1274 if lib.md.mbedtls_md(lib.md.mbedtls_md_info_from_type(lib.crypt.alg.sha256.id),
1129 1275 [&uint8](pw.ptr), pw.ct, &hash[0]) ~= 0 then
1130 1276 lib.bail('cannot hash password')
1131 1277 end
1132 1278 if reset then queries.auth_purge_type.exec(src, nil, uid, 'pw-%') end
1133 - queries.auth_create_pw.exec(src, uid, [lib.mem.ptr(uint8)] {ptr = &hash[0], ct = [hash.type.N]})
1279 + queries.auth_create_pw.exec(src, uid, binblob {ptr = &hash[0], ct = [hash.type.N]}, comment)
1134 1280 end];
1135 1281
1136 1282 auth_purge_pw = [terra(src: &lib.store.source, uid: uint64, handle: rawstring): {}
1137 1283 queries.auth_purge_type.exec(src, handle, uid, 'pw-%')
1138 1284 end];
1139 1285
1140 1286 auth_purge_otp = [terra(src: &lib.store.source, uid: uint64, handle: rawstring): {}
................................................................................
1208 1354 src: &lib.store.source,
1209 1355 post: &lib.store.post
1210 1356 ): {}
1211 1357 queries.post_save.exec(src,
1212 1358 post.id, post.chgcount, post.edited,
1213 1359 post.subject, post.acl, post.body)
1214 1360 end];
1361 +
1362 + post_enum_parent = [terra(
1363 + src: &lib.store.source,
1364 + post: uint64
1365 + ): lib.mem.ptr(lib.mem.ptr(lib.store.post))
1366 + var r = queries.post_enum_parent.exec(src,post)
1367 + if r.sz == 0 then
1368 + return [lib.mem.ptr(lib.mem.ptr(lib.store.post))].null()
1369 + end
1370 + defer r:free()
1371 + var lst = lib.mem.heapa([lib.mem.ptr(lib.store.post)], r.sz)
1372 +
1373 + for i=0, r.sz do lst.ptr[i] = row_to_post(&r, i) end
1374 +
1375 + return lst
1376 + end];
1377 +
1378 + thread_latest_arrival_calc = [terra(
1379 + src: &lib.store.source,
1380 + post: uint64
1381 + ): lib.store.timepoint
1382 + var r = queries.thread_latest_arrival_calc.exec(src,post)
1383 + if r.sz == 0 or r:null(0,0) then return 0 end
1384 + var tp: lib.store.timepoint = r:int(int64,0,0)
1385 + r:free()
1386 + return tp
1387 + end];
1215 1388
1216 1389 auth_sigtime_user_fetch = [terra(
1217 1390 src: &lib.store.source,
1218 1391 uid: uint64
1219 1392 ): lib.store.timepoint
1220 1393 var r = queries.auth_sigtime_user_fetch.exec(src, uid)
1221 1394 if r.sz > 0 then defer r:free()
................................................................................
1226 1399
1227 1400 auth_sigtime_user_alter = [terra(
1228 1401 src: &lib.store.source,
1229 1402 uid: uint64,
1230 1403 time: lib.store.timepoint
1231 1404 ): {} queries.auth_sigtime_user_alter.exec(src, uid, time) end];
1232 1405
1406 + actor_conf_str_enum = nil;
1407 + actor_conf_str_get = [terra(src: &lib.store.source, uid: uint64, key: rawstring): pstring
1408 + var r = queries.actor_conf_str_get.exec(src, uid, key)
1409 + if r.sz > 0 then
1410 + var ret = r:String(0,0)
1411 + r:free()
1412 + return ret
1413 + else return pstring.null() end
1414 + end];
1415 + actor_conf_str_set = [terra(src: &lib.store.source, uid: uint64, key: rawstring, value: rawstring): {}
1416 + queries.actor_conf_str_set.exec(src,uid,key,value) end];
1417 + actor_conf_str_reset = [terra(src: &lib.store.source, uid: uint64, key: rawstring): {}
1418 + queries.actor_conf_str_reset.exec(src,uid,key) end];
1419 +
1420 + actor_conf_int_enum = nil;
1421 + actor_conf_int_get = [terra(src: &lib.store.source, uid: uint64, key: rawstring)
1422 + var r = queries.actor_conf_int_get.exec(src, uid, key)
1423 + if r.sz > 0 then
1424 + var ret = r:int(uint64,0,0)
1425 + r:free()
1426 + return ret, true
1427 + end
1428 + return 0, false
1429 + end];
1430 + actor_conf_int_set = [terra(src: &lib.store.source, uid: uint64, key: rawstring, value: uint64): {}
1431 + queries.actor_conf_int_set.exec(src,uid,key,value) end];
1432 + actor_conf_int_reset = [terra(src: &lib.store.source, uid: uint64, key: rawstring): {}
1433 + queries.actor_conf_int_reset.exec(src,uid,key) end];
1434 +
1233 1435 actor_auth_register_uid = nil; -- TODO better support non-view based auth
1234 1436 }
1235 1437
1236 1438 return b