mirror of
https://github.com/weyne85/rustdesk.git
synced 2025-10-29 17:00:05 +00:00
password: safe/random personal password
Signed-off-by: 21pages <pages21@163.com>
This commit is contained in:
@@ -537,14 +537,6 @@ pub fn is_setup(name: &str) -> bool {
|
||||
name.to_lowercase().ends_with("setdown.exe") || name.to_lowercase().ends_with("安装.exe")
|
||||
}
|
||||
|
||||
pub fn get_uuid() -> Vec<u8> {
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
if let Ok(id) = machine_uid::get() {
|
||||
return id.into();
|
||||
}
|
||||
Config::get_key_pair().1
|
||||
}
|
||||
|
||||
pub fn get_custom_rendezvous_server(custom: String) -> String {
|
||||
if !custom.is_empty() {
|
||||
return custom;
|
||||
|
||||
207
src/ipc.rs
207
src/ipc.rs
@@ -7,7 +7,9 @@ use hbb_common::{
|
||||
config::{self, Config, Config2},
|
||||
futures::StreamExt as _,
|
||||
futures_util::sink::SinkExt,
|
||||
log, timeout, tokio,
|
||||
log,
|
||||
password_security::password,
|
||||
timeout, tokio,
|
||||
tokio::io::{AsyncRead, AsyncWrite},
|
||||
tokio_util::codec::Framed,
|
||||
ResultType,
|
||||
@@ -20,6 +22,16 @@ use std::{collections::HashMap, sync::atomic::Ordering};
|
||||
#[cfg(not(windows))]
|
||||
use std::{fs::File, io::prelude::*};
|
||||
|
||||
const STR_RANDOM_PASSWORD: &'static str = "random-password";
|
||||
const STR_SECURITY_PASSWORD: &'static str = "security-password";
|
||||
const STR_RANDOM_PASSWORD_UPDATE_METHOD: &'static str = "random-password-update-method";
|
||||
const STR_RANDOM_PASSWORD_ENABLED: &'static str = "random-password-enabled";
|
||||
const STR_SECURITY_PASSWORD_ENABLED: &'static str = "security-password-enabled";
|
||||
const STR_ONETIME_PASSWORD_ENABLED: &'static str = "onetime-password-enabled";
|
||||
const STR_ONETIME_PASSWORD_ACTIVATED: &'static str = "onetime-password-activated";
|
||||
const STR_RANDOM_PASSWORD_VALID: &'static str = "random-password-valid";
|
||||
pub const STR_PASSWORD_DESCRIPTION: &'static str = "password-description";
|
||||
|
||||
// State with timestamp, because std::time::Instant cannot be serialized
|
||||
#[derive(Debug, Serialize, Deserialize, Copy, Clone)]
|
||||
#[serde(tag = "t", content = "c")]
|
||||
@@ -128,6 +140,7 @@ pub enum Data {
|
||||
ClipboardFileEnabled(bool),
|
||||
PrivacyModeState((i32, PrivacyModeState)),
|
||||
TestRendezvousServer,
|
||||
Bool((String, Option<bool>)),
|
||||
}
|
||||
|
||||
#[tokio::main(flavor = "current_thread")]
|
||||
@@ -282,8 +295,20 @@ async fn handle(data: Data, stream: &mut Connection) {
|
||||
let value;
|
||||
if name == "id" {
|
||||
value = Some(Config::get_id());
|
||||
} else if name == "password" {
|
||||
value = Some(Config::get_password());
|
||||
} else if name == STR_RANDOM_PASSWORD {
|
||||
value = Some(password::random_password());
|
||||
} else if name == STR_SECURITY_PASSWORD {
|
||||
value = Some(Config::get_security_password());
|
||||
} else if name == STR_RANDOM_PASSWORD_UPDATE_METHOD {
|
||||
value = Some(password::update_method().to_string());
|
||||
} else if name == STR_PASSWORD_DESCRIPTION {
|
||||
value = Some(
|
||||
password::random_password()
|
||||
+ &password::security_enabled().to_string()
|
||||
+ &password::random_enabled().to_string()
|
||||
+ &password::onetime_password_enabled().to_string()
|
||||
+ &password::onetime_password_activated().to_string(),
|
||||
);
|
||||
} else if name == "salt" {
|
||||
value = Some(Config::get_salt());
|
||||
} else if name == "rendezvous_server" {
|
||||
@@ -303,8 +328,12 @@ async fn handle(data: Data, stream: &mut Connection) {
|
||||
if name == "id" {
|
||||
Config::set_key_confirmed(false);
|
||||
Config::set_id(&value);
|
||||
} else if name == "password" {
|
||||
Config::set_password(&value);
|
||||
} else if name == STR_RANDOM_PASSWORD {
|
||||
password::set_random_password(&value);
|
||||
} else if name == STR_SECURITY_PASSWORD {
|
||||
Config::set_security_password(&value);
|
||||
} else if name == STR_RANDOM_PASSWORD_UPDATE_METHOD {
|
||||
password::set_update_method(&value);
|
||||
} else if name == "salt" {
|
||||
Config::set_salt(&value);
|
||||
} else {
|
||||
@@ -344,6 +373,36 @@ async fn handle(data: Data, stream: &mut Connection) {
|
||||
Data::TestRendezvousServer => {
|
||||
crate::test_rendezvous_server();
|
||||
}
|
||||
Data::Bool((name, value)) => match value {
|
||||
None => {
|
||||
let value;
|
||||
if name == STR_SECURITY_PASSWORD_ENABLED {
|
||||
value = Some(password::security_enabled());
|
||||
} else if name == STR_RANDOM_PASSWORD_ENABLED {
|
||||
value = Some(password::random_enabled());
|
||||
} else if name == STR_ONETIME_PASSWORD_ENABLED {
|
||||
value = Some(password::onetime_password_enabled());
|
||||
} else if name == STR_ONETIME_PASSWORD_ACTIVATED {
|
||||
value = Some(password::onetime_password_activated());
|
||||
} else if name == STR_RANDOM_PASSWORD_VALID {
|
||||
value = Some(password::random_password_valid());
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
allow_err!(stream.send(&Data::Bool((name, value))).await);
|
||||
}
|
||||
Some(value) => {
|
||||
if name == STR_SECURITY_PASSWORD_ENABLED {
|
||||
password::set_security_enabled(value);
|
||||
} else if name == STR_RANDOM_PASSWORD_ENABLED {
|
||||
password::set_random_enabled(value);
|
||||
} else if name == STR_ONETIME_PASSWORD_ENABLED {
|
||||
password::set_onetime_password_enabled(value);
|
||||
} else if name == STR_ONETIME_PASSWORD_ACTIVATED {
|
||||
password::set_onetime_password_activated(value);
|
||||
}
|
||||
}
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
@@ -426,6 +485,10 @@ where
|
||||
.await
|
||||
}
|
||||
|
||||
async fn send_bool(&mut self, name: &str, value: bool) -> ResultType<()> {
|
||||
self.send(&Data::Bool((name.to_owned(), Some(value)))).await
|
||||
}
|
||||
|
||||
pub async fn next_timeout(&mut self, ms_timeout: u64) -> ResultType<Option<Data>> {
|
||||
Ok(timeout(ms_timeout, self.next()).await??)
|
||||
}
|
||||
@@ -497,9 +560,128 @@ pub async fn set_config(name: &str, value: String) -> ResultType<()> {
|
||||
set_config_async(name, value).await
|
||||
}
|
||||
|
||||
pub fn set_password(v: String) -> ResultType<()> {
|
||||
Config::set_password(&v);
|
||||
set_config("password", v)
|
||||
#[tokio::main(flavor = "current_thread")]
|
||||
async fn get_bool(name: &str) -> ResultType<Option<bool>> {
|
||||
get_bool_async(name, 1_000).await
|
||||
}
|
||||
|
||||
async fn get_bool_async(name: &str, ms_timeout: u64) -> ResultType<Option<bool>> {
|
||||
let mut c = connect(ms_timeout, "").await?;
|
||||
c.send(&Data::Bool((name.to_owned(), None))).await?;
|
||||
if let Some(Data::Bool((name2, value))) = c.next_timeout(ms_timeout).await? {
|
||||
if name == name2 {
|
||||
return Ok(value);
|
||||
}
|
||||
}
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
pub async fn set_bool_async(name: &str, value: bool) -> ResultType<()> {
|
||||
let mut c = connect(1000, "").await?;
|
||||
c.send_bool(name, value).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::main(flavor = "current_thread")]
|
||||
pub async fn set_bool(name: &str, value: bool) -> ResultType<()> {
|
||||
set_bool_async(name, value).await
|
||||
}
|
||||
|
||||
pub fn get_random_password() -> String {
|
||||
if let Ok(Some(password)) = get_config(STR_RANDOM_PASSWORD) {
|
||||
password::set_random_password(&password);
|
||||
password
|
||||
} else {
|
||||
password::random_password()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_random_password(v: String) -> ResultType<()> {
|
||||
password::set_random_password(&v);
|
||||
set_config(STR_RANDOM_PASSWORD, v)
|
||||
}
|
||||
|
||||
pub fn set_security_password(v: String) -> ResultType<()> {
|
||||
Config::set_security_password(&v);
|
||||
set_config(STR_SECURITY_PASSWORD, v)
|
||||
}
|
||||
|
||||
pub fn random_password_update_method() -> String {
|
||||
if let Ok(Some(method)) = get_config(STR_RANDOM_PASSWORD_UPDATE_METHOD) {
|
||||
password::set_update_method(&method);
|
||||
method
|
||||
} else {
|
||||
password::update_method()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_random_password_update_method(method: String) -> ResultType<()> {
|
||||
password::set_update_method(&method);
|
||||
set_config(STR_RANDOM_PASSWORD_UPDATE_METHOD, method)
|
||||
}
|
||||
|
||||
pub fn is_random_password_enabled() -> bool {
|
||||
if let Ok(Some(enabled)) = get_bool(STR_RANDOM_PASSWORD_ENABLED) {
|
||||
password::set_random_enabled(enabled);
|
||||
enabled
|
||||
} else {
|
||||
password::random_enabled()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_random_password_enabled(enabled: bool) -> ResultType<()> {
|
||||
password::set_random_enabled(enabled);
|
||||
set_bool(STR_RANDOM_PASSWORD_ENABLED, enabled)
|
||||
}
|
||||
|
||||
pub fn is_security_password_enabled() -> bool {
|
||||
if let Ok(Some(enabled)) = get_bool(STR_SECURITY_PASSWORD_ENABLED) {
|
||||
password::set_security_enabled(enabled);
|
||||
enabled
|
||||
} else {
|
||||
password::security_enabled()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_security_password_enabled(enabled: bool) -> ResultType<()> {
|
||||
password::set_security_enabled(enabled);
|
||||
set_bool(STR_SECURITY_PASSWORD_ENABLED, enabled)
|
||||
}
|
||||
|
||||
pub fn is_onetime_password_enabled() -> bool {
|
||||
if let Ok(Some(enabled)) = get_bool(STR_ONETIME_PASSWORD_ENABLED) {
|
||||
password::set_onetime_password_enabled(enabled);
|
||||
enabled
|
||||
} else {
|
||||
password::onetime_password_enabled()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_onetime_password_enabled(enabled: bool) -> ResultType<()> {
|
||||
password::set_onetime_password_enabled(enabled);
|
||||
set_bool(STR_ONETIME_PASSWORD_ENABLED, enabled)
|
||||
}
|
||||
|
||||
pub fn is_onetime_password_activated() -> bool {
|
||||
if let Ok(Some(activated)) = get_bool(STR_ONETIME_PASSWORD_ACTIVATED) {
|
||||
password::set_onetime_password_activated(activated);
|
||||
activated
|
||||
} else {
|
||||
password::onetime_password_activated()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_onetime_password_activated(activated: bool) -> ResultType<()> {
|
||||
password::set_onetime_password_activated(activated);
|
||||
set_bool(STR_ONETIME_PASSWORD_ACTIVATED, activated)
|
||||
}
|
||||
|
||||
pub fn is_random_password_valid() -> bool {
|
||||
if let Ok(Some(valid)) = get_bool(STR_RANDOM_PASSWORD_VALID) {
|
||||
valid
|
||||
} else {
|
||||
password::random_password_valid()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_id() -> String {
|
||||
@@ -518,15 +700,6 @@ pub fn get_id() -> String {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_password() -> String {
|
||||
if let Ok(Some(v)) = get_config("password") {
|
||||
Config::set_password(&v);
|
||||
v
|
||||
} else {
|
||||
Config::get_password()
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn get_rendezvous_server(ms_timeout: u64) -> (String, Vec<String>) {
|
||||
if let Ok(Some(v)) = get_config_async("rendezvous_server", ms_timeout).await {
|
||||
let mut urls = v.split(",");
|
||||
|
||||
@@ -287,5 +287,18 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Keep RustDesk background service", "保持RustDesk后台服务"),
|
||||
("Ignore Battery Optimizations", "忽略电池优化"),
|
||||
("android_open_battery_optimizations_tip", "如需关闭此功能,请在接下来的RustDesk应用设置页面中,找到并进入 [电源] 页面,取消勾选 [不受限制]"),
|
||||
("Random Password After Session", "会话结束更新随机密码"),
|
||||
("Keep", "保持"),
|
||||
("Update", "更新"),
|
||||
("Disable", "禁用"),
|
||||
("Onetime Password", "一次性口令"),
|
||||
("Verification Method", "密码验证方式"),
|
||||
("Enable security password", "启用安全密码"),
|
||||
("Enable random password", "启用随机密码"),
|
||||
("Enable onetime password", "启用一次性访问功能"),
|
||||
("Disable onetime password", "禁用一次性访问功能"),
|
||||
("Activate onetime password", "激活一次性访问功能"),
|
||||
("Set security password", "设置安全密码"),
|
||||
("Connection not allowed", "对方不允许连接"),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -287,5 +287,18 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Keep RustDesk background service", ""),
|
||||
("Ignore Battery Optimizations", ""),
|
||||
("android_open_battery_optimizations_tip", ""),
|
||||
("Random Password After Session", ""),
|
||||
("Keep", ""),
|
||||
("Update", ""),
|
||||
("Disable", ""),
|
||||
("Onetime Password", ""),
|
||||
("Verification Method", ""),
|
||||
("Enable security password", ""),
|
||||
("Enable random password", ""),
|
||||
("Enable onetime password", ""),
|
||||
("Disable onetime password", ""),
|
||||
("Activate onetime password", ""),
|
||||
("Set security password", ""),
|
||||
("Connection not allowed", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -287,5 +287,18 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Keep RustDesk background service", ""),
|
||||
("Ignore Battery Optimizations", ""),
|
||||
("android_open_battery_optimizations_tip", ""),
|
||||
("Random Password After Session", ""),
|
||||
("Keep", ""),
|
||||
("Update", ""),
|
||||
("Disable", ""),
|
||||
("Onetime Password", ""),
|
||||
("Verification Method", ""),
|
||||
("Enable security password", ""),
|
||||
("Enable random password", ""),
|
||||
("Enable onetime password", ""),
|
||||
("Disable onetime password", ""),
|
||||
("Activate onetime password", ""),
|
||||
("Set security password", ""),
|
||||
("Connection not allowed", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -287,5 +287,18 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Keep RustDesk background service", ""),
|
||||
("Ignore Battery Optimizations", ""),
|
||||
("android_open_battery_optimizations_tip", ""),
|
||||
("Random Password After Session", ""),
|
||||
("Keep", ""),
|
||||
("Update", ""),
|
||||
("Disable", ""),
|
||||
("Onetime Password", ""),
|
||||
("Verification Method", ""),
|
||||
("Enable security password", ""),
|
||||
("Enable random password", ""),
|
||||
("Enable onetime password", ""),
|
||||
("Disable onetime password", ""),
|
||||
("Activate onetime password", ""),
|
||||
("Set security password", ""),
|
||||
("Connection not allowed", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -287,5 +287,18 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Keep RustDesk background service", ""),
|
||||
("Ignore Battery Optimizations", ""),
|
||||
("android_open_battery_optimizations_tip", ""),
|
||||
("Random Password After Session", ""),
|
||||
("Keep", ""),
|
||||
("Update", ""),
|
||||
("Disable", ""),
|
||||
("Onetime Password", ""),
|
||||
("Verification Method", ""),
|
||||
("Enable security password", ""),
|
||||
("Enable random password", ""),
|
||||
("Enable onetime password", ""),
|
||||
("Disable onetime password", ""),
|
||||
("Activate onetime password", ""),
|
||||
("Set security password", ""),
|
||||
("Connection not allowed", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -287,5 +287,18 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Keep RustDesk background service", ""),
|
||||
("Ignore Battery Optimizations", ""),
|
||||
("android_open_battery_optimizations_tip", ""),
|
||||
("Random Password After Session", ""),
|
||||
("Keep", ""),
|
||||
("Update", ""),
|
||||
("Disable", ""),
|
||||
("Onetime Password", ""),
|
||||
("Verification Method", ""),
|
||||
("Enable security password", ""),
|
||||
("Enable random password", ""),
|
||||
("Enable onetime password", ""),
|
||||
("Disable onetime password", ""),
|
||||
("Activate onetime password", ""),
|
||||
("Set security password", ""),
|
||||
("Connection not allowed", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -287,5 +287,18 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Keep RustDesk background service", ""),
|
||||
("Ignore Battery Optimizations", ""),
|
||||
("android_open_battery_optimizations_tip", ""),
|
||||
("Random Password After Session", ""),
|
||||
("Keep", ""),
|
||||
("Update", ""),
|
||||
("Disable", ""),
|
||||
("Onetime Password", ""),
|
||||
("Verification Method", ""),
|
||||
("Enable security password", ""),
|
||||
("Enable random password", ""),
|
||||
("Enable onetime password", ""),
|
||||
("Disable onetime password", ""),
|
||||
("Activate onetime password", ""),
|
||||
("Set security password", ""),
|
||||
("Connection not allowed", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -287,5 +287,18 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Keep RustDesk background service", ""),
|
||||
("Ignore Battery Optimizations", ""),
|
||||
("android_open_battery_optimizations_tip", ""),
|
||||
("Random Password After Session", ""),
|
||||
("Keep", ""),
|
||||
("Update", ""),
|
||||
("Disable", ""),
|
||||
("Onetime Password", ""),
|
||||
("Verification Method", ""),
|
||||
("Enable security password", ""),
|
||||
("Enable random password", ""),
|
||||
("Enable onetime password", ""),
|
||||
("Disable onetime password", ""),
|
||||
("Activate onetime password", ""),
|
||||
("Set security password", ""),
|
||||
("Connection not allowed", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -287,5 +287,18 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Keep RustDesk background service", ""),
|
||||
("Ignore Battery Optimizations", ""),
|
||||
("android_open_battery_optimizations_tip", ""),
|
||||
("Random Password After Session", ""),
|
||||
("Keep", ""),
|
||||
("Update", ""),
|
||||
("Disable", ""),
|
||||
("Onetime Password", ""),
|
||||
("Verification Method", ""),
|
||||
("Enable security password", ""),
|
||||
("Enable random password", ""),
|
||||
("Enable onetime password", ""),
|
||||
("Disable onetime password", ""),
|
||||
("Activate onetime password", ""),
|
||||
("Set security password", ""),
|
||||
("Connection not allowed", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -287,5 +287,18 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Keep RustDesk background service", ""),
|
||||
("Ignore Battery Optimizations", ""),
|
||||
("android_open_battery_optimizations_tip", ""),
|
||||
("Random Password After Session", ""),
|
||||
("Keep", ""),
|
||||
("Update", ""),
|
||||
("Disable", ""),
|
||||
("Onetime Password", ""),
|
||||
("Verification Method", ""),
|
||||
("Enable security password", ""),
|
||||
("Enable random password", ""),
|
||||
("Enable onetime password", ""),
|
||||
("Disable onetime password", ""),
|
||||
("Activate onetime password", ""),
|
||||
("Set security password", ""),
|
||||
("Connection not allowed", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -287,5 +287,18 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Keep RustDesk background service", ""),
|
||||
("Ignore Battery Optimizations", ""),
|
||||
("android_open_battery_optimizations_tip", ""),
|
||||
("Random Password After Session", ""),
|
||||
("Keep", ""),
|
||||
("Update", ""),
|
||||
("Disable", ""),
|
||||
("Onetime Password", ""),
|
||||
("Verification Method", ""),
|
||||
("Enable security password", ""),
|
||||
("Enable random password", ""),
|
||||
("Enable onetime password", ""),
|
||||
("Disable onetime password", ""),
|
||||
("Activate onetime password", ""),
|
||||
("Set security password", ""),
|
||||
("Connection not allowed", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -287,5 +287,18 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Keep RustDesk background service", ""),
|
||||
("Ignore Battery Optimizations", ""),
|
||||
("android_open_battery_optimizations_tip", ""),
|
||||
("Random Password After Session", ""),
|
||||
("Keep", ""),
|
||||
("Update", ""),
|
||||
("Disable", ""),
|
||||
("Onetime Password", ""),
|
||||
("Verification Method", ""),
|
||||
("Enable security password", ""),
|
||||
("Enable random password", ""),
|
||||
("Enable onetime password", ""),
|
||||
("Disable onetime password", ""),
|
||||
("Activate onetime password", ""),
|
||||
("Set security password", ""),
|
||||
("Connection not allowed", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -287,5 +287,18 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Keep RustDesk background service", ""),
|
||||
("Ignore Battery Optimizations", ""),
|
||||
("android_open_battery_optimizations_tip", ""),
|
||||
("Random Password After Session", ""),
|
||||
("Keep", ""),
|
||||
("Update", ""),
|
||||
("Disable", ""),
|
||||
("Onetime Password", ""),
|
||||
("Verification Method", ""),
|
||||
("Enable security password", ""),
|
||||
("Enable random password", ""),
|
||||
("Enable onetime password", ""),
|
||||
("Disable onetime password", ""),
|
||||
("Activate onetime password", ""),
|
||||
("Set security password", ""),
|
||||
("Connection not allowed", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -287,5 +287,18 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Keep RustDesk background service", ""),
|
||||
("Ignore Battery Optimizations", ""),
|
||||
("android_open_battery_optimizations_tip", ""),
|
||||
("Random Password After Session", ""),
|
||||
("Keep", ""),
|
||||
("Update", ""),
|
||||
("Disable", ""),
|
||||
("Onetime Password", ""),
|
||||
("Verification Method", ""),
|
||||
("Enable security password", ""),
|
||||
("Enable random password", ""),
|
||||
("Enable onetime password", ""),
|
||||
("Disable onetime password", ""),
|
||||
("Activate onetime password", ""),
|
||||
("Set security password", ""),
|
||||
("Connection not allowed", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -287,5 +287,18 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Keep RustDesk background service", ""),
|
||||
("Ignore Battery Optimizations", ""),
|
||||
("android_open_battery_optimizations_tip", ""),
|
||||
("Random Password After Session", ""),
|
||||
("Keep", ""),
|
||||
("Update", ""),
|
||||
("Disable", ""),
|
||||
("Onetime Password", ""),
|
||||
("Verification Method", ""),
|
||||
("Enable security password", ""),
|
||||
("Enable random password", ""),
|
||||
("Enable onetime password", ""),
|
||||
("Disable onetime password", ""),
|
||||
("Activate onetime password", ""),
|
||||
("Set security password", ""),
|
||||
("Connection not allowed", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -287,5 +287,18 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Keep RustDesk background service", "保持RustDesk後台服務"),
|
||||
("Ignore Battery Optimizations", "忽略電池優化"),
|
||||
("android_open_battery_optimizations_tip", "如需關閉此功能,請在接下來的RustDesk應用設置頁面中,找到並進入 [電源] 頁面,取消勾選 [不受限制]"),
|
||||
("Random Password After Session", "會話結束更新隨機密碼"),
|
||||
("Keep", "保持"),
|
||||
("Update", "更新"),
|
||||
("Disable", "禁用"),
|
||||
("Onetime Password", "一次性口令"),
|
||||
("Verification Method", "密碼驗證方式"),
|
||||
("Enable security password", "啟用安全密碼"),
|
||||
("Enable random password", "啟用隨機密碼"),
|
||||
("Enable onetime password", "啟用一次性訪問功能"),
|
||||
("Disable onetime password", "禁用一次性訪問功能"),
|
||||
("Activate onetime password", "激活一次性訪問功能"),
|
||||
("Set security password", "設置安全密碼"),
|
||||
("Connection not allowed", "對方不允許連接"),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -148,7 +148,7 @@ fn main() {
|
||||
return;
|
||||
} else if args[0] == "--password" {
|
||||
if args.len() == 2 {
|
||||
ipc::set_password(args[1].to_owned()).unwrap();
|
||||
ipc::set_security_password(args[1].to_owned()).unwrap();
|
||||
}
|
||||
return;
|
||||
} else if args[0] == "--check-hwcodec-config" {
|
||||
|
||||
@@ -389,7 +389,7 @@ impl RendezvousMediator {
|
||||
async fn register_pk(&mut self, socket: &mut FramedSocket) -> ResultType<()> {
|
||||
let mut msg_out = Message::new();
|
||||
let pk = Config::get_key_pair().1;
|
||||
let uuid = crate::get_uuid();
|
||||
let uuid = hbb_common::get_uuid();
|
||||
let id = Config::get_id();
|
||||
self.last_id_pk_registry = id.clone();
|
||||
msg_out.set_register_pk(RegisterPk {
|
||||
|
||||
@@ -8,6 +8,7 @@ use crate::video_service;
|
||||
use crate::{common::MOBILE_INFO2, mobile::connection_manager::start_channel};
|
||||
use crate::{ipc, VERSION};
|
||||
use hbb_common::fs::can_enable_overwrite_detection;
|
||||
use hbb_common::password_security::password;
|
||||
use hbb_common::{
|
||||
config::Config,
|
||||
fs,
|
||||
@@ -398,6 +399,7 @@ impl Connection {
|
||||
video_service::notify_video_frame_feched(id, None);
|
||||
scrap::codec::Encoder::update_video_encoder(id, scrap::codec::EncoderUpdate::Remove);
|
||||
video_service::VIDEO_QOS.lock().unwrap().reset();
|
||||
password::after_session(conn.authorized);
|
||||
if let Err(err) = conn.try_port_forward_loop(&mut rx_from_cm).await {
|
||||
conn.on_close(&err.to_string(), false);
|
||||
}
|
||||
@@ -571,7 +573,7 @@ impl Connection {
|
||||
let url = self.api_server.clone();
|
||||
let mut v = v;
|
||||
v["id"] = json!(Config::get_id());
|
||||
v["uuid"] = json!(base64::encode(crate::get_uuid()));
|
||||
v["uuid"] = json!(base64::encode(hbb_common::get_uuid()));
|
||||
v["Id"] = json!(self.inner.id);
|
||||
tokio::spawn(async move {
|
||||
allow_err!(Self::post_audit_async(url, v).await);
|
||||
@@ -778,6 +780,36 @@ impl Connection {
|
||||
self.tx_input.send(MessageInput::Key((msg, press))).ok();
|
||||
}
|
||||
|
||||
fn validate_password(&mut self, lr_password: Vec<u8>) -> bool {
|
||||
let validate = |password: String| {
|
||||
if password.len() == 0 {
|
||||
return false;
|
||||
}
|
||||
let mut hasher = Sha256::new();
|
||||
hasher.update(password);
|
||||
hasher.update(&self.hash.salt);
|
||||
let mut hasher2 = Sha256::new();
|
||||
hasher2.update(&hasher.finalize()[..]);
|
||||
hasher2.update(&self.hash.challenge);
|
||||
hasher2.finalize()[..] == lr_password[..]
|
||||
};
|
||||
if password::security_enabled() {
|
||||
if validate(Config::get_security_password()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if password::random_password_valid() {
|
||||
if validate(password::random_password()) {
|
||||
if password::onetime_password_activated() {
|
||||
password::set_onetime_password_activated(false);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
async fn on_message(&mut self, msg: Message) -> bool {
|
||||
if let Some(message::Union::LoginRequest(lr)) = msg.union {
|
||||
if let Some(o) = lr.option.as_ref() {
|
||||
@@ -853,12 +885,10 @@ impl Connection {
|
||||
} else if lr.password.is_empty() {
|
||||
self.try_start_cm(lr.my_id, lr.my_name, false);
|
||||
} else {
|
||||
let mut hasher = Sha256::new();
|
||||
hasher.update(&Config::get_password());
|
||||
hasher.update(&self.hash.salt);
|
||||
let mut hasher2 = Sha256::new();
|
||||
hasher2.update(&hasher.finalize()[..]);
|
||||
hasher2.update(&self.hash.challenge);
|
||||
if password::passwords().len() == 0 {
|
||||
self.send_login_error("Connection not allowed").await;
|
||||
return false;
|
||||
}
|
||||
let mut failure = LOGIN_FAILURES
|
||||
.lock()
|
||||
.unwrap()
|
||||
@@ -871,7 +901,7 @@ impl Connection {
|
||||
.await;
|
||||
} else if time == failure.0 && failure.1 > 6 {
|
||||
self.send_login_error("Please try 1 minute later").await;
|
||||
} else if hasher2.finalize()[..] != lr.password[..] {
|
||||
} else if !self.validate_password(lr.password.clone()) {
|
||||
if failure.0 == time {
|
||||
failure.1 += 1;
|
||||
failure.2 += 1;
|
||||
|
||||
99
src/ui.rs
99
src/ui.rs
@@ -43,6 +43,7 @@ struct UI(
|
||||
Arc<Mutex<HashMap<String, String>>>,
|
||||
Arc<Mutex<String>>,
|
||||
mpsc::UnboundedSender<ipc::Data>,
|
||||
Arc<Mutex<String>>,
|
||||
);
|
||||
|
||||
struct UIHostHandler;
|
||||
@@ -169,7 +170,7 @@ pub fn start(args: &mut [String]) {
|
||||
impl UI {
|
||||
fn new(childs: Childs) -> Self {
|
||||
let res = check_connect_status(true);
|
||||
Self(childs, res.0, res.1, Default::default(), res.2)
|
||||
Self(childs, res.0, res.1, Default::default(), res.2, res.3)
|
||||
}
|
||||
|
||||
fn recent_sessions_updated(&mut self) -> bool {
|
||||
@@ -186,16 +187,16 @@ impl UI {
|
||||
ipc::get_id()
|
||||
}
|
||||
|
||||
fn get_password(&mut self) -> String {
|
||||
ipc::get_password()
|
||||
fn get_random_password(&self) -> String {
|
||||
ipc::get_random_password()
|
||||
}
|
||||
|
||||
fn update_password(&mut self, password: String) {
|
||||
if password.is_empty() {
|
||||
allow_err!(ipc::set_password(Config::get_auto_password()));
|
||||
} else {
|
||||
allow_err!(ipc::set_password(password));
|
||||
}
|
||||
fn update_random_password(&self) {
|
||||
allow_err!(ipc::set_random_password(Config::get_auto_password()));
|
||||
}
|
||||
|
||||
fn set_security_password(&self, password: String) {
|
||||
allow_err!(ipc::set_security_password(password));
|
||||
}
|
||||
|
||||
fn get_remote_id(&mut self) -> String {
|
||||
@@ -704,7 +705,7 @@ impl UI {
|
||||
}
|
||||
|
||||
fn get_uuid(&self) -> String {
|
||||
base64::encode(crate::get_uuid())
|
||||
base64::encode(hbb_common::get_uuid())
|
||||
}
|
||||
|
||||
fn open_url(&self, url: String) {
|
||||
@@ -774,6 +775,54 @@ impl UI {
|
||||
fn get_langs(&self) -> String {
|
||||
crate::lang::LANGS.to_string()
|
||||
}
|
||||
|
||||
fn random_password_update_method(&self) -> String {
|
||||
ipc::random_password_update_method()
|
||||
}
|
||||
|
||||
fn set_random_password_update_method(&self, method: String) {
|
||||
allow_err!(ipc::set_random_password_update_method(method));
|
||||
}
|
||||
|
||||
fn is_random_password_enabled(&self) -> bool {
|
||||
ipc::is_random_password_enabled()
|
||||
}
|
||||
|
||||
fn set_random_password_enabled(&self, enabled: bool) {
|
||||
allow_err!(ipc::set_random_password_enabled(enabled));
|
||||
}
|
||||
|
||||
fn is_security_password_enabled(&self) -> bool {
|
||||
ipc::is_security_password_enabled()
|
||||
}
|
||||
|
||||
fn set_security_password_enabled(&self, enabled: bool) {
|
||||
allow_err!(ipc::set_security_password_enabled(enabled));
|
||||
}
|
||||
|
||||
fn is_onetime_password_enabled(&self) -> bool {
|
||||
ipc::is_onetime_password_enabled()
|
||||
}
|
||||
|
||||
fn set_onetime_password_enabled(&self, enabled: bool) {
|
||||
allow_err!(ipc::set_onetime_password_enabled(enabled));
|
||||
}
|
||||
|
||||
fn is_onetime_password_activated(&self) -> bool {
|
||||
ipc::is_onetime_password_activated()
|
||||
}
|
||||
|
||||
fn set_onetime_password_activated(&self, activated: bool) {
|
||||
allow_err!(ipc::set_onetime_password_activated(activated));
|
||||
}
|
||||
|
||||
fn is_random_password_valid(&self) -> bool {
|
||||
ipc::is_random_password_valid()
|
||||
}
|
||||
|
||||
fn password_description(&mut self) -> String {
|
||||
self.5.lock().unwrap().clone()
|
||||
}
|
||||
}
|
||||
|
||||
impl sciter::EventHandler for UI {
|
||||
@@ -783,8 +832,9 @@ impl sciter::EventHandler for UI {
|
||||
fn is_xfce();
|
||||
fn using_public_server();
|
||||
fn get_id();
|
||||
fn get_password();
|
||||
fn update_password(String);
|
||||
fn get_random_password();
|
||||
fn update_random_password();
|
||||
fn set_security_password(String);
|
||||
fn get_remote_id();
|
||||
fn set_remote_id(String);
|
||||
fn closing(i32, i32, i32, i32);
|
||||
@@ -854,6 +904,18 @@ impl sciter::EventHandler for UI {
|
||||
fn get_uuid();
|
||||
fn has_hwcodec();
|
||||
fn get_langs();
|
||||
fn random_password_update_method();
|
||||
fn set_random_password_update_method(String);
|
||||
fn is_random_password_enabled();
|
||||
fn set_random_password_enabled(bool);
|
||||
fn is_security_password_enabled();
|
||||
fn set_security_password_enabled(bool);
|
||||
fn is_onetime_password_enabled();
|
||||
fn set_onetime_password_enabled(bool);
|
||||
fn is_onetime_password_activated();
|
||||
fn set_onetime_password_activated(bool);
|
||||
fn is_random_password_valid();
|
||||
fn password_description();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -893,6 +955,7 @@ async fn check_connect_status_(
|
||||
status: Arc<Mutex<Status>>,
|
||||
options: Arc<Mutex<HashMap<String, String>>>,
|
||||
rx: mpsc::UnboundedReceiver<ipc::Data>,
|
||||
password: Arc<Mutex<String>>,
|
||||
) {
|
||||
let mut key_confirmed = false;
|
||||
let mut rx = rx;
|
||||
@@ -919,6 +982,8 @@ async fn check_connect_status_(
|
||||
Ok(Some(ipc::Data::Config((name, Some(value))))) => {
|
||||
if name == "id" {
|
||||
id = value;
|
||||
} else if name == ipc::STR_PASSWORD_DESCRIPTION {
|
||||
*password.lock().unwrap() = value;
|
||||
}
|
||||
}
|
||||
Ok(Some(ipc::Data::OnlineStatus(Some((mut x, c))))) => {
|
||||
@@ -938,6 +1003,7 @@ async fn check_connect_status_(
|
||||
c.send(&ipc::Data::OnlineStatus(None)).await.ok();
|
||||
c.send(&ipc::Data::Options(None)).await.ok();
|
||||
c.send(&ipc::Data::Config(("id".to_owned(), None))).await.ok();
|
||||
c.send(&ipc::Data::Config((ipc::STR_PASSWORD_DESCRIPTION.to_owned(), None))).await.ok();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -986,14 +1052,19 @@ fn check_connect_status(
|
||||
Arc<Mutex<Status>>,
|
||||
Arc<Mutex<HashMap<String, String>>>,
|
||||
mpsc::UnboundedSender<ipc::Data>,
|
||||
Arc<Mutex<String>>,
|
||||
) {
|
||||
let status = Arc::new(Mutex::new((0, false, 0, "".to_owned())));
|
||||
let options = Arc::new(Mutex::new(Config::get_options()));
|
||||
let cloned = status.clone();
|
||||
let cloned_options = options.clone();
|
||||
let (tx, rx) = mpsc::unbounded_channel::<ipc::Data>();
|
||||
std::thread::spawn(move || check_connect_status_(reconnect, cloned, cloned_options, rx));
|
||||
(status, options, tx)
|
||||
let password = Arc::new(Mutex::new(String::default()));
|
||||
let cloned_password = password.clone();
|
||||
std::thread::spawn(move || {
|
||||
check_connect_status_(reconnect, cloned, cloned_options, rx, cloned_password)
|
||||
});
|
||||
(status, options, tx, password)
|
||||
}
|
||||
|
||||
const INVALID_FORMAT: &'static str = "Invalid format";
|
||||
|
||||
@@ -120,7 +120,7 @@ textarea:empty {
|
||||
@ELLIPSIS;
|
||||
}
|
||||
|
||||
div.password svg {
|
||||
div.password svg:not(.checkmark) {
|
||||
padding-left: 1em;
|
||||
size: 16px;
|
||||
color: #ddd;
|
||||
|
||||
@@ -141,7 +141,7 @@ function adjustBorder() {
|
||||
if (el) el.attributes.toggleClass("active", view.windowState == View.WINDOW_FULL_SCREEN);
|
||||
}
|
||||
|
||||
var svg_checkmark = <svg viewBox="0 0 492 492"><path d="M484 105l-16-17a27 27 0 00-38 0L204 315 62 173c-5-5-12-7-19-7s-14 2-19 7L8 189a27 27 0 000 38l160 160v1l16 16c5 5 12 8 19 8 8 0 14-3 20-8l16-16v-1l245-244a27 27 0 000-38z"/></svg>;
|
||||
var svg_checkmark = <svg class="checkmark" viewBox="0 0 492 492"><path d="M484 105l-16-17a27 27 0 00-38 0L204 315 62 173c-5-5-12-7-19-7s-14 2-19 7L8 189a27 27 0 000 38l160 160v1l16 16c5 5 12 8 19 8 8 0 14-3 20-8l16-16v-1l245-244a27 27 0 000-38z"/></svg>;
|
||||
var svg_edit = <svg #edit viewBox="0 0 384 384">
|
||||
<path d="M0 304v80h80l236-236-80-80zM378 56L328 6c-8-8-22-8-30 0l-39 39 80 80 39-39c8-8 8-22 0-30z"/>
|
||||
</svg>;
|
||||
|
||||
@@ -403,3 +403,18 @@ div.remote-session svg#menu {
|
||||
background: none;
|
||||
color: white;
|
||||
}
|
||||
|
||||
svg#refresh-password {
|
||||
display: inline-block;
|
||||
stroke:#ddd;
|
||||
}
|
||||
|
||||
svg#refresh-password:hover {
|
||||
stroke:color(text);
|
||||
}
|
||||
|
||||
li:disabled, li:disabled:hover {
|
||||
color: color(lighter-text);
|
||||
background: color(menu);
|
||||
}
|
||||
|
||||
|
||||
189
src/ui/index.tis
189
src/ui/index.tis
@@ -20,6 +20,7 @@ var svg_menu = <svg #menu viewBox="0 0 512 512">
|
||||
<circle cx="256" cy="448" r="64"/>
|
||||
<circle cx="256" cy="64" r="64"/>
|
||||
</svg>;
|
||||
var svg_refresh_password = <svg #refresh-password xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><path d="M2.5 2v6h6M2.66 15.57a10 10 0 1 0 .57-8.38"/></svg>;
|
||||
|
||||
var my_id = "";
|
||||
function get_id() {
|
||||
@@ -520,10 +521,6 @@ class App: Reactor.Component
|
||||
var is_can_screen_recording = handler.is_can_screen_recording(false);
|
||||
return
|
||||
<div .app>
|
||||
<popup><menu.context #edit-password-context>
|
||||
<li #refresh-password>{translate('Refresh random password')}</li>
|
||||
<li #set-password>{translate('Set your own password')}</li>
|
||||
</menu></popup>
|
||||
<div .left-pane>
|
||||
<div>
|
||||
<div .title>{translate('Your Desktop')}</div>
|
||||
@@ -533,8 +530,7 @@ class App: Reactor.Component
|
||||
{key_confirmed ? <input type="text" readonly value={formatId(get_id())}/> : translate("Generating ...")}
|
||||
</div>
|
||||
<div .your-desktop>
|
||||
<div>{translate('Password')}</div>
|
||||
<Password />
|
||||
<PasswordArea />
|
||||
</div>
|
||||
</div>
|
||||
{!is_win || handler.is_installed() ? "": <InstallMe />}
|
||||
@@ -806,44 +802,151 @@ function watch_screen_recording() {
|
||||
|
||||
class PasswordEyeArea : Reactor.Component {
|
||||
render() {
|
||||
var show = handler.is_random_password_valid();
|
||||
var value = show ? handler.get_random_password() : "-";
|
||||
return
|
||||
<div .eye-area style="width: *">
|
||||
<input|text @{this.input} readonly value="******" />
|
||||
{svg_eye}
|
||||
<input|text @{this.input} readonly value={value} />
|
||||
{svg_refresh_password}
|
||||
</div>;
|
||||
}
|
||||
|
||||
event mouseenter {
|
||||
var me = this;
|
||||
me.leaved = false;
|
||||
me.timer(300ms, function() {
|
||||
if (me.leaved) return;
|
||||
me.input.value = handler.get_password();
|
||||
});
|
||||
}
|
||||
|
||||
event mouseleave {
|
||||
this.leaved = true;
|
||||
this.input.value = "******";
|
||||
event click $(svg#refresh-password) (_, me) {
|
||||
if (handler.is_random_password_valid()) handler.update_random_password();
|
||||
this.update();
|
||||
}
|
||||
}
|
||||
|
||||
class Password: Reactor.Component {
|
||||
var verificationMethodMenu;
|
||||
class VerificationMethodMenu: Reactor.Component {
|
||||
function this() {
|
||||
verificationMethodMenu = this;
|
||||
}
|
||||
|
||||
function render() {
|
||||
return <div .password style="flow:horizontal">
|
||||
<PasswordEyeArea />
|
||||
{svg_edit}
|
||||
if (!this.show) return <li />;
|
||||
var me = this;
|
||||
self.timer(1ms, function() { me.toggleMenuState() });
|
||||
return <li>{translate('Verification Method')}
|
||||
<menu #verification-method>
|
||||
<li #verification-method-security><span>{svg_checkmark}</span>{translate('Enable security password')}</li>
|
||||
<li #verification-method-random><span>{svg_checkmark}</span>{translate('Enable random password')}</li>
|
||||
</menu>
|
||||
</li>;
|
||||
}
|
||||
|
||||
function toggleMenuState() {
|
||||
var security_enabled = handler.is_security_password_enabled();
|
||||
var random_enabled = handler.is_random_password_enabled();
|
||||
var onetime_enabled = handler.is_onetime_password_enabled();
|
||||
for (var (index, el) in this.$$(menu#verification-method>li)) {
|
||||
if (index == 0) el.attributes.toggleClass("selected", security_enabled);
|
||||
if (index == 1) el.attributes.toggleClass("selected", random_enabled);
|
||||
}
|
||||
}
|
||||
|
||||
event click $(menu#verification-method>li) (_, me) {
|
||||
switch (me.id.substring('verification-method-'.length)) {
|
||||
case 'security':
|
||||
{
|
||||
var security_enabled = handler.is_security_password_enabled();
|
||||
handler.set_security_password_enabled(!security_enabled);
|
||||
}
|
||||
break;
|
||||
case 'random':
|
||||
{
|
||||
var random_enabled = handler.is_random_password_enabled();
|
||||
handler.set_random_password_enabled(!random_enabled);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
this.toggleMenuState();
|
||||
passwordArea.update();
|
||||
}
|
||||
}
|
||||
|
||||
var randomPasswordUpdateMethodMenu;
|
||||
class RandomPasswordUpdateMethodMenu: Reactor.Component {
|
||||
function this() {
|
||||
randomPasswordUpdateMethodMenu = this;
|
||||
}
|
||||
|
||||
function render() {
|
||||
if (!this.show) return <li />;
|
||||
var me = this;
|
||||
var random_enabled = handler.is_random_password_enabled();
|
||||
self.timer(1ms, function() { me.toggleMenuState() });
|
||||
return <li disabled={ random_enabled ? "false" : "true" }>{translate('Random Password After Session')}
|
||||
<menu #random-password-update-method>
|
||||
<li #random-password-update-method-keep><span>{svg_checkmark}</span>{translate('Keep')}</li>
|
||||
<li #random-password-update-method-update><span>{svg_checkmark}</span>{translate('Update')}</li>
|
||||
<li #random-password-update-method-disable><span>{svg_checkmark}</span>{translate('Disable')}</li>
|
||||
</menu>
|
||||
</li>;
|
||||
}
|
||||
|
||||
function toggleMenuState() {
|
||||
var method = handler.random_password_update_method();
|
||||
for (var (index, el) in this.$$(menu#random-password-update-method>li)) {
|
||||
if (index == 0) el.attributes.toggleClass("selected", method == "KEEP");
|
||||
if (index == 1) el.attributes.toggleClass("selected", method == "UPDATE");
|
||||
if (index == 2) el.attributes.toggleClass("selected", method == "DISABLE");
|
||||
}
|
||||
}
|
||||
|
||||
event click $(menu#random-password-update-method>li) (_, me) {
|
||||
if (me.id === 'random-password-update-method-keep') handler.set_random_password_update_method("KEEP");
|
||||
if (me.id === 'random-password-update-method-update') handler.set_random_password_update_method("UPDATE");
|
||||
if (me.id === 'random-password-update-method-disable') handler.set_random_password_update_method("DISABLE");
|
||||
this.toggleMenuState();
|
||||
passwordArea.update();
|
||||
}
|
||||
}
|
||||
|
||||
var passwordArea;
|
||||
class PasswordArea: Reactor.Component {
|
||||
function this() {
|
||||
passwordArea = this;
|
||||
}
|
||||
|
||||
function render() {
|
||||
var onetime_enabled = handler.is_onetime_password_enabled();
|
||||
|
||||
return
|
||||
<div>
|
||||
<div>{translate(onetime_enabled ? 'Onetime Password' : 'Password')}</div>
|
||||
<div .password style="flow:horizontal">
|
||||
{this.renderPop()}
|
||||
<PasswordEyeArea />
|
||||
{svg_edit}
|
||||
</div>
|
||||
</div>;
|
||||
}
|
||||
|
||||
event click $(svg#edit) (_, me) {
|
||||
var menu = $(menu#edit-password-context);
|
||||
me.popup(menu);
|
||||
function renderPop() {
|
||||
var security_enabled = handler.is_security_password_enabled();
|
||||
var random_enabled = handler.is_random_password_enabled();
|
||||
var onetime_enabled = handler.is_onetime_password_enabled();
|
||||
var onetime_activated = handler.is_onetime_password_activated();
|
||||
|
||||
return <popup><menu.context #edit-password-context>
|
||||
<li #enable-onetime-password disabled={ random_enabled ? "false" : "true" }>{translate(onetime_enabled ? "Disable onetime password" : "Enable onetime password")}</li>
|
||||
<li #activate-onetime-password disabled={ !random_enabled || !onetime_enabled || onetime_activated ? "true" : "false" }>{translate('Activate onetime password')}</li>
|
||||
<div .separator />
|
||||
<VerificationMethodMenu />
|
||||
<div .separator />
|
||||
<li #set-password disabled={ security_enabled ? "false" : "true" }>{translate('Set security password')}</li>
|
||||
<div .separator />
|
||||
<RandomPasswordUpdateMethodMenu />
|
||||
</menu></popup>;
|
||||
}
|
||||
|
||||
event click $(li#refresh-password) {
|
||||
handler.update_password("");
|
||||
this.update();
|
||||
event click $(svg#edit) (_, me) {
|
||||
randomPasswordUpdateMethodMenu.update({show: true });
|
||||
verificationMethodMenu.update({show: true });
|
||||
var menu = $(menu#edit-password-context);
|
||||
me.popup(menu);
|
||||
}
|
||||
|
||||
event click $(li#set-password) {
|
||||
@@ -862,12 +965,36 @@ class Password: Reactor.Component {
|
||||
if (p0 != p1) {
|
||||
return translate("The confirmation is not identical.");
|
||||
}
|
||||
handler.update_password(p0);
|
||||
handler.set_security_password(p0);
|
||||
me.update();
|
||||
});
|
||||
}
|
||||
|
||||
event click $(li#enable-onetime-password) {
|
||||
var onetime_enabled = handler.is_onetime_password_enabled();
|
||||
handler.set_onetime_password_enabled(!onetime_enabled);
|
||||
passwordArea.update();
|
||||
}
|
||||
|
||||
event click $(li#activate-onetime-password) {
|
||||
handler.set_onetime_password_activated(true);
|
||||
passwordArea.update();
|
||||
}
|
||||
}
|
||||
|
||||
var last_password_description = "";
|
||||
function updatePasswordArea() {
|
||||
self.timer(1s, function() {
|
||||
var description = handler.password_description();
|
||||
if (last_password_description != description) {
|
||||
last_password_description = description
|
||||
passwordArea.update();
|
||||
}
|
||||
updatePasswordArea();
|
||||
});
|
||||
}
|
||||
updatePasswordArea();
|
||||
|
||||
class ID: Reactor.Component {
|
||||
function render() {
|
||||
return <input type="text" #remote_id .outline-focus novalue={translate("Enter Remote ID")} maxlength="21"
|
||||
|
||||
Reference in New Issue
Block a user