geochan/src/moderation.ml

108 lines
3.3 KiB
OCaml
Raw Normal View History

2024-05-29 19:16:48 +02:00
open Syntax
open Types
open Caqti_request.Infix
open Caqti_type
open Caqti_db
(* TODO do something for multiples report on same post
- don't allow multiple report on same post from same user
- add TEST *)
let () =
let tables =
[| (unit ->. unit)
"CREATE TABLE IF NOT EXISTS report (report_id TEXT, date FLOAT, \
post_id INTEGER, user_id TEXT, reason TEXT, FOREIGN KEY(post_id) \
REFERENCES post(id) ON DELETE CASCADE, FOREIGN KEY(user_id) \
REFERENCES user(user_id) ON DELETE CASCADE)"
; (unit ->. unit)
"CREATE TABLE IF NOT EXISTS banished (nick TEXT, email TEXT)"
|]
in
Array.iter (fun query -> Db.exec_unsafe query ()) tables
module Q = struct
let upload_report =
Db.exec
((t5 string float int string string ->. unit)
"INSERT INTO report VALUES (?,?,?,?,?)" )
let get_reports_all =
Db.collect_list
((unit ->* t6 string float int string string string)
"SELECT r.report_id, r.date, r.post_id, r.user_id, u.nick, reason \
FROM report r JOIN user u ON r.user_id = u.user_id" )
let get_reports_made_by =
Db.collect_list
((string ->* t6 string float int string string string)
"SELECT r.report_id, r.date, r.post_id, r.user_id, u.nick, reason \
FROM report r JOIN user u ON r.user_id = u.user_id WHERE r.user_id=?" )
let delete_report =
Db.exec @@ (int ->. unit) "DELETE FROM report WHERE post_id=?"
let upload_banished =
Db.exec @@ (t2 string string ->. unit) "INSERT INTO banished VALUES (?,?)"
let find_banished =
Db.find_opt
@@ (t2 string string ->! t2 string string)
"SELECT * FROM banished WHERE nick=? OR email=?"
end
let get_report_aux
( report_id
, report_date
, reported_post_id
, reporter_user_id
, reporter_nick
, reason ) =
let+ reported_post = Post.get_post reported_post_id in
{ report_id
; report_date
; reported_post
; reporter_user_id
; reporter_nick
; reason
}
let get_reports_all () =
Db.do_transaction @@ fun () ->
let* l = Q.get_reports_all () in
list_map get_report_aux l
let get_reports_made_by user_id =
Db.do_transaction @@ fun () ->
let* l = Q.get_reports_made_by user_id in
list_map get_report_aux l
let make_report ~reporter_user_id ~reason reported_post_id =
let* reason = Validate_str.report reason in
(* check post exists *)
let* _post = Post.get_post reported_post_id in
let report_date = Unix.time () in
let report_id = Util.gen_uuid () in
Db.do_transaction @@ fun () ->
Q.upload_report
( report_id
, report_date
, reported_post_id
, reporter_user_id
, (reason :> string) )
(* todo sql: no need to use transaction for a single query? *)
let delete_report id = Db.do_transaction @@ fun () -> Q.delete_report id
let is_banished login =
let+ opt = Db.do_transaction @@ fun () -> Q.find_banished (login, login) in
match opt with None -> false | Some _ -> true
(* it would be better to also invalidate banned user's session here
since Api.get_logged_user check for user existance it should be fine *)
let banish user_id =
let* user_private = User.get_user_private user_id in
let* () = User.delete_user user_id in
Db.do_transaction @@ fun () ->
Q.upload_banished (user_private.user_nick, user_private.email)