From c53a9e392678ec64d5d542618bf9c0b002033af6 Mon Sep 17 00:00:00 2001 From: SuperErnD Date: Thu, 20 Jun 2024 20:51:33 +0300 Subject: [PATCH] new tokens --- api/Dockerfile | 2 +- api/src/account.v | 23 +++++++++++++++++++---- api/src/etc.v | 10 +++++++++- api/src/main.v | 17 ++++++++++++++++- api/src/utils.v | 9 +++++++-- 5 files changed, 52 insertions(+), 9 deletions(-) diff --git a/api/Dockerfile b/api/Dockerfile index ddaac5e..b448d76 100644 --- a/api/Dockerfile +++ b/api/Dockerfile @@ -11,7 +11,7 @@ RUN apk add --no-cache git build-base sqlite-dev libsodium-dev && \ WORKDIR /build/v -RUN make && /build/v/v install SuperErnD.cn +RUN make && /build/v/v install SuperErnD.cn && /build/v/v install elitru.jwt RUN rm -rf doc examples/ tutorials/ vc/ ./vlib/v/tests/ \ ./vlib/v/slow_tests/ ./vlib/v/embed_file/tests/ \ diff --git a/api/src/account.v b/api/src/account.v index 7f365a1..4326cc8 100644 --- a/api/src/account.v +++ b/api/src/account.v @@ -3,6 +3,7 @@ module main import veb import veb.auth import db.tables +import elitru.jwt import net.http import json @@ -15,6 +16,10 @@ enum UserStatus { banned = 3 // User is banned, user cant enter the game at all } +struct UserClaims { + id int +} + @[post] pub fn (mut app App) register(mut ctx Context) veb.Result { name := ctx.query['name'] or { return ctx.request_error('Username is not provided.') } @@ -38,7 +43,12 @@ pub fn (mut app App) register(mut ctx Context) veb.Result { } if x := app.find_user_by_name(name) { - token := app.auth.add_token(x.id) or { '' } + alg := jwt.new_algorithm(jwt.AlgorithmType.hs256) + token := jwt.encode(UserClaims{ + id: x.id + }, alg, app.salt, 168 * 60 * 60) or { + return ctx.request_error("Something went wrong while creating token!") + } return ctx.json({ 'token': token }) @@ -56,12 +66,17 @@ pub fn (mut app App) login(mut ctx Context) veb.Result { user := app.find_user_by_name(name) or { return ctx.request_error('Bad credentials') } - // Verify user password using veb.auth + if !auth.compare_password_with_hash(password, user.salt, user.password_hash) { return ctx.request_error('Bad credentials') } - // Find the user token in the Token table - token := app.auth.add_token(user.id) or { '' } + + alg := jwt.new_algorithm(jwt.AlgorithmType.hs256) + token := jwt.encode(UserClaims{ + id: user.id + }, alg, app.salt, 168 * 60 * 60) or { + return ctx.request_error("Something went wrong while creating token!") + } return ctx.json({ 'token': token diff --git a/api/src/etc.v b/api/src/etc.v index 0dbfef0..6aa92ee 100644 --- a/api/src/etc.v +++ b/api/src/etc.v @@ -11,9 +11,17 @@ fn get_commit() ?string { @[get] pub fn (mut app App) version(mut ctx Context) veb.Result { - commit := (get_commit() or { "0" }) + commit := (get_commit() or { "UNKNOWN_COMMIT" }) return ctx.json({ 'version': '0.0.0-DEV+${commit}' 'os': os.user_os() }) +} + +pub fn (mut ctx Context) not_found() veb.Result { + // 404 + ctx.res.set_status(.not_found) + return ctx.json({ + "error": "404 bro" + }) } \ No newline at end of file diff --git a/api/src/main.v b/api/src/main.v index 67d238f..6a6b097 100644 --- a/api/src/main.v +++ b/api/src/main.v @@ -9,6 +9,8 @@ import saving import veb.auth import db.sqlite import db.tables +import crypto.bcrypt +import encoding.hex pub struct Context { veb.Context @@ -22,6 +24,7 @@ pub mut: auth auth.Auth[orm.Connection] game_servers []string // a list lol private_token_key string + salt string } fn main() { @@ -37,6 +40,18 @@ fn main() { mut conf := toml.parse_file(conf_file) or { log.error("Failed to read config!"); panic(err) } // купил письки? фатальная ошибка + mut salt := "" + + if conf.value("donotedit.salt") == toml.null { + eprintln(error("seems its first setup, generating salt..")) + salt = hex.encode(bcrypt.generate_salt().bytes()) + mut f := os.open_append(conf_file) or { panic(err) } + f.write_string("\n\n# DO NOT EDIT, THIS PART IS AUTOGENERATED\n[donotedit]\nsalt=\"$salt\"") or { panic(err) } + f.close() + } else { + salt = conf.value("donotedit.salt").string() + } + mut saver := saving.Saver(unsafe { nil }) if conf.value("saver.backend").string() == "local" { @@ -54,7 +69,7 @@ fn main() { app.game_servers << s.string() } app.private_token_key = conf.value("game.private_token_key").string() - + app.salt = salt app.auth = auth.new(app.db) app.use(veb.cors[Context](veb.CorsOptions{ origins: ['*'] diff --git a/api/src/utils.v b/api/src/utils.v index 437eaf7..962f507 100644 --- a/api/src/utils.v +++ b/api/src/utils.v @@ -1,6 +1,7 @@ module main import db.tables +import elitru.jwt pub struct IpApiResponse { pub: @@ -30,8 +31,12 @@ pub fn (mut app App) find_user_by_id(id int) ?tables.User { } pub fn (mut app App) auth_user(mut ctx Context) !tables.User { - token := app.auth.find_token(ctx.get_header(.authorization)!) or { return error("Token not found.") } + alg := jwt.new_algorithm(jwt.AlgorithmType.hs256) + claims_decoded := jwt.verify(ctx.get_header(.authorization)!, alg, app.salt) or { + return err + } + //token := app.auth.find_token(ctx.get_header(.authorization)!) or { return error("Token not found.") } - return app.find_user_by_id(token.user_id) or { return error("User not found.") } + return app.find_user_by_id(claims_decoded.id) or { return error("User not found.") } }