From a84ee7a6ec9299b709683d1ea6eb9b959b721d6b Mon Sep 17 00:00:00 2001 From: fufesou Date: Sat, 22 Oct 2022 22:19:14 +0800 Subject: [PATCH] oidc: init debug Signed-off-by: fufesou --- Cargo.toml | 3 +- flutter/lib/desktop/widgets/login.dart | 338 +++++++++++--------- flutter/lib/mobile/pages/settings_page.dart | 6 +- flutter/lib/models/user_model.dart | 51 +-- src/flutter_ffi.rs | 8 +- src/hbbs_http.rs | 12 +- src/hbbs_http/account.rs | 109 ++++--- src/main.rs | 15 +- src/server.rs | 13 +- src/ui_interface.rs | 14 +- 10 files changed, 322 insertions(+), 247 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 9516d8526..1eb92c4e4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -66,8 +66,7 @@ errno = "0.2.8" rdev = { git = "https://github.com/asur4s/rdev" } url = { version = "2.1", features = ["serde"] } -[target.'cfg(not(target_os = "linux"))'.dependencies] -reqwest = { version = "0.11", features = ["json", "rustls-tls"], default-features=false } +reqwest = { version = "0.11", features = ["blocking", "json", "rustls-tls"], default-features=false } [target.'cfg(not(any(target_os = "android", target_os = "linux")))'.dependencies] cpal = "0.13.5" diff --git a/flutter/lib/desktop/widgets/login.dart b/flutter/lib/desktop/widgets/login.dart index dec304cda..5f849d822 100644 --- a/flutter/lib/desktop/widgets/login.dart +++ b/flutter/lib/desktop/widgets/login.dart @@ -2,15 +2,12 @@ import 'dart:async'; import 'dart:convert'; import 'package:flutter/material.dart'; -import 'package:flutter_hbb/consts.dart'; import 'package:flutter_hbb/models/platform_model.dart'; import 'package:get/get.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:url_launcher/url_launcher.dart'; -import 'package:url_launcher/url_launcher_string.dart'; import '../../common.dart'; -import '../widgets/button.dart'; class _IconOP extends StatelessWidget { final String icon; @@ -92,10 +89,12 @@ class ConfigOP { class WidgetOP extends StatefulWidget { final ConfigOP config; final RxString curOP; + final Function(String) cbLogin; const WidgetOP({ Key? key, required this.config, required this.curOP, + required this.cbLogin, }) : super(key: key); @override @@ -107,9 +106,8 @@ class WidgetOP extends StatefulWidget { class _WidgetOPState extends State { Timer? _updateTimer; String _stateMsg = ''; - String _stateFailedMsg = ''; + String _FailedMsg = ''; String _url = ''; - String _username = ''; @override void initState() { @@ -138,17 +136,28 @@ class _WidgetOPState extends State { return; } final String stateMsg = resultMap['state_msg']; - final String failedMsg = resultMap['failed_msg']; - // to-do: test null url - final String url = resultMap['url']; - if (_stateMsg != stateMsg) { - if (_url.isEmpty && url.isNotEmpty) { + String failedMsg = resultMap['failed_msg']; + final String? url = resultMap['url']; + final authBody = resultMap['auth_body']; + if (_stateMsg != stateMsg || _FailedMsg != failedMsg) { + if (_url.isEmpty && url != null && url.isNotEmpty) { launchUrl(Uri.parse(url)); _url = url; } + if (authBody != null) { + _updateTimer?.cancel(); + final String username = authBody['user']['name']; + widget.curOP.value = ''; + widget.cbLogin(username); + } + setState(() { _stateMsg = stateMsg; - _stateFailedMsg = failedMsg; + _FailedMsg = failedMsg; + if (failedMsg.isNotEmpty) { + widget.curOP.value = ''; + _updateTimer?.cancel(); + } }); } }); @@ -156,74 +165,95 @@ class _WidgetOPState extends State { _resetState() { _stateMsg = ''; - _stateFailedMsg = ''; + _FailedMsg = ''; _url = ''; - _username = ''; } @override Widget build(BuildContext context) { - return ConstrainedBox( - constraints: const BoxConstraints(minWidth: 500), - child: Column( - children: [ - ButtonOP( - op: widget.config.op, - curOP: widget.curOP, - iconWidth: widget.config.iconWidth, - primaryColor: str2color(widget.config.op, 0x7f), - height: 40, - onTap: () { - widget.curOP.value = widget.config.op; - bind.mainAccountAuth(op: widget.config.op); - _beginQueryState(); - }, - ), - Obx(() => Offstage( - offstage: widget.curOP.value != widget.config.op, - child: Text( - _stateMsg, - style: TextStyle(fontSize: 12), - ))), - Obx( - () => Offstage( - offstage: widget.curOP.value != widget.config.op, - child: const SizedBox( - height: 5.0, - ), - ), - ), - Obx( - () => Offstage( - offstage: widget.curOP.value != widget.config.op, - child: ConstrainedBox( - constraints: BoxConstraints(maxHeight: 20), - child: ElevatedButton( - onPressed: () { - widget.curOP.value = ''; - _updateTimer?.cancel(); - _resetState(); - }, - child: Text( - translate('Cancel'), - style: TextStyle(fontSize: 15), + return Column( + children: [ + ButtonOP( + op: widget.config.op, + curOP: widget.curOP, + iconWidth: widget.config.iconWidth, + primaryColor: str2color(widget.config.op, 0x7f), + height: 40, + onTap: () async { + _resetState(); + widget.curOP.value = widget.config.op; + await bind.mainAccountAuth(op: widget.config.op); + _beginQueryState(); + }, + ), + Obx(() { + if (widget.curOP.isNotEmpty && + widget.curOP.value != widget.config.op) { + _FailedMsg = ''; + } + return Offstage( + offstage: + _FailedMsg.isEmpty && widget.curOP.value != widget.config.op, + child: Row( + children: [ + Text( + _stateMsg, + style: TextStyle(fontSize: 12), + ), + SizedBox(width: 8), + Text( + _FailedMsg, + style: TextStyle( + fontSize: 14, + color: Colors.red, ), ), + ], + )); + }), + Obx( + () => Offstage( + offstage: widget.curOP.value != widget.config.op, + child: const SizedBox( + height: 5.0, + ), + ), + ), + Obx( + () => Offstage( + offstage: widget.curOP.value != widget.config.op, + child: ConstrainedBox( + constraints: BoxConstraints(maxHeight: 20), + child: ElevatedButton( + onPressed: () { + widget.curOP.value = ''; + _updateTimer?.cancel(); + _resetState(); + bind.mainAccountAuthCancel(); + }, + child: Text( + translate('Cancel'), + style: TextStyle(fontSize: 15), ), ), ), - ], - )); + ), + ), + ], + ); } } class LoginWidgetOP extends StatelessWidget { final List ops; - final RxString curOP = ''.obs; + final RxString curOP; + final Function(String) cbLogin; LoginWidgetOP({ Key? key, required this.ops, + required this.curOP, + required this.cbLogin, }) : super(key: key); @override @@ -233,6 +263,7 @@ class LoginWidgetOP extends StatelessWidget { WidgetOP( config: op, curOP: curOP, + cbLogin: cbLogin, ), const Divider() ]) @@ -256,6 +287,7 @@ class LoginWidgetUserPass extends StatelessWidget { final String usernameMsg; final String passMsg; final bool isInProgress; + final RxString curOP; final Function(String, String) onLogin; const LoginWidgetUserPass({ Key? key, @@ -264,6 +296,7 @@ class LoginWidgetUserPass extends StatelessWidget { required this.usernameMsg, required this.passMsg, required this.isInProgress, + required this.curOP, required this.onLogin, }) : super(key: key); @@ -271,86 +304,90 @@ class LoginWidgetUserPass extends StatelessWidget { Widget build(BuildContext context) { var userController = TextEditingController(text: username); var pwdController = TextEditingController(text: pass); - return ConstrainedBox( - constraints: const BoxConstraints(minWidth: 500), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const SizedBox( - height: 8.0, - ), - Row( - children: [ - ConstrainedBox( - constraints: const BoxConstraints(minWidth: 100), - child: Text( - '${translate("Username")}:', - textAlign: TextAlign.start, - ).marginOnly(bottom: 16.0)), - const SizedBox( - width: 24.0, - ), - Expanded( - child: TextField( - decoration: InputDecoration( - border: const OutlineInputBorder(), - errorText: usernameMsg.isNotEmpty ? usernameMsg : null), - controller: userController, - focusNode: FocusNode()..requestFocus(), - ), - ), - ], - ), - const SizedBox( - height: 8.0, - ), - Row( - children: [ - ConstrainedBox( - constraints: const BoxConstraints(minWidth: 100), - child: Text('${translate("Password")}:') - .marginOnly(bottom: 16.0)), - const SizedBox( - width: 24.0, - ), - Expanded( - child: TextField( - obscureText: true, - decoration: InputDecoration( - border: const OutlineInputBorder(), - errorText: passMsg.isNotEmpty ? passMsg : null), - controller: pwdController, - ), - ), - ], - ), - const SizedBox( - height: 4.0, - ), - Offstage( - offstage: !isInProgress, child: const LinearProgressIndicator()), - const SizedBox( - height: 12.0, - ), - Row(children: [ + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const SizedBox( + height: 8.0, + ), + Row( + children: [ + ConstrainedBox( + constraints: const BoxConstraints(minWidth: 100), + child: Text( + '${translate("Username")}:', + textAlign: TextAlign.start, + ).marginOnly(bottom: 16.0)), + const SizedBox( + width: 24.0, + ), Expanded( - child: Container( - height: 50, - padding: const EdgeInsets.fromLTRB(10, 0, 10, 0), - child: ElevatedButton( - child: const Text( - 'Login', - style: TextStyle(fontSize: 18), - ), - onPressed: () { - onLogin(userController.text, pwdController.text); - }, - ), + child: TextField( + decoration: InputDecoration( + border: const OutlineInputBorder(), + errorText: usernameMsg.isNotEmpty ? usernameMsg : null), + controller: userController, + focusNode: FocusNode()..requestFocus(), ), ), - ]), - ], - ), + ], + ), + const SizedBox( + height: 8.0, + ), + Row( + children: [ + ConstrainedBox( + constraints: const BoxConstraints(minWidth: 100), + child: + Text('${translate("Password")}:').marginOnly(bottom: 16.0)), + const SizedBox( + width: 24.0, + ), + Expanded( + child: TextField( + obscureText: true, + decoration: InputDecoration( + border: const OutlineInputBorder(), + errorText: passMsg.isNotEmpty ? passMsg : null), + controller: pwdController, + ), + ), + ], + ), + const SizedBox( + height: 4.0, + ), + Offstage( + offstage: !isInProgress, child: const LinearProgressIndicator()), + const SizedBox( + height: 12.0, + ), + Row(children: [ + Expanded( + child: Container( + height: 50, + padding: const EdgeInsets.fromLTRB(10, 0, 10, 0), + child: Obx(() => ElevatedButton( + style: curOP.value.isEmpty || curOP.value == 'rustdesk' + ? null + : ElevatedButton.styleFrom( + primary: Colors.grey, + ), + child: const Text( + 'Login', + style: TextStyle(fontSize: 18), + ), + onPressed: curOP.value.isEmpty || curOP.value == 'rustdesk' + ? () { + onLogin(userController.text, pwdController.text); + } + : null, + )), + ), + ), + ]), + ], ); } } @@ -364,6 +401,7 @@ Future loginDialog() async { var passMsg = ''; var isInProgress = false; var completer = Completer(); + final RxString curOP = ''.obs; gFFI.dialogManager.show((setState, close) { cancel() { @@ -379,6 +417,7 @@ Future loginDialog() async { isInProgress = true; }); cancel() { + curOP.value = ''; if (isInProgress) { setState(() { isInProgress = false; @@ -386,17 +425,16 @@ Future loginDialog() async { } } + curOP.value = 'rustdesk'; username = username0; pass = pass0; if (username.isEmpty) { usernameMsg = translate('Username missed'); - debugPrint('REMOVE ME ====================== username empty'); cancel(); return; } if (pass.isEmpty) { passMsg = translate('Password missed'); - debugPrint('REMOVE ME ====================== password empty'); cancel(); return; } @@ -404,7 +442,6 @@ Future loginDialog() async { final resp = await gFFI.userModel.login(username, pass); if (resp.containsKey('error')) { passMsg = resp['error']; - debugPrint('REMOVE ME ====================== password error'); cancel(); return; } @@ -414,8 +451,6 @@ Future loginDialog() async { completer.complete(true); } catch (err) { debugPrint(err.toString()); - debugPrint( - 'REMOVE ME ====================== login error ${err.toString()}'); cancel(); return; } @@ -438,6 +473,7 @@ Future loginDialog() async { usernameMsg: usernameMsg, passMsg: passMsg, isInProgress: isInProgress, + curOP: curOP, onLogin: onLogin, ), const SizedBox( @@ -451,11 +487,19 @@ Future loginDialog() async { const SizedBox( height: 8.0, ), - LoginWidgetOP(ops: [ - ConfigOP(op: 'Github', iconWidth: 24), - ConfigOP(op: 'Google', iconWidth: 24), - ConfigOP(op: 'Okta', iconWidth: 46), - ]), + LoginWidgetOP( + ops: [ + ConfigOP(op: 'Github', iconWidth: 24), + ConfigOP(op: 'Google', iconWidth: 24), + ConfigOP(op: 'Okta', iconWidth: 46), + ], + curOP: curOP, + cbLogin: (String username) { + gFFI.userModel.userName.value = username; + completer.complete(true); + close(); + }, + ), ], ), ), diff --git a/flutter/lib/mobile/pages/settings_page.dart b/flutter/lib/mobile/pages/settings_page.dart index 7a82bcdd8..269439b1d 100644 --- a/flutter/lib/mobile/pages/settings_page.dart +++ b/flutter/lib/mobile/pages/settings_page.dart @@ -291,12 +291,12 @@ class _SettingsState extends State with WidgetsBindingObserver { return SettingsList( sections: [ SettingsSection( - title: Text(translate("Account")), + title: Text(translate('Account')), tiles: [ SettingsTile.navigation( title: Obx(() => Text(gFFI.userModel.userName.value.isEmpty - ? translate("Login") - : '${translate("Logout")} (${gFFI.userModel.userName.value})')), + ? translate('Login') + : '${translate('Logout')} (${gFFI.userModel.userName.value})')), leading: Icon(Icons.person), onPressed: (context) { if (gFFI.userModel.userName.value.isEmpty) { diff --git a/flutter/lib/models/user_model.dart b/flutter/lib/models/user_model.dart index cfbe71cfe..d2e83990b 100644 --- a/flutter/lib/models/user_model.dart +++ b/flutter/lib/models/user_model.dart @@ -1,6 +1,7 @@ import 'dart:async'; import 'dart:convert'; +import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:http/http.dart' as http; @@ -9,7 +10,7 @@ import 'model.dart'; import 'platform_model.dart'; class UserModel { - var userName = "".obs; + var userName = ''.obs; WeakReference parent; UserModel(this.parent) { @@ -18,7 +19,7 @@ class UserModel { void refreshCurrentUser() async { await getUserName(); - final token = await bind.mainGetLocalOption(key: "access_token"); + final token = await bind.mainGetLocalOption(key: 'access_token'); if (token == '') return; final url = await bind.mainGetApiServer(); final body = { @@ -28,8 +29,8 @@ class UserModel { try { final response = await http.post(Uri.parse('$url/api/currentUser'), headers: { - "Content-Type": "application/json", - "Authorization": "Bearer $token" + 'Content-Type': 'application/json', + 'Authorization': 'Bearer $token' }, body: json.encode(body)); final status = response.statusCode; @@ -44,9 +45,9 @@ class UserModel { } void resetToken() async { - await bind.mainSetLocalOption(key: "access_token", value: ""); - await bind.mainSetLocalOption(key: "user_info", value: ""); - userName.value = ""; + await bind.mainSetLocalOption(key: 'access_token', value: ''); + await bind.mainSetLocalOption(key: 'user_info', value: ''); + userName.value = ''; } Future _parseResp(String body) async { @@ -57,13 +58,13 @@ class UserModel { } final token = data['access_token']; if (token != null) { - await bind.mainSetLocalOption(key: "access_token", value: token); + await bind.mainSetLocalOption(key: 'access_token', value: token); } final info = data['user']; if (info != null) { final value = json.encode(info); - await bind.mainSetOption(key: "user_info", value: value); - userName.value = info["name"]; + await bind.mainSetOption(key: 'user_info', value: value); + userName.value = info['name']; } return ''; } @@ -74,7 +75,7 @@ class UserModel { } final userInfo = await bind.mainGetLocalOption(key: 'user_info'); if (userInfo.trim().isEmpty) { - return ""; + return ''; } final m = jsonDecode(userInfo); if (m == null) { @@ -88,10 +89,10 @@ class UserModel { Future logOut() async { final tag = gFFI.dialogManager.showLoading(translate('Waiting')); final url = await bind.mainGetApiServer(); - final _ = await http.post(Uri.parse("$url/api/logout"), + final _ = await http.post(Uri.parse('$url/api/logout'), body: { - "id": await bind.mainGetMyId(), - "uuid": await bind.mainGetUuid(), + 'id': await bind.mainGetMyId(), + 'uuid': await bind.mainGetUuid(), }, headers: await getHttpHeaders()); await Future.wait([ @@ -100,30 +101,30 @@ class UserModel { bind.mainSetLocalOption(key: 'selected-tags', value: ''), ]); parent.target?.abModel.clear(); - userName.value = ""; + userName.value = ''; gFFI.dialogManager.dismissByTag(tag); } Future> login(String userName, String pass) async { final url = await bind.mainGetApiServer(); try { - final resp = await http.post(Uri.parse("$url/api/login"), - headers: {"Content-Type": "application/json"}, + final resp = await http.post(Uri.parse('$url/api/login'), + headers: {'Content-Type': 'application/json'}, body: jsonEncode({ - "username": userName, - "password": pass, - "id": await bind.mainGetMyId(), - "uuid": await bind.mainGetUuid() + 'username': userName, + 'password': pass, + 'id': await bind.mainGetMyId(), + 'uuid': await bind.mainGetUuid() })); final body = jsonDecode(resp.body); bind.mainSetLocalOption( - key: "access_token", value: body['access_token'] ?? ""); + key: 'access_token', value: body['access_token'] ?? ''); bind.mainSetLocalOption( - key: "user_info", value: jsonEncode(body['user'])); - this.userName.value = body['user']?['name'] ?? ""; + key: 'user_info', value: jsonEncode(body['user'])); + this.userName.value = body['user']?['name'] ?? ''; return body; } catch (err) { - return {"error": "$err"}; + return {'error': '$err'}; } } } diff --git a/src/flutter_ffi.rs b/src/flutter_ffi.rs index 937c108ed..9552bd36e 100644 --- a/src/flutter_ffi.rs +++ b/src/flutter_ffi.rs @@ -1085,7 +1085,13 @@ pub fn install_install_path() -> SyncReturn { } pub fn main_account_auth(op: String) { - account_auth(op); + let id = get_id(); + let uuid = get_uuid(); + account_auth(op, id, uuid); +} + +pub fn main_account_auth_cancel() { + account_auth_cancel() } pub fn main_account_auth_result() -> String { diff --git a/src/hbbs_http.rs b/src/hbbs_http.rs index b0e8cdbab..4360b6e8c 100644 --- a/src/hbbs_http.rs +++ b/src/hbbs_http.rs @@ -2,13 +2,14 @@ use hbb_common::{ anyhow::{self, bail}, tokio, ResultType, }; -use reqwest::Response; +use reqwest::blocking::Response; +use serde::de::DeserializeOwned; use serde_derive::Deserialize; use serde_json::{Map, Value}; -use serde::de::DeserializeOwned; pub mod account; +#[derive(Debug)] pub enum HbbHttpResponse { ErrorFormat, Error(String), @@ -16,16 +17,11 @@ pub enum HbbHttpResponse { Data(T), } -#[tokio::main(flavor = "current_thread")] -async fn resp_to_serde_map(resp: Response) -> reqwest::Result> { - resp.json().await -} - impl TryFrom for HbbHttpResponse { type Error = reqwest::Error; fn try_from(resp: Response) -> Result>::Error> { - let map = resp_to_serde_map(resp)?; + let map = resp.json::>()?; if let Some(error) = map.get("error") { if let Some(err) = error.as_str() { Ok(Self::Error(err.to_owned())) diff --git a/src/hbbs_http/account.rs b/src/hbbs_http/account.rs index 4a2e365f4..cdf724971 100644 --- a/src/hbbs_http/account.rs +++ b/src/hbbs_http/account.rs @@ -1,9 +1,13 @@ use super::HbbHttpResponse; -use hbb_common::{config::Config, log, sleep, tokio, tokio::sync::RwLock, ResultType}; +use hbb_common::{ + config::{Config, LocalConfig}, + log, sleep, tokio, ResultType, +}; +use reqwest::blocking::Client; use serde_derive::{Deserialize, Serialize}; use std::{ collections::HashMap, - sync::Arc, + sync::{Arc, RwLock}, time::{Duration, Instant}, }; use url::Url; @@ -15,12 +19,12 @@ lazy_static::lazy_static! { } const QUERY_INTERVAL_SECS: f32 = 1.0; -const QUERY_TIMEOUT_SECS: u64 = 60; +const QUERY_TIMEOUT_SECS: u64 = 60 * 3; const REQUESTING_ACCOUNT_AUTH: &str = "Requesting account auth"; const WAITING_ACCOUNT_AUTH: &str = "Waiting account auth"; const LOGIN_ACCOUNT_AUTH: &str = "Login account auth"; -#[derive(Deserialize, Clone)] +#[derive(Deserialize, Clone, Debug)] pub struct OidcAuthUrl { code: String, url: Url, @@ -45,7 +49,7 @@ pub struct AuthBody { } pub struct OidcSession { - client: reqwest::Client, + client: Client, state_msg: &'static str, failed_msg: String, code_url: Option, @@ -66,7 +70,7 @@ pub struct AuthResult { impl OidcSession { fn new() -> Self { Self { - client: reqwest::Client::new(), + client: Client::new(), state_msg: REQUESTING_ACCOUNT_AUTH, failed_msg: "".to_owned(), code_url: None, @@ -77,30 +81,28 @@ impl OidcSession { } } - async fn auth(op: &str, id: &str, uuid: &str) -> ResultType> { + fn auth(op: &str, id: &str, uuid: &str) -> ResultType> { Ok(OIDC_SESSION .read() - .await + .unwrap() .client .post(format!("{}/api/oidc/auth", *API_SERVER)) .json(&HashMap::from([("op", op), ("id", id), ("uuid", uuid)])) - .send() - .await? + .send()? .try_into()?) } - async fn query(code: &str, id: &str, uuid: &str) -> ResultType> { + fn query(code: &str, id: &str, uuid: &str) -> ResultType> { let url = reqwest::Url::parse_with_params( &format!("{}/api/oidc/auth-query", *API_SERVER), &[("code", code), ("id", id), ("uuid", uuid)], )?; Ok(OIDC_SESSION .read() - .await + .unwrap() .client .get(url) - .send() - .await? + .send()? .try_into()?) } @@ -113,36 +115,42 @@ impl OidcSession { self.auth_body = None; } - async fn before_task(&mut self) { + fn before_task(&mut self) { self.reset(); self.running = true; } - async fn after_task(&mut self) { + fn after_task(&mut self) { self.running = false; } - async fn auth_task(op: String, id: String, uuid: String) { - let code_url = match Self::auth(&op, &id, &uuid).await { + fn sleep(secs: f32) { + std::thread::sleep(std::time::Duration::from_secs_f32(secs)); + } + + fn auth_task(op: String, id: String, uuid: String) { + let auth_request_res = Self::auth(&op, &id, &uuid); + log::info!("Request oidc auth result: {:?}", &auth_request_res); + let code_url = match auth_request_res { Ok(HbbHttpResponse::<_>::Data(code_url)) => code_url, Ok(HbbHttpResponse::<_>::Error(err)) => { OIDC_SESSION .write() - .await + .unwrap() .set_state(REQUESTING_ACCOUNT_AUTH, err); return; } Ok(_) => { OIDC_SESSION .write() - .await + .unwrap() .set_state(REQUESTING_ACCOUNT_AUTH, "Invalid auth response".to_owned()); return; } Err(err) => { OIDC_SESSION .write() - .await + .unwrap() .set_state(REQUESTING_ACCOUNT_AUTH, err.to_string()); return; } @@ -150,22 +158,29 @@ impl OidcSession { OIDC_SESSION .write() - .await + .unwrap() .set_state(WAITING_ACCOUNT_AUTH, "".to_owned()); - OIDC_SESSION.write().await.code_url = Some(code_url.clone()); + OIDC_SESSION.write().unwrap().code_url = Some(code_url.clone()); let begin = Instant::now(); - let query_timeout = OIDC_SESSION.read().await.query_timeout; - while OIDC_SESSION.read().await.keep_querying && begin.elapsed() < query_timeout { - match Self::query(&code_url.code, &id, &uuid).await { + let query_timeout = OIDC_SESSION.read().unwrap().query_timeout; + while OIDC_SESSION.read().unwrap().keep_querying && begin.elapsed() < query_timeout { + match Self::query(&code_url.code, &id, &uuid) { Ok(HbbHttpResponse::<_>::Data(auth_body)) => { + LocalConfig::set_option( + "access_token".to_owned(), + auth_body.access_token.clone(), + ); + LocalConfig::set_option( + "user_info".to_owned(), + serde_json::to_string(&auth_body.user).unwrap_or_default(), + ); OIDC_SESSION .write() - .await + .unwrap() .set_state(LOGIN_ACCOUNT_AUTH, "".to_owned()); - OIDC_SESSION.write().await.auth_body = Some(auth_body); + OIDC_SESSION.write().unwrap().auth_body = Some(auth_body); return; - // to-do, set access-token } Ok(HbbHttpResponse::<_>::Error(err)) => { if err.contains("No authed oidc is found") { @@ -173,7 +188,7 @@ impl OidcSession { } else { OIDC_SESSION .write() - .await + .unwrap() .set_state(WAITING_ACCOUNT_AUTH, err); return; } @@ -186,13 +201,13 @@ impl OidcSession { // ignore } } - sleep(QUERY_INTERVAL_SECS).await; + Self::sleep(QUERY_INTERVAL_SECS); } if begin.elapsed() >= query_timeout { OIDC_SESSION .write() - .await + .unwrap() .set_state(WAITING_ACCOUNT_AUTH, "timeout".to_owned()); } @@ -204,20 +219,20 @@ impl OidcSession { self.failed_msg = failed_msg; } - pub async fn account_auth(op: String, id: String, uuid: String) { - if OIDC_SESSION.read().await.running { - OIDC_SESSION.write().await.keep_querying = false; - } + fn wait_stop_querying() { let wait_secs = 0.3; - sleep(wait_secs).await; - while OIDC_SESSION.read().await.running { - sleep(wait_secs).await; + while OIDC_SESSION.read().unwrap().running { + Self::sleep(wait_secs); } + } - tokio::spawn(async move { - OIDC_SESSION.write().await.before_task().await; - Self::auth_task(op, id, uuid).await; - OIDC_SESSION.write().await.after_task().await; + pub fn account_auth(op: String, id: String, uuid: String) { + Self::auth_cancel(); + Self::wait_stop_querying(); + OIDC_SESSION.write().unwrap().before_task(); + std::thread::spawn(|| { + Self::auth_task(op, id, uuid); + OIDC_SESSION.write().unwrap().after_task(); }); } @@ -230,7 +245,11 @@ impl OidcSession { } } - pub async fn get_result() -> AuthResult { - OIDC_SESSION.read().await.get_result_() + pub fn auth_cancel() { + OIDC_SESSION.write().unwrap().keep_querying = false; + } + + pub fn get_result() -> AuthResult { + OIDC_SESSION.read().unwrap().get_result_() } } diff --git a/src/main.rs b/src/main.rs index ac8fd5219..9c7170309 100644 --- a/src/main.rs +++ b/src/main.rs @@ -32,8 +32,8 @@ fn main() { if !common::global_init() { return; } - use hbb_common::log; use clap::App; + use hbb_common::log; let args = format!( "-p, --port-forward=[PORT-FORWARD-OPTIONS] 'Format: remote-id:local-port:remote-port[:remote-host]' -k, --key=[KEY] '' @@ -45,7 +45,7 @@ fn main() { .about("RustDesk command line tool") .args_from_usage(&args) .get_matches(); - use hbb_common::{env_logger::*, config::LocalConfig}; + use hbb_common::{config::LocalConfig, env_logger::*}; init_from_env(Env::default().filter_or(DEFAULT_FILTER_ENV, "info")); if let Some(p) = matches.value_of("port-forward") { let options: Vec = p.split(":").map(|x| x.to_owned()).collect(); @@ -73,7 +73,14 @@ fn main() { } let key = matches.value_of("key").unwrap_or("").to_owned(); let token = LocalConfig::get_option("access_token"); - cli::start_one_port_forward(options[0].clone(), port, remote_host, remote_port, key, token); + cli::start_one_port_forward( + options[0].clone(), + port, + remote_host, + remote_port, + key, + token, + ); } common::global_clean(); -} \ No newline at end of file +} diff --git a/src/server.rs b/src/server.rs index 58aab8fd1..04814db42 100644 --- a/src/server.rs +++ b/src/server.rs @@ -1,4 +1,5 @@ use crate::ipc::Data; +use bytes::Bytes; pub use connection::*; use hbb_common::{ allow_err, @@ -20,7 +21,6 @@ use std::{ sync::{Arc, Mutex, RwLock, Weak}, time::Duration, }; -use bytes::Bytes; pub mod audio_service; cfg_if::cfg_if! { @@ -140,7 +140,8 @@ pub async fn create_tcp_connection( .write_to_bytes() .unwrap_or_default(), &sk, - ).into(), + ) + .into(), ..Default::default() }); timeout(CONNECT_TIMEOUT, stream.send(&msg_out)).await??; @@ -310,9 +311,9 @@ pub fn check_zombie() { } /// Start the host server that allows the remote peer to control the current machine. -/// +/// /// # Arguments -/// +/// /// * `is_server` - Whether the current client is definitely the server. /// If true, the server will be started. /// Otherwise, client will check if there's already a server and start one if not. @@ -323,9 +324,9 @@ pub async fn start_server(is_server: bool) { } /// Start the host server that allows the remote peer to control the current machine. -/// +/// /// # Arguments -/// +/// /// * `is_server` - Whether the current client is definitely the server. /// If true, the server will be started. /// Otherwise, client will check if there's already a server and start one if not. diff --git a/src/ui_interface.rs b/src/ui_interface.rs index 78d9433b1..04ba90cb2 100644 --- a/src/ui_interface.rs +++ b/src/ui_interface.rs @@ -842,14 +842,16 @@ pub(crate) fn check_connect_status(reconnect: bool) -> mpsc::UnboundedSender String { - serde_json::to_string(&account::OidcSession::get_result().await).unwrap_or_default() +pub fn account_auth_cancel() { + account::OidcSession::auth_cancel(); +} + +pub fn account_auth_result() -> String { + serde_json::to_string(&account::OidcSession::get_result()).unwrap_or_default() } // notice: avoiding create ipc connecton repeatly,