Overview
| Comment: | start work on user mgmt |
|---|---|
| Downloads: | Tarball | ZIP archive | SQL archive |
| Timelines: | family | ancestors | descendants | both | trunk |
| Files: | files | file ages | folders |
| SHA3-256: |
db4c5fd644227803a989a7a70a842129 |
| User & Date: | lexi on 2020-12-31 02:18:38 |
| Other Links: | manifest | tags |
Context
|
2021-01-01
| ||
| 04:33 | add live updates, system to only update when necessary almost works check-in: 24ec409083 user: lexi tags: trunk | |
|
2020-12-31
| ||
| 02:18 | start work on user mgmt check-in: db4c5fd644 user: lexi tags: trunk | |
| 00:15 | add lots more shit check-in: d4ecea913f user: lexi tags: trunk | |
Changes
Modified backend/pgsql.t from [af6b4187ca] to [35848d4bf0].
300 301 302 303 304 305 306 307 308 309 310 311 312 313 ... 773 774 775 776 777 778 779 780 781 782 783 784 785 786 ... 803 804 805 806 807 808 809 810 811 812 813 814 815 816 ... 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 .... 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 |
$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,
................................................................................
end
end
end
return powers
end
local b = `lib.store.backend {
id = "pgsql";
open = [terra(src: &lib.store.source): &opaque
lib.report('connecting to postgres database: ', src.string.ptr)
var [con] = lib.pq.PQconnectdb(src.string.ptr)
if lib.pq.PQstatus(con) ~= lib.pq.CONNECTION_OK then
lib.warn('postgres backend connection failed')
................................................................................
return nil
end
return con
end];
close = [terra(src: &lib.store.source) lib.pq.PQfinish([&lib.pq.PGconn](src.handle)) end];
conprep = [terra(src: &lib.store.source, mode: lib.store.prepmode.t)
var [con] = [&lib.pq.PGconn](src.handle)
if mode == lib.store.prepmode.full then [prep]
elseif mode == lib.store.prepmode.conf or
mode == lib.store.prepmode.admin then
queries.conf_get.prep(con)
................................................................................
if lib.pq.PQresultStatus(res) == lib.pq.PGRES_COMMAND_OK then
lib.report('successfully wiped out everything parsav-related in database')
return true
else
lib.warn('backend pgsql - failed to obliterate database: \n', lib.pq.PQresultErrorMessage(res))
return false
end
end];
tx_enter = [terra(src: &lib.store.source)
var res = lib.pq.PQexec([&lib.pq.PGconn](src.handle), 'begin')
if lib.pq.PQresultStatus(res) == lib.pq.PGRES_COMMAND_OK then
lib.dbg('beginning pgsql transaction')
return true
else
lib.warn('backend pgsql - failed to begin transaction: \n', lib.pq.PQresultErrorMessage(res))
return false
end
end];
tx_complete = [terra(src: &lib.store.source)
var res = lib.pq.PQexec([&lib.pq.PGconn](src.handle), 'end')
if lib.pq.PQresultStatus(res) == lib.pq.PGRES_COMMAND_OK then
lib.dbg('completing pgsql transaction')
return true
else
lib.warn('backend pgsql - failed to complete transaction: \n', lib.pq.PQresultErrorMessage(res))
return false
end
end];
conf_get = [terra(src: &lib.store.source, key: rawstring)
var r = queries.conf_get.exec(src, key)
if r.sz == 0 then return [lib.mem.ptr(int8)] { ptr = nil, ct = 0 } else
defer r:free()
return r:String(0,0)
................................................................................
): 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
|
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > < < < < < < < < < < < < < < < < < < < < < < > > > > > > > > > > |
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 ... 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 ... 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 ... 876 877 878 879 880 881 882 883 884 885 886 887 888 889 .... 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 |
$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_destroy_prepare = { params = {uint64}, cmd = true, sql = [[ update parsav_posts set parent = (select parent from parsav_posts where id = $1::bigint limit 1) where parent = $1::bigint ]] }; post_destroy = { params = {uint64}, cmd = true, sql = [[ delete from parsav_posts where id = $1::bigint ]] }; 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, ................................................................................ end end end return powers end local txdo = terra(src: &lib.store.source) var res = lib.pq.PQexec([&lib.pq.PGconn](src.handle), 'begin') if lib.pq.PQresultStatus(res) == lib.pq.PGRES_COMMAND_OK then lib.dbg('beginning pgsql transaction') return true else lib.warn('backend pgsql - failed to begin transaction: \n', lib.pq.PQresultErrorMessage(res)) return false end end local txdone = terra(src: &lib.store.source) var res = lib.pq.PQexec([&lib.pq.PGconn](src.handle), 'end') if lib.pq.PQresultStatus(res) == lib.pq.PGRES_COMMAND_OK then lib.dbg('completing pgsql transaction') return true else lib.warn('backend pgsql - failed to complete transaction: \n', lib.pq.PQresultErrorMessage(res)) return false end end local b = `lib.store.backend { id = "pgsql"; open = [terra(src: &lib.store.source): &opaque lib.report('connecting to postgres database: ', src.string.ptr) var [con] = lib.pq.PQconnectdb(src.string.ptr) if lib.pq.PQstatus(con) ~= lib.pq.CONNECTION_OK then lib.warn('postgres backend connection failed') ................................................................................ return nil end return con end]; close = [terra(src: &lib.store.source) lib.pq.PQfinish([&lib.pq.PGconn](src.handle)) end]; tx_enter = txdo, tx_complete = txdone; conprep = [terra(src: &lib.store.source, mode: lib.store.prepmode.t) var [con] = [&lib.pq.PGconn](src.handle) if mode == lib.store.prepmode.full then [prep] elseif mode == lib.store.prepmode.conf or mode == lib.store.prepmode.admin then queries.conf_get.prep(con) ................................................................................ if lib.pq.PQresultStatus(res) == lib.pq.PGRES_COMMAND_OK then lib.report('successfully wiped out everything parsav-related in database') return true else lib.warn('backend pgsql - failed to obliterate database: \n', lib.pq.PQresultErrorMessage(res)) return false end end]; conf_get = [terra(src: &lib.store.source, key: rawstring) var r = queries.conf_get.exec(src, key) if r.sz == 0 then return [lib.mem.ptr(int8)] { ptr = nil, ct = 0 } else defer r:free() return r:String(0,0) ................................................................................ ): 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_destroy = [terra( src: &lib.store.source, post: uint64 ): {} txdo(src) queries.post_destroy_prepare.exec(src, post) queries.post_destroy.exec(src, post) txdone(src) 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 |
Modified parsav.t from [022b1bf037] to [90c24eca6f].
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 ... 431 432 433 434 435 436 437 438 439 440 441 442 443 444 ... 609 610 611 612 613 614 615 616 617 618 619 |
local buildopts, buildargs = util.parseargs{...}
config = dofile('config.lua')
lib = {
init = {}, util = util;
load = function(lst)
for _, l in pairs(lst) do
local path = {}
for m in l:gmatch('([^:]+)') do path[#path+1]=m end
local tgt = lib
for i=1,#path-1 do
if tgt[path[i]] == nil then tgt[path[i]] = {} end
tgt = tgt[path[i]]
end
tgt[path[#path]:gsub('-','_')] = terralib.loadfile(l:gsub(':','/') .. '.t')()
end
end;
loadlib = function(name,hdr)
local p = config.pkg[name]
-- for _,v in pairs(p.dylibs) do
-- terralib.linklibrary(p.libdir .. '/' .. v)
-- end
................................................................................
'render:user-page';
'render:timeline';
'render:docpage';
'render:conf:profile';
'render:conf:sec';
'render:conf';
'route';
}
do
local p = string.format('parsav: %s\nbuilt on %s\n', config.build.str, config.build.when)
terra version() lib.io.send(1, p, [#p]) end
................................................................................
if bflag('lsan','S') then linkargs[#linkargs+1] = '-fsanitize=leak' end
for _,p in pairs(config.pkg) do util.append(linkargs, p.linkargs) end
local linkargs_d = linkargs -- controller is not multithreaded
if config.posix then
linkargs_d[#linkargs_d+1] = '-pthread'
end
holler('linking with args',util.dump(linkargs))
terralib.saveobj('parsavd'..suffix, { main = entry_daemon }, linkargs_d, target)
terralib.saveobj('parsav' ..suffix, { main = lib.mgtool }, linkargs, target)
|
> | > > > > > > > > < < > > > > |
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 ... 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 ... 618 619 620 621 622 623 624 625 626 627 628 629 630 |
local buildopts, buildargs = util.parseargs{...}
config = dofile('config.lua')
lib = {
init = {}, util = util;
load = function(lst)
for _, l in pairs(lst) do
io.stdout:write(' · processing module \27[1m' .. l ..'\27[m… ')
local path = {}
for m in l:gmatch('([^:]+)') do path[#path+1]=m end
local tgt = lib
for i=1,#path-1 do
if tgt[path[i]] == nil then tgt[path[i]] = {} end
tgt = tgt[path[i]]
end
local chunk = terralib.loadfile(l:gsub(':','/') .. '.t')
if chunk ~= nil then
tgt[path[#path]:gsub('-','_')] = chunk()
print(' \27[1m[ \27[32mok\27[;1m ]\27[m')
else
print(' \27[1m[\27[31mfail\27[;1m]\27[m')
os.exit(2)
end
end
end;
loadlib = function(name,hdr)
local p = config.pkg[name]
-- for _,v in pairs(p.dylibs) do
-- terralib.linklibrary(p.libdir .. '/' .. v)
-- end
................................................................................
'render:user-page';
'render:timeline';
'render:docpage';
'render:conf:profile';
'render:conf:sec';
'render:conf:users';
'render:conf';
'route';
}
do
local p = string.format('parsav: %s\nbuilt on %s\n', config.build.str, config.build.when)
terra version() lib.io.send(1, p, [#p]) end
................................................................................
if bflag('lsan','S') then linkargs[#linkargs+1] = '-fsanitize=leak' end
for _,p in pairs(config.pkg) do util.append(linkargs, p.linkargs) end
local linkargs_d = linkargs -- controller is not multithreaded
if config.posix then
linkargs_d[#linkargs_d+1] = '-pthread'
end
holler(' → linking \27[1mparsav\27[m with "' .. table.concat(linkargs,' ') .. '"')
terralib.saveobj('parsav' ..suffix, { main = lib.mgtool }, linkargs, target)
holler(' → linking \27[1mparsavd\27[m with "' .. table.concat(linkargs_d,' ') .. '"')
terralib.saveobj('parsavd'..suffix, { main = entry_daemon }, linkargs_d, target)
|
Added render/conf/users.t version [6e4ba75dd2].
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
-- vim: ft=terra local pstr = lib.mem.ptr(int8) local pref = lib.mem.ref(int8) local terra cs(s: rawstring) return pstr { ptr = s, ct = lib.str.sz(s) } end local terra render_conf_users(co: &lib.srv.convo, path: lib.mem.ptr(pref)): pstr if path.ct == 2 then var uid, ok = lib.math.shorthand.parse(path(1).ptr,path(1).ct) var user = co.srv:actor_fetch_uid(uid) if not user then goto e404 end var islinkct = false var cinp: lib.str.acc var clnk: lib.str.acc clnk:compose('<hr>') var cinpp = cinp:finalize() defer cinpp:free() var clnkp: pstr if islinkct then clnkp = clnk:finalize() else clnk:free() clnkp = pstr { ptr='', ct=0 } end var pg = data.view.conf_user_ctl { name = cs(user(0).handle); inputcontent = cinpp; linkcontent = clnkp; } var ret = pg:tostr() if islinkct then clnkp:free() end return ret else end do return pstr.null() end ::e404:: co:complain(404, 'not found', 'there is no user or resource by that identifier on this server') do return pstr.null() end end return render_conf_users |
Modified route.t from [2469fad253] to [a9eb70a00e].
175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 ... 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 ... 250 251 252 253 254 255 256 257 258 259 260 261 262 263 |
if not post then co:complain(404, 'post not found', 'no such post is known to this server') return end defer post:free() if path.ct == 3 then if path(2):cmp(lib.str.lit 'edit') then if post(0).author ~= co.who.id then co:complain(403, 'forbidden', 'you cannot edit other people\'s posts') return end if meth == method.get then lib.render.compose(co, post.ptr, nil) return elseif meth == method.post then var newbody = co:postv('post')._0 var newacl = co:postv('acl')._0 var newsubj = co:postv('subject')._0 if newbody ~= nil then post(0).body = newbody end if newacl ~= nil then post(0).acl = newacl end if newsubj ~= nil then post(0).subject = newsubj end post(0):save(true) var lnk: lib.str.acc lnk:compose('/post/', path(1)) co:reroute(lnk.buf) lnk:free() end return else goto badurl end end if meth == method.post then co:complain(405, 'invalid operation', 'the operation you have attempted on this post is not meaningful') return end lib.render.tweet_page(co, path, post.ptr) do return end ::badurl:: co:complain(404, 'invalid URL', 'this URL does not reference extant content or functionality') end terra http.configure(co: &lib.srv.convo, path: hpath, meth: method.t) var msg = pstring.null() if meth == method.post and path.ct >= 1 then var user_refresh = false var fail = false if path(1):cmp(lib.str.lit 'profile') then ................................................................................ co.who.nym = co:postv('nym')._0 if co.who.bio ~= nil and @co.who.bio == 0 then co.who.bio = nil end if co.who.nym ~= nil and @co.who.nym == 0 then co.who.nym = nil end co.who.source:actor_save(co.who) msg = lib.str.plit 'profile changes saved' --user_refresh = true -- not really necessary here, actually elseif path(1):cmp(lib.str.lit 'srv') then elseif path(1):cmp(lib.str.lit 'users') then elseif path(1):cmp(lib.str.lit 'sec') then var act = co:ppostv('act') if act:cmp(lib.str.plit 'invalidate') then lib.dbg('setting user\'s cookie validation time to now') co.who.source:auth_sigtime_user_alter(co.who.id, lib.osclock.time(nil)) -- the current session has been invalidated as well, so we need to immediately install a new authentication cookie with the same aid so the user doesn't need to log back in all over again co:installkey('/conf/sec',co.aid) ................................................................................ var go,golen = co:getv('go') if not fail and go ~= nil then co:reroute(go) return end end lib.render.conf(co,path,msg) end do local branches = quote end local filename, flen = symbol(&int8), symbol(intptr) local page = symbol(lib.http.page) local send = label() local storage = data.stmap |
| > | | | < < > < < | < > > > | | > | > > > > > > > | < > > > > | > | > > > > | > > > > > > > > > |
175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 ... 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 ... 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 |
if not post then co:complain(404, 'post not found', 'no such post is known to this server') return end defer post:free() if path.ct == 3 then var lnk: lib.str.acc lnk:compose('/post/', path(1)) var lnkp = lnk:finalize() defer lnkp:free() if post(0).author ~= co.who.id then co:complain(403, 'forbidden', 'you cannot alter other people\'s posts') return elseif path(2):cmp(lib.str.lit 'edit') then if meth == method.get then lib.render.compose(co, post.ptr, nil) return elseif meth == method.post then var newbody = co:postv('post')._0 var newacl = co:postv('acl')._0 var newsubj = co:postv('subject')._0 if newbody ~= nil then post(0).body = newbody end if newacl ~= nil then post(0).acl = newacl end if newsubj ~= nil then post(0).subject = newsubj end post(0):save(true) co:reroute(lnkp.ptr) end return elseif path(2):cmp(lib.str.lit 'del') then if meth == method.get then var conf = data.view.confirm { title = lib.str.plit 'delete post'; query = lib.str.plit 'are you sure you want to delete this post?'; cancel = lnkp } var body = conf:tostr() defer body:free() co:stdpage([lib.srv.convo.page] { title = lib.str.plit 'post :: delete'; class = lib.str.plit 'query'; body = body; cache = false; }) return elseif meth == method.post then var act = co:ppostv('act') if act:cmp(lib.str.plit 'confirm') then post(0).source:post_destroy(post(0).id) co:reroute('/') -- TODO maybe return to parent or conversation if possible return else goto badop end end else goto badurl end end if meth == method.post then goto badop end lib.render.tweet_page(co, path, post.ptr) do return end ::badurl:: do co:complain(404, 'invalid URL', 'this URL does not reference extant content or functionality') return end ::badop :: do co:complain(405, 'invalid operation', 'the operation you have attempted on this post is not meaningful') return end end terra http.configure(co: &lib.srv.convo, path: hpath, meth: method.t) var msg = pstring.null() if meth == method.post and path.ct >= 1 then var user_refresh = false var fail = false if path(1):cmp(lib.str.lit 'profile') then ................................................................................ co.who.nym = co:postv('nym')._0 if co.who.bio ~= nil and @co.who.bio == 0 then co.who.bio = nil end if co.who.nym ~= nil and @co.who.nym == 0 then co.who.nym = nil end co.who.source:actor_save(co.who) msg = lib.str.plit 'profile changes saved' --user_refresh = true -- not really necessary here, actually elseif path(1):cmp(lib.str.lit 'srv') then if not co.who.rights.powers.config() then goto nopriv end elseif path(1):cmp(lib.str.lit 'brand') then if not co.who.rights.powers.rebrand() then goto nopriv end elseif path(1):cmp(lib.str.lit 'users') then if not co.who.rights.powers:affect_users() then goto nopriv end elseif path(1):cmp(lib.str.lit 'sec') then var act = co:ppostv('act') if act:cmp(lib.str.plit 'invalidate') then lib.dbg('setting user\'s cookie validation time to now') co.who.source:auth_sigtime_user_alter(co.who.id, lib.osclock.time(nil)) -- the current session has been invalidated as well, so we need to immediately install a new authentication cookie with the same aid so the user doesn't need to log back in all over again co:installkey('/conf/sec',co.aid) ................................................................................ var go,golen = co:getv('go') if not fail and go ~= nil then co:reroute(go) return end end lib.render.conf(co,path,msg) do return end ::nopriv:: co:complain(403,'insufficient privileges','you do not have the necessary powers to perform this action') end do local branches = quote end local filename, flen = symbol(&int8), symbol(intptr) local page = symbol(lib.http.page) local send = label() local storage = data.stmap |
Modified static/style.scss from [9b25bded91] to [ada3763759].
68 69 70 71 72 73 74 75 76 77 78 79 80 81 ... 339 340 341 342 343 344 345 346 347 348 349 350 351 352 ... 522 523 524 525 526 527 528 529 530 531 532 533 534 535 ... 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 |
padding: 0.1in 0.2in;
border: 1px solid black;
color: tone(25%);
text-shadow: 1px 1px black;
text-decoration: none;
text-align: center;
cursor: default;
background: linear-gradient(to bottom,
tone(-47%),
tone(-50%) 15%,
tone(-50%) 75%,
tone(-53%)
);
&:hover, &:focus {
................................................................................
.message {
@extend %box;
display: block;
width: 4in;
margin:auto;
padding: 0.5in;
text-align: center;
}
div.login {
@extend %box;
width: 4in;
padding: 0.4in;
> .msg {
................................................................................
background: linear-gradient(to right, tone(-50%), transparent);
margin-left: -0.4in;
padding-left: 0.2in;
text-shadow: 0 2px 0 black;
}
}
body.conf main {
display: grid;
grid-template-columns: 2in 1fr;
grid-template-rows: max-content 1fr;
> menu {
margin-left: -0.25in;
grid-column: 1/2; grid-row: 1/2;
................................................................................
}
&.vertical-float {
flex-flow: column;
float: right;
width: 40%;
margin-left: 0.1in;
}
> %button { display: block; margin: 2px; flex-grow: 1 }
}
.check-panel {
display: flex;
flex-flow: row wrap;
> label {
display: block;
|
> > > > > > | > |
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 ... 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 ... 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 ... 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 |
padding: 0.1in 0.2in; border: 1px solid black; color: tone(25%); text-shadow: 1px 1px black; text-decoration: none; text-align: center; cursor: default; user-select: none; background: linear-gradient(to bottom, tone(-47%), tone(-50%) 15%, tone(-50%) 75%, tone(-53%) ); &:hover, &:focus { ................................................................................ .message { @extend %box; display: block; width: 4in; margin:auto; padding: 0.5in; text-align: center; menu:first-of-type { margin-top: 0.3in; } } div.login { @extend %box; width: 4in; padding: 0.4in; > .msg { ................................................................................ background: linear-gradient(to right, tone(-50%), transparent); margin-left: -0.4in; padding-left: 0.2in; text-shadow: 0 2px 0 black; } } menu { all: unset; display: block; } body.conf main { display: grid; grid-template-columns: 2in 1fr; grid-template-rows: max-content 1fr; > menu { margin-left: -0.25in; grid-column: 1/2; grid-row: 1/2; ................................................................................ } &.vertical-float { flex-flow: column; float: right; width: 40%; margin-left: 0.1in; } > %button { flex-basis: 0; flex-grow: 1; display: block; margin: 2px; } } .check-panel { display: flex; flex-flow: row wrap; > label { display: block; |
Modified store.t from [004846cca6] to [d79d41c9fe].
335 336 337 338 339 340 341 342 343 344 345 346 347 348 |
-- uid: uint64
auth_sigtime_user_alter: {&m.source, uint64, m.timepoint} -> {}
-- uid: uint64
-- timestamp: timepoint
post_save: {&m.source, &m.post} -> {}
post_create: {&m.source, &m.post} -> uint64
post_fetch: {&m.source, uint64} -> lib.mem.ptr(m.post)
post_enum_author_uid: {&m.source, uint64, m.range} -> lib.mem.ptr(lib.mem.ptr(m.post))
post_attach_ctl: {&m.source, uint64, uint64, bool} -> {}
-- attaches or detaches an existing database artifact
-- post id: uint64
-- artifact id: uint64
-- detach: bool
|
> |
335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 |
-- uid: uint64
auth_sigtime_user_alter: {&m.source, uint64, m.timepoint} -> {}
-- uid: uint64
-- timestamp: timepoint
post_save: {&m.source, &m.post} -> {}
post_create: {&m.source, &m.post} -> uint64
post_destroy: {&m.source, uint64} -> {}
post_fetch: {&m.source, uint64} -> lib.mem.ptr(m.post)
post_enum_author_uid: {&m.source, uint64, m.range} -> lib.mem.ptr(lib.mem.ptr(m.post))
post_attach_ctl: {&m.source, uint64, uint64, bool} -> {}
-- attaches or detaches an existing database artifact
-- post id: uint64
-- artifact id: uint64
-- detach: bool
|
Added view/conf-user-ctl.tpl version [9830040aea].
> > > > > > > > > |
1 2 3 4 5 6 7 8 9 |
<form method="post"> <div class="elem"> <label>user</label> <div class="txtbox">@name</div> </div> @inputcontent <button>alter</button> @linkcontent </form> |
Modified view/confirm.tpl from [9198c794e9] to [0d2952df9c].
1 2 3 4 5 6 7 8 9 |
<form class="message"> <img class="icon" src="/s/query.webp"> <h1>@title</h1> <p>@query</p> <menu class="horizontal choice"> <a class="button" href="@:cancel">cancel</a> <button name="act" value="confirm">confirm</button> </menu> </form> |
| |
1 2 3 4 5 6 7 8 9 |
<form class="message" method="post">
<img class="icon" src="/s/query.webp">
<h1>@title</h1>
<p>@query</p>
<menu class="horizontal choice">
<a class="button" href="@:cancel">cancel</a>
<button name="act" value="confirm">confirm</button>
</menu>
</form>
|
Modified view/load.lua from [212041720e] to [dd2878563c].
13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
'login-username';
'login-challenge';
'conf';
'conf-profile';
'conf-sec';
'conf-sec-credmg';
}
local ingest = function(filename)
local hnd = io.open(path..'/'..filename)
local txt = hnd:read('*a')
io.close(hnd)
txt = txt:gsub('([^\\])!%b[]', '%1')
|
> |
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
'login-username';
'login-challenge';
'conf';
'conf-profile';
'conf-sec';
'conf-sec-credmg';
'conf-user-ctl';
}
local ingest = function(filename)
local hnd = io.open(path..'/'..filename)
local txt = hnd:read('*a')
io.close(hnd)
txt = txt:gsub('([^\\])!%b[]', '%1')
|