parsav  Diff

Differences From Artifact [70d0da6b8e]:

To Artifact [d7d680b0a3]:


    53     53   		co:complain(404, 'no such user', 'no user by that ID is known to this instance')
    54     54   		return
    55     55   	end
    56     56   	defer actor:free()
    57     57   
    58     58   	lib.render.userpage(co, actor.ptr)
    59     59   end
           60  +
           61  +terra http.login_form(co: &lib.srv.convo, meth: method.t)
           62  +	if meth == method.get then
           63  +		-- request a username
           64  +		lib.render.login(co, nil, nil, nil)
           65  +	elseif meth == method.post then
           66  +		var usn, usnl = co:postv('user')
           67  +		lib.dbg('got name ',{usn,usnl})
           68  +		lib.io.fmt('name len %llu\n',usnl)
           69  +		var am, aml = co:postv('authmethod')
           70  +		var chrs, chrsl = co:postv('response')
           71  +		var cs, authok = co.srv:actor_auth_how(co.peer, usn)
           72  +		var act = co.srv:actor_fetch_xid([lib.mem.ptr(int8)] {
           73  +			ptr = usn, ct = usnl
           74  +		})
           75  +		if authok == false then
           76  +			lib.render.login(co, nil, nil, 'access denied')
           77  +			return
           78  +		end
           79  +		var fakeact = false
           80  +		var fakeactor: lib.store.actor
           81  +		if act.ptr == nil then
           82  +			-- the user is known to us but has not yet claimed an
           83  +			-- account on the server. create a template for the
           84  +			-- account that will be created once they log in
           85  +			fakeact = true
           86  +			fakeactor = lib.store.actor {
           87  +				id = 0, handle = usn, nym = usn;
           88  +				origin = 0, bio = nil;
           89  +				key = [lib.mem.ptr(uint8)] {ptr=nil, ct=0}
           90  +			}
           91  +			act.ct = 1
           92  +			act.ptr = &fakeactor
           93  +			act.ptr.rights = lib.store.rights_default()
           94  +		end
           95  +		if am == nil then
           96  +			-- pick an auth method
           97  +			lib.render.login(co, act.ptr, &cs, nil)
           98  +		else var aid: uint64 = 0
           99  +			lib.dbg('authentication attempt beginning')
          100  +			-- attempt login with provided method
          101  +			if lib.str.ncmp('pw', am, lib.math.biggest(2,aml)) == 0 and chrs ~= nil then
          102  +				aid = co.srv:actor_auth_pw(co.peer,
          103  +					[lib.mem.ptr(int8)]{ptr=usn,ct=usnl},
          104  +					[lib.mem.ptr(int8)]{ptr=chrs,ct=chrsl})
          105  +			elseif lib.str.ncmp('otp', am, lib.math.biggest(2,aml)) == 0 and chrs ~= nil then
          106  +				lib.dbg('using otp auth')
          107  +				-- ยทยทยท --
          108  +			else
          109  +				lib.dbg('invalid auth method')
          110  +			end
          111  +
          112  +			lib.io.fmt('login got aid = %llu\n', aid)
          113  +			-- error out
          114  +			if aid == 0 then
          115  +				lib.render.login(co, nil, nil, 'authentication failure')
          116  +			else
          117  +				var sesskey: int8[lib.session.maxlen + #lib.session.cookiename + #"=; Path=/" + 1]
          118  +				do var p = &sesskey[0]
          119  +					p = lib.str.ncpy(p, [lib.session.cookiename .. '='], [#lib.session.cookiename + 1])
          120  +					p = p + lib.session.cookie_gen(co.srv.cfg.secret, aid, lib.osclock.time(nil), p)
          121  +					lib.dbg('sending cookie',&sesskey[0])
          122  +					p = lib.str.ncpy(p, '; Path=/', 9)
          123  +				end
          124  +				co:reroute_cookie('/', &sesskey[0])
          125  +			end
          126  +		end
          127  +		if act.ptr ~= nil and fakeact == false then act:free() end
          128  +	else
          129  +		::wrongmeth:: co:complain(405, 'method not allowed', 'that method is not meaningful for this endpoint') do return end
          130  +	end
          131  +	return
          132  +end
          133  +
          134  +terra http.post_compose(co: &lib.srv.convo, meth: method.t)
          135  +	if meth == method.get then
          136  +		lib.render.compose(co, nil)
          137  +	elseif meth == method.post then
          138  +		if co.who.rights.powers.post() == false then
          139  +			co:complain(401,'insufficient privileges','you lack the <strong>post</strong> power and cannot perform this action') return
          140  +		end
          141  +
          142  +	end
          143  +end
    60    144   
    61    145   do local branches = quote end
    62    146   	local filename, flen = symbol(&int8), symbol(intptr)
    63    147   	local page = symbol(lib.http.page)
    64    148   	local send = label()
    65    149   	local storage = data.stmap
    66    150   	for i,e in ipairs(config.embeds) do local id,mime = e[1],e[2]
................................................................................
    86    170   		}
    87    171   		[branches]
    88    172   		do return false end
    89    173   		::[send]:: page:send(co.con) return true
    90    174   	end
    91    175   end
    92    176   
    93         -http.static_content:printpretty()
          177  +
          178  +terra http.local_avatar(co: &lib.srv.convo, handle: lib.mem.ptr(int8))
          179  +	-- TODO retrieve user avatars
          180  +	co:reroute('/s/default-avatar.webp')
          181  +end
    94    182   
    95    183   -- entry points
    96    184   terra r.dispatch_http(co: &lib.srv.convo, uri: lib.mem.ptr(int8), meth: method.t)
          185  +	lib.dbg('handling URI of form ', {uri.ptr,uri.ct})
          186  +	co.navbar = lib.render.nav(co)
          187  +	-- some routes are non-hierarchical, and can be resolved with a simple strcmp
          188  +	-- we run through those first before giving up and parsing the URI
    97    189   	if uri.ptr[0] ~= @'/' then
    98    190   		co:complain(404, 'what the hell', 'how did you do that')
          191  +		return
          192  +	elseif uri.ct == 1 then -- root
          193  +		lib.io.fmt('root directory, aid is %llu\n', co.aid)
          194  +		if (co.srv.cfg.pol_sec == lib.srv.secmode.private or
          195  +		   co.srv.cfg.pol_sec == lib.srv.secmode.lockdown) and co.aid == 0 then
          196  +		   http.login_form(co, meth)
          197  +		else
          198  +			-- FIXME display home screen
          199  +			goto notfound
          200  +		end
          201  +		return
    99    202   	elseif uri.ptr[1] == @'@' then
   100    203   		http.actor_profile_xid(co, uri, meth)
          204  +		return
   101    205   	elseif uri.ptr[1] == @'s' and uri.ptr[2] == @'/' and uri.ct > 3 then
   102    206   		if meth ~= method.get then goto wrongmeth end
   103    207   		if not http.static_content(co, uri.ptr + 3, uri.ct - 3) then goto notfound end
   104         -	else
          208  +		return
          209  +	elseif lib.str.ncmp('/avi/', uri.ptr, 5) == 0 then
          210  +		http.local_avatar(co, [lib.mem.ptr(int8)] {ptr = uri.ptr + 5, ct = uri.ct - 5})
          211  +		return
          212  +	elseif lib.str.ncmp('/compose', uri.ptr, lib.math.biggest(uri.ct,8)) == 0 then
          213  +		if co.aid == 0 then co:reroute('/login') return end
          214  +		http.post_compose(co,meth)
          215  +		return
          216  +	elseif lib.str.ncmp('/login', uri.ptr, lib.math.biggest(uri.ct,6)) == 0 then
          217  +		if co.aid == 0
          218  +			then http.login_form(co, meth)
          219  +			else co:reroute('/')
          220  +		end
          221  +		return
          222  +	elseif lib.str.ncmp('/logout', uri.ptr, lib.math.biggest(uri.ct,7)) == 0 then
          223  +		if co.aid == 0
          224  +			then goto notfound
          225  +			else co:reroute_cookie('/','auth=; Path=/')
          226  +		end
          227  +		return
          228  +	else -- hierarchical routes
   105    229   		var path = lib.http.hier(uri) defer path:free()
   106    230   		if path.ptr[0]:cmp(lib.str.lit('user')) then
   107    231   			http.actor_profile_uid(co, path, meth)
   108    232   		else goto notfound end
          233  +		return
   109    234   	end
   110    235   
   111         -	::wrongmeth:: co:complain(405, 'method not allowed', 'that method is not meaningful for this path') do return end
          236  +	::wrongmeth:: co:complain(405, 'method not allowed', 'that method is not meaningful for this endpoint') do return end
   112    237   	::notfound:: co:complain(404, 'not found', 'no such resource available') do return end
   113    238   end