+12
-7
src/auth/auth.v
+12
-7
src/auth/auth.v
···
1
// From: https://github.com/vlang/v/blob/1fae506900c79e3aafc00e08e1f861fc7cbf8012/vlib/veb/auth/auth.v
2
// The original file's source is licensed under MIT.
3
4
// This fork re-introduces the `ip` field of each token for additional security,
5
// along with delete_tokens_for_ip
6
7
module auth
8
···
22
id int @[primary; sql: serial]
23
user_id int
24
value string
25
-
ip string
26
}
27
28
pub fn new[T](db T) Auth[T] {
···
35
}
36
}
37
38
-
pub fn (mut app Auth[T]) add_token(user_id int, ip string) !string {
39
mut uuid := rand.uuid_v4()
40
token := Token{
41
user_id: user_id
42
value: uuid
43
-
ip: ip
44
}
45
sql app.db {
46
insert token into Token
···
48
return uuid
49
}
50
51
-
pub fn (app &Auth[T]) find_token(value string, ip string) ?Token {
52
tokens := sql app.db {
53
-
select from Token where value == value && ip == ip limit 1
54
} or { []Token{} }
55
if tokens.len == 0 {
56
return none
···
58
return tokens.first()
59
}
60
61
pub fn (mut app Auth[T]) delete_tokens_for_user(user_id int) ! {
62
sql app.db {
63
delete from Token where user_id == user_id
64
}!
65
}
66
67
-
pub fn (mut app Auth[T]) delete_tokens_for_ip(ip string) ! {
68
sql app.db {
69
-
delete from Token where ip == ip
70
}!
71
}
72
···
1
// From: https://github.com/vlang/v/blob/1fae506900c79e3aafc00e08e1f861fc7cbf8012/vlib/veb/auth/auth.v
2
// The original file's source is licensed under MIT.
3
4
+
// ~~
5
// This fork re-introduces the `ip` field of each token for additional security,
6
// along with delete_tokens_for_ip
7
+
// ~~
8
+
// IP has been removed since IPs can change randomly and it causes you to need
9
+
// to relog wayyyy more often. I'm keeping this fork just in case I do need to
10
+
// change the auth system in the future.
11
12
module auth
13
···
27
id int @[primary; sql: serial]
28
user_id int
29
value string
30
}
31
32
pub fn new[T](db T) Auth[T] {
···
39
}
40
}
41
42
+
pub fn (mut app Auth[T]) add_token(user_id int) !string {
43
mut uuid := rand.uuid_v4()
44
token := Token{
45
user_id: user_id
46
value: uuid
47
}
48
sql app.db {
49
insert token into Token
···
51
return uuid
52
}
53
54
+
pub fn (app &Auth[T]) find_token(value string) ?Token {
55
tokens := sql app.db {
56
+
select from Token where value == value limit 1
57
} or { []Token{} }
58
if tokens.len == 0 {
59
return none
···
61
return tokens.first()
62
}
63
64
+
// logs out of all devices
65
pub fn (mut app Auth[T]) delete_tokens_for_user(user_id int) ! {
66
sql app.db {
67
delete from Token where user_id == user_id
68
}!
69
}
70
71
+
// logs out of one device
72
+
pub fn (mut app Auth[T]) delete_tokens_for_value(value string) ! {
73
sql app.db {
74
+
delete from Token where value == value
75
}!
76
}
77
+9
-5
src/webapp/api.v
+9
-5
src/webapp/api.v
···
83
if x := app.new_user(user) {
84
app.send_notification_to(x.id, app.config.welcome.summary.replace('%s', x.get_name()),
85
app.config.welcome.body.replace('%s', x.get_name()))
86
-
token := app.auth.add_token(x.id, ctx.ip()) or {
87
eprintln(err)
88
ctx.error('api_user_register: could not create token for user with id ${x.id}')
89
return ctx.redirect('/')
···
180
return ctx.redirect('/login')
181
}
182
183
-
token := app.auth.add_token(user.id, ctx.ip()) or {
184
eprintln('failed to add token on log in: ${err}')
185
ctx.error('could not create token for user with id ${user.id}')
186
return ctx.redirect('/login')
···
200
@['/api/user/logout']
201
fn (mut app App) api_user_logout(mut ctx Context) veb.Result {
202
if token := ctx.get_cookie('token') {
203
-
if user := app.get_user_by_token(ctx, token) {
204
-
app.auth.delete_tokens_for_ip(ctx.ip()) or {
205
eprintln('failed to yeet tokens for ${user.id} with ip ${ctx.ip()} (${err})')
206
return ctx.redirect('/login')
207
}
···
226
@['/api/user/full_logout']
227
fn (mut app App) api_user_full_logout(mut ctx Context) veb.Result {
228
if token := ctx.get_cookie('token') {
229
-
if user := app.get_user_by_token(ctx, token) {
230
app.auth.delete_tokens_for_user(user.id) or {
231
eprintln('failed to yeet tokens for ${user.id}')
232
return ctx.redirect('/login')
···
83
if x := app.new_user(user) {
84
app.send_notification_to(x.id, app.config.welcome.summary.replace('%s', x.get_name()),
85
app.config.welcome.body.replace('%s', x.get_name()))
86
+
token := app.auth.add_token(x.id) or {
87
eprintln(err)
88
ctx.error('api_user_register: could not create token for user with id ${x.id}')
89
return ctx.redirect('/')
···
180
return ctx.redirect('/login')
181
}
182
183
+
token := app.auth.add_token(user.id) or {
184
eprintln('failed to add token on log in: ${err}')
185
ctx.error('could not create token for user with id ${user.id}')
186
return ctx.redirect('/login')
···
200
@['/api/user/logout']
201
fn (mut app App) api_user_logout(mut ctx Context) veb.Result {
202
if token := ctx.get_cookie('token') {
203
+
if user := app.get_user_by_token(token) {
204
+
// app.auth.delete_tokens_for_ip(ctx.ip()) or {
205
+
// eprintln('failed to yeet tokens for ${user.id} with ip ${ctx.ip()} (${err})')
206
+
// return ctx.redirect('/login')
207
+
// }
208
+
app.auth.delete_tokens_for_value(token) or {
209
eprintln('failed to yeet tokens for ${user.id} with ip ${ctx.ip()} (${err})')
210
return ctx.redirect('/login')
211
}
···
230
@['/api/user/full_logout']
231
fn (mut app App) api_user_full_logout(mut ctx Context) veb.Result {
232
if token := ctx.get_cookie('token') {
233
+
if user := app.get_user_by_token(token) {
234
app.auth.delete_tokens_for_user(user.id) or {
235
eprintln('failed to yeet tokens for ${user.id}')
236
return ctx.redirect('/login')
+3
-3
src/webapp/app.v
+3
-3
src/webapp/app.v
···
31
32
// get_user_by_token returns a user by their token, returns none if the user was
33
// not found.
34
-
pub fn (app &App) get_user_by_token(ctx &Context, token string) ?User {
35
-
user_token := app.auth.find_token(token, ctx.ip()) or {
36
eprintln('no such user corresponding to token')
37
return none
38
}
···
46
if token == '' {
47
return none
48
}
49
-
if user := app.get_user_by_token(ctx, token) {
50
if user.username == '' || user.id == 0 {
51
eprintln('a user had a token for the blank user')
52
// Clear token
···
31
32
// get_user_by_token returns a user by their token, returns none if the user was
33
// not found.
34
+
pub fn (app &App) get_user_by_token(token string) ?User {
35
+
user_token := app.auth.find_token(token) or {
36
eprintln('no such user corresponding to token')
37
return none
38
}
···
46
if token == '' {
47
return none
48
}
49
+
if user := app.get_user_by_token(token) {
50
if user.username == '' || user.id == 0 {
51
eprintln('a user had a token for the blank user')
52
// Clear token