feat: support subscribe token (#464)
* feat: support subscribe token * feat: support get collab * feat: support browser rule for get collab * fix: update collab version
This commit is contained in:
parent
3901356e8a
commit
5041f9f164
|
|
@ -8,12 +8,26 @@ on:
|
||||||
required: true
|
required: true
|
||||||
default: 'libs/client-api-wasm'
|
default: 'libs/client-api-wasm'
|
||||||
package_name:
|
package_name:
|
||||||
description: 'Package name'
|
description: 'Which package to publish'
|
||||||
required: true
|
required: true
|
||||||
default: '@appflowyinc/client-api-wasm'
|
default: '@appflowyinc/client-api-wasm'
|
||||||
|
type: choice
|
||||||
|
options:
|
||||||
|
- '@appflowyinc/client-api-wasm'
|
||||||
package_version:
|
package_version:
|
||||||
description: 'Package version'
|
description: 'Package version'
|
||||||
required: true
|
required: true
|
||||||
|
prerelease_preid:
|
||||||
|
description: 'Preid for prerelease version (e.g., alpha, beta, rc)'
|
||||||
|
required: false
|
||||||
|
type: choice
|
||||||
|
default: ''
|
||||||
|
options:
|
||||||
|
- ''
|
||||||
|
- 'alpha'
|
||||||
|
- 'beta'
|
||||||
|
- 'rc'
|
||||||
|
|
||||||
env:
|
env:
|
||||||
NODE_VERSION: '20.12.0'
|
NODE_VERSION: '20.12.0'
|
||||||
RUST_TOOLCHAIN: "1.75"
|
RUST_TOOLCHAIN: "1.75"
|
||||||
|
|
@ -43,11 +57,18 @@ jobs:
|
||||||
run: wasm-pack build
|
run: wasm-pack build
|
||||||
working-directory: ${{ github.event.inputs.working_directory }}
|
working-directory: ${{ github.event.inputs.working_directory }}
|
||||||
|
|
||||||
- name: Update package.json
|
- name: Update name
|
||||||
|
working-directory: ${{ github.event.inputs.working_directory }}/pkg
|
||||||
run: |
|
run: |
|
||||||
cd ${{ github.event.inputs.working_directory }}/pkg
|
jq '.name = "${{ github.event.inputs.package_name }}"' package.json > package.json.tmp
|
||||||
jq '.name = "${{ github.event.inputs.package_name }}" | .version = "${{ github.event.inputs.package_version }}"' package.json > package.json.tmp
|
|
||||||
mv package.json.tmp package.json
|
mv package.json.tmp package.json
|
||||||
|
- name: Update version
|
||||||
|
working-directory: ${{ github.event.inputs.working_directory }}/pkg
|
||||||
|
run: |
|
||||||
|
npm version ${{ github.event.inputs.package_version }}
|
||||||
|
if [ "${{ github.event.inputs.prerelease_preid }}" != "" ]; then
|
||||||
|
npm version prerelease --preid ${{ github.event.inputs.prerelease_preid }}
|
||||||
|
fi
|
||||||
|
|
||||||
- name: Configure npm for wasm-pack
|
- name: Configure npm for wasm-pack
|
||||||
run: echo "//registry.npmjs.org/:_authToken=${{ secrets.NPM_TOKEN }}" > ${{ github.event.inputs.working_directory }}/pkg/.npmrc
|
run: echo "//registry.npmjs.org/:_authToken=${{ secrets.NPM_TOKEN }}" > ${{ github.event.inputs.working_directory }}/pkg/.npmrc
|
||||||
|
|
|
||||||
|
|
@ -1510,11 +1510,17 @@ dependencies = [
|
||||||
name = "client-api-wasm"
|
name = "client-api-wasm"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"bytes",
|
||||||
"client-api",
|
"client-api",
|
||||||
|
"collab-entity",
|
||||||
|
"collab-rt-entity",
|
||||||
"console_error_panic_hook",
|
"console_error_panic_hook",
|
||||||
|
"database-entity",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"serde",
|
"serde",
|
||||||
|
"serde-wasm-bindgen",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
"serde_repr",
|
||||||
"tracing",
|
"tracing",
|
||||||
"tracing-core",
|
"tracing-core",
|
||||||
"tracing-wasm",
|
"tracing-wasm",
|
||||||
|
|
@ -5076,6 +5082,17 @@ dependencies = [
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde-wasm-bindgen"
|
||||||
|
version = "0.6.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8302e169f0eddcc139c70f139d19d6467353af16f9fce27e8c30158036a1e16b"
|
||||||
|
dependencies = [
|
||||||
|
"js-sys",
|
||||||
|
"serde",
|
||||||
|
"wasm-bindgen",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_derive"
|
name = "serde_derive"
|
||||||
version = "1.0.197"
|
version = "1.0.197"
|
||||||
|
|
|
||||||
|
|
@ -15,18 +15,23 @@ wasm-bindgen = "0.2.84"
|
||||||
# all the `std::fmt` and `std::panicking` infrastructure, so isn't great for
|
# all the `std::fmt` and `std::panicking` infrastructure, so isn't great for
|
||||||
# code size when deploying.
|
# code size when deploying.
|
||||||
console_error_panic_hook = { version = "0.1.7", optional = true }
|
console_error_panic_hook = { version = "0.1.7", optional = true }
|
||||||
serde = "1.0.197"
|
serde = { version = "1.0.197", features = ["derive"] }
|
||||||
serde_json = "1.0.64"
|
serde_json = "1.0.64"
|
||||||
client-api = { path = "../client-api" }
|
client-api = { path = "../client-api" }
|
||||||
lazy_static = "1.4.0"
|
lazy_static = "1.4.0"
|
||||||
wasm-bindgen-futures = "0.4.20"
|
wasm-bindgen-futures = "0.4.20"
|
||||||
tsify = "0.4.5"
|
tsify = "0.4.5"
|
||||||
tracing.workspace = true
|
tracing.workspace = true
|
||||||
|
bytes.workspace = true
|
||||||
tracing-core = { version = "0.1.32" }
|
tracing-core = { version = "0.1.32" }
|
||||||
tracing-wasm = "0.2.1"
|
tracing-wasm = "0.2.1"
|
||||||
uuid.workspace = true
|
uuid.workspace = true
|
||||||
|
database-entity.workspace = true
|
||||||
|
collab-rt-entity.workspace = true
|
||||||
|
collab-entity.workspace = true
|
||||||
|
serde_repr = "0.1.18"
|
||||||
wee_alloc = { version = "0.4.5", optional = true }
|
wee_alloc = { version = "0.4.5", optional = true }
|
||||||
|
serde-wasm-bindgen = "0.6.5"
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
wasm-bindgen-test = "0.3.34"
|
wasm-bindgen-test = "0.3.34"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,10 @@
|
||||||
use client_api::error::ErrorCode;
|
use client_api::entity::AFUserProfile;
|
||||||
|
use client_api::error::{AppResponseError, ErrorCode};
|
||||||
|
use collab_entity::CollabType;
|
||||||
|
use collab_rt_entity::EncodedCollab;
|
||||||
|
use database_entity::dto::{QueryCollab, QueryCollabParams};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
use serde_repr::{Deserialize_repr, Serialize_repr};
|
||||||
use tsify::Tsify;
|
use tsify::Tsify;
|
||||||
use wasm_bindgen::JsValue;
|
use wasm_bindgen::JsValue;
|
||||||
|
|
||||||
|
|
@ -7,7 +12,13 @@ macro_rules! from_struct_for_jsvalue {
|
||||||
($type:ty) => {
|
($type:ty) => {
|
||||||
impl From<$type> for JsValue {
|
impl From<$type> for JsValue {
|
||||||
fn from(value: $type) -> Self {
|
fn from(value: $type) -> Self {
|
||||||
JsValue::from_str(&serde_json::to_string(&value).unwrap())
|
match serde_wasm_bindgen::to_value(&value) {
|
||||||
|
Ok(js_value) => js_value,
|
||||||
|
Err(err) => {
|
||||||
|
tracing::error!("Failed to convert User to JsValue: {:?}", err);
|
||||||
|
JsValue::NULL
|
||||||
|
},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -39,3 +50,86 @@ pub struct ClientResponse {
|
||||||
}
|
}
|
||||||
|
|
||||||
from_struct_for_jsvalue!(ClientResponse);
|
from_struct_for_jsvalue!(ClientResponse);
|
||||||
|
impl From<AppResponseError> for ClientResponse {
|
||||||
|
fn from(err: AppResponseError) -> Self {
|
||||||
|
ClientResponse {
|
||||||
|
code: err.code,
|
||||||
|
message: err.message.to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Tsify, Serialize, Deserialize)]
|
||||||
|
#[tsify(into_wasm_abi, from_wasm_abi)]
|
||||||
|
pub struct User {
|
||||||
|
pub uid: String,
|
||||||
|
pub uuid: String,
|
||||||
|
pub email: Option<String>,
|
||||||
|
pub name: Option<String>,
|
||||||
|
pub latest_workspace_id: String,
|
||||||
|
pub icon_url: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
from_struct_for_jsvalue!(User);
|
||||||
|
impl From<AFUserProfile> for User {
|
||||||
|
fn from(profile: AFUserProfile) -> Self {
|
||||||
|
User {
|
||||||
|
uid: profile.uid.to_string(),
|
||||||
|
uuid: profile.uuid.to_string(),
|
||||||
|
email: profile.email,
|
||||||
|
name: profile.name,
|
||||||
|
latest_workspace_id: profile.latest_workspace_id.to_string(),
|
||||||
|
icon_url: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Tsify, Serialize, Deserialize, Default, Debug)]
|
||||||
|
#[tsify(into_wasm_abi, from_wasm_abi)]
|
||||||
|
pub struct ClientQueryCollabParams {
|
||||||
|
pub workspace_id: String,
|
||||||
|
pub object_id: String,
|
||||||
|
#[tsify(type = "0 | 1 | 2 | 3 | 4 | 5")]
|
||||||
|
pub collab_type: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Into<QueryCollabParams> for ClientQueryCollabParams {
|
||||||
|
fn into(self) -> QueryCollabParams {
|
||||||
|
QueryCollabParams {
|
||||||
|
workspace_id: self.workspace_id,
|
||||||
|
inner: QueryCollab {
|
||||||
|
collab_type: CollabType::from(self.collab_type),
|
||||||
|
object_id: self.object_id,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Tsify, Serialize, Deserialize, Default)]
|
||||||
|
#[tsify(into_wasm_abi, from_wasm_abi)]
|
||||||
|
pub struct ClientEncodeCollab {
|
||||||
|
pub state_vector: Vec<u8>,
|
||||||
|
pub doc_state: Vec<u8>,
|
||||||
|
#[serde(default)]
|
||||||
|
pub version: ClientEncoderVersion,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Tsify, Default, Serialize_repr, Deserialize_repr)]
|
||||||
|
#[repr(u8)]
|
||||||
|
pub enum ClientEncoderVersion {
|
||||||
|
#[default]
|
||||||
|
V1 = 0,
|
||||||
|
V2 = 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
from_struct_for_jsvalue!(ClientEncodeCollab);
|
||||||
|
|
||||||
|
impl From<EncodedCollab> for ClientEncodeCollab {
|
||||||
|
fn from(collab: EncodedCollab) -> Self {
|
||||||
|
ClientEncodeCollab {
|
||||||
|
state_vector: collab.state_vector.to_vec(),
|
||||||
|
doc_state: collab.doc_state.to_vec(),
|
||||||
|
version: ClientEncoderVersion::V1,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,11 @@
|
||||||
pub mod entities;
|
pub mod entities;
|
||||||
use crate::entities::{ClientAPIConfig, ClientResponse};
|
|
||||||
|
use crate::entities::*;
|
||||||
|
use client_api::entity::QueryCollabParams;
|
||||||
|
use client_api::notify::TokenState;
|
||||||
use client_api::{Client, ClientConfiguration};
|
use client_api::{Client, ClientConfiguration};
|
||||||
|
use std::sync::Arc;
|
||||||
|
use tracing;
|
||||||
use wasm_bindgen::prelude::*;
|
use wasm_bindgen::prelude::*;
|
||||||
|
|
||||||
#[cfg(feature = "enable_wee_alloc")]
|
#[cfg(feature = "enable_wee_alloc")]
|
||||||
|
|
@ -27,11 +32,16 @@ extern "C" {
|
||||||
#[wasm_bindgen(js_namespace = console)]
|
#[wasm_bindgen(js_namespace = console)]
|
||||||
fn trace(msg: &str);
|
fn trace(msg: &str);
|
||||||
|
|
||||||
|
#[wasm_bindgen(js_namespace = window)]
|
||||||
|
fn refresh_token(token: &str);
|
||||||
|
|
||||||
|
#[wasm_bindgen(js_namespace = window)]
|
||||||
|
fn invalid_token();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[wasm_bindgen]
|
#[wasm_bindgen]
|
||||||
pub struct ClientAPI {
|
pub struct ClientAPI {
|
||||||
client: Client,
|
client: Arc<Client>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[wasm_bindgen]
|
#[wasm_bindgen]
|
||||||
|
|
@ -55,54 +65,77 @@ impl ClientAPI {
|
||||||
configuration,
|
configuration,
|
||||||
config.client_id.as_str(),
|
config.client_id.as_str(),
|
||||||
);
|
);
|
||||||
|
|
||||||
tracing::debug!("Client API initialized, config: {:?}", config);
|
tracing::debug!("Client API initialized, config: {:?}", config);
|
||||||
ClientAPI { client }
|
ClientAPI {
|
||||||
|
client: Arc::new(client),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// pub async fn get_user(&self) -> ClientResponse {
|
pub fn subscribe(&self) {
|
||||||
// if let Err(err) = self.client.get_profile().await {
|
let mut rx = self.client.subscribe_token_state();
|
||||||
// log::error!("Get user failed: {:?}", err);
|
let client = self.client.clone();
|
||||||
// return ClientResponse<bool> {
|
|
||||||
// code: ClientErrorCode::from(err.code),
|
|
||||||
// message: err.message.to_string(),
|
|
||||||
// data: None
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// log::info!("Get user success");
|
|
||||||
// ClientResponse {
|
|
||||||
// code: ClientErrorCode::Ok,
|
|
||||||
// message: "Get user success".to_string(),
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
pub async fn sign_up_email_verified(
|
wasm_bindgen_futures::spawn_local(async move {
|
||||||
&self,
|
while let Ok(state) = rx.recv().await {
|
||||||
email: &str,
|
match state {
|
||||||
password: &str,
|
TokenState::Refresh => {
|
||||||
) -> Result<bool, ClientResponse> {
|
if let Ok(token) = client.get_token() {
|
||||||
if let Err(err) = self.client.sign_up(email, password).await {
|
refresh_token(token.as_str());
|
||||||
return Err(ClientResponse {
|
} else {
|
||||||
code: err.code,
|
invalid_token();
|
||||||
message: err.message.to_string(),
|
}
|
||||||
|
},
|
||||||
|
TokenState::Invalid => {
|
||||||
|
invalid_token();
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
pub async fn login(&self, email: &str, password: &str) -> Result<(), ClientResponse> {
|
||||||
Ok(true)
|
match self.client.sign_in_password(email, password).await {
|
||||||
|
Ok(_) => Ok(()),
|
||||||
|
Err(err) => Err(ClientResponse::from(err)),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn sign_in_password(
|
pub async fn sign_up(&self, email: &str, password: &str) -> Result<(), ClientResponse> {
|
||||||
|
match self.client.sign_up(email, password).await {
|
||||||
|
Ok(_) => Ok(()),
|
||||||
|
Err(err) => Err(ClientResponse::from(err)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn logout(&self) -> Result<(), ClientResponse> {
|
||||||
|
match self.client.sign_out().await {
|
||||||
|
Ok(_) => Ok(()),
|
||||||
|
Err(err) => Err(ClientResponse::from(err)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn get_user(&self) -> Result<User, ClientResponse> {
|
||||||
|
match self.client.get_profile().await {
|
||||||
|
Ok(profile) => Ok(User::from(profile)),
|
||||||
|
Err(err) => Err(ClientResponse::from(err)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn restore_token(&self, token: &str) -> Result<(), ClientResponse> {
|
||||||
|
match self.client.restore_token(token) {
|
||||||
|
Ok(_) => Ok(()),
|
||||||
|
Err(err) => Err(ClientResponse::from(err)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn get_collab(
|
||||||
&self,
|
&self,
|
||||||
email: &str,
|
params: ClientQueryCollabParams,
|
||||||
password: &str,
|
) -> Result<ClientEncodeCollab, ClientResponse> {
|
||||||
) -> Result<bool, ClientResponse> {
|
tracing::debug!("get_collab: {:?}", params);
|
||||||
if let Err(err) = self.client.sign_in_password(email, password).await {
|
match self.client.get_collab(params.into()).await {
|
||||||
return Err(ClientResponse {
|
Ok(data) => Ok(ClientEncodeCollab::from(data)),
|
||||||
code: err.code,
|
Err(err) => Err(ClientResponse::from(err)),
|
||||||
message: err.message.to_string(),
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(true)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,7 @@ features = ["tungstenite"]
|
||||||
wasm-bindgen-futures = "0.4.40"
|
wasm-bindgen-futures = "0.4.40"
|
||||||
getrandom = { version = "0.2", features = ["js"]}
|
getrandom = { version = "0.2", features = ["js"]}
|
||||||
tokio = { workspace = true, features = ["sync"]}
|
tokio = { workspace = true, features = ["sync"]}
|
||||||
again = "0.1.2"
|
again = { version = "0.1.2" }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
collab-sync = ["collab", "yrs"]
|
collab-sync = ["collab", "yrs"]
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,21 @@
|
||||||
use crate::http::log_request_id;
|
use crate::http::log_request_id;
|
||||||
use crate::ws::{WSClientHttpSender, WSError};
|
use crate::ws::{WSClientHttpSender, WSError};
|
||||||
use crate::Client;
|
use crate::Client;
|
||||||
|
use crate::RefreshTokenRetryCondition;
|
||||||
|
use again::RetryPolicy;
|
||||||
use app_error::gotrue::GoTrueError;
|
use app_error::gotrue::GoTrueError;
|
||||||
use app_error::ErrorCode;
|
use app_error::{AppError, ErrorCode};
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use collab_rt_entity::EncodedCollab;
|
use collab_rt_entity::EncodedCollab;
|
||||||
use database_entity::dto::{CollabParams, QueryCollabParams};
|
use database_entity::dto::{CollabParams, QueryCollabParams};
|
||||||
use gotrue::grant::{Grant, RefreshTokenGrant};
|
use gotrue::grant::{Grant, RefreshTokenGrant};
|
||||||
use reqwest::Method;
|
use reqwest::Method;
|
||||||
|
use shared_entity::dto::workspace_dto::CollabTypeParam;
|
||||||
use shared_entity::response::{AppResponse, AppResponseError};
|
use shared_entity::response::{AppResponse, AppResponseError};
|
||||||
use std::future::Future;
|
use std::future::Future;
|
||||||
use std::sync::atomic::Ordering;
|
use std::sync::atomic::Ordering;
|
||||||
use tracing::instrument;
|
use std::time::Duration;
|
||||||
|
use tracing::{event, instrument};
|
||||||
|
|
||||||
impl Client {
|
impl Client {
|
||||||
pub async fn create_collab_list(
|
pub async fn create_collab_list(
|
||||||
|
|
@ -32,13 +36,14 @@ impl Client {
|
||||||
params: QueryCollabParams,
|
params: QueryCollabParams,
|
||||||
) -> Result<EncodedCollab, AppResponseError> {
|
) -> Result<EncodedCollab, AppResponseError> {
|
||||||
let url = format!(
|
let url = format!(
|
||||||
"{}/api/workspace/{}/collab/{}",
|
"{}/api/workspace/v1/{}/collab/{}",
|
||||||
self.base_url, ¶ms.workspace_id, ¶ms.object_id
|
self.base_url, ¶ms.workspace_id, ¶ms.object_id
|
||||||
);
|
);
|
||||||
|
let collab_type = params.collab_type.clone();
|
||||||
let resp = self
|
let resp = self
|
||||||
.http_client_with_auth(Method::GET, &url)
|
.http_client_with_auth(Method::GET, &url)
|
||||||
.await?
|
.await?
|
||||||
.json(¶ms)
|
.query(&CollabTypeParam { collab_type })
|
||||||
.send()
|
.send()
|
||||||
.await?;
|
.await?;
|
||||||
log_request_id(&resp);
|
log_request_id(&resp);
|
||||||
|
|
@ -67,6 +72,42 @@ impl Client {
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn inner_refresh_token(&self) -> Result<(), AppResponseError> {
|
async fn inner_refresh_token(&self) -> Result<(), AppResponseError> {
|
||||||
|
// let policy = RetryPolicy::fixed(Duration::from_secs(2)).with_max_retries(4).with_jitter(false);
|
||||||
|
// let refresh_token = self
|
||||||
|
// .token
|
||||||
|
// .read()
|
||||||
|
// .as_ref()
|
||||||
|
// .ok_or(GoTrueError::NotLoggedIn(
|
||||||
|
// "fail to refresh user token".to_owned(),
|
||||||
|
// ))?
|
||||||
|
// .refresh_token
|
||||||
|
// .as_str()
|
||||||
|
// .to_owned();
|
||||||
|
// match policy.retry_if(move || {
|
||||||
|
// let grant = Grant::RefreshToken(RefreshTokenGrant { refresh_token: refresh_token.clone() });
|
||||||
|
// async move {
|
||||||
|
// self
|
||||||
|
// .gotrue_client
|
||||||
|
// .token(&grant).await
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// }, RefreshTokenRetryCondition).await {
|
||||||
|
// Ok(new_token) => {
|
||||||
|
// event!(tracing::Level::INFO, "refresh token success");
|
||||||
|
// self.token.write().set(new_token);
|
||||||
|
// Ok(())
|
||||||
|
// },
|
||||||
|
// Err(err) => {
|
||||||
|
// let err = AppError::from(err);
|
||||||
|
// event!(tracing::Level::ERROR, "refresh token failed: {}", err);
|
||||||
|
//
|
||||||
|
// // If the error is an OAuth error, unset the token.
|
||||||
|
// if err.is_unauthorized() {
|
||||||
|
// self.token.write().unset();
|
||||||
|
// }
|
||||||
|
// Err(err.into())
|
||||||
|
// },
|
||||||
|
// }
|
||||||
let refresh_token = self
|
let refresh_token = self
|
||||||
.token
|
.token
|
||||||
.read()
|
.read()
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,17 @@
|
||||||
use crate::ws::{ConnectInfo, CurrentConnInfo, StateNotify, WSError};
|
use crate::ws::{ConnectInfo, CurrentConnInfo, StateNotify, WSError};
|
||||||
|
use again::Condition;
|
||||||
|
use app_error::gotrue::GoTrueError;
|
||||||
use client_websocket::{connect_async, WebSocketStream};
|
use client_websocket::{connect_async, WebSocketStream};
|
||||||
use reqwest::header::HeaderMap;
|
use reqwest::header::HeaderMap;
|
||||||
use std::sync::Weak;
|
use std::sync::Weak;
|
||||||
|
|
||||||
|
pub(crate) struct RefreshTokenRetryCondition;
|
||||||
|
|
||||||
|
impl Condition<GoTrueError> for RefreshTokenRetryCondition {
|
||||||
|
fn is_retryable(&mut self, error: &GoTrueError) -> bool {
|
||||||
|
error.is_network_error()
|
||||||
|
}
|
||||||
|
}
|
||||||
pub async fn retry_connect(
|
pub async fn retry_connect(
|
||||||
url: String,
|
url: String,
|
||||||
info: ConnectInfo,
|
info: ConnectInfo,
|
||||||
|
|
|
||||||
|
|
@ -25,5 +25,6 @@ actix-web = { version = "4.4.1", default-features = false, features = ["http2"],
|
||||||
validator = { version = "0.16", features = ["validator_derive", "derive"], optional = true }
|
validator = { version = "0.16", features = ["validator_derive", "derive"], optional = true }
|
||||||
rust-s3 = { version = "0.33.0", optional = true }
|
rust-s3 = { version = "0.33.0", optional = true }
|
||||||
|
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
cloud = ["actix-web", "validator", "rust-s3"]
|
cloud = ["actix-web", "validator", "rust-s3"]
|
||||||
|
|
|
||||||
|
|
@ -142,7 +142,6 @@ where
|
||||||
Ok(resp)
|
Ok(resp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize, thiserror::Error)]
|
#[derive(Clone, Debug, Serialize, Deserialize, thiserror::Error)]
|
||||||
pub struct AppResponseError {
|
pub struct AppResponseError {
|
||||||
pub code: ErrorCode,
|
pub code: ErrorCode,
|
||||||
|
|
|
||||||
|
|
@ -7,3 +7,6 @@ mod conn_test;
|
||||||
|
|
||||||
// #[cfg(target_arch = "wasm32")]
|
// #[cfg(target_arch = "wasm32")]
|
||||||
// mod user_test;
|
// mod user_test;
|
||||||
|
|
||||||
|
// #[cfg(target_arch = "wasm32")]
|
||||||
|
// mod collab_test;
|
||||||
|
|
|
||||||
|
|
@ -25,3 +25,18 @@ async fn wasm_sign_in_success() {
|
||||||
|
|
||||||
assert!(val);
|
assert!(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[wasm_bindgen_test]
|
||||||
|
async fn wasm_logout_success() {
|
||||||
|
let test_client = TestClient::new_user().await;
|
||||||
|
let user = test_client.user;
|
||||||
|
|
||||||
|
test_client
|
||||||
|
.api_client
|
||||||
|
.sign_in_password(user.email.as_str(), user.password.as_str())
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
let res = test_client.api_client.sign_out().await;
|
||||||
|
|
||||||
|
assert!(res.is_ok());
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue