ggdgsdbsdbbb / api_token.v
76 lines · 68 sloc · 1.71 KB · f5e6951a04fdbbd0436fbfe2e6b421fb3696f872
Raw
1// Copyright (c) 2019-2026 Alexander Medvednikov. All rights reserved.
2// Use of this source code is governed by a GPL license that can be found in the LICENSE file.
3module main
4
5import time
6import crypto.sha256
7import rand
8import encoding.hex
9
10struct ApiToken {
11 id int @[primary; sql: serial]
12mut:
13 user_id int
14 name string
15 token_hash string
16 created_at int
17 last_used_at int
18}
19
20fn hash_api_token(plain string) string {
21 return sha256.sum(plain.bytes()).hex()
22}
23
24fn generate_api_token_plaintext() string {
25 mut buf := []u8{len: 24}
26 for i in 0 .. buf.len {
27 buf[i] = u8(rand.intn(256) or { 0 })
28 }
29 return 'glt_' + hex.encode(buf)
30}
31
32fn (mut app App) add_api_token(user_id int, name string) !(int, string) {
33 plain := generate_api_token_plaintext()
34 t := ApiToken{
35 user_id: user_id
36 name: name
37 token_hash: hash_api_token(plain)
38 created_at: int(time.now().unix())
39 }
40 sql app.db {
41 insert t into ApiToken
42 }!
43 return db_last_insert_id(app.db), plain
44}
45
46fn (mut app App) list_user_api_tokens(user_id int) []ApiToken {
47 return sql app.db {
48 select from ApiToken where user_id == user_id order by id desc
49 } or { []ApiToken{} }
50}
51
52fn (mut app App) delete_api_token(user_id int, id int) ! {
53 sql app.db {
54 delete from ApiToken where id == id && user_id == user_id
55 }!
56}
57
58fn (mut app App) user_for_api_token(plain string) ?User {
59 if plain == '' {
60 return none
61 }
62 hashed := hash_api_token(plain)
63 rows := sql app.db {
64 select from ApiToken where token_hash == hashed limit 1
65 } or { []ApiToken{} }
66 if rows.len == 0 {
67 return none
68 }
69 t := rows.first()
70 now := int(time.now().unix())
71 id := t.id
72 sql app.db {
73 update ApiToken set last_used_at = now where id == id
74 } or {}
75 return app.get_user_by_id(t.user_id)
76}
77