In web programming, a common pattern for form submission is:
- If the form is valid, redirect to another page (Post/Redirect/Get).
- If the form is not valid, redisplay the form (possibly including error messages this time).
How do I express this in Ocsigen?
I've been reading the documentation, but could not figure out how to accomplish this simple (and very common) task.
Example use case:
Suppose I have a login form that guards against unauthorized access to the admin panel (a page that should only be accessed by administrators). If the user provides the correct credentials at the login form, the user should be redirected to the admin panel. If the credentials are incorrect, the user should be redirected back to the login form. So far, I have successfully implemented this functionality.
However, I am at loss when it comes to implementing the following: if the user is already logged in and tries to access the login form, the user should be redirected to the admin panel. Also, if the user is not logged in and tries to access the admin panel, the user should be redirected to the login form.
Below is my code up the point I got stuck:
(* Secret login credentials. *)
let username = "admin"
let password = "123456"
(* Create Eliom services. *)
let login_form_service = Eliom_service.create
~path:(Eliom_service.Path ["login"])
~meth:(Eliom_service.Get Eliom_parameter.unit)
()
let login_service = Eliom_service.create_attached_post
~fallback:login_form_service
~post_params:Eliom_parameter.(string "user" ** string "pass")
()
let admin_panel_service = Eliom_service.create
~path:(Eliom_service.Path ["admin-panel"])
~meth:(Eliom_service.Get Eliom_parameter.unit)
()
let session_username : string option Eliom_reference.eref =
Eliom_reference.eref ~scope:Eliom_common.default_session_scope None
(* Register Eliom services. *)
let () = Eliom_content.Html.D.(
Eliom_registration.Html.register
~service:login_form_service
(fun () () -> Lwt.return
(Eliom_tools.D.html
~title:"Login"
(body [h1 [pcdata "Login"];
Form.post_form
~service:login_service
(fun (user, pass) ->
[fieldset
[label [pcdata "Username: "];
Form.input ~input_type:`Text
~name:user
Form.string;
br ();
label [pcdata "Password: "];
Form.input ~input_type:`Password
~name:pass
Form.string;
br ();
Form.input ~input_type:`Submit
~value:"Login"
Form.string
]]) ()])));
Eliom_registration.Redirection.register
~service:login_service
(fun () (user, pass) ->
if user = username && pass = password then (
Eliom_reference.set session_username (Some username);
Lwt.return (Eliom_registration.Redirection admin_panel_service))
else
Lwt.return (Eliom_registration.Redirection login_form_service));
Eliom_registration.Html.register
~service:admin_panel_service
(fun () () ->
(* Admin panel html here ... *))
);
What is the proper method of solving this problem?
Thank you.