From c3814c14cc15dac68611a2b05d7cb523309ce866 Mon Sep 17 00:00:00 2001 From: Fu Zi Xiang Date: Thu, 9 Nov 2023 21:55:16 +0800 Subject: [PATCH] fix: refactor and clean up test case --- libs/client-api/src/http.rs | 52 ++++++++----------------------------- tests/gotrue/admin.rs | 5 ++-- tests/user/sign_in.rs | 22 +++++++++++----- tests/user/utils.rs | 28 ++++++++++++++++++-- 4 files changed, 55 insertions(+), 52 deletions(-) diff --git a/libs/client-api/src/http.rs b/libs/client-api/src/http.rs index e329deda..f2c2629a 100644 --- a/libs/client-api/src/http.rs +++ b/libs/client-api/src/http.rs @@ -1,5 +1,5 @@ use crate::notify::{ClientToken, TokenStateReceiver}; -use anyhow::{anyhow, Context}; +use anyhow::Context; use prost::Message as ProstMessage; use app_error::AppError; @@ -23,7 +23,6 @@ use realtime_entity::EncodedCollabV1; use reqwest::header; use reqwest::Method; use reqwest::RequestBuilder; -use scraper::{Html, Selector}; use shared_entity::dto::auth_dto::SignInTokenResponse; use shared_entity::dto::auth_dto::UpdateUserParams; use shared_entity::dto::workspace_dto::{ @@ -231,39 +230,24 @@ impl Client { Ok(url.to_string()) } - /// Returns an OAuth URL by constructing the authorization URL for the specified provider. - /// The URL looks like, e.g., `appflowy-flutter://#access_token=...&expires_in=3600&provider_token=...&refresh_token=...&token_type=bearer`. - /// + /// This is only applicable if user token is with admin privilege. + /// This is typically used to generate a sign in url for another user, given the user's email. + /// User then click on the link in the browser, which calls gotrue authentication server, which + /// then redirects to the appflowy-flutter:// #[instrument(level = "debug", skip_all, err)] - pub async fn generate_sign_in_url_with_email( - &self, - admin_user_email: &str, - admin_user_password: &str, - user_email: &str, - ) -> Result { - let admin_token = self - .gotrue_client - .token(&Grant::Password(PasswordGrant { - email: admin_user_email.to_string(), - password: admin_user_password.to_string(), - })) - .await?; - + pub async fn generate_sign_in_url(&self, email: &str) -> Result { let admin_user_params: GenerateLinkParams = GenerateLinkParams { - email: user_email.to_string(), + email: email.to_string(), ..Default::default() }; let link_resp = self .gotrue_client - .admin_generate_link(&admin_token.access_token, &admin_user_params) + .admin_generate_link(&self.access_token()?, &admin_user_params) .await?; - assert_eq!(link_resp.email, user_email); + assert_eq!(link_resp.email, email); - let action_link = link_resp.action_link; - let resp = reqwest::Client::new().get(action_link).send().await?; - let resp_text = resp.text().await?; - Ok(extract_sign_in_url(&resp_text)?) + Ok(link_resp.action_link) } #[inline] @@ -1026,21 +1010,7 @@ impl Client { } } -pub fn extract_sign_in_url(html_str: &str) -> Result { - let fragment = Html::parse_fragment(html_str); - let selector = Selector::parse("a").unwrap(); - let url = fragment - .select(&selector) - .next() - .ok_or(anyhow!("no a tag found in html: {}", html_str))? - .value() - .attr("href") - .ok_or(anyhow!("no href found in html: {}", html_str))? - .to_string(); - Ok(url) -} - -pub fn url_missing_param(param: &str) -> AppResponseError { +fn url_missing_param(param: &str) -> AppResponseError { AppError::InvalidRequest(format!("Url Missing Parameter:{}", param)).into() } diff --git a/tests/gotrue/admin.rs b/tests/gotrue/admin.rs index 6e8206a8..58780b23 100644 --- a/tests/gotrue/admin.rs +++ b/tests/gotrue/admin.rs @@ -1,4 +1,3 @@ -use client_api::extract_sign_in_url; use gotrue::{ api::Client, grant::{Grant, PasswordGrant}, @@ -7,7 +6,7 @@ use gotrue::{ use crate::{ localhost_client, - user::utils::{generate_unique_email, ADMIN_USER}, + user::utils::{extract_sign_in_url, generate_unique_email, ADMIN_USER}, LOCALHOST_GOTRUE, }; @@ -152,7 +151,7 @@ async fn admin_generate_link_and_user_sign_in_and_invite() { .await .unwrap(); let resp_text = resp.text().await.unwrap(); - let appflowy_sign_in_url = extract_sign_in_url(&resp_text).unwrap(); + let appflowy_sign_in_url = extract_sign_in_url(&resp_text); let client = localhost_client(); let is_new = client diff --git a/tests/user/sign_in.rs b/tests/user/sign_in.rs index 7608c20d..3b9841e1 100644 --- a/tests/user/sign_in.rs +++ b/tests/user/sign_in.rs @@ -1,5 +1,8 @@ use crate::localhost_client; -use crate::user::utils::{generate_unique_email, generate_unique_registered_user, ADMIN_USER}; +use crate::user::utils::{ + extract_sign_in_url, generate_sign_in_url_for_email, generate_unique_email, + generate_unique_registered_user, +}; use app_error::ErrorCode; #[tokio::test] @@ -101,10 +104,17 @@ async fn sign_in_with_invalid_url() { #[tokio::test] async fn sign_in_with_url() { let c = localhost_client(); - let user_email = generate_unique_email(); - let url_str = c - .generate_sign_in_url_with_email(&ADMIN_USER.email, &ADMIN_USER.password, &user_email) + let email = generate_unique_email(); + let gotrue_url = generate_sign_in_url_for_email(&email) .await - .unwrap(); - let _ = c.sign_in_with_url(&url_str).await.unwrap(); + .replacen("/gotrue", "", 1); // compabilitiy with local testing + println!("url: {}", gotrue_url); + + // simulating url click + let resp = reqwest::Client::new().get(gotrue_url).send().await.unwrap(); + let resp_text = resp.text().await.unwrap(); + let sign_in_url = extract_sign_in_url(&resp_text); + + // simulating back to the app with url + let _ = c.sign_in_with_url(&sign_in_url).await.unwrap(); } diff --git a/tests/user/utils.rs b/tests/user/utils.rs index 501fb3af..c0e4032e 100644 --- a/tests/user/utils.rs +++ b/tests/user/utils.rs @@ -1,5 +1,6 @@ use client_api::Client; use dotenv::dotenv; +use scraper::{Html, Selector}; use sqlx::types::Uuid; use lazy_static::lazy_static; @@ -27,13 +28,17 @@ pub fn generate_unique_email() -> String { format!("user_{}@appflowy.io", Uuid::new_v4()) } -pub async fn generate_unique_registered_user() -> User { - // log in as admin +pub async fn admin_user_client() -> Client { let admin_client = localhost_client(); admin_client .sign_in_password(&ADMIN_USER.email, &ADMIN_USER.password) .await .unwrap(); + admin_client +} + +pub async fn generate_unique_registered_user() -> User { + let admin_client = admin_user_client().await; // create new user let email = generate_unique_email(); @@ -59,3 +64,22 @@ pub async fn generate_unique_registered_user_client() -> (Client, User) { .unwrap(); (registered_user_client, registered_user) } + +pub async fn generate_sign_in_url_for_email(email: &str) -> String { + setup_log(); + let admin_client = admin_user_client().await; + admin_client.generate_sign_in_url(email).await.unwrap() +} + +pub fn extract_sign_in_url(html_str: &str) -> String { + let fragment = Html::parse_fragment(html_str); + let selector = Selector::parse("a").unwrap(); + fragment + .select(&selector) + .next() + .unwrap() + .value() + .attr("href") + .unwrap() + .to_string() +}