use serde::{Deserialize, Serialize};
use super::enums::{LoginStatus, LockStatus};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct LoginState {
#[serde(rename = "password_type")]
pub password_type: String,
#[serde(rename = "extern_password_type")]
pub extern_password_type: String,
#[serde(rename = "history_login_flag")]
pub history_login_flag: String,
#[serde(rename = "State")]
pub state: LoginStatus,
#[serde(rename = "guidemodifypwdpageflag")]
pub guide_modify_pwd_page_flag: String,
#[serde(rename = "rsapadingtype")]
pub rsa_padding_type: String,
#[serde(rename = "accounts_number")]
pub accounts_number: String,
#[serde(rename = "wifipwdsamewithwebpwd")]
pub wifi_pwd_same_with_web_pwd: String,
#[serde(rename = "remainwaittime")]
pub remain_wait_time: String,
#[serde(rename = "lockstatus")]
pub lock_status: LockStatus,
#[serde(rename = "forceskipguide")]
pub force_skip_guide: String,
#[serde(rename = "username")]
pub username: String,
#[serde(rename = "firstlogin")]
pub first_login: String,
#[serde(rename = "userlevel")]
pub user_level: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct LoginRequest {
#[serde(rename = "Username")]
pub username: String,
#[serde(rename = "Password")]
pub password: String,
#[serde(rename = "password_type")]
pub password_type: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct LogoutRequest {
#[serde(rename = "Logout")]
pub logout: String,
}
impl LoginState {
pub fn is_logged_in(&self) -> bool {
self.state.is_logged_in()
}
pub fn is_locked(&self) -> bool {
self.lock_status.is_locked()
}
pub fn password_encoding(&self) -> PasswordEncoding {
match self.password_type.as_str() {
"0" => PasswordEncoding::Base64,
"3" => PasswordEncoding::Base64AfterChange,
"4" => PasswordEncoding::Sha256,
_ => PasswordEncoding::Unknown,
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub enum PasswordEncoding {
Base64,
Base64AfterChange,
Sha256,
Unknown,
}
impl LoginRequest {
pub fn new(username: String, password: String, password_type: String) -> Self {
Self {
username,
password,
password_type,
}
}
}
impl LogoutRequest {
pub fn new() -> Self {
Self {
logout: "1".to_string(),
}
}
}
impl Default for LogoutRequest {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_login_state_parsing() {
let xml = r#"
<response>
<password_type>4</password_type>
<extern_password_type>1</extern_password_type>
<history_login_flag>0</history_login_flag>
<State>-1</State>
<guidemodifypwdpageflag>0</guidemodifypwdpageflag>
<rsapadingtype>1</rsapadingtype>
<accounts_number>1</accounts_number>
<wifipwdsamewithwebpwd>0</wifipwdsamewithwebpwd>
<remainwaittime>0</remainwaittime>
<lockstatus>0</lockstatus>
<forceskipguide>0</forceskipguide>
<username></username>
<firstlogin>0</firstlogin>
<userlevel></userlevel>
</response>"#;
let state: LoginState = serde_xml_rs::from_str(xml).unwrap();
assert_eq!(state.password_type, "4");
assert_eq!(state.state, LoginStatus::NotLoggedIn);
assert!(!state.is_logged_in());
assert!(!state.is_locked());
assert_eq!(state.password_encoding(), PasswordEncoding::Sha256);
}
#[test]
fn test_login_request_serialization() {
let request = LoginRequest::new(
"admin".to_string(),
"encoded_password".to_string(),
"4".to_string(),
);
let xml = serde_xml_rs::to_string(&request).unwrap();
assert!(xml.contains("<Username>admin</Username>"));
assert!(xml.contains("<Password>encoded_password</Password>"));
assert!(xml.contains("<password_type>4</password_type>"));
}
#[test]
fn test_password_encoding_detection() {
let mut state = LoginState {
password_type: "0".to_string(),
state: LoginStatus::NotLoggedIn,
lock_status: LockStatus::Unlocked,
extern_password_type: "1".to_string(),
history_login_flag: "0".to_string(),
guide_modify_pwd_page_flag: "0".to_string(),
rsa_padding_type: "1".to_string(),
accounts_number: "1".to_string(),
wifi_pwd_same_with_web_pwd: "0".to_string(),
remain_wait_time: "0".to_string(),
force_skip_guide: "0".to_string(),
username: "".to_string(),
first_login: "0".to_string(),
user_level: "".to_string(),
};
assert_eq!(state.password_encoding(), PasswordEncoding::Base64);
state.password_type = "4".to_string();
assert_eq!(state.password_encoding(), PasswordEncoding::Sha256);
}
}