a mini social media app for small communities

don't store IP with tokens

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