parsav  Diff

Differences From Artifact [d54604496b]:

To Artifact [af6b4187ca]:


167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
...
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
...
209
210
211
212
213
214
215
216



217
218
219
220
221
222
223
...
234
235
236
237
238
239
240















241
242
243
244
245
246
247
...
252
253
254
255
256
257
258















259
260
261
262
263
264
265
...
266
267
268
269
270
271
272














273
274
275
276
277
278
279

280
281
282
283
284
285
286
287
...
294
295
296
297
298
299
300

301
302
303
304
305
306
307
308
...
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585

586
587
588




589
590
591
592
593
594
595
...
918
919
920
921
922
923
924
925

926
927
928
929
930
931
932
933
934
...
959
960
961
962
963
964
965











966
967
968
969
970
971
972
....
1106
1107
1108
1109
1110
1111
1112


























1113
1114
1115
1116
1117

			values (
				(select count(tweets.*)::bigint from tweets),
				(select count(follows.*)::bigint from follows),
				(select count(followers.*)::bigint from followers),
				(select count(mutuals.*)::bigint from mutuals)
			)
		]]):gsub('<(%w+)>',function(r) return tostring(lib.store.relation[r]) end)
	};

	actor_auth_how = {
		params = {rawstring, lib.store.inet}, sql = [[
		with mts as (select a.kind from parsav_auth as a
			left join parsav_actors as u on u.id = a.uid
			where (a.uid is null or u.handle = $1::text or (
................................................................................
				(select count(*) from mts where kind like 'otp-%') > 0,
				(select count(*) from mts where kind like 'challenge-%') > 0,
				(select count(*) from mts where kind = 'trust') > 0
		]]; -- cheat
	};

	actor_session_fetch = {
		params = {uint64, lib.store.inet}, sql = [[
			select a.id, a.nym, a.handle, a.origin, a.bio,
			       a.avataruri, a.rank, a.quota, a.key, a.epithet,
			       extract(epoch from a.knownsince)::bigint,
				   coalesce(a.handle || '@' || s.domain,
				            '@' || a.handle) as xid,

			       au.restrict,
................................................................................
						array['admin' ] <@ au.restrict as can_admin

			from      parsav_auth au
			left join parsav_actors a     on au.uid = a.id
			left join parsav_servers s    on a.origin = s.id

			where au.aid = $1::bigint and au.blacklist = false and
				(au.netmask is null or au.netmask >> $2::inet)



		]];
	};

	actor_powers_fetch = {
		params = {uint64}, sql = [[
			select key, allow from parsav_rights where actor = $1::bigint
		]]
................................................................................
	actor_power_delete = {
		params = {uint64,lib.mem.ptr(int8)}, cmd = true, sql = [[
			delete from parsav_rights where
				actor = $1::bigint and
				key = $2::text
		]]
	};
















	auth_create_pw = {
		params = {uint64, lib.mem.ptr(uint8)}, cmd = true, sql = [[
			insert into parsav_auth (uid, name, kind, cred) values (
				$1::bigint,
				(select handle from parsav_actors where id = $1::bigint),
				'pw-sha256', $2::bytea
................................................................................
	auth_purge_type = {
		params = {rawstring, uint64, rawstring}, cmd = true, sql = [[
			delete from parsav_auth where
				((uid = 0 and name = $1::text) or uid = $2::bigint) and
				kind like $3::text
		]]
	};
















	post_create = {
		params = {uint64, rawstring, rawstring, rawstring}, sql = [[
			insert into parsav_posts (
				author, subject, acl, body,
				posted, discovered,
				circles, mentions
................................................................................
			) values (
				$1::bigint, case when $2::text = '' then null else $2::text end,
				$3::text, $4::text, 
				now(), now(), array[]::bigint[], array[]::bigint[]
			) returning id
		]]; -- TODO array handling
	};















	post_enum_author_uid = {
		params = {uint64,uint64,uint64,uint64, uint64}, sql = [[
			select a.origin is null,
				p.id, p.author, p.subject, p.acl, p.body,
				extract(epoch from p.posted    )::bigint,
				extract(epoch from p.discovered)::bigint,

				p.parent, p.convoheaduri
			from parsav_posts as p
				inner join parsav_actors as a on p.author = a.id
			where p.author = $5::bigint and
				($1::bigint = 0 or p.posted <= to_timestamp($1::bigint)) and
				($2::bigint = 0 or to_timestamp($2::bigint) < p.posted)
			order by (p.posted, p.discovered) desc
			limit case when $3::bigint = 0 then null
................................................................................

	timeline_instance_fetch = {
		params = {uint64, uint64, uint64, uint64}, sql = [[
			select true,
				p.id, p.author, p.subject, p.acl, p.body,
				extract(epoch from p.posted    )::bigint,
				extract(epoch from p.discovered)::bigint,

				p.parent, null::text
			from parsav_posts as p
				inner join parsav_actors as a on p.author = a.id
			where
				($1::bigint = 0 or p.posted <= to_timestamp($1::bigint)) and
				($2::bigint = 0 or to_timestamp($2::bigint) < p.posted) and
				(a.origin is null)
			order by (p.posted, p.discovered) desc
................................................................................
local terra row_to_post(r: &pqr, row: intptr): lib.mem.ptr(lib.store.post)
	var subj: rawstring, sblen: intptr
	var cvhu: rawstring, cvhlen: intptr
	if r:null(row,3)
		then subj = nil sblen = 0
		else subj = r:string(row,3) sblen = r:len(row,3)+1
	end
	if r:null(row,9)
		then cvhu = nil cvhlen = 0
		else cvhu = r:string(row,9) cvhlen = r:len(row,9)+1
	end
	var p = [ lib.str.encapsulate(lib.store.post, {
		subject = { `subj, `sblen };
		acl = {`r:string(row,4), `r:len(row,4)+1};
		body = {`r:string(row,5), `r:len(row,5)+1};
		convoheaduri = { `cvhu, `cvhlen }; --FIXME
	}) ]
	p.ptr.id = r:int(uint64,row,1)
	p.ptr.author = r:int(uint64,row,2)
	p.ptr.posted = r:int(uint64,row,6)
	p.ptr.discovered = r:int(uint64,row,7)

	if r:null(row,8)
		then p.ptr.parent = 0
		else p.ptr.parent = r:int(uint64,row,8)




	end 
	p.ptr.localpost = r:bool(row,0)

	return p
end
local terra row_to_actor(r: &pqr, row: intptr): lib.mem.ptr(lib.store.actor)
	var a: lib.mem.ptr(lib.store.actor)
................................................................................
		s.mutuals = r:int(uint64, 0, 3)
		return s
	end];

	actor_session_fetch = [terra(
		src: &lib.store.source,
		aid: uint64,
		ip : lib.store.inet

	): { lib.stat(lib.store.auth), lib.mem.ptr(lib.store.actor) }
		var r = queries.actor_session_fetch.exec(src, aid, ip)
		if r.sz == 0 then goto fail end
		do defer r:free()

			if r:null(0,0) then goto fail end

			var a = row_to_actor(&r, 0)
			a.ptr.source = src
................................................................................
	): uint64
		var r = queries.post_create.exec(src,post.author,post.subject,post.acl,post.body) 
		if r.sz == 0 then return 0 end
		defer r:free()
		var id = r:int(uint64,0,0)
		return id
	end];












	timeline_instance_fetch = [terra(src: &lib.store.source, rg: lib.store.range)
		var r = pqr { sz = 0 }
		var A,B,C,D = rg:matrix() -- :/
		r = queries.timeline_instance_fetch.exec(src,A,B,C,D)
		
		var ret: lib.mem.ptr(lib.mem.ptr(lib.store.post)) ret:init(r.sz)
................................................................................
		detach: bool
	): {}
		if detach
			then queries.post_attach_ctl_del.exec(src,post,artifact)
			else queries.post_attach_ctl_ins.exec(src,post,artifact)
		end
	end];



























	actor_auth_register_uid = nil; -- TODO better support non-view based auth
}

return b







|







 







|







 







|
>
>
>







 







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







 







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







 







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







>
|







 







>
|







 







|

|











>
|

|
>
>
>
>







 







|
>

|







 







>
>
>
>
>
>
>
>
>
>
>







 







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





167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
...
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
...
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
...
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
...
270
271
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
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
...
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
...
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
...
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
....
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
....
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209

			values (
				(select count(tweets.*)::bigint from tweets),
				(select count(follows.*)::bigint from follows),
				(select count(followers.*)::bigint from followers),
				(select count(mutuals.*)::bigint from mutuals)
			)
		]]):gsub('<(%w+)>',function(r) return tostring(lib.store.relation.idvmap[r]) end)
	};

	actor_auth_how = {
		params = {rawstring, lib.store.inet}, sql = [[
		with mts as (select a.kind from parsav_auth as a
			left join parsav_actors as u on u.id = a.uid
			where (a.uid is null or u.handle = $1::text or (
................................................................................
				(select count(*) from mts where kind like 'otp-%') > 0,
				(select count(*) from mts where kind like 'challenge-%') > 0,
				(select count(*) from mts where kind = 'trust') > 0
		]]; -- cheat
	};

	actor_session_fetch = {
		params = {uint64, lib.store.inet, int64}, sql = [[
			select a.id, a.nym, a.handle, a.origin, a.bio,
			       a.avataruri, a.rank, a.quota, a.key, a.epithet,
			       extract(epoch from a.knownsince)::bigint,
				   coalesce(a.handle || '@' || s.domain,
				            '@' || a.handle) as xid,

			       au.restrict,
................................................................................
						array['admin' ] <@ au.restrict as can_admin

			from      parsav_auth au
			left join parsav_actors a     on au.uid = a.id
			left join parsav_servers s    on a.origin = s.id

			where au.aid = $1::bigint and au.blacklist = false and
				(au.netmask is null or au.netmask >> $2::inet) and
				($3::bigint = 0 or --slightly abusing the epoch time fmt here, but
					((a.authtime   is null or a.authtime   <= to_timestamp($3::bigint)) and
					 (au.valperiod is null or au.valperiod <= to_timestamp($3::bigint))))
		]];
	};

	actor_powers_fetch = {
		params = {uint64}, sql = [[
			select key, allow from parsav_rights where actor = $1::bigint
		]]
................................................................................
	actor_power_delete = {
		params = {uint64,lib.mem.ptr(int8)}, cmd = true, sql = [[
			delete from parsav_rights where
				actor = $1::bigint and
				key = $2::text
		]]
	};

	auth_sigtime_user_fetch = {
		params = {uint64}, sql = [[
			select extract(epoch from authtime)::bigint
			from parsav_actors where id = $1::bigint
		]];
	};

	auth_sigtime_user_alter = {
		params = {uint64,int64}, cmd = true, sql = [[
			update parsav_actors set
				authtime = to_timestamp($2::bigint)
				where id = $1::bigint
		]];
	};

	auth_create_pw = {
		params = {uint64, lib.mem.ptr(uint8)}, cmd = true, sql = [[
			insert into parsav_auth (uid, name, kind, cred) values (
				$1::bigint,
				(select handle from parsav_actors where id = $1::bigint),
				'pw-sha256', $2::bytea
................................................................................
	auth_purge_type = {
		params = {rawstring, uint64, rawstring}, cmd = true, sql = [[
			delete from parsav_auth where
				((uid = 0 and name = $1::text) or uid = $2::bigint) and
				kind like $3::text
		]]
	};

	post_save = {
		params = {
			uint64, uint32, int64;
			rawstring, rawstring, rawstring;
		}, cmd = true, sql = [[
			update parsav_posts set
				subject = $4::text,
				acl = $5::text,
				body = $6::text,
				chgcount = $2::integer,
				edited = to_timestamp($3::bigint)
			where id = $1::bigint
		]]
	};

	post_create = {
		params = {uint64, rawstring, rawstring, rawstring}, sql = [[
			insert into parsav_posts (
				author, subject, acl, body,
				posted, discovered,
				circles, mentions
................................................................................
			) values (
				$1::bigint, case when $2::text = '' then null else $2::text end,
				$3::text, $4::text, 
				now(), now(), array[]::bigint[], array[]::bigint[]
			) returning id
		]]; -- TODO array handling
	};

	post_fetch = {
		params = {uint64}, sql = [[
			select a.origin is null,
				p.id, p.author, p.subject, p.acl, p.body,
				extract(epoch from p.posted    )::bigint,
				extract(epoch from p.discovered)::bigint,
				extract(epoch from p.edited    )::bigint,
				p.parent, p.convoheaduri, p.chgcount
			from parsav_posts as p
				inner join parsav_actors as a on p.author = a.id
			where p.id = $1::bigint
		]];
	};

	post_enum_author_uid = {
		params = {uint64,uint64,uint64,uint64, uint64}, sql = [[
			select a.origin is null,
				p.id, p.author, p.subject, p.acl, p.body,
				extract(epoch from p.posted    )::bigint,
				extract(epoch from p.discovered)::bigint,
				extract(epoch from p.edited    )::bigint,
				p.parent, p.convoheaduri, p.chgcount
			from parsav_posts as p
				inner join parsav_actors as a on p.author = a.id
			where p.author = $5::bigint and
				($1::bigint = 0 or p.posted <= to_timestamp($1::bigint)) and
				($2::bigint = 0 or to_timestamp($2::bigint) < p.posted)
			order by (p.posted, p.discovered) desc
			limit case when $3::bigint = 0 then null
................................................................................

	timeline_instance_fetch = {
		params = {uint64, uint64, uint64, uint64}, sql = [[
			select true,
				p.id, p.author, p.subject, p.acl, p.body,
				extract(epoch from p.posted    )::bigint,
				extract(epoch from p.discovered)::bigint,
				extract(epoch from p.edited    )::bigint,
				p.parent, null::text, p.chgcount
			from parsav_posts as p
				inner join parsav_actors as a on p.author = a.id
			where
				($1::bigint = 0 or p.posted <= to_timestamp($1::bigint)) and
				($2::bigint = 0 or to_timestamp($2::bigint) < p.posted) and
				(a.origin is null)
			order by (p.posted, p.discovered) desc
................................................................................
local terra row_to_post(r: &pqr, row: intptr): lib.mem.ptr(lib.store.post)
	var subj: rawstring, sblen: intptr
	var cvhu: rawstring, cvhlen: intptr
	if r:null(row,3)
		then subj = nil sblen = 0
		else subj = r:string(row,3) sblen = r:len(row,3)+1
	end
	if r:null(row,10)
		then cvhu = nil cvhlen = 0
		else cvhu = r:string(row,10) cvhlen = r:len(row,10)+1
	end
	var p = [ lib.str.encapsulate(lib.store.post, {
		subject = { `subj, `sblen };
		acl = {`r:string(row,4), `r:len(row,4)+1};
		body = {`r:string(row,5), `r:len(row,5)+1};
		convoheaduri = { `cvhu, `cvhlen }; --FIXME
	}) ]
	p.ptr.id = r:int(uint64,row,1)
	p.ptr.author = r:int(uint64,row,2)
	p.ptr.posted = r:int(uint64,row,6)
	p.ptr.discovered = r:int(uint64,row,7)
	p.ptr.edited = r:int(uint64,row,8)
	if r:null(row,9)
		then p.ptr.parent = 0
		else p.ptr.parent = r:int(uint64,row,9)
	end 
	if r:null(row,11)
		then p.ptr.chgcount = 0
		else p.ptr.chgcount = r:int(uint32,row,11)
	end 
	p.ptr.localpost = r:bool(row,0)

	return p
end
local terra row_to_actor(r: &pqr, row: intptr): lib.mem.ptr(lib.store.actor)
	var a: lib.mem.ptr(lib.store.actor)
................................................................................
		s.mutuals = r:int(uint64, 0, 3)
		return s
	end];

	actor_session_fetch = [terra(
		src: &lib.store.source,
		aid: uint64,
		ip : lib.store.inet,
		issuetime: lib.store.timepoint
	): { lib.stat(lib.store.auth), lib.mem.ptr(lib.store.actor) }
		var r = queries.actor_session_fetch.exec(src, aid, ip, issuetime)
		if r.sz == 0 then goto fail end
		do defer r:free()

			if r:null(0,0) then goto fail end

			var a = row_to_actor(&r, 0)
			a.ptr.source = src
................................................................................
	): uint64
		var r = queries.post_create.exec(src,post.author,post.subject,post.acl,post.body) 
		if r.sz == 0 then return 0 end
		defer r:free()
		var id = r:int(uint64,0,0)
		return id
	end];

	post_fetch = [terra(
		src: &lib.store.source,
		post: uint64
	): lib.mem.ptr(lib.store.post)
		var r = queries.post_fetch.exec(src, post)
		if r.sz == 0 then return [lib.mem.ptr(lib.store.post)].null() end
		var p = row_to_post(&r, 0)
		p.ptr.source = src
		return p
	end];

	timeline_instance_fetch = [terra(src: &lib.store.source, rg: lib.store.range)
		var r = pqr { sz = 0 }
		var A,B,C,D = rg:matrix() -- :/
		r = queries.timeline_instance_fetch.exec(src,A,B,C,D)
		
		var ret: lib.mem.ptr(lib.mem.ptr(lib.store.post)) ret:init(r.sz)
................................................................................
		detach: bool
	): {}
		if detach
			then queries.post_attach_ctl_del.exec(src,post,artifact)
			else queries.post_attach_ctl_ins.exec(src,post,artifact)
		end
	end];
	
	post_save = [terra(
		src: &lib.store.source,
		post: &lib.store.post
	): {}
		queries.post_save.exec(src,
			post.id, post.chgcount, post.edited,
			post.subject, post.acl, post.body)
	end];

	auth_sigtime_user_fetch = [terra(
		src: &lib.store.source,
		uid: uint64
	): lib.store.timepoint
		var r = queries.auth_sigtime_user_fetch.exec(src, uid)
		if r.sz > 0 then defer r:free()
			var t = r:int(int64,0,0)
			return t
		else return 0 end
	end];

	auth_sigtime_user_alter = [terra(
		src: &lib.store.source,
		uid: uint64,
		time: lib.store.timepoint
	): {} queries.auth_sigtime_user_alter.exec(src, uid, time) end];

	actor_auth_register_uid = nil; -- TODO better support non-view based auth
}

return b