1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
use super::config;
use rocket::Response;
use rocket::response::Redirect;
use rocket::response::Responder;
use rocket::request::{FormItems, FromForm, Request};
use rocket::http::{Status, Cookie, Cookies};
use std::collections::HashMap;
use super::authenticator::Authenticator;
pub enum LoginStatus<A>{
Succeed(A),
Failed(A)
}
pub struct LoginRedirect(Redirect);
impl<A: Authenticator> LoginStatus<A> {
pub fn get_authenticator (&self) -> &A{
match self{
&LoginStatus::Succeed(ref authenticator) => authenticator,
&LoginStatus::Failed(ref authenticator) => authenticator
}
}
fn succeed<T: Into<String>>(self, url: T, mut cookies: Cookies) -> Redirect {
let cookie_identifier = config::get_cookie_identifier();
cookies.add_private(Cookie::new(cookie_identifier, self.get_authenticator().user().to_string()));
Redirect::to(url.into().as_str())
}
fn failed<T: Into<String>>(self, url: T) -> Redirect {
Redirect::to(url.into().as_str())
}
pub fn redirect<T: Into<String>, S: Into<String>>(self, success_url: T, failure_url: S, cookies: Cookies) -> LoginRedirect{
let redirect = match self {
LoginStatus::Succeed(_) => self.succeed(success_url, cookies),
LoginStatus::Failed(_) => self.failed(failure_url)
};
LoginRedirect(redirect)
}
}
impl<'f,A: Authenticator> FromForm<'f> for LoginStatus<A>{
type Error = &'static str;
fn from_form(form_items: &mut FormItems<'f>, _strict: bool) -> Result<Self, Self::Error> {
let mut user_pass = HashMap::new();
for (key,value) in form_items{
match key.as_str(){
"username" => user_pass.insert("username", value.url_decode().unwrap()).map_or((), |_v| ()),
"password" => user_pass.insert("password", value.url_decode().unwrap()).map_or((), |_v| ()),
_ => ()
}
}
if user_pass.get("username").is_none() || user_pass.get("password").is_none() {
Err("invalid form")
} else {
let result = A::check_credentials(user_pass.get("username").unwrap().to_string(), user_pass.get("password").unwrap().to_string());
Ok(match result{
Ok(authenticator) => LoginStatus::Succeed(authenticator),
Err(authenticator) => LoginStatus::Failed(authenticator)
})
}
}
}
impl<'r> Responder<'r> for LoginRedirect{
fn respond_to(self, request: &Request) -> Result<Response<'r>, Status>{
self.0.respond_to(request)
}
}