Differences From
Artifact [30375d8380]:
26 26
27 27 actor_fetch_uid = {
28 28 params = {uint64}, sql = [[
29 29 select a.id, a.nym, a.handle, a.origin, a.bio,
30 30 a.avataruri, a.rank, a.quota, a.key, a.epithet,
31 31 extract(epoch from a.knownsince)::bigint,
32 32 coalesce(a.handle || '@' || s.domain,
33 - '@' || a.handle) as xid
33 + '@' || a.handle) as xid,
34 + a.invites
34 35
35 36 from parsav_actors as a
36 37 left join parsav_servers as s
37 38 on a.origin = s.id
38 39 where a.id = $1::bigint
39 40 ]];
40 41 };
................................................................................
42 43 actor_fetch_xid = {
43 44 params = {pstring}, sql = [[
44 45 select a.id, a.nym, a.handle, a.origin, a.bio,
45 46 a.avataruri, a.rank, a.quota, a.key, a.epithet,
46 47 extract(epoch from a.knownsince)::bigint,
47 48 coalesce(a.handle || '@' || s.domain,
48 49 '@' || a.handle) as xid,
50 + a.invites,
49 51
50 52 coalesce(s.domain,
51 53 (select value from parsav_config
52 54 where key='domain' limit 1)) as domain
53 55
54 56 from parsav_actors as a
55 57 left join parsav_servers as s
................................................................................
58 60 where $1::text = (a.handle || '@' || domain) or
59 61 $1::text = ('@' || a.handle || '@' || domain) or
60 62 (a.origin is null and
61 63 $1::text = a.handle or
62 64 $1::text = ('@' || a.handle))
63 65 ]];
64 66 };
67 +
68 + actor_purge_uid = {
69 + params = {uint64}, cmd = true, sql = [[
70 + with d as ( -- cheating
71 + delete from parsav_sanctions where victim = $1::bigint
72 + )
73 + delete from parsav_actors where id = $1::bigint
74 + ]];
75 + };
65 76
66 77 actor_save = {
67 78 params = {
68 79 uint64, --id
69 80 rawstring, --nym
70 81 rawstring, --handle
71 82 rawstring, --bio
72 83 rawstring, --epithet
73 84 rawstring, --avataruri
74 85 uint64, --avatarid
75 86 uint16, --rank
76 - uint32 --quota
87 + uint32, --quota
88 + uint32 --invites
77 89 }, cmd = true, sql = [[
78 90 update parsav_actors set
79 91 nym = $2::text,
80 92 handle = $3::text,
81 93 bio = $4::text,
82 94 epithet = $5::text,
83 95 avataruri = $6::text,
84 96 avatarid = $7::bigint,
85 97 rank = $8::smallint,
86 - quota = $9::integer
87 - --invites are controlled by their own specialized routines
98 + quota = $9::integer,
99 + invites = $10::integer
88 100 where id = $1::bigint
89 101 ]];
90 102 };
91 103
92 104 actor_create = {
93 105 params = {
94 106 rawstring, rawstring, uint64, lib.store.timepoint,
95 107 rawstring, rawstring, lib.mem.ptr(uint8),
96 - rawstring, uint16, uint32
108 + rawstring, uint16, uint32, uint32
97 109 };
98 110 sql = [[
99 111 insert into parsav_actors (
100 112 nym,handle,
101 113 origin,knownsince,
102 114 bio,avataruri,key,
103 - epithet,rank,quota
115 + epithet,rank,quota,
116 + invites
104 117 ) values ($1::text, $2::text,
105 118 case when $3::bigint = 0 then null
106 119 else $3::bigint end,
107 120 to_timestamp($4::bigint),
108 121 $5::bigint, $6::bigint, $7::bytea,
109 - $8::text, $9::smallint, $10::integer
122 + $8::text, $9::smallint, $10::integer,
123 + $11::integer
110 124 ) returning id
111 125 ]];
112 126 };
113 127
114 128 actor_auth_pw = {
115 129 params = {pstring,rawstring,pstring,lib.store.inet}, sql = [[
116 130 select a.aid, a.uid, a.name from parsav_auth as a
................................................................................
125 139 };
126 140
127 141 actor_enum_local = {
128 142 params = {}, sql = [[
129 143 select id, nym, handle, origin, bio,
130 144 null::text, rank, quota, key, epithet,
131 145 extract(epoch from knownsince)::bigint,
132 - handle ||'@'||
133 - (select value from parsav_config
134 - where key='domain' limit 1) as xid
146 + '@' || handle,
147 + invites
135 148 from parsav_actors where origin is null
149 + order by nullif(rank,0) nulls last, handle
136 150 ]];
137 151 };
138 152
139 153 actor_enum = {
140 154 params = {}, sql = [[
141 155 select a.id, a.nym, a.handle, a.origin, a.bio,
142 156 a.avataruri, a.rank, a.quota, a.key, a.epithet,
143 157 extract(epoch from a.knownsince)::bigint,
144 158 coalesce(a.handle || '@' || s.domain,
145 - '@' || a.handle) as xid
159 + '@' || a.handle) as xid,
160 + invites
146 161 from parsav_actors a
147 162 left join parsav_servers s on s.id = a.origin
163 + order by nullif(a.rank,0) nulls last, a.handle, a.origin
148 164 ]];
149 165 };
150 166
151 167 actor_stats = {
152 168 params = {uint64}, sql = ([[
153 169 with tweets as (
154 170 select from parsav_posts where author = $1::bigint
................................................................................
786 802 end
787 803 local terra row_to_actor(r: &pqr, row: intptr): lib.mem.ptr(lib.store.actor)
788 804 var a: lib.mem.ptr(lib.store.actor)
789 805 var av: rawstring, avlen: intptr
790 806 var nym: rawstring, nymlen: intptr
791 807 var bio: rawstring, biolen: intptr
792 808 var epi: rawstring, epilen: intptr
793 - if r:null(row,5) then avlen = 0 av = nil else
809 + var origin: uint64 = 0
810 + var handle = r:_string(row, 2)
811 + if not r:null(row,3) then origin = r:int(uint64,row,3) end
812 +
813 + var avia = lib.str.acc {buf=nil}
814 + if origin == 0 then
815 + avia:compose('/avi/',handle)
816 + av = avia.buf
817 + avlen = avia.sz+1
818 + elseif r:null(row,5) then
794 819 av = r:string(row,5)
795 820 avlen = r:len(row,5)+1
821 + else
822 + av = '/s/default-avatar.webp'
823 + avlen = 22
796 824 end
825 +
797 826 if r:null(row,1) then nymlen = 0 nym = nil else
798 827 nym = r:string(row,1)
799 828 nymlen = r:len(row,1)+1
800 829 end
801 830 if r:null(row,4) then biolen = 0 bio = nil else
802 831 bio = r:string(row,4)
803 832 biolen = r:len(row,4)+1
................................................................................
807 836 epilen = r:len(row,9)+1
808 837 end
809 838 a = [ lib.str.encapsulate(lib.store.actor, {
810 839 nym = {`nym, `nymlen};
811 840 bio = {`bio, `biolen};
812 841 epithet = {`epi, `epilen};
813 842 avatar = {`av,`avlen};
814 - handle = {`r:string(row, 2); `r:len(row,2) + 1};
843 + handle = {`handle.ptr, `handle.ct + 1};
815 844 xid = {`r:string(row, 11); `r:len(row,11) + 1};
816 845 }) ]
817 846 a.ptr.id = r:int(uint64, row, 0);
818 847 a.ptr.rights = lib.store.rights_default();
819 848 a.ptr.rights.rank = r:int(uint16, row, 6);
820 849 a.ptr.rights.quota = r:int(uint32, row, 7);
850 + a.ptr.rights.invites = r:int(uint32, row, 12);
821 851 a.ptr.knownsince = r:int(int64,row, 10);
822 852 if r:null(row,8) then
823 853 a.ptr.key.ct = 0 a.ptr.key.ptr = nil
824 854 else
825 855 a.ptr.key = r:bin(row,8)
826 856 end
827 - if r:null(row,3) then a.ptr.origin = 0
828 - else a.ptr.origin = r:int(uint64,row,3) end
857 + a.ptr.origin = origin
858 + if avia.buf ~= nil then avia:free() end
829 859 return a
830 860 end
831 861
832 862 local privmap = lib.store.privmap
833 863
834 864 local checksha = function(src, hash, origin, username, pw)
835 865 local validate = function(kind, cred, credlen)
................................................................................
873 903 local schema = sqlsquash(lib.util.ingest('backend/schema/pgsql.sql'))
874 904 local obliterator = sqlsquash(lib.util.ingest('backend/schema/pgsql-drop.sql'))
875 905
876 906 local privupdate = terra(
877 907 src: &lib.store.source,
878 908 ac: &lib.store.actor
879 909 ): {}
880 - var pdef = lib.store.rights_default().powers
910 + var pdef: lib.store.powerset pdef:clear()
881 911 var map = array([privmap])
882 912 for i=0, [map.type.N] do
883 913 var d = pdef and map[i].priv
884 914 var u = ac.rights.powers and map[i].priv
885 915 queries.actor_power_delete.exec(src, ac.id, map[i].name)
886 916 if d:sz() > 0 and u:sz() == 0 then
887 917 lib.dbg('blocking power ', {map[i].name.ptr, map[i].name.ct})
................................................................................
1042 1072 return a
1043 1073 end
1044 1074 end];
1045 1075
1046 1076 actor_enum = [terra(src: &lib.store.source)
1047 1077 var r = queries.actor_enum.exec(src)
1048 1078 if r.sz == 0 then
1049 - return [lib.mem.ptr(&lib.store.actor)] { ct = 0, ptr = nil }
1079 + return [lib.mem.lstptr(lib.store.actor)].null()
1050 1080 else defer r:free()
1051 - var mem = lib.mem.heapa([&lib.store.actor], r.sz)
1081 + var mem = lib.mem.heapa([lib.mem.ptr(lib.store.actor)], r.sz)
1052 1082 for i=0,r.sz do
1053 - mem.ptr[i] = row_to_actor(&r, i).ptr
1054 - mem.ptr[i].source = src
1083 + mem.ptr[i] = row_to_actor(&r, i)
1084 + mem(i).ptr.source = src
1055 1085 end
1056 - return [lib.mem.ptr(&lib.store.actor)] { ct = r.sz, ptr = mem.ptr }
1086 + return [lib.mem.lstptr(lib.store.actor)] { ct = r.sz, ptr = mem.ptr }
1057 1087 end
1058 1088 end];
1059 1089
1060 1090 actor_enum_local = [terra(src: &lib.store.source)
1061 1091 var r = queries.actor_enum_local.exec(src)
1062 1092 if r.sz == 0 then
1063 - return [lib.mem.ptr(&lib.store.actor)] { ct = 0, ptr = nil }
1093 + return [lib.mem.lstptr(lib.store.actor)].null()
1064 1094 else defer r:free()
1065 - var mem = lib.mem.heapa([&lib.store.actor], r.sz)
1095 + var mem = lib.mem.heapa([lib.mem.ptr(lib.store.actor)], r.sz)
1066 1096 for i=0,r.sz do
1067 - mem.ptr[i] = row_to_actor(&r, i).ptr
1068 - mem.ptr[i].source = src
1097 + mem.ptr[i] = row_to_actor(&r, i)
1098 + mem(i).ptr.source = src
1069 1099 end
1070 - return [lib.mem.ptr(&lib.store.actor)] { ct = r.sz, ptr = mem.ptr }
1100 + return [lib.mem.lstptr(lib.store.actor)] { ct = r.sz, ptr = mem.ptr }
1071 1101 end
1072 1102 end];
1073 1103
1074 1104 actor_auth_how = [terra(
1075 1105 src: &lib.store.source,
1076 1106 ip: lib.store.inet,
1077 1107 username: rawstring
................................................................................
1129 1159
1130 1160 var a = row_to_actor(&r, 0)
1131 1161 a.ptr.source = src
1132 1162
1133 1163 var au = [lib.stat(lib.store.auth)] { ok = true }
1134 1164 au.val.aid = aid
1135 1165 au.val.uid = a.ptr.id
1136 - if not r:null(0,13) then -- restricted?
1166 + if not r:null(0,14) then -- restricted?
1137 1167 au.val.privs:clear()
1138 - (au.val.privs.post << r:bool(0,14))
1139 - (au.val.privs.edit << r:bool(0,15))
1140 - (au.val.privs.acct << r:bool(0,16))
1141 - (au.val.privs.upload << r:bool(0,17))
1142 - (au.val.privs.censor << r:bool(0,18))
1143 - (au.val.privs.admin << r:bool(0,19))
1168 + (au.val.privs.post << r:bool(0,15))
1169 + (au.val.privs.edit << r:bool(0,16))
1170 + (au.val.privs.acct << r:bool(0,17))
1171 + (au.val.privs.upload << r:bool(0,18))
1172 + (au.val.privs.censor << r:bool(0,19))
1173 + (au.val.privs.admin << r:bool(0,20))
1144 1174 else au.val.privs:fill() end
1145 1175
1146 1176 return au, a
1147 1177 end
1148 1178
1149 1179 ::fail:: return [lib.stat (lib.store.auth) ] { ok = false },
1150 1180 [lib.mem.ptr(lib.store.actor)] { ptr = nil, ct = 0 }
................................................................................
1219 1249 end];
1220 1250
1221 1251 actor_powers_fetch = getpow;
1222 1252 actor_save = [terra(
1223 1253 src: &lib.store.source,
1224 1254 ac: &lib.store.actor
1225 1255 ): {}
1256 + var avatar = ac.avatar
1257 + if ac.origin == 0 then avatar = nil end
1226 1258 queries.actor_save.exec(src,
1227 1259 ac.id, ac.nym, ac.handle,
1228 - ac.bio, ac.epithet, ac.avatar,
1229 - ac.avatarid, ac.rights.rank, ac.rights.quota)
1260 + ac.bio, ac.epithet, avatar,
1261 + ac.avatarid, ac.rights.rank, ac.rights.quota, ac.rights.invites)
1230 1262 end];
1231 1263
1232 1264 actor_save_privs = privupdate;
1233 1265
1234 1266 actor_create = [terra(
1235 1267 src: &lib.store.source,
1236 1268 ac: &lib.store.actor
1237 1269 ): uint64
1238 - var r = queries.actor_create.exec(src,ac.nym, ac.handle, ac.origin, ac.knownsince, ac.bio, ac.avatar, ac.key, ac.epithet, ac.rights.rank, ac.rights.quota)
1270 + var r = queries.actor_create.exec(src,ac.nym, ac.handle, ac.origin, ac.knownsince, ac.bio, ac.avatar, ac.key, ac.epithet, ac.rights.rank, ac.rights.quota,ac.rights.invites)
1239 1271 if r.sz == 0 then lib.bail('failed to create actor!') end
1240 1272 ac.id = r:int(uint64,0,0)
1241 1273
1242 1274 -- check against default rights, insert records for wherever powers differ
1243 1275 lib.dbg('created new actor, establishing powers')
1244 1276 privupdate(src,ac)
1245 1277
1246 1278 lib.dbg('powers established')
1247 1279 return ac.id
1248 1280 end];
1249 1281
1282 + actor_purge_uid = [terra(
1283 + src: &lib.store.source,
1284 + uid: uint64
1285 + ) queries.actor_purge_uid.exec(src,uid) end];
1286 +
1250 1287 auth_enum_uid = [terra(
1251 1288 src: &lib.store.source,
1252 1289 uid: uint64
1253 1290 ): lib.mem.ptr(lib.mem.ptr(lib.store.auth))
1254 1291 var r = queries.auth_enum_uid.exec(src,uid)
1255 1292 if r.sz == 0 then return [lib.mem.ptr(lib.mem.ptr(lib.store.auth))].null() end
1256 1293 var ret = lib.mem.heapa([lib.mem.ptr(lib.store.auth)], r.sz)