add avatar upload
This commit is contained in:
parent
81c52860e6
commit
ed9e134c6f
4 changed files with 128 additions and 31 deletions
BIN
src/content/assets/img/default_avatar.png
Executable file
BIN
src/content/assets/img/default_avatar.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 253 KiB |
|
|
@ -45,7 +45,14 @@ let register_post request =
|
||||||
match%lwt Dream.form request with
|
match%lwt Dream.form request with
|
||||||
| `Ok [ ("email", email); ("nick", nick); ("password", password) ] ->
|
| `Ok [ ("email", email); ("nick", nick); ("password", password) ] ->
|
||||||
render_unsafe (Register.f ~nick ~email ~password request) request
|
render_unsafe (Register.f ~nick ~email ~password request) request
|
||||||
| _ -> assert false
|
| `Ok _
|
||||||
|
| `Many_tokens _
|
||||||
|
| `Missing_token _
|
||||||
|
| `Invalid_token _
|
||||||
|
| `Wrong_session _
|
||||||
|
| `Expired _
|
||||||
|
| `Wrong_content_type ->
|
||||||
|
assert false
|
||||||
|
|
||||||
let login_get request = render_unsafe (Login.f request) request
|
let login_get request = render_unsafe (Login.f request) request
|
||||||
|
|
||||||
|
|
@ -64,12 +71,65 @@ let logout request =
|
||||||
let content = "Logged out !" in
|
let content = "Logged out !" in
|
||||||
render_unsafe content request
|
render_unsafe content request
|
||||||
|
|
||||||
let profile_get request = render_unsafe (User_profile.f request) request
|
let profile_get request =
|
||||||
|
match Dream.session "nick" request with
|
||||||
|
| None -> render_unsafe "Not logged in" request
|
||||||
|
| Some nick ->
|
||||||
|
let bio =
|
||||||
|
match User.get_bio nick with
|
||||||
|
| Ok bio -> bio
|
||||||
|
| Error e -> e
|
||||||
|
in
|
||||||
|
render_unsafe (User_profile.f nick bio request) request
|
||||||
|
|
||||||
let profile_post request =
|
let profile_post request =
|
||||||
match%lwt Dream.form request with
|
match Dream.session "nick" request with
|
||||||
| `Ok [ ("bio", bio) ] -> render_unsafe (User_profile.f ~bio request) request
|
| None -> render_unsafe "Not logged in" request
|
||||||
| _ -> assert false
|
| Some nick -> (
|
||||||
|
match%lwt Dream.form request with
|
||||||
|
| `Ok [ ("bio", bio) ] ->
|
||||||
|
let res =
|
||||||
|
match User.update_bio bio nick with
|
||||||
|
| Ok () -> "Bio updated!"
|
||||||
|
| Error e -> e
|
||||||
|
in
|
||||||
|
render_unsafe res request
|
||||||
|
| `Ok _
|
||||||
|
| `Many_tokens _
|
||||||
|
| `Missing_token _
|
||||||
|
| `Invalid_token _
|
||||||
|
| `Wrong_session _
|
||||||
|
| `Expired _
|
||||||
|
| `Wrong_content_type -> (
|
||||||
|
match%lwt Dream.multipart request with
|
||||||
|
| `Ok [ ("files", files) ] ->
|
||||||
|
let res =
|
||||||
|
match User.upload_avatar files nick with
|
||||||
|
| Ok () -> "Avatar was uploaded!"
|
||||||
|
| Error e -> e
|
||||||
|
in
|
||||||
|
render_unsafe res request
|
||||||
|
| `Ok _ -> Dream.empty `Bad_Request
|
||||||
|
| `Expired _
|
||||||
|
| `Many_tokens _
|
||||||
|
| `Missing_token _
|
||||||
|
| `Invalid_token _
|
||||||
|
| `Wrong_session _
|
||||||
|
| `Wrong_content_type ->
|
||||||
|
Dream.empty `Bad_Request ) )
|
||||||
|
|
||||||
|
let avatar_image request =
|
||||||
|
let nick = Dream.param "user" request in
|
||||||
|
let avatar = User.get_avatar nick in
|
||||||
|
match avatar with
|
||||||
|
| Ok (Some avatar) ->
|
||||||
|
Dream.respond ~headers:[ ("Content-Type", "image") ] avatar
|
||||||
|
| Ok None
|
||||||
|
| Error _ -> (
|
||||||
|
match Content.read "/assets/img/default_avatar.png" with
|
||||||
|
| None -> Dream.empty `Not_Found
|
||||||
|
| Some avatar -> Dream.respond ~headers:[ ("Content-Type", "image") ] avatar
|
||||||
|
)
|
||||||
|
|
||||||
let () =
|
let () =
|
||||||
Dream.run @@ Dream.logger @@ Dream.memory_sessions
|
Dream.run @@ Dream.logger @@ Dream.memory_sessions
|
||||||
|
|
@ -82,6 +142,7 @@ let () =
|
||||||
; Dream.post "/login" login_post
|
; Dream.post "/login" login_post
|
||||||
; Dream.get "/user" user
|
; Dream.get "/user" user
|
||||||
; Dream.get "/user/:user" user_profile
|
; Dream.get "/user/:user" user_profile
|
||||||
|
; Dream.get "/user/:user/avatar" avatar_image
|
||||||
; Dream.get "/logout" logout
|
; Dream.get "/logout" logout
|
||||||
; Dream.get "/profile" profile_get
|
; Dream.get "/profile" profile_get
|
||||||
; Dream.post "/profile" profile_post
|
; Dream.post "/profile" profile_post
|
||||||
|
|
|
||||||
59
src/user.ml
59
src/user.ml
|
|
@ -3,6 +3,7 @@ type t =
|
||||||
; password : string
|
; password : string
|
||||||
; email : string (* TODO: make email optional ? *)
|
; email : string (* TODO: make email optional ? *)
|
||||||
; bio : string
|
; bio : string
|
||||||
|
; avatar : string
|
||||||
}
|
}
|
||||||
|
|
||||||
let () =
|
let () =
|
||||||
|
|
@ -11,7 +12,7 @@ let () =
|
||||||
Db.with_db (fun db ->
|
Db.with_db (fun db ->
|
||||||
exec0 db
|
exec0 db
|
||||||
"CREATE TABLE IF NOT EXISTS user (nick TEXT, password TEXT, email \
|
"CREATE TABLE IF NOT EXISTS user (nick TEXT, password TEXT, email \
|
||||||
TEXT, bio TEXT);" )
|
TEXT, bio TEXT, avatar BLOB);" )
|
||||||
in
|
in
|
||||||
match res with
|
match res with
|
||||||
| Ok () -> ()
|
| Ok () -> ()
|
||||||
|
|
@ -78,11 +79,12 @@ let register ~email ~nick ~password =
|
||||||
| Ok [ [| Data.INT 0L |] ] -> (
|
| Ok [ [| Data.INT 0L |] ] -> (
|
||||||
let res =
|
let res =
|
||||||
Db.with_db (fun db ->
|
Db.with_db (fun db ->
|
||||||
exec_raw_args db "INSERT INTO user VALUES (?, ?, ?, ?);"
|
exec_raw_args db "INSERT INTO user VALUES (?, ?, ?, ?, ?);"
|
||||||
[| Data.TEXT nick
|
[| Data.TEXT nick
|
||||||
; Data.TEXT password
|
; Data.TEXT password
|
||||||
; Data.TEXT email
|
; Data.TEXT email
|
||||||
; Data.TEXT ""
|
; Data.TEXT ""
|
||||||
|
; Data.BLOB ""
|
||||||
|]
|
|]
|
||||||
~f:Cursor.to_list )
|
~f:Cursor.to_list )
|
||||||
in
|
in
|
||||||
|
|
@ -118,10 +120,18 @@ let public_profile request =
|
||||||
in
|
in
|
||||||
match user with
|
match user with
|
||||||
| Ok
|
| Ok
|
||||||
[ [| Data.TEXT nick; Data.TEXT password; Data.TEXT email; Data.TEXT bio |]
|
[ [| Data.TEXT nick
|
||||||
|
; Data.TEXT password
|
||||||
|
; Data.TEXT email
|
||||||
|
; Data.TEXT bio
|
||||||
|
; Data.BLOB _
|
||||||
|
|]
|
||||||
] ->
|
] ->
|
||||||
Format.sprintf "nick = `%s`; password = `%s`; email = `%s`; bio = '%s'" nick
|
Format.sprintf
|
||||||
password email (Dream.html_escape bio)
|
{|nick = `%s`; password = `%s`; email = `%s`; bio = '%s';
|
||||||
|
<img src="/user/%s/avatar" class="img-thumbnail" alt="Your avatar picture">
|
||||||
|
|}
|
||||||
|
nick password email (Dream.html_escape bio) nick
|
||||||
| Ok _ -> "incoherent db answer"
|
| Ok _ -> "incoherent db answer"
|
||||||
| Error e -> Format.sprintf "db error: %s" (Rc.to_string e)
|
| Error e -> Format.sprintf "db error: %s" (Rc.to_string e)
|
||||||
|
|
||||||
|
|
@ -158,3 +168,42 @@ let get_bio nick =
|
||||||
| Ok [ [| Data.TEXT bio |] ] -> Ok bio
|
| Ok [ [| Data.TEXT bio |] ] -> Ok bio
|
||||||
| Error e -> Error (Format.sprintf "db error: %s" (Rc.to_string e))
|
| Error e -> Error (Format.sprintf "db error: %s" (Rc.to_string e))
|
||||||
| Ok _ -> Error "incoherent db result"
|
| Ok _ -> Error "incoherent db result"
|
||||||
|
|
||||||
|
let get_avatar nick =
|
||||||
|
let open Sqlite3_utils in
|
||||||
|
let res =
|
||||||
|
Db.with_db (fun db ->
|
||||||
|
exec_raw_args db "SELECT avatar FROM user WHERE nick=?;"
|
||||||
|
[| Data.TEXT nick |] ~f:Cursor.to_list )
|
||||||
|
in
|
||||||
|
match res with
|
||||||
|
| Ok [ [| Data.BLOB avatar |] ] ->
|
||||||
|
if String.length avatar = 0 then
|
||||||
|
(* TODO default avatar *)
|
||||||
|
Ok None
|
||||||
|
else
|
||||||
|
Ok (Some avatar)
|
||||||
|
| Error e -> Error (Format.sprintf "db error: %s" (Rc.to_string e))
|
||||||
|
| Ok _ -> Error "incoherent db result"
|
||||||
|
|
||||||
|
let upload_avatar files nick =
|
||||||
|
match files with
|
||||||
|
| [] -> Error "No file provided"
|
||||||
|
| [ (_, content) ] -> (
|
||||||
|
(* TODO validate image data with konan etc*)
|
||||||
|
(* TODO file_name in db??*)
|
||||||
|
let valid = true in
|
||||||
|
if not valid then
|
||||||
|
Error "Invalid image"
|
||||||
|
else
|
||||||
|
let open Sqlite3_utils in
|
||||||
|
let res =
|
||||||
|
Db.with_db (fun db ->
|
||||||
|
exec_raw_args db "UPDATE user SET avatar=? WHERE nick=?;"
|
||||||
|
[| Data.BLOB content; Data.TEXT nick |]
|
||||||
|
~f:Cursor.to_list )
|
||||||
|
in
|
||||||
|
match res with
|
||||||
|
| Ok _ -> Ok ()
|
||||||
|
| Error e -> Error (Format.sprintf "db error: %s" (Rc.to_string e)) )
|
||||||
|
| _files -> Error "More than one file provided"
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,5 @@
|
||||||
let f ?bio request =
|
let f nick bio request =
|
||||||
% begin match Dream.session "nick" request with
|
<%s Format.sprintf "Hello %s !" nick %>
|
||||||
% | None ->
|
|
||||||
not logged in
|
|
||||||
% | Some nick ->
|
|
||||||
%begin match bio with
|
|
||||||
% | None ->
|
|
||||||
% let bio = match User.get_bio nick with
|
|
||||||
% | Ok bio -> bio
|
|
||||||
% | Error e -> e
|
|
||||||
%in
|
|
||||||
<%s Format.sprintf "Hello %s !" nick %>
|
|
||||||
<%s! Dream.form_tag ~action:"/profile" request %>
|
<%s! Dream.form_tag ~action:"/profile" request %>
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="bio" class="form-label">Bio</label>
|
<label for="bio" class="form-label">Bio</label>
|
||||||
|
|
@ -18,12 +8,9 @@ not logged in
|
||||||
</div>
|
</div>
|
||||||
<button type="submit" class="btn btn-primary">Save</button>
|
<button type="submit" class="btn btn-primary">Save</button>
|
||||||
</form>
|
</form>
|
||||||
% | Some bio ->
|
|
||||||
% begin match User.update_bio bio nick with
|
<img src="/user/<%s nick %>/avatar" class="img-thumbnail" alt="Your avatar picture">
|
||||||
% | Ok () ->
|
<%s! Dream.form_tag ~action:"/profile" ~enctype:`Multipart_form_data request %>
|
||||||
Bio updated !
|
<input name="files" type="file" multiple>
|
||||||
% | Error e ->
|
<button>Submit!</button>
|
||||||
<%s e %>
|
</form>
|
||||||
% end;
|
|
||||||
% end;
|
|
||||||
%end;
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue