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 }