+20
doc/database_spec.md
+20
doc/database_spec.md
···
60
60
| `id` | int | identifier for this entry |
61
61
| `post_id` | int | the post this entry is for |
62
62
| `likes` | int | the net amount of likes this post has |
63
+
64
+
## `Site`
65
+
66
+
> stores mutable, site-wide data. there should only ever be one entry here
67
+
68
+
| name | type | desc |
69
+
|--------|--------|----------------------------------------------|
70
+
| `id` | int | identifier for this (should always be 0) |
71
+
| `motd` | string | the message of the day displayed on `/index` |
72
+
73
+
## `Notification`
74
+
75
+
> represents a notification sent to a user
76
+
77
+
| name | type | desc |
78
+
|-----------|--------|------------------------------------------|
79
+
| `id` | int | identifier for this notification |
80
+
| `user_id` | int | the user that receives this notification |
81
+
| `summary` | string | the summary for this notification |
82
+
| `body` | string | the full text for this notification |
+1
-1
doc/todo.md
+1
-1
doc/todo.md
···
10
10
- [ ] post:tags ('hashtags')
11
11
- [ ] post:images (should have a config.maple toggle to enable/disable)
12
12
- [ ] post:saving (add the post to a list of saved posts that a user can view later)
13
-
- [ ] user:deletion
14
13
15
14
## ideas
16
15
···
23
22
- [x] user:bio/about me
24
23
- [x] user:listed pronouns
25
24
- [x] user:notifications
25
+
- [x] user:deletion
26
26
- [x] post:likes/dislikes
27
27
- [x] post:mentioning ('tagging') other users in posts
28
28
- [x] post:mentioning:who mentioned you (send notifications when a user mentions you)
+5
readme.md
+5
readme.md
···
28
28
```
29
29
30
30
then go to the configured url to view (default is `http://localhost:8008`).
31
+
32
+
if you do not have a database, you can either self-host a postgresql database on
33
+
your machine, or you can find a free one online. i use and like
34
+
[neon.tech](https://neon.tech), their free plan is pretty comfortable for a
35
+
small beep instance!
+61
src/api.v
+61
src/api.v
···
318
318
return ctx.redirect('/inbox')
319
319
}
320
320
321
+
@['/api/user/delete']
322
+
fn (mut app App) api_user_delete(mut ctx Context, id int) veb.Result {
323
+
user := app.whoami(mut ctx) or {
324
+
ctx.error('you are not logged in!')
325
+
return ctx.redirect('/login')
326
+
}
327
+
328
+
println('attempting to delete ${id} as ${user.id}')
329
+
330
+
if user.admin || user.id == id {
331
+
// yeet
332
+
sql app.db {
333
+
delete from User where id == id
334
+
delete from Like where user_id == id
335
+
delete from Notification where user_id == id
336
+
} or {
337
+
ctx.error('failed to delete user: ${id}')
338
+
return ctx.redirect('/')
339
+
}
340
+
341
+
// delete posts and their likes
342
+
posts_from_this_user := sql app.db {
343
+
select from Post where author_id == id
344
+
} or { [] }
345
+
346
+
for post in posts_from_this_user {
347
+
sql app.db {
348
+
delete from Like where post_id == post.id
349
+
delete from LikeCache where post_id == post.id
350
+
} or {
351
+
eprintln('failed to delete like cache for post during user deletion: ${post.id}')
352
+
}
353
+
}
354
+
355
+
sql app.db {
356
+
delete from Post where author_id == id
357
+
} or {
358
+
eprintln('failed to delete posts by deleting user: ${user.id}')
359
+
}
360
+
361
+
app.auth.delete_tokens_for_user(id) or {
362
+
eprintln('failed to delete tokens for user during deletion: ${id}')
363
+
}
364
+
// log out
365
+
if user.id == id {
366
+
ctx.set_cookie(
367
+
name: 'token'
368
+
value: ''
369
+
same_site: .same_site_none_mode
370
+
secure: true
371
+
path: '/'
372
+
)
373
+
}
374
+
println('deleted user ${id}')
375
+
} else {
376
+
ctx.error('be nice. deleting other users is off-limits.')
377
+
}
378
+
379
+
return ctx.redirect('/')
380
+
}
381
+
321
382
////// post //////
322
383
323
384
@['/api/post/new_post'; post]
+37
-1
src/templates/user.html
+37
-1
src/templates/user.html
···
132
132
<input type="submit" value="save">
133
133
</form>
134
134
@end
135
+
<br>
136
+
<details>
137
+
<summary>dangerous settings (click to reveal)</summary>
138
+
<div>
139
+
<form action="/api/user/delete" autocomplete="off">
140
+
<input
141
+
type="number"
142
+
name="id"
143
+
id="id"
144
+
value="@user.id"
145
+
required
146
+
readonly
147
+
hidden
148
+
aria-hidden
149
+
>
150
+
<p><strong>there is NO GOING BACK after deleting your account.</strong></p>
151
+
<p><strong>EVERY ONE of your posts, notifications, likes, dislikes, and ALL OTHER USER DATA WILL BE PERMANENTLY DELETED</strong></p>
152
+
<div>
153
+
<input type="checkbox" name="are-you-sure" id="are-you-sure" required>
154
+
<label for="are-you-sure">click to confirm</label>
155
+
</div>
156
+
<br>
157
+
<div>
158
+
<input type="checkbox" name="are-you-really-sure" id="are-you-really-sure" required>
159
+
<label for="are-you-really-sure">click to doubly confirm</label>
160
+
</div>
161
+
<br>
162
+
<div>
163
+
<input type="checkbox" name="are-you-absolutely-sure" id="are-you-absolutely-sure" required>
164
+
<label for="are-you-absolutely-sure">click to triply confirm</label>
165
+
</div>
166
+
<br>
167
+
<input type="submit" value="delete your account">
168
+
</form>
169
+
</div>
170
+
</details>
135
171
</div>
136
172
@end
137
173
···
140
176
<h2>admin powers:</h2>
141
177
<form action="/api/user/set_muted" method="post">
142
178
<input
143
-
type="text"
179
+
type="number"
144
180
name="id"
145
181
id="id"
146
182
value="@user.id"