parsav  Check-in [ac4a630ad5]

Overview
Comment:enable profile editing
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: ac4a630ad562c1ae6efc8ee1a5a3e5935f29f856e7a6c64d6677d272b93ba172
User & Date: lexi on 2020-12-30 02:44:15
Other Links: manifest | tags
Context
2020-12-31
00:15
add lots more shit check-in: d4ecea913f user: lexi tags: trunk
2020-12-30
02:44
enable profile editing check-in: ac4a630ad5 user: lexi tags: trunk
00:43
continued iteration check-in: 0324d62546 user: lexi tags: trunk
Changes

Modified backend/pgsql.t from [30de1dd276] to [d54604496b].

    58     58   			where $1::text = (a.handle || '@' || domain) or
    59     59   			      $1::text = ('@' || a.handle || '@' || domain) or
    60     60   				  (a.origin is null and
    61     61   					  $1::text = a.handle or
    62     62   					  $1::text = ('@' || a.handle))
    63     63   		]];
    64     64   	};
           65  +
           66  +	actor_save = {
           67  +		params = {
           68  +			uint64, --id
           69  +			rawstring, --nym
           70  +			rawstring, --handle
           71  +			rawstring, --bio 
           72  +			rawstring, --epithet
           73  +			rawstring, --avataruri
           74  +			uint64, --avatarid
           75  +			uint16, --rank
           76  +			uint32 --quota
           77  +		}, cmd = true, sql = [[
           78  +			update parsav_actors set
           79  +				nym = $2::text,
           80  +				handle = $3::text,
           81  +				bio = $4::text,
           82  +				epithet = $5::text,
           83  +				avataruri = $6::text,
           84  +				avatarid = $7::bigint,
           85  +				rank = $8::smallint,
           86  +				quota = $9::integer
           87  +				--invites are controlled by their own specialized routines
           88  +			where id = $1::bigint
           89  +		]];
           90  +	};
    65     91   
    66     92   	actor_create = {
    67     93   		params = {
    68     94   			rawstring, rawstring, uint64, lib.store.timepoint,
    69     95   			rawstring, rawstring, lib.mem.ptr(uint8),
    70     96   			rawstring, uint16, uint32
    71     97   		};
................................................................................
   823    849   
   824    850   	actor_enum = [terra(src: &lib.store.source)
   825    851   		var r = queries.actor_enum.exec(src)
   826    852   		if r.sz == 0 then
   827    853   			return [lib.mem.ptr(&lib.store.actor)] { ct = 0, ptr = nil }
   828    854   		else defer r:free()
   829    855   			var mem = lib.mem.heapa([&lib.store.actor], r.sz)
   830         -			for i=0,r.sz do mem.ptr[i] = row_to_actor(&r, i).ptr end
          856  +			for i=0,r.sz do
          857  +				mem.ptr[i] = row_to_actor(&r, i).ptr
          858  +				mem.ptr[i].source = src
          859  +			end
   831    860   			return [lib.mem.ptr(&lib.store.actor)] { ct = r.sz, ptr = mem.ptr }
   832    861   		end
   833    862   	end];
   834    863   
   835    864   	actor_enum_local = [terra(src: &lib.store.source)
   836    865   		var r = queries.actor_enum_local.exec(src)
   837    866   		if r.sz == 0 then
   838    867   			return [lib.mem.ptr(&lib.store.actor)] { ct = 0, ptr = nil }
   839    868   		else defer r:free()
   840    869   			var mem = lib.mem.heapa([&lib.store.actor], r.sz)
   841         -			for i=0,r.sz do mem.ptr[i] = row_to_actor(&r, i).ptr end
          870  +			for i=0,r.sz do
          871  +				mem.ptr[i] = row_to_actor(&r, i).ptr
          872  +				mem.ptr[i].source = src
          873  +			end
   842    874   			return [lib.mem.ptr(&lib.store.actor)] { ct = r.sz, ptr = mem.ptr }
   843    875   		end
   844    876   	end];
   845    877   
   846    878   	actor_auth_how = [terra(
   847    879   			src: &lib.store.source,
   848    880   			ip: lib.store.inet,
................................................................................
   934    966   
   935    967   	timeline_instance_fetch = [terra(src: &lib.store.source, rg: lib.store.range)
   936    968   		var r = pqr { sz = 0 }
   937    969   		var A,B,C,D = rg:matrix() -- :/
   938    970   		r = queries.timeline_instance_fetch.exec(src,A,B,C,D)
   939    971   		
   940    972   		var ret: lib.mem.ptr(lib.mem.ptr(lib.store.post)) ret:init(r.sz)
   941         -		for i=0,r.sz do ret.ptr[i] = row_to_post(&r, i) end -- MUST FREE ALL
          973  +		for i=0,r.sz do
          974  +			ret.ptr[i] = row_to_post(&r, i) -- MUST FREE ALL
          975  +			ret.ptr[i].ptr.source = src
          976  +		end
   942    977   
   943    978   		return ret
   944    979   	end];
   945    980   
   946    981   	post_enum_author_uid = [terra(
   947    982   		src: &lib.store.source,
   948    983   		uid: uint64,
................................................................................
   949    984   		rg: lib.store.range
   950    985   	): lib.mem.ptr(lib.mem.ptr(lib.store.post))
   951    986   		var r = pqr { sz = 0 }
   952    987   		var A,B,C,D = rg:matrix() -- :/
   953    988   		r = queries.post_enum_author_uid.exec(src,A,B,C,D,uid)
   954    989   		
   955    990   		var ret: lib.mem.ptr(lib.mem.ptr(lib.store.post)) ret:init(r.sz)
   956         -		for i=0,r.sz do ret.ptr[i] = row_to_post(&r, i) end -- MUST FREE ALL
          991  +		for i=0,r.sz do
          992  +			ret.ptr[i] = row_to_post(&r, i) -- MUST FREE ALL
          993  +			ret.ptr[i].ptr.source = src
          994  +		end
   957    995   
   958    996   		return ret
   959    997   	end];
   960    998   
   961    999   	actor_powers_fetch = getpow;
         1000  +	actor_save = [terra(
         1001  +		src: &lib.store.source,
         1002  +		ac: &lib.store.actor
         1003  +	): {}
         1004  +		queries.actor_save.exec(src,
         1005  +			ac.id, ac.nym, ac.handle,
         1006  +			ac.bio, ac.epithet, ac.avatar,
         1007  +			ac.avatarid, ac.rights.rank, ac.rights.quota)
         1008  +	end];
         1009  +
   962   1010   	actor_save_privs = privupdate;
   963   1011   
   964   1012   	actor_create = [terra(
   965   1013   		src: &lib.store.source,
   966   1014   		ac: &lib.store.actor
   967   1015   	): uint64
   968   1016   		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)

Modified parsav.t from [b85f6f7647] to [dc97a3f269].

   558    558   	print(util.dump(config))
   559    559   	os.exit(0)
   560    560   end
   561    561   
   562    562   local holler = print
   563    563   local suffix = config.exe and '' or ('.'..config.outform)
   564    564   local out = 'parsavd' .. suffix
   565         -local linkargs = {}
          565  +local linkargs = {'-O4'}
   566    566   local target = config.tgttrip and terralib.newtarget {
   567    567   	Triple = config.tgttrip;
   568    568   	CPU = config.tgtcpu;
   569    569   	FloatABIHard = config.tgthf;
   570    570   } or nil
   571    571   
   572    572   if bflag('quiet','q') then holler = function() end end

Modified render/conf.t from [79b6da76d7] to [1b75d5dd6d].

    35     35   				body:free()
    36     36   			else [invoker] end
    37     37   		end
    38     38   	end
    39     39   end
    40     40   
    41     41   local terra 
    42         -render_conf([co], [path])
           42  +render_conf([co], [path], notify: pstr)
    43     43   	var menu: lib.str.acc menu:init(64):lpush('<hr>') defer menu:free()
    44     44   
    45     45   	-- build menu
    46     46   	do var p = co.who.rights.powers
    47     47   		if p.config() then menu:lpush '<a href="/conf/srv">server settings</a>' end
    48     48   		if p.rebrand() then menu:lpush '<a href="/conf/brand">instance branding</a>' end
    49     49   		if p.censor() then menu:lpush '<a href="/conf/censor">badthink alerts</a>' end
................................................................................
    58     58   	var mptr = pstr { ptr = menu.buf, ct = menu.sz }
    59     59   	if menu.sz <= 4 then mptr.ct = 0 end -- 🙄
    60     60   	var pg = data.view.conf {
    61     61   		menu = mptr;
    62     62   		panel = panel;
    63     63   	}
    64     64   
    65         -	var pgt = pg:tostr() defer pgt:free()
           65  +	var pgt: pstr
           66  +	if notify:ref() then
           67  +		var fnpg: lib.str.acc
           68  +		fnpg:compose('<div class="flashmsg">', notify, '</div>')
           69  +		pg:append(&fnpg)
           70  +		pgt = fnpg:finalize()
           71  +	else pgt = pg:tostr() end
           72  +	defer pgt:free()
           73  +
    66     74   	co:stdpage([lib.srv.convo.page] {
    67     75   		title = 'configure'; body = pgt;
    68     76   		class = lib.str.plit 'conf';
    69     77   		cache = false;
    70     78   	})
    71     79   
    72     80   	if panel.ct ~= 0 then panel:free() end
    73     81   end
    74     82   
    75     83   return render_conf

Modified render/profile.t from [03b39adc21] to [19457b4b7c].

     3      3   local terra cs(s: rawstring)
     4      4   	return pstr { ptr = s, ct = lib.str.sz(s) }
     5      5   end
     6      6   
     7      7   local terra 
     8      8   render_profile(co: &lib.srv.convo, actor: &lib.store.actor)
     9      9   	var aux: lib.str.acc
    10         -	var auxp: pstr
    11     10   	if co.aid ~= 0 and co.who.id == actor.id then
    12         -		auxp = lib.str.plit '<a href="/conf/profile">alter</a>'
           11  +		aux:compose('<a href="/conf/profile?go=/',actor.xid,'">alter</a>')
    13     12   	elseif co.aid ~= 0 then
    14     13   		aux:compose('<a href="/', actor.xid, '/follow">follow</a><a href="/',
    15     14   			actor.xid, '/chat">chat</a>')
    16     15   		if co.who.rights.powers:affect_users() then
    17     16   			aux:lpush('<a href="/'):push(actor.xid,0):lpush('/ctl">control</a>')
    18     17   		end
    19         -		auxp = aux:finalize()
    20     18   	else
    21     19   		aux:compose('<a href="/', actor.xid, '/follow">remote follow</a>')
    22         -		auxp = aux:finalize()
    23     20   	end
           21  +	var auxp = aux:finalize()
    24     22   	var avistr: lib.str.acc if actor.origin == 0 then
    25     23   		avistr:compose('/avi/',actor.handle)
    26     24   	end
    27     25   	var timestr: int8[26] lib.osclock.ctime_r(&actor.knownsince, &timestr[0])
    28     26   
    29     27   	var strfbuf: int8[28*4]
    30     28   	var stats = co.srv:actor_stats(actor.id)
    31     29   		var sn_posts     = cs(lib.math.decstr_friendly(stats.posts, &strfbuf[ [strfbuf.type.N - 1] ]))
    32     30   		var sn_follows   = cs(lib.math.decstr_friendly(stats.follows, sn_posts.ptr - 1))
    33     31   		var sn_followers = cs(lib.math.decstr_friendly(stats.followers, sn_follows.ptr - 1))
    34     32   		var sn_mutuals   = cs(lib.math.decstr_friendly(stats.mutuals, sn_followers.ptr - 1))
    35     33   	var bio = lib.str.plit "<em>tall, dark, and mysterious</em>"
    36     34   	if actor.bio ~= nil then
    37         -		bio = lib.html.sanitize(cs(actor.bio), false)
           35  +		bio = lib.smackdown.html(cs(actor.bio))
    38     36   	end
    39     37   	var fullname = lib.render.nym(actor,0) defer fullname:free()
    40     38   	var profile = data.view.profile {
    41     39   		nym = fullname;
    42     40   		bio = bio;
    43     41   		xid = cs(actor.xid);
    44     42   		avatar = lib.trn(actor.origin == 0, pstr{ptr=avistr.buf,ct=avistr.sz},
................................................................................
    50     48   		timephrase = lib.trn(actor.origin == 0, lib.str.plit'joined', lib.str.plit'known since');
    51     49   
    52     50   		auxbtn = auxp;
    53     51   	}
    54     52   
    55     53   	var ret = profile:tostr()
    56     54   	if actor.origin == 0 then avistr:free() end
    57         -	if not (co.aid ~= 0 and co.who.id == actor.id) then auxp:free() end
           55  +	auxp:free() 
    58     56   	if actor.bio ~= nil then bio:free() end
    59     57   	return ret
    60     58   end
    61     59   
    62     60   return render_profile

Modified route.t from [5e16c3f22b] to [ae96c17fe6].

   172    172   	elseif path.ct == 1 then
   173    173   		lib.render.docpage(co, rstring.null())
   174    174   	else
   175    175   		co:complain(404, 'no such documentation', 'invalid documentation URL')
   176    176   	end
   177    177   end
   178    178   
   179         -terra http.configure(co: &lib.srv.convo, path: hpath)
   180         -	lib.render.conf(co,path)
          179  +terra http.configure(co: &lib.srv.convo, path: hpath, meth: method.t)
          180  +	var msg = pstring.null()
          181  +	if meth == method.post and path.ct >= 1 then
          182  +		var user_refresh = false var fail = false
          183  +		if path(1):cmp(lib.str.lit 'profile') then
          184  +			co.who.bio = co:postv('bio')._0
          185  +			co.who.nym = co:postv('nym')._0
          186  +			if co.who.bio ~= nil and @co.who.bio == 0 then co.who.bio = nil end
          187  +			if co.who.nym ~= nil and @co.who.nym == 0 then co.who.nym = nil end
          188  +			co.who.source:actor_save(co.who)
          189  +			msg = lib.str.plit 'profile changes saved'
          190  +			--user_refresh = true -- not really necessary here, actually
          191  +		elseif path(1):cmp(lib.str.lit 'srv') then
          192  +		elseif path(1):cmp(lib.str.lit 'users') then
          193  +
          194  +		end
          195  +
          196  +		if user_refresh then -- refresh the user info for the renderer
          197  +			var usr = co.srv:actor_fetch_uid(co.who.id)
          198  +			lib.mem.heapf(co.who)
          199  +			co.who = usr.ptr
          200  +		end
          201  +		var go,golen = co:getv('go')
          202  +		if not fail and go ~= nil then
          203  +			co:reroute(go)
          204  +			return
          205  +		end
          206  +	end
          207  +	lib.render.conf(co,path,msg)
   181    208   end
   182    209   
   183    210   do local branches = quote end
   184    211   	local filename, flen = symbol(&int8), symbol(intptr)
   185    212   	local page = symbol(lib.http.page)
   186    213   	local send = label()
   187    214   	local storage = data.stmap
................................................................................
   270    297   		elseif path.ptr[0]:cmp(lib.str.lit('tl')) then
   271    298   			http.timeline(co, path)
   272    299   		elseif path.ptr[0]:cmp(lib.str.lit('doc')) then
   273    300   			if meth ~= method.get and meth ~= method.head then goto wrongmeth end
   274    301   			http.documentation(co, path)
   275    302   		elseif path.ptr[0]:cmp(lib.str.lit('conf')) then
   276    303   			if co.aid == 0 then goto unauth end
   277         -			http.configure(co,path)
          304  +			http.configure(co,path,meth)
   278    305   		else goto notfound end
   279    306   		return
   280    307   	end
   281    308   
   282    309   	::wrongmeth:: co:complain(405, 'method not allowed', 'that method is not meaningful for this endpoint') do return end
   283    310   	::notfound:: co:complain(404, 'not found', 'no such resource available') do return end
   284    311   	::unauth:: co:complain(401, 'unauthorized', 'this content is not available at your clearance level') do return end
   285    312   end

Modified static/style.scss from [a08d589c48] to [2a06f65525].

   557    557   		.txtbox {
   558    558   			@extend %serif;
   559    559   			box-sizing: border-box;
   560    560   			padding: 0.08in 0.1in;
   561    561   			border: 1px solid black;
   562    562   			background: tone(-55%);
   563    563   		}
          564  +		textarea { resize: vertical; min-height: 2in; }
   564    565   		input, textarea, .txtbox {
   565    566   			display: block;
   566    567   			width: 100%;
   567    568   		}
   568    569   		button { float: right; width: 50%; }
   569    570   	}
   570    571   }
          572  +
          573  +@keyframes flashup {
          574  +	0% { opacity: 0; transform: scale(0.8); }
          575  +	10% { opacity: 1; transform: scale(1.1); }
          576  +	80% { opacity: 1; transform: scale(1); }
          577  +	100% { opacity: 0; transform: scale(0.9) translateY(-0.12in); display: none; }
          578  +}
          579  +.flashmsg {
          580  +	display: block;
          581  +	position: fixed;
          582  +	top: 1.3in;
          583  +	max-width: 3in;
          584  +	padding: 0.5in 0.2in;
          585  +	left: 0; right: 0;
          586  +	text-align: center;
          587  +	text-shadow: 0 0 15px tone(10%);
          588  +	margin: auto;
          589  +	background: linear-gradient(to bottom, tone(-49%), tone(-43%,-0.1));
          590  +	border: 1px solid tone(0%);
          591  +	border-radius: 3px;
          592  +	box-shadow: 0 0 50px tone(-55%);
          593  +	color: white;
          594  +	animation: ease forwards flashup;
          595  +	//cubic-bezier(0.4, 0.63, 0.6, 0.31)
          596  +	animation-duration: 3s;
          597  +}

Modified store.t from [69369cc5c2] to [f53ab94a55].

    53     53   
    54     54   struct m.source
    55     55   
    56     56   struct m.rights {
    57     57   	rank: uint16 -- lower = more powerful except 0 = regular user
    58     58   	-- creating staff automatically assigns rank immediately below you
    59     59   	quota: uint32 -- # of allowed tweets per day; 0 = no limit
    60         -	invites: intptr -- # of people left this user can invite
           60  +	invites: uint32 -- # of people left this user can invite
    61     61   	
    62     62   	powers: m.powerset
    63     63   }
    64     64   
    65     65   terra m.rights_default()
    66     66   	var pow: m.powerset pow:clear()
    67     67   	(pow.login     << true)
................................................................................
    79     79   	id: uint64
    80     80   	nym: str
    81     81   	handle: str
    82     82   	origin: uint64
    83     83   	bio: str
    84     84   	epithet: str
    85     85   	avatar: str
           86  +	avatarid: uint64
    86     87   	knownsince: m.timepoint
    87     88   	rights: m.rights
    88     89   	key: lib.mem.ptr(uint8)
    89     90   
    90     91   -- ephemera
    91     92   	xid: str
    92     93   	source: &m.source
................................................................................
   247    248   	-- not have the desired effect
   248    249   
   249    250   	conf_get: {&m.source, rawstring} -> lib.mem.ptr(int8)
   250    251   	conf_set: {&m.source, rawstring, rawstring} -> {}
   251    252   	conf_reset: {&m.source, rawstring} -> {}
   252    253   
   253    254   	actor_create: {&m.source, &m.actor} -> uint64
          255  +	actor_save: {&m.source, &m.actor} -> {}
   254    256   	actor_save_privs: {&m.source, &m.actor} -> {}
   255    257   	actor_fetch_xid: {&m.source, lib.mem.ptr(int8)} -> lib.mem.ptr(m.actor)
   256    258   	actor_fetch_uid: {&m.source, uint64} -> lib.mem.ptr(m.actor)
   257    259   	actor_notif_fetch_uid: {&m.source, uint64} -> lib.mem.ptr(m.notif)
   258    260   	actor_enum: {&m.source} -> lib.mem.ptr(&m.actor)
   259    261   	actor_enum_local: {&m.source} -> lib.mem.ptr(&m.actor)
   260    262   	actor_stats: {&m.source, uint64} -> m.actor_stats