use marshal for user metadata
This commit is contained in:
parent
2c8c02d7e6
commit
5c019df8b4
3 changed files with 40 additions and 47 deletions
|
|
@ -40,7 +40,7 @@ blockquote.blockquote {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.display-nick {
|
.nick {
|
||||||
color: #FFB300;
|
color: #FFB300;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -220,14 +220,14 @@ let account_post request =
|
||||||
(*TODO ask for confirmation *)
|
(*TODO ask for confirmation *)
|
||||||
let res =
|
let res =
|
||||||
Result.fold ~error:Fun.id
|
Result.fold ~error:Fun.id
|
||||||
~ok:(fun _ -> "Your account was deleted")
|
~ok:(fun () -> "Your account was deleted")
|
||||||
(User.delete_user user_id)
|
(User.delete_user user_id)
|
||||||
in
|
in
|
||||||
render_unsafe res request
|
render_unsafe res request
|
||||||
| `Ok [ ("email", email) ] ->
|
| `Ok [ ("email", email) ] ->
|
||||||
let res =
|
let res =
|
||||||
Result.fold ~error:Fun.id
|
Result.fold ~error:Fun.id
|
||||||
~ok:(fun _ -> "Your email was updated!")
|
~ok:(fun () -> "Your email was updated!")
|
||||||
(User.update_email email user_id)
|
(User.update_email email user_id)
|
||||||
in
|
in
|
||||||
render_unsafe res request
|
render_unsafe res request
|
||||||
|
|
|
||||||
81
src/user.ml
81
src/user.ml
|
|
@ -8,7 +8,7 @@ type t =
|
||||||
; email : string
|
; email : string
|
||||||
; bio : string
|
; bio : string
|
||||||
; avatar : string
|
; avatar : string
|
||||||
; metadata : (int * string * string) list
|
; metadata : (string * string) list
|
||||||
}
|
}
|
||||||
|
|
||||||
module Q = struct
|
module Q = struct
|
||||||
|
|
@ -23,24 +23,21 @@ module Q = struct
|
||||||
|
|
||||||
let create_metadata_table =
|
let create_metadata_table =
|
||||||
Caqti_request.exec Caqti_type.unit
|
Caqti_request.exec Caqti_type.unit
|
||||||
"CREATE TABLE IF NOT EXISTS metadata (user_id TEXT, count INT, label \
|
"CREATE TABLE IF NOT EXISTS user_metadata (user_id TEXT, metadata TEXT, \
|
||||||
TEXT, content TEXT, FOREIGN KEY(user_id) REFERENCES user(user_id) ON \
|
FOREIGN KEY(user_id) REFERENCES user(user_id) ON DELETE CASCADE);"
|
||||||
DELETE CASCADE);"
|
|
||||||
|
|
||||||
let get_metadata =
|
let get_metadata =
|
||||||
Caqti_request.collect Caqti_type.string
|
Caqti_request.find Caqti_type.string Caqti_type.string
|
||||||
Caqti_type.(tup3 int string string)
|
"SELECT metadata FROM user_metadata WHERE user_id=?;"
|
||||||
"SELECT count, label, content FROM metadata WHERE user_id=?;"
|
|
||||||
|
|
||||||
let upload_metadata =
|
let upload_metadata =
|
||||||
Caqti_request.exec
|
Caqti_request.exec
|
||||||
Caqti_type.(tup4 string int string string)
|
Caqti_type.(tup2 string string)
|
||||||
"INSERT INTO metadata VALUES (?, ?, ?, ?);"
|
"INSERT INTO user_metadata VALUES (?, ?);"
|
||||||
|
|
||||||
let delete_metadata =
|
let delete_metadata =
|
||||||
Caqti_request.exec
|
Caqti_request.exec Caqti_type.string
|
||||||
Caqti_type.(tup2 string int)
|
"DELETE FROM user_metadata WHERE user_id=?;"
|
||||||
"DELETE FROM metadata WHERE user_id=? AND count=?;"
|
|
||||||
|
|
||||||
let get_user_id_from_nick =
|
let get_user_id_from_nick =
|
||||||
Caqti_request.find Caqti_type.string Caqti_type.string
|
Caqti_request.find Caqti_type.string Caqti_type.string
|
||||||
|
|
@ -146,8 +143,8 @@ let () =
|
||||||
let exist_nick nick = Result.is_ok (Db.find Q.get_user nick)
|
let exist_nick nick = Result.is_ok (Db.find Q.get_user nick)
|
||||||
|
|
||||||
let get_metadata nick =
|
let get_metadata nick =
|
||||||
let^ metadata = Db.collect_list Q.get_metadata nick in
|
let^ metadata = Db.find Q.get_metadata nick in
|
||||||
let metadata = List.sort (fun (a, _, _) (b, _, _) -> compare a b) metadata in
|
let metadata : (string * string) list = Marshal.from_string metadata 0 in
|
||||||
Ok metadata
|
Ok metadata
|
||||||
|
|
||||||
let get_user_id_from_nick nick =
|
let get_user_id_from_nick nick =
|
||||||
|
|
@ -191,7 +188,7 @@ let valid_password password =
|
||||||
String.length password < 128 && String.length password > 0
|
String.length password < 128 && String.length password > 0
|
||||||
|
|
||||||
let valid_email email =
|
let valid_email email =
|
||||||
match Emile.of_string email with Ok _ -> true | Error _ -> false
|
match Emile.of_string email with Ok _mail -> true | Error _e -> false
|
||||||
|
|
||||||
let register ~email ~nick ~password =
|
let register ~email ~nick ~password =
|
||||||
let valid = valid_nick nick && valid_email email && valid_password password in
|
let valid = valid_nick nick && valid_email email && valid_password password in
|
||||||
|
|
@ -207,6 +204,7 @@ let register ~email ~nick ~password =
|
||||||
let^ () =
|
let^ () =
|
||||||
Db.exec Q.upload_user (user_id, nick, password, (email, "", ""))
|
Db.exec Q.upload_user (user_id, nick, password, (email, "", ""))
|
||||||
in
|
in
|
||||||
|
let^ () = Db.exec Q.upload_metadata (user_id, Marshal.to_string [] []) in
|
||||||
Ok ()
|
Ok ()
|
||||||
else Error "nick or email already exists"
|
else Error "nick or email already exists"
|
||||||
|
|
||||||
|
|
@ -298,30 +296,24 @@ let update_metadata count label content user_id =
|
||||||
if String.length label > 200 || String.length content > 400 then
|
if String.length label > 200 || String.length content > 400 then
|
||||||
Error "label or content is too long"
|
Error "label or content is too long"
|
||||||
else
|
else
|
||||||
(* rewrite all user's metadata *)
|
|
||||||
let* metadata = get_metadata user_id in
|
let* metadata = get_metadata user_id in
|
||||||
let^ _unit_list =
|
let metadata =
|
||||||
unwrap_list
|
if List.length metadata > 0 && List.length metadata > count then
|
||||||
(fun (count, _l, _c) -> Db.exec Q.delete_metadata (user_id, count))
|
List.mapi
|
||||||
metadata
|
(fun i (l, c) -> if i = count then (label, content) else (l, c))
|
||||||
|
metadata
|
||||||
|
else metadata @ [ (label, content) ]
|
||||||
in
|
in
|
||||||
let l = List.filter (fun (i, _, _) -> i <> count) metadata in
|
let metadata =
|
||||||
let l =
|
List.filter (fun (l, c) -> not (l = "" && c = "")) metadata
|
||||||
if not (label = "" && content = "") then (count, label, content) :: l
|
|
||||||
else l
|
|
||||||
in
|
|
||||||
let l = List.sort (fun (a, _, _) (b, _, _) -> compare a b) l in
|
|
||||||
let l = List.mapi (fun i (_, label, content) -> (i, label, content)) l in
|
|
||||||
let^ _unit_list =
|
|
||||||
unwrap_list
|
|
||||||
(fun (i, label, content) ->
|
|
||||||
Db.exec Q.upload_metadata (user_id, i, label, content) )
|
|
||||||
l
|
|
||||||
in
|
in
|
||||||
|
let s = Marshal.to_string metadata [] in
|
||||||
|
let^ () = Db.exec Q.delete_metadata user_id in
|
||||||
|
let^ () = Db.exec Q.upload_metadata (user_id, s) in
|
||||||
Ok ()
|
Ok ()
|
||||||
|
|
||||||
let pp_metadata fmt metadata =
|
let pp_metadata fmt pair =
|
||||||
let _count, label, content = metadata in
|
let label, content = pair in
|
||||||
Format.fprintf fmt
|
Format.fprintf fmt
|
||||||
{|
|
{|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
|
@ -331,10 +323,10 @@ let pp_metadata fmt metadata =
|
||||||
|}
|
|}
|
||||||
label content
|
label content
|
||||||
|
|
||||||
let pp_metadata_form fmt ?is_last metadata request =
|
let pp_metadata_form fmt is_last count pair request =
|
||||||
let count, label, content = metadata in
|
let label, content = pair in
|
||||||
let form_tag = Dream.form_tag ~action:"/profile" request in
|
let form_tag = Dream.form_tag ~action:"/profile" request in
|
||||||
let button_text = if Option.is_some is_last then "Add" else "Save" in
|
let button_text = if is_last then "Add" else "Save" in
|
||||||
Format.fprintf fmt
|
Format.fprintf fmt
|
||||||
{|
|
{|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
|
@ -358,10 +350,7 @@ let pp_metadata_table fmt metadata =
|
||||||
metadata
|
metadata
|
||||||
|
|
||||||
let pp_metadata_table_form fmt metadata request =
|
let pp_metadata_table_form fmt metadata request =
|
||||||
let length = List.length metadata in
|
let l = List.mapi (fun i e -> (i, e)) metadata in
|
||||||
let new_metadata_field fmt () =
|
|
||||||
pp_metadata_form fmt ~is_last:() (length, "", "") request
|
|
||||||
in
|
|
||||||
Format.fprintf fmt
|
Format.fprintf fmt
|
||||||
{|
|
{|
|
||||||
<div class="metadata-form-table">
|
<div class="metadata-form-table">
|
||||||
|
|
@ -369,9 +358,13 @@ let pp_metadata_table_form fmt metadata request =
|
||||||
%a
|
%a
|
||||||
</div>
|
</div>
|
||||||
|}
|
|}
|
||||||
(Format.pp_print_list ~pp_sep:Format.pp_print_space (fun fmt metadata ->
|
(Format.pp_print_list ~pp_sep:Format.pp_print_space
|
||||||
pp_metadata_form fmt metadata request ) )
|
(fun fmt (count, metadata) ->
|
||||||
metadata new_metadata_field ()
|
pp_metadata_form fmt false count metadata request ) )
|
||||||
|
l
|
||||||
|
(fun fmt (count, metadata) ->
|
||||||
|
pp_metadata_form fmt true count metadata request )
|
||||||
|
(List.length l, ("", ""))
|
||||||
|
|
||||||
let public_profile user_id =
|
let public_profile user_id =
|
||||||
let* user = get_user user_id in
|
let* user = get_user user_id in
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue