sciter 2fa setting (#6951)

not add qr code text line as it's not selectable, and selectable input will steal the focus.

Signed-off-by: 21pages <pages21@163.com>
This commit is contained in:
21pages 2024-01-22 16:29:08 +08:00 committed by GitHub
parent b1a946ec20
commit 016f4abb32
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 112 additions and 12 deletions

33
Cargo.lock generated
View File

@ -3036,6 +3036,15 @@ version = "3.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62adaabb884c94955b19907d60019f4e145d091c75345379e70d1ee696f7854f"
[[package]]
name = "html-escape"
version = "0.2.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6d1ad449764d627e22bfd7cd5e8868264fc9236e07c752972b4080cd351cb476"
dependencies = [
"utf8-width",
]
[[package]]
name = "http"
version = "0.2.9"
@ -4828,6 +4837,23 @@ dependencies = [
"bytemuck",
]
[[package]]
name = "qrcode-generator"
version = "4.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d06cb9646c7a14096231a2474d7f21e5e8c13de090c68d13bde6157cfe7f159"
dependencies = [
"html-escape",
"image",
"qrcodegen",
]
[[package]]
name = "qrcodegen"
version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4339fc7a1021c9c1621d87f5e3505f2805c8c105420ba2f2a4df86814590c142"
[[package]]
name = "quest"
version = "0.3.0"
@ -5436,6 +5462,7 @@ dependencies = [
"pam",
"parity-tokio-ipc",
"percent-encoding",
"qrcode-generator",
"rdev",
"repng",
"reqwest",
@ -6826,6 +6853,12 @@ dependencies = [
"byteorder",
]
[[package]]
name = "utf8-width"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "86bd8d4e895da8537e5315b8254664e6b769c4ff3db18321b297a1e7004392e3"
[[package]]
name = "utf8parse"
version = "0.2.1"

View File

@ -97,6 +97,7 @@ clipboard = { path = "libs/clipboard" }
ctrlc = "3.2"
arboard = { version = "3.2", features = ["wayland-data-control"] }
system_shutdown = "4.0"
qrcode-generator = "4.1"
[target.'cfg(target_os = "windows")'.dependencies]
winapi = { version = "0.3", features = ["winuser", "wincrypt", "shellscalingapi", "pdh", "synchapi", "memoryapi"] }

View File

@ -180,10 +180,7 @@ pub fn session_login(
}
}
pub fn session_send2fa(
session_id: SessionID,
code: String,
) {
pub fn session_send2fa(session_id: SessionID, code: String) {
if let Some(session) = sessions::get_session_by_session_id(&session_id) {
session.send2fa(code);
}
@ -2026,20 +2023,15 @@ pub fn main_supported_input_source() -> SyncReturn<String> {
}
pub fn main_generate2fa() -> String {
crate::auth_2fa::generate2fa()
generate2fa()
}
pub fn main_verify2fa(code: String) -> bool {
let res = crate::auth_2fa::verify2fa(code);
if res {
refresh_options();
}
res
verify2fa(code)
}
pub fn main_has_valid_2fa_sync() -> SyncReturn<bool> {
let raw = get_option("2fa");
SyncReturn(crate::auth_2fa::get_2fa(Some(raw)).is_some())
SyncReturn(has_valid_2fa())
}
#[cfg(target_os = "android")]

View File

@ -603,6 +603,28 @@ impl UI {
fn support_remove_wallpaper(&self) -> bool {
support_remove_wallpaper()
}
fn has_valid_2fa(&self) -> bool {
has_valid_2fa()
}
fn generate2fa(&self) -> String {
generate2fa()
}
pub fn verify2fa(&self, code: String) -> bool {
verify2fa(code)
}
fn generate_2fa_img_src(&self, data: String) -> String {
let v = qrcode_generator::to_png_to_vec(data, qrcode_generator::QrCodeEcc::Low, 64)
.unwrap_or_default();
let s = hbb_common::sodiumoxide::base64::encode(
v,
hbb_common::sodiumoxide::base64::Variant::Original,
);
format!("data:image/png;base64,{s}")
}
}
impl sciter::EventHandler for UI {
@ -690,6 +712,10 @@ impl sciter::EventHandler for UI {
fn handle_relay_id(String);
fn get_login_device_info();
fn support_remove_wallpaper();
fn has_valid_2fa();
fn generate2fa();
fn generate_2fa_img_src(String);
fn verify2fa(String);
}
}

View File

@ -912,6 +912,8 @@ class PasswordArea: Reactor.Component {
{ !show_password ? '' : <div .separator /> }
{ !show_password ? '' : <li #set-password disabled={ method == 'use-temporary-password' ? "true" : "false" }>{translate('Set permanent password')}</li> }
{ !show_password ? '' : <TemporaryPasswordLengthMenu /> }
<div .separator />
<li #tfa><span>{svg_checkmark}</span>{translate('enable-2fa-title')}</li>
</menu></popup>;
}
@ -927,11 +929,14 @@ class PasswordArea: Reactor.Component {
var pwd_id = handler.get_option('verification-method');
if (pwd_id != 'use-temporary-password' && pwd_id != 'use-permanent-password')
pwd_id = 'use-both-passwords';
var has_valid_2fa = handler.has_valid_2fa();
for (var el in this.$$(menu#edit-password-context>li)) {
if (el.id.indexOf("approve-mode-") == 0)
el.attributes.toggleClass("selected", el.id == mode_id);
if (el.id.indexOf("use-") == 0)
el.attributes.toggleClass("selected", el.id == pwd_id);
if (el.id == "tfa")
el.attributes.toggleClass("selected", has_valid_2fa);
}
}
@ -984,6 +989,32 @@ class PasswordArea: Reactor.Component {
passwordArea.update();
}
}
event click $(li#tfa) {
var me = this;
var has_valid_2fa = handler.has_valid_2fa();
if (has_valid_2fa) {
handler.set_option('2fa', '');
me.update();
} else {
var new2fa = handler.generate2fa();
var src = handler.generate_2fa_img_src(new2fa);
msgbox("custom-2fa-setting", translate('enable-2fa-title'),
<div .form>
<div>{translate('enable-2fa-desc')}</div>
<img src={src} />
<div .code><input name='code' type='text' .outline-focus /></div>
</div>
, "", function(res=null) {
if (!res) return;
if (!res.code) return;
if (!handler.verify2fa(res.code)) {
return translate('wrong-2fa-code');
}
me.update();
}, 320);
}
}
}
var password_cache = ["","","",""];

View File

@ -1301,3 +1301,20 @@ pub fn support_remove_wallpaper() -> bool {
#[cfg(not(any(target_os = "windows", target_os = "linux")))]
return false;
}
pub fn has_valid_2fa() -> bool {
let raw = get_option("2fa");
crate::auth_2fa::get_2fa(Some(raw)).is_some()
}
pub fn generate2fa() -> String {
crate::auth_2fa::generate2fa()
}
pub fn verify2fa(code: String) -> bool {
let res = crate::auth_2fa::verify2fa(code);
if res {
refresh_options();
}
res
}