+26
src/database/like.v
+26
src/database/like.v
···
2
3
import entity { Like, LikeCache }
4
5
+
// add_like adds a like to the database, returns true if this succeeds and false
6
+
// otherwise.
7
+
pub fn (app &DatabaseAccess) add_like(like &Like) bool {
8
+
sql app.db {
9
+
insert like into Like
10
+
// yeet the old cached like value
11
+
delete from LikeCache where post_id == like.post_id
12
+
} or {
13
+
return false
14
+
}
15
+
return true
16
+
}
17
+
18
// get_net_likes_for_post returns the net likes of the given post.
19
pub fn (app &DatabaseAccess) get_net_likes_for_post(post_id int) int {
20
// check cache
···
56
57
return likes
58
}
59
+
60
+
// unlike_post removes a (dis)like from the given post, returns true if this
61
+
// succeeds and false otherwise.
62
+
pub fn (app &DatabaseAccess) unlike_post(post_id int, user_id int) bool {
63
+
sql app.db {
64
+
delete from Like where user_id == user_id && post_id == post_id
65
+
// yeet the old cached like value
66
+
delete from LikeCache where post_id == post_id
67
+
} or {
68
+
return false
69
+
}
70
+
return true
71
+
}
+34
src/database/notification.v
+34
src/database/notification.v
···
2
3
import entity { Notification }
4
5
+
// get_notification_by_id gets a notification by its given id, returns none if
6
+
// the notification does not exist.
7
+
pub fn (app &DatabaseAccess) get_notification_by_id(id int) ?Notification {
8
+
notifications := sql app.db {
9
+
select from Notification where id == id
10
+
} or { [] }
11
+
if notifications.len != 1 {
12
+
return none
13
+
}
14
+
return notifications[0]
15
+
}
16
+
17
+
// delete_notification deletes the given notification, returns true if this
18
+
// succeeded and false otherwise.
19
+
pub fn (app &DatabaseAccess) delete_notification(id int) bool {
20
+
sql app.db {
21
+
delete from Notification where id == id
22
+
} or {
23
+
return false
24
+
}
25
+
return true
26
+
}
27
+
28
+
// delete_notifications_for_user deletes all notifications for the given user,
29
+
// returns true if this succeeded and false otherwise.
30
+
pub fn (app &DatabaseAccess) delete_notifications_for_user(user_id int) bool {
31
+
sql app.db {
32
+
delete from Notification where user_id == user_id
33
+
} or {
34
+
return false
35
+
}
36
+
return true
37
+
}
38
+
39
// get_notifications_for gets a list of notifications for the given user.
40
pub fn (app &DatabaseAccess) get_notifications_for(user_id int) []Notification {
41
notifications := sql app.db {
+46
src/database/post.v
+46
src/database/post.v
···
3
import time
4
import entity { Post, Like, LikeCache }
5
6
+
// add_post adds a new post to the database, returns true if this succeeded and
7
+
// false otherwise.
8
+
pub fn (app &DatabaseAccess) add_post(post &Post) bool {
9
+
sql app.db {
10
+
insert post into Post
11
+
} or {
12
+
return false
13
+
}
14
+
return true
15
+
}
16
+
17
// get_post_by_id gets a post by its id, returns none if it does not exist.
18
pub fn (app &DatabaseAccess) get_post_by_id(id int) ?Post {
19
posts := sql app.db {
···
95
} or { [] }
96
return posts
97
}
98
+
99
+
// pin_post pins the given post, returns true if this succeeds and false
100
+
// otherwise.
101
+
pub fn (app &DatabaseAccess) pin_post(post_id int) bool {
102
+
sql app.db {
103
+
update Post set pinned = true where id == post_id
104
+
} or {
105
+
return false
106
+
}
107
+
return true
108
+
}
109
+
110
+
// update_post updates the given post's title and body with the given title and
111
+
// body, returns true if this succeeds and false otherwise.
112
+
pub fn (app &DatabaseAccess) update_post(post_id int, new_title string, new_body string) bool {
113
+
sql app.db {
114
+
update Post set body = new_body, title = new_title where id == post_id
115
+
} or {
116
+
return false
117
+
}
118
+
return true
119
+
}
120
+
121
+
// delete_post deletes the given post and all likes associated with it, returns
122
+
// true if this succeeds and false otherwise.
123
+
pub fn (app &DatabaseAccess) delete_post(id int) bool {
124
+
sql app.db {
125
+
delete from Post where id == id
126
+
delete from Like where post_id == id
127
+
delete from LikeCache where post_id == id
128
+
} or {
129
+
return false
130
+
}
131
+
return true
132
+
}
+11
src/database/site.v
+11
src/database/site.v
···
18
}
19
return configs[0]
20
}
21
+
22
+
// set_motd sets the site's current message of the day, returns true if this
23
+
// succeeds and false otherwise.
24
+
pub fn (app &DatabaseAccess) set_motd(motd string) bool {
25
+
sql app.db {
26
+
update Site set motd = motd where id == 1
27
+
} or {
28
+
return false
29
+
}
30
+
return true
31
+
}
+35
-1
src/database/user.v
+35
-1
src/database/user.v
···
1
module database
2
3
+
import entity { User, Notification, Like, LikeCache, Post }
4
5
// new_user creates a new user and returns their struct after creation.
6
pub fn (app &DatabaseAccess) new_user(user User) ?User {
···
172
}
173
return likes.len == 1
174
}
175
+
176
+
// delete_user deletes the given user and their data, returns true if this
177
+
// succeeded and false otherwise.
178
+
pub fn (app &DatabaseAccess) delete_user(user_id int) bool {
179
+
sql app.db {
180
+
delete from User where id == user_id
181
+
delete from Like where user_id == user_id
182
+
delete from Notification where user_id == user_id
183
+
} or {
184
+
return false
185
+
}
186
+
187
+
// delete posts and their likes
188
+
posts_from_this_user := sql app.db {
189
+
select from Post where author_id == id
190
+
} or { [] }
191
+
192
+
for post in posts_from_this_user {
193
+
sql app.db {
194
+
delete from Like where post_id == post.id
195
+
delete from LikeCache where post_id == post.id
196
+
} or {
197
+
eprintln('failed to delete like cache for post during user deletion: ${post.id}')
198
+
}
199
+
}
200
+
201
+
sql app.db {
202
+
delete from Post where author_id == id
203
+
} or {
204
+
eprintln('failed to delete posts by deleting user: ${user_id}')
205
+
}
206
+
207
+
return true
208
+
}
+30
-78
src/webapp/api.v
+30
-78
src/webapp/api.v
···
329
330
@['/api/user/notification/clear']
331
fn (mut app App) api_user_notification_clear(mut ctx Context, id int) veb.Result {
332
-
if !ctx.is_logged_in() {
333
ctx.error('you are not logged in!')
334
return ctx.redirect('/login')
335
}
336
-
sql app.db {
337
-
delete from Notification where id == id
338
-
} or {
339
-
ctx.error('failed to delete notification')
340
-
return ctx.redirect('/inbox')
341
}
342
return ctx.redirect('/inbox')
343
}
344
···
348
ctx.error('you are not logged in!')
349
return ctx.redirect('/login')
350
}
351
-
sql app.db {
352
-
delete from Notification where user_id == user.id
353
-
} or {
354
ctx.error('failed to delete notifications')
355
return ctx.redirect('/inbox')
356
}
···
368
369
if user.admin || user.id == id {
370
// yeet
371
-
sql app.db {
372
-
delete from User where id == id
373
-
delete from Like where user_id == id
374
-
delete from Notification where user_id == id
375
-
} or {
376
ctx.error('failed to delete user: ${id}')
377
return ctx.redirect('/')
378
-
}
379
-
380
-
// delete posts and their likes
381
-
posts_from_this_user := sql app.db {
382
-
select from Post where author_id == id
383
-
} or { [] }
384
-
385
-
for post in posts_from_this_user {
386
-
sql app.db {
387
-
delete from Like where post_id == post.id
388
-
delete from LikeCache where post_id == post.id
389
-
} or {
390
-
eprintln('failed to delete like cache for post during user deletion: ${post.id}')
391
-
}
392
-
}
393
-
394
-
sql app.db {
395
-
delete from Post where author_id == id
396
-
} or {
397
-
eprintln('failed to delete posts by deleting user: ${user.id}')
398
}
399
400
app.auth.delete_tokens_for_user(id) or {
···
459
post.replying_to = replying_to
460
}
461
462
-
sql app.db {
463
-
insert post into Post
464
-
} or {
465
ctx.error('failed to post!')
466
println('failed to post: ${post} from user ${user.id}')
467
return ctx.redirect('/post/new')
···
490
}
491
492
if user.admin || user.id == post.author_id {
493
-
sql app.db {
494
-
delete from Post where id == id
495
-
delete from Like where post_id == id
496
-
} or {
497
ctx.error('failed to delete post')
498
eprintln('failed to delete post: ${id}')
499
return ctx.redirect('/')
···
514
post := app.get_post_by_id(id) or { return ctx.server_error('post does not exist') }
515
516
if app.does_user_like_post(user.id, post.id) {
517
-
sql app.db {
518
-
delete from Like where user_id == user.id && post_id == post.id
519
-
// yeet the old cached like value
520
-
delete from LikeCache where post_id == post.id
521
-
} or {
522
eprintln('user ${user.id} failed to unlike post ${id}')
523
return ctx.server_error('failed to unlike post')
524
}
···
526
} else {
527
// remove the old dislike, if it exists
528
if app.does_user_dislike_post(user.id, post.id) {
529
-
sql app.db {
530
-
delete from Like where user_id == user.id && post_id == post.id
531
-
} or {
532
eprintln('user ${user.id} failed to remove dislike on post ${id} when liking it')
533
}
534
}
···
538
post_id: post.id
539
is_like: true
540
}
541
-
sql app.db {
542
-
insert like into Like
543
-
// yeet the old cached like value
544
-
delete from LikeCache where post_id == post.id
545
-
} or {
546
eprintln('user ${user.id} failed to like post ${id}')
547
return ctx.server_error('failed to like post')
548
}
···
557
post := app.get_post_by_id(id) or { return ctx.server_error('post does not exist') }
558
559
if app.does_user_dislike_post(user.id, post.id) {
560
-
sql app.db {
561
-
delete from Like where user_id == user.id && post_id == post.id
562
-
// yeet the old cached like value
563
-
delete from LikeCache where post_id == post.id
564
-
} or {
565
-
eprintln('user ${user.id} failed to unlike post ${id}')
566
-
return ctx.server_error('failed to unlike post')
567
}
568
return ctx.ok('undisliked post')
569
} else {
570
// remove the old like, if it exists
571
if app.does_user_like_post(user.id, post.id) {
572
-
sql app.db {
573
-
delete from Like where user_id == user.id && post_id == post.id
574
-
} or {
575
eprintln('user ${user.id} failed to remove like on post ${id} when disliking it')
576
}
577
}
···
581
post_id: post.id
582
is_like: false
583
}
584
-
sql app.db {
585
-
insert like into Like
586
-
// yeet the old cached like value
587
-
delete from LikeCache where post_id == post.id
588
-
} or {
589
eprintln('user ${user.id} failed to dislike post ${id}')
590
return ctx.server_error('failed to dislike post')
591
}
···
614
return ctx.redirect('/')
615
}
616
617
-
sql app.db {
618
-
update Post set body = body, title = title where id == id
619
-
} or {
620
eprintln('failed to update post')
621
ctx.error('failed to update post')
622
return ctx.redirect('/')
···
633
}
634
635
if user.admin {
636
-
sql app.db {
637
-
update Post set pinned = true where id == id
638
-
} or {
639
eprintln('failed to pin post: ${id}')
640
ctx.error('failed to pin post')
641
return ctx.redirect('/post/${id}')
···
658
}
659
660
if user.admin {
661
-
sql app.db {
662
-
update Site set motd = motd where id == 1
663
-
} or {
664
ctx.error('failed to set motd')
665
eprintln('failed to set motd: ${motd}')
666
return ctx.redirect('/')
···
329
330
@['/api/user/notification/clear']
331
fn (mut app App) api_user_notification_clear(mut ctx Context, id int) veb.Result {
332
+
user := app.whoami(mut ctx) or {
333
ctx.error('you are not logged in!')
334
return ctx.redirect('/login')
335
}
336
+
337
+
if notification := app.get_notification_by_id(id) {
338
+
if notification.user_id != user.id {
339
+
ctx.error('no such notification for user')
340
+
return ctx.redirect('/inbox')
341
+
} else {
342
+
if !app.delete_notification(id) {
343
+
ctx.error('failed to delete notification')
344
+
return ctx.redirect('/inbox')
345
+
}
346
+
}
347
+
} else {
348
+
ctx.error('no such notification for user')
349
}
350
+
351
return ctx.redirect('/inbox')
352
}
353
···
357
ctx.error('you are not logged in!')
358
return ctx.redirect('/login')
359
}
360
+
if !app.delete_notifications_for_user(user.id) {
361
ctx.error('failed to delete notifications')
362
return ctx.redirect('/inbox')
363
}
···
375
376
if user.admin || user.id == id {
377
// yeet
378
+
if !app.delete_user(user.id) {
379
ctx.error('failed to delete user: ${id}')
380
return ctx.redirect('/')
381
}
382
383
app.auth.delete_tokens_for_user(id) or {
···
442
post.replying_to = replying_to
443
}
444
445
+
if !app.add_post(post) {
446
ctx.error('failed to post!')
447
println('failed to post: ${post} from user ${user.id}')
448
return ctx.redirect('/post/new')
···
471
}
472
473
if user.admin || user.id == post.author_id {
474
+
if !app.delete_post(post.id) {
475
ctx.error('failed to delete post')
476
eprintln('failed to delete post: ${id}')
477
return ctx.redirect('/')
···
492
post := app.get_post_by_id(id) or { return ctx.server_error('post does not exist') }
493
494
if app.does_user_like_post(user.id, post.id) {
495
+
if !app.unlike_post(post.id, user.id) {
496
eprintln('user ${user.id} failed to unlike post ${id}')
497
return ctx.server_error('failed to unlike post')
498
}
···
500
} else {
501
// remove the old dislike, if it exists
502
if app.does_user_dislike_post(user.id, post.id) {
503
+
if !app.unlike_post(post.id, user.id) {
504
eprintln('user ${user.id} failed to remove dislike on post ${id} when liking it')
505
}
506
}
···
510
post_id: post.id
511
is_like: true
512
}
513
+
if !app.add_like(like) {
514
eprintln('user ${user.id} failed to like post ${id}')
515
return ctx.server_error('failed to like post')
516
}
···
525
post := app.get_post_by_id(id) or { return ctx.server_error('post does not exist') }
526
527
if app.does_user_dislike_post(user.id, post.id) {
528
+
if !app.unlike_post(post.id, user.id) {
529
+
eprintln('user ${user.id} failed to undislike post ${id}')
530
+
return ctx.server_error('failed to undislike post')
531
}
532
return ctx.ok('undisliked post')
533
} else {
534
// remove the old like, if it exists
535
if app.does_user_like_post(user.id, post.id) {
536
+
if !app.unlike_post(post.id, user.id) {
537
eprintln('user ${user.id} failed to remove like on post ${id} when disliking it')
538
}
539
}
···
543
post_id: post.id
544
is_like: false
545
}
546
+
if !app.add_like(like) {
547
eprintln('user ${user.id} failed to dislike post ${id}')
548
return ctx.server_error('failed to dislike post')
549
}
···
572
return ctx.redirect('/')
573
}
574
575
+
if !app.update_post(id, title, body) {
576
eprintln('failed to update post')
577
ctx.error('failed to update post')
578
return ctx.redirect('/')
···
589
}
590
591
if user.admin {
592
+
if !app.pin_post(id) {
593
eprintln('failed to pin post: ${id}')
594
ctx.error('failed to pin post')
595
return ctx.redirect('/post/${id}')
···
612
}
613
614
if user.admin {
615
+
if !app.set_motd(motd) {
616
ctx.error('failed to set motd')
617
eprintln('failed to set motd: ${motd}')
618
return ctx.redirect('/')