|  | @ -1,4 +1,5 @@ | 
			
		
	
		
		
			
				
					|  |  | use std::collections::HashMap; |  |  | use std::collections::HashMap; | 
			
		
	
		
		
			
				
					|  |  |  |  |  | use std::net::{IpAddr, Ipv4Addr, SocketAddr}; | 
			
		
	
		
		
			
				
					|  |  | 
 |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  | use rocket::request::{self, Form, FormItems, FromForm, FromRequest, Request}; |  |  | use rocket::request::{self, Form, FormItems, FromForm, FromRequest, Request}; | 
			
		
	
		
		
			
				
					|  |  | use rocket::{Outcome, Route}; |  |  | use rocket::{Outcome, Route}; | 
			
		
	
	
		
		
			
				
					|  | @ -21,12 +22,12 @@ pub fn routes() -> Vec<Route> { | 
			
		
	
		
		
			
				
					|  |  | } |  |  | } | 
			
		
	
		
		
			
				
					|  |  | 
 |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  | #[post("/connect/token", data = "<connect_data>")] |  |  | #[post("/connect/token", data = "<connect_data>")] | 
			
		
	
		
		
			
				
					
					|  |  | fn login(connect_data: Form<ConnectData>, device_type: DeviceType, conn: DbConn) -> JsonResult { |  |  | fn login(connect_data: Form<ConnectData>, device_type: DeviceType, conn: DbConn, socket: Option<SocketAddr>) -> JsonResult { | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					|  |  |     let data = connect_data.get(); |  |  |     let data = connect_data.get(); | 
			
		
	
		
		
			
				
					|  |  | 
 |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  |     match data.grant_type { |  |  |     match data.grant_type { | 
			
		
	
		
		
			
				
					|  |  |         GrantType::RefreshToken => _refresh_login(data, device_type, conn), |  |  |         GrantType::RefreshToken => _refresh_login(data, device_type, conn), | 
			
		
	
		
		
			
				
					
					|  |  |         GrantType::Password => _password_login(data, device_type, conn), |  |  |         GrantType::Password => _password_login(data, device_type, conn, socket), | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					|  |  |     } |  |  |     } | 
			
		
	
		
		
			
				
					|  |  | } |  |  | } | 
			
		
	
		
		
			
				
					|  |  | 
 |  |  | 
 | 
			
		
	
	
		
		
			
				
					|  | @ -57,7 +58,13 @@ fn _refresh_login(data: &ConnectData, _device_type: DeviceType, conn: DbConn) -> | 
			
		
	
		
		
			
				
					|  |  |     }))) |  |  |     }))) | 
			
		
	
		
		
			
				
					|  |  | } |  |  | } | 
			
		
	
		
		
			
				
					|  |  | 
 |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  | fn _password_login(data: &ConnectData, device_type: DeviceType, conn: DbConn) -> JsonResult { |  |  | fn _password_login(data: &ConnectData, device_type: DeviceType, conn: DbConn, remote: Option<SocketAddr>) -> JsonResult { | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					|  |  |  |  |  |     // Get the ip for error reporting
 | 
			
		
	
		
		
			
				
					|  |  |  |  |  |     let ip = match remote { | 
			
		
	
		
		
			
				
					|  |  |  |  |  |         Some(ip) => ip.ip(), | 
			
		
	
		
		
			
				
					|  |  |  |  |  |         None => IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), | 
			
		
	
		
		
			
				
					|  |  |  |  |  |     }; | 
			
		
	
		
		
			
				
					|  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  |     // Validate scope
 |  |  |     // Validate scope
 | 
			
		
	
		
		
			
				
					|  |  |     let scope = data.get("scope"); |  |  |     let scope = data.get("scope"); | 
			
		
	
		
		
			
				
					|  |  |     if scope != "api offline_access" { |  |  |     if scope != "api offline_access" { | 
			
		
	
	
		
		
			
				
					|  | @ -68,13 +75,19 @@ fn _password_login(data: &ConnectData, device_type: DeviceType, conn: DbConn) -> | 
			
		
	
		
		
			
				
					|  |  |     let username = data.get("username"); |  |  |     let username = data.get("username"); | 
			
		
	
		
		
			
				
					|  |  |     let user = match User::find_by_mail(username, &conn) { |  |  |     let user = match User::find_by_mail(username, &conn) { | 
			
		
	
		
		
			
				
					|  |  |         Some(user) => user, |  |  |         Some(user) => user, | 
			
		
	
		
		
			
				
					
					|  |  |         None => err!("Username or password is incorrect. Try again."), |  |  |         None => err!(format!( | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					|  |  |  |  |  |             "Username or password is incorrect. Try again. IP: {}. Username: {}.", | 
			
		
	
		
		
			
				
					|  |  |  |  |  |             ip, username | 
			
		
	
		
		
			
				
					|  |  |  |  |  |         )), | 
			
		
	
		
		
			
				
					|  |  |     }; |  |  |     }; | 
			
		
	
		
		
			
				
					|  |  | 
 |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  |     // Check password
 |  |  |     // Check password
 | 
			
		
	
		
		
			
				
					|  |  |     let password = data.get("password"); |  |  |     let password = data.get("password"); | 
			
		
	
		
		
			
				
					|  |  |     if !user.check_valid_password(password) { |  |  |     if !user.check_valid_password(password) { | 
			
		
	
		
		
			
				
					
					|  |  |         err!("Username or password is incorrect. Try again.") |  |  |         err!(format!( | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					|  |  |  |  |  |             "Username or password is incorrect. Try again. IP: {}. Username: {}.", | 
			
		
	
		
		
			
				
					|  |  |  |  |  |             ip, username | 
			
		
	
		
		
			
				
					|  |  |  |  |  |         )) | 
			
		
	
		
		
			
				
					|  |  |     } |  |  |     } | 
			
		
	
		
		
			
				
					|  |  | 
 |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  |     // Let's only use the header and ignore the 'devicetype' parameter
 |  |  |     // Let's only use the header and ignore the 'devicetype' parameter
 | 
			
		
	
	
		
		
			
				
					|  | 
 |