Differences From
Artifact [70d0da6b8e]:
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