121 lines
2.5 KiB
V
121 lines
2.5 KiB
V
module main
|
|
|
|
import vweb
|
|
import json
|
|
import time
|
|
|
|
struct Status {
|
|
status int
|
|
message string
|
|
}
|
|
|
|
[get; head]
|
|
pub fn (mut app App) index() vweb.Result {
|
|
rlock app.config {
|
|
if app.config.redirect {
|
|
return app.redirect(app.config.redirect_url)
|
|
}
|
|
}
|
|
|
|
return app.not_found()
|
|
}
|
|
|
|
['/api/v1/score/list'; get; head]
|
|
pub fn (mut app App) score_list() vweb.Result {
|
|
app.add_cors_headers()
|
|
|
|
if !app.auth() {
|
|
app.set_status(401, '')
|
|
return app.json(Status{401, 'Access token is wrong or missing'})
|
|
}
|
|
|
|
scores := app.get_scores()
|
|
|
|
return app.json(scores)
|
|
}
|
|
|
|
['/api/v1/score/submit'; post]
|
|
pub fn (mut app App) score_submit() vweb.Result {
|
|
app.add_cors_headers()
|
|
|
|
if !app.auth() {
|
|
app.set_status(401, '')
|
|
return app.json(Status{401, 'Access token is wrong or missing'})
|
|
}
|
|
|
|
body := json.decode(Score, app.req.data) or {
|
|
app.set_status(400, '')
|
|
return app.json(Status{400, 'Bad JSON object'})
|
|
}
|
|
|
|
if body.player.trim_space().len == 0 {
|
|
app.set_status(400, '')
|
|
return app.json(Status{400, 'Name cannot be empty'})
|
|
}
|
|
|
|
if body.score <= 0 {
|
|
app.set_status(400, '')
|
|
return app.json(Status{400, 'Illegal score'})
|
|
}
|
|
|
|
// TODO: Bad word filter
|
|
|
|
score := app.insert_score(ScoreRes{
|
|
player: body.player
|
|
score: body.score
|
|
time: time.now().unix_time()
|
|
})
|
|
|
|
return app.json(score)
|
|
}
|
|
|
|
['/api/v1/score/list'; options]
|
|
pub fn (mut app App) handle_score_list_options() vweb.Result {
|
|
return app.handle_options()
|
|
}
|
|
|
|
['/api/v1/score/submit'; options]
|
|
pub fn (mut app App) handle_score_submit_options() vweb.Result {
|
|
return app.handle_options()
|
|
}
|
|
|
|
fn (mut app App) handle_options() vweb.Result {
|
|
app.set_status(204, '')
|
|
app.add_cors_headers()
|
|
return app.ok('')
|
|
}
|
|
|
|
fn (mut app App) add_cors_headers() {
|
|
origin := app.get_header('origin')
|
|
|
|
// Only return headers if actual cross-origin request
|
|
if origin.len == 0 {
|
|
return
|
|
}
|
|
|
|
rlock app.config {
|
|
origins := app.config.origins
|
|
|
|
default_origin := origins[0] or { '*' }
|
|
allowed_origin := if origins.any(it == origin) { origin } else { default_origin }
|
|
|
|
app.add_header('Access-Control-Allow-Origin', allowed_origin)
|
|
}
|
|
app.add_header('Access-Control-Allow-Methods', 'OPTIONS, HEAD, GET, POST')
|
|
app.add_header('Access-Control-Allow-Headers', 'Authorization, Content-Type')
|
|
app.add_header('Access-Control-Max-Age', '86400')
|
|
}
|
|
|
|
fn (mut app App) auth() bool {
|
|
auth_header := app.get_header('Authorization')
|
|
token := auth_header.after('Bearer ')
|
|
|
|
mut config_token := ''
|
|
|
|
rlock app.config {
|
|
config_token = app.config.token
|
|
}
|
|
|
|
return config_token.len != 0 && token == config_token
|
|
}
|