a mini social media app for small communities
1module main
2
3import veb
4import auth
5import entity { User, Post }
6
7////// Users //////
8
9@['/api/user/register'; post]
10fn (mut app App) api_user_register(mut ctx Context, username string, password string) veb.Result {
11 println('reg: ${username}')
12
13 if app.get_user_by_name(username) != none {
14 ctx.error('username taken')
15 return ctx.redirect('/register')
16 }
17
18 salt := auth.generate_salt()
19 user := User{
20 username: username
21 password: auth.hash_password_with_salt(password, salt)
22 password_salt: salt
23 }
24
25 sql app.db {
26 insert user into User
27 } or {
28 eprintln('failed to insert user ${user}')
29 return ctx.redirect('/')
30 }
31
32 if x := app.get_user_by_name(username) {
33 token := app.auth.add_token(x.id, ctx.ip()) or {
34 eprintln(err)
35 ctx.error('could not create token for user with id ${user.id}')
36 return ctx.redirect('/')
37 }
38 ctx.set_cookie(
39 name: 'token'
40 value: token
41 same_site: .same_site_none_mode
42 secure: true
43 path: '/'
44 )
45 } else {
46 eprintln('could not log into newly-created user: ${user}')
47 ctx.error('could not log into newly-created user.')
48 }
49
50 return ctx.redirect('/')
51}
52
53@['/api/user/login'; post]
54fn (mut app App) api_user_login(mut ctx Context, username string, password string) veb.Result {
55 user := app.get_user_by_name(username) or {
56 ctx.error('invalid credentials')
57 return ctx.redirect('/login')
58 }
59 if !auth.compare_password_with_hash(password, user.password_salt, user.password) {
60 ctx.error('invalid credentials')
61 return ctx.redirect('/login')
62 }
63 token := app.auth.add_token(user.id, ctx.ip()) or {
64 eprintln('failed to add token on log in: ${err}')
65 ctx.error('could not create token for user with id ${user.id}')
66 return ctx.redirect('/login')
67 }
68 ctx.set_cookie(
69 name: 'token'
70 value: token
71 same_site: .same_site_none_mode
72 secure: true
73 path: '/'
74 )
75 return ctx.redirect('/')
76}
77
78@['/api/user/logout']
79fn (mut app App) api_user_logout(mut ctx Context) veb.Result {
80 if token := ctx.get_cookie('token') {
81 if user := app.get_user_by_token(ctx, token) {
82 app.auth.delete_tokens_for_ip(ctx.ip()) or {
83 eprintln('failed to yeet tokens for ${user.id} with ip ${ctx.ip()}')
84 return ctx.redirect('/login')
85 }
86 } else {
87 eprintln('failed to get user for token: `${token}` for logout')
88 }
89 } else {
90 eprintln('failed to get token cookie for logout')
91 }
92 ctx.set_cookie(
93 name: 'token'
94 value: ''
95 same_site: .same_site_none_mode
96 secure: true
97 path: '/'
98 )
99 return ctx.redirect('/login')
100}
101
102@['/api/user/full_logout']
103fn (mut app App) api_user_full_logout(mut ctx Context) veb.Result {
104 if token := ctx.get_cookie('token') {
105 if user := app.get_user_by_token(ctx, token) {
106 app.auth.delete_tokens_for_user(user.id) or {
107 eprintln('failed to yeet tokens for ${user.id}')
108 return ctx.redirect('/login')
109 }
110 } else {
111 eprintln('failed to get user for token: `${token}` for full_logout')
112 }
113 } else {
114 eprintln('failed to get token cookie for full_logout')
115 }
116 ctx.set_cookie(
117 name: 'token'
118 value: ''
119 same_site: .same_site_none_mode
120 secure: true
121 path: '/'
122 )
123 return ctx.redirect('/login')
124}
125
126////// Posts //////
127
128@['/api/post/new_post'; post]
129fn (mut app App) api_post_new_post(mut ctx Context, title string, body string) veb.Result {
130 mut user := app.whoami(mut ctx) or {
131 ctx.error('not logged in!')
132 return ctx.redirect('/')
133 }
134
135 post := Post{
136 author_id: user.id
137 title: title
138 body: body
139 }
140
141 sql app.db {
142 insert post into Post
143 } or {
144 ctx.error('failed to post!')
145 println('failed to post: ${post} from user ${user.id}')
146 return ctx.redirect('/me')
147 }
148
149 user.posts << post
150
151 return ctx.redirect('/me')
152}