107 lines
3.3 KiB
OCaml
107 lines
3.3 KiB
OCaml
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)
|