+10
-20
src/api.v
+10
-20
src/api.v
···
2
2
3
3
import veb
4
4
import auth
5
-
import entity { Site, User, Post, Like, LikeCache }
5
+
import entity { Like, LikeCache, Post, Site, User }
6
6
7
7
////// Users //////
8
8
···
27
27
28
28
salt := auth.generate_salt()
29
29
mut user := User{
30
-
username: username
31
-
password: auth.hash_password_with_salt(password, salt)
30
+
username: username
31
+
password: auth.hash_password_with_salt(password, salt)
32
32
password_salt: salt
33
33
}
34
34
···
277
277
278
278
@['/api/user/get_name']
279
279
fn (mut app App) api_user_get_name(mut ctx Context, username string) veb.Result {
280
-
user := app.get_user_by_name(username) or {
281
-
return ctx.server_error('no such user')
282
-
}
280
+
user := app.get_user_by_name(username) or { return ctx.server_error('no such user') }
283
281
return ctx.text(user.get_name())
284
282
}
285
283
···
311
309
312
310
post := Post{
313
311
author_id: user.id
314
-
title: title
315
-
body: body
312
+
title: title
313
+
body: body
316
314
}
317
315
318
316
sql app.db {
···
358
356
359
357
@['/api/post/like']
360
358
fn (mut app App) api_post_like(mut ctx Context, id int) veb.Result {
361
-
user := app.whoami(mut ctx) or {
362
-
return ctx.unauthorized('not logged in')
363
-
}
359
+
user := app.whoami(mut ctx) or { return ctx.unauthorized('not logged in') }
364
360
365
-
post := app.get_post_by_id(id) or {
366
-
return ctx.server_error('post does not exist')
367
-
}
361
+
post := app.get_post_by_id(id) or { return ctx.server_error('post does not exist') }
368
362
369
363
if app.does_user_like_post(user.id, post.id) {
370
364
sql app.db {
···
405
399
406
400
@['/api/post/dislike']
407
401
fn (mut app App) api_post_dislike(mut ctx Context, id int) veb.Result {
408
-
user := app.whoami(mut ctx) or {
409
-
return ctx.unauthorized('not logged in')
410
-
}
402
+
user := app.whoami(mut ctx) or { return ctx.unauthorized('not logged in') }
411
403
412
-
post := app.get_post_by_id(id) or {
413
-
return ctx.server_error('post does not exist')
414
-
}
404
+
post := app.get_post_by_id(id) or { return ctx.server_error('post does not exist') }
415
405
416
406
if app.does_user_dislike_post(user.id, post.id) {
417
407
sql app.db {
+12
-14
src/app.v
+12
-14
src/app.v
···
3
3
import veb
4
4
import db.pg
5
5
import auth
6
-
import entity { Site, User, Post, Like, LikeCache }
6
+
import entity { LikeCache, Like, Post, Site, User }
7
7
8
8
pub struct App {
9
9
veb.StaticHandler
···
13
13
db pg.DB
14
14
auth auth.Auth[pg.DB]
15
15
validators struct {
16
-
pub:
16
+
pub mut:
17
17
username StringValidator
18
18
password StringValidator
19
19
nickname StringValidator
···
98
98
}
99
99
100
100
pub fn (app &App) whoami(mut ctx Context) ?User {
101
-
token := ctx.get_cookie('token') or {
102
-
return none
103
-
}.trim_space()
101
+
token := ctx.get_cookie('token') or { return none }.trim_space()
104
102
if token == '' {
105
103
return none
106
104
}
···
133
131
}
134
132
135
133
pub fn (app &App) get_unknown_user() User {
136
-
return User{ username: 'unknown' }
134
+
return User{
135
+
username: 'unknown'
136
+
}
137
137
}
138
138
139
139
pub fn (app &App) logged_in_as(mut ctx Context, id int) bool {
···
204
204
}
205
205
206
206
// cache
207
-
cached := LikeCache {
207
+
cached := LikeCache{
208
208
post_id: post_id
209
-
likes: likes
209
+
likes: likes
210
210
}
211
211
sql app.db {
212
212
insert cached into LikeCache
···
223
223
224
224
pub fn (app &App) get_or_create_site_config() Site {
225
225
configs := sql app.db {
226
-
select from entity.Site
226
+
select from Site
227
227
} or { [] }
228
228
if configs.len == 0 {
229
229
// make the site config
230
-
site_config := entity.Site{ }
230
+
site_config := Site{}
231
231
sql app.db {
232
-
insert site_config into entity.Site
233
-
} or {
234
-
panic('failed to create site config (${err})')
235
-
}
232
+
insert site_config into Site
233
+
} or { panic('failed to create site config (${err})') }
236
234
} else if configs.len > 1 {
237
235
// this should never happen
238
236
panic('there are multiple site configs')
+12
-12
src/config.v
+12
-12
src/config.v
···
6
6
pub mut:
7
7
dev_mode bool
8
8
static_path string
9
-
instance struct {
9
+
instance struct {
10
10
pub mut:
11
11
name string
12
12
welcome string
13
13
default_theme string
14
14
allow_changing_theme bool
15
15
}
16
-
http struct {
16
+
http struct {
17
17
pub mut:
18
18
port int
19
19
}
20
-
postgres struct {
20
+
postgres struct {
21
21
pub mut:
22
-
host string
23
-
port int
24
-
user string
22
+
host string
23
+
port int
24
+
user string
25
25
password string
26
-
db string
26
+
db string
27
27
}
28
-
post struct {
28
+
post struct {
29
29
pub mut:
30
30
title_min_len int
31
31
title_max_len int
32
32
title_pattern string
33
-
body_min_len int
34
-
body_max_len int
35
-
body_pattern string
33
+
body_min_len int
34
+
body_max_len int
35
+
body_pattern string
36
36
}
37
-
user struct {
37
+
user struct {
38
38
pub mut:
39
39
username_min_len int
40
40
username_max_len int
+3
-3
src/entity/likes.v
+3
-3
src/entity/likes.v
+2
-2
src/entity/post.v
+2
-2
src/entity/post.v
+1
-1
src/entity/site.v
+1
-1
src/entity/site.v
+12
-11
src/main.v
+12
-11
src/main.v
···
33
33
34
34
mut app := &App{
35
35
config: config
36
-
db: db
37
-
auth: auth.new(db)
38
-
validators: struct {
39
-
username: StringValidator.new(config.user.username_min_len, config.user.username_max_len, config.user.username_pattern)
40
-
password: StringValidator.new(config.user.username_min_len, config.user.username_max_len, config.user.username_pattern)
41
-
nickname: StringValidator.new(config.user.nickname_min_len, config.user.nickname_max_len, config.user.nickname_pattern)
42
-
user_bio: StringValidator.new(config.user.bio_min_len, config.user.bio_max_len, config.user.bio_pattern)
43
-
pronouns: StringValidator.new(config.user.pronouns_min_len, config.user.pronouns_max_len, config.user.pronouns_pattern)
44
-
post_title: StringValidator.new(config.post.title_min_len, config.post.title_max_len, config.post.title_pattern)
45
-
post_body: StringValidator.new(config.post.body_min_len, config.post.body_max_len, config.post.body_pattern)
46
-
}
36
+
db: db
37
+
auth: auth.new(db)
47
38
}
39
+
40
+
// vfmt off
41
+
app.validators.username = StringValidator.new(config.user.username_min_len, config.user.username_max_len, config.user.username_pattern)
42
+
app.validators.password = StringValidator.new(config.user.username_min_len, config.user.username_max_len, config.user.username_pattern)
43
+
app.validators.nickname = StringValidator.new(config.user.nickname_min_len, config.user.nickname_max_len, config.user.nickname_pattern)
44
+
app.validators.user_bio = StringValidator.new(config.user.bio_min_len, config.user.bio_max_len, config.user.bio_pattern)
45
+
app.validators.pronouns = StringValidator.new(config.user.pronouns_min_len, config.user.pronouns_max_len, config.user.pronouns_pattern)
46
+
app.validators.post_title = StringValidator.new(config.post.title_min_len, config.post.title_max_len, config.post.title_pattern)
47
+
app.validators.post_body = StringValidator.new(config.post.body_min_len, config.post.body_max_len, config.post.body_pattern)
48
+
// vfmt on
48
49
49
50
app.mount_static_folder_at(app.config.static_path, '/static')!
50
51
init_db(db)!
+1
-1
src/pages.v
+1
-1
src/pages.v
+2
-1
src/validation.v
+2
-1
src/validation.v
···
12
12
13
13
@[inline]
14
14
pub fn (validator StringValidator) validate(str string) bool {
15
-
return str.len > validator.min_len && str.len < validator.max_len && validator.pattern.matches_string(str)
15
+
return str.len > validator.min_len && str.len < validator.max_len
16
+
&& validator.pattern.matches_string(str)
16
17
}
17
18
18
19
pub fn StringValidator.new(min int, max int, pattern string) StringValidator {