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