feat: integrate postgres storage (#2604)

* chore: env config

* chore: get user workspace

* feat: enable postgres storage

* chore: add new env

* chore: add set env ffi

* chore: pass env before backend init

* chore: update

* fix: ci tests

* chore: commit the generate env file

* chore: remove unused import
This commit is contained in:
Nathan.fooo
2023-05-23 23:55:21 +08:00
committed by GitHub
parent 51a7954af7
commit 056e2d49d0
87 changed files with 1421 additions and 1131 deletions

View File

@ -34,7 +34,6 @@ unicode-segmentation = "1.10"
fancy-regex = "0.11.0"
[dev-dependencies]
flowy-test = { path = "../flowy-test" }
nanoid = "0.4.0"
fake = "2.0.0"
rand = "0.8.4"

View File

@ -16,6 +16,7 @@ pub async fn sign_in(
) -> DataResult<UserProfilePB, FlowyError> {
let params: SignInParams = data.into_inner().try_into()?;
let auth_type = params.auth_type.clone();
let user_profile: UserProfilePB = session
.sign_in(&auth_type, BoxAny::new(params))
.await?

View File

@ -40,6 +40,7 @@ pub trait UserStatusCallback: Send + Sync + 'static {
/// The user cloud service provider.
/// The provider can be supabase, firebase, aws, or any other cloud service.
pub trait UserCloudServiceProvider: Send + Sync + 'static {
fn set_auth_type(&self, auth_type: AuthType);
fn get_auth_service(&self, auth_type: &AuthType) -> Result<Arc<dyn UserAuthService>, FlowyError>;
}
@ -47,6 +48,10 @@ impl<T> UserCloudServiceProvider for Arc<T>
where
T: UserCloudServiceProvider,
{
fn set_auth_type(&self, auth_type: AuthType) {
(**self).set_auth_type(auth_type)
}
fn get_auth_service(&self, auth_type: &AuthType) -> Result<Arc<dyn UserAuthService>, FlowyError> {
(**self).get_auth_service(auth_type)
}

View File

@ -104,6 +104,7 @@ impl UserSession {
auth_type: &AuthType,
params: BoxAny,
) -> Result<UserProfile, FlowyError> {
self.cloud_services.set_auth_type(auth_type.clone());
let resp = self
.cloud_services
.get_auth_service(auth_type)?
@ -134,6 +135,7 @@ impl UserSession {
auth_type: &AuthType,
params: BoxAny,
) -> Result<UserProfile, FlowyError> {
self.cloud_services.set_auth_type(auth_type.clone());
let resp = self
.cloud_services
.get_auth_service(auth_type)?
@ -163,6 +165,7 @@ impl UserSession {
.execute(&*(self.db_connection()?))?;
self.database.close_user_db(session.user_id)?;
self.set_session(None)?;
let server = self.cloud_services.get_auth_service(auth_type)?;
let token = session.token;
let _ = tokio::spawn(async move {

View File

@ -1,117 +0,0 @@
use flowy_test::{event_builder::UserModuleEventBuilder, FlowySDKTest};
use flowy_user::entities::{AuthTypePB, SignInPayloadPB, SignUpPayloadPB, UserProfilePB};
use flowy_user::{errors::ErrorCode, event_map::UserEvent::*};
use crate::helper::*;
#[tokio::test]
async fn sign_up_with_invalid_email() {
for email in invalid_email_test_case() {
let sdk = FlowySDKTest::default();
let request = SignUpPayloadPB {
email: email.to_string(),
name: valid_name(),
password: login_password(),
auth_type: AuthTypePB::Local,
};
assert_eq!(
UserModuleEventBuilder::new(sdk)
.event(SignUp)
.payload(request)
.async_send()
.await
.error()
.code,
ErrorCode::EmailFormatInvalid.value()
);
}
}
#[tokio::test]
async fn sign_up_with_invalid_password() {
for password in invalid_password_test_case() {
let sdk = FlowySDKTest::default();
let request = SignUpPayloadPB {
email: random_email(),
name: valid_name(),
password,
auth_type: AuthTypePB::Local,
};
UserModuleEventBuilder::new(sdk)
.event(SignUp)
.payload(request)
.async_send()
.await
.assert_error();
}
}
#[tokio::test]
async fn sign_in_success() {
let test = FlowySDKTest::default();
let _ = UserModuleEventBuilder::new(test.clone())
.event(SignOut)
.sync_send();
let sign_up_context = test.sign_up().await;
let request = SignInPayloadPB {
email: sign_up_context.user_profile.email.clone(),
password: sign_up_context.password.clone(),
name: "".to_string(),
auth_type: AuthTypePB::Local,
};
let response = UserModuleEventBuilder::new(test.clone())
.event(SignIn)
.payload(request)
.async_send()
.await
.parse::<UserProfilePB>();
dbg!(&response);
}
#[tokio::test]
async fn sign_in_with_invalid_email() {
for email in invalid_email_test_case() {
let sdk = FlowySDKTest::default();
let request = SignInPayloadPB {
email: email.to_string(),
password: login_password(),
name: "".to_string(),
auth_type: AuthTypePB::Local,
};
assert_eq!(
UserModuleEventBuilder::new(sdk)
.event(SignIn)
.payload(request)
.async_send()
.await
.error()
.code,
ErrorCode::EmailFormatInvalid.value()
);
}
}
#[tokio::test]
async fn sign_in_with_invalid_password() {
for password in invalid_password_test_case() {
let sdk = FlowySDKTest::default();
let request = SignInPayloadPB {
email: random_email(),
password,
name: "".to_string(),
auth_type: AuthTypePB::Local,
};
UserModuleEventBuilder::new(sdk)
.event(SignIn)
.payload(request)
.async_send()
.await
.assert_error();
}
}

View File

@ -1,42 +0,0 @@
pub use flowy_test::{
event_builder::*,
prelude::{login_password, random_email},
};
pub(crate) fn invalid_email_test_case() -> Vec<String> {
// https://gist.github.com/cjaoude/fd9910626629b53c4d25
vec![
"annie@",
"annie@gmail@",
"#@%^%#$@#$@#.com",
"@example.com",
"Joe Smith <email@example.com>",
"email.example.com",
"email@example@example.com",
"email@-example.com",
"email@example..com",
"あいうえお@example.com",
/* The following email is valid according to the validate_email function return
* ".email@example.com",
* "email.@example.com",
* "email..email@example.com",
* "email@example",
* "email@example.web",
* "email@111.222.333.44444",
* "Abc..123@example.com", */
]
.iter()
.map(|s| s.to_string())
.collect::<Vec<_>>()
}
pub(crate) fn invalid_password_test_case() -> Vec<String> {
vec!["123456", "1234".repeat(100).as_str()]
.iter()
.map(|s| s.to_string())
.collect::<Vec<_>>()
}
pub(crate) fn valid_name() -> String {
"AppFlowy".to_string()
}

View File

@ -1,3 +0,0 @@
mod auth_test;
mod helper;
mod user_profile_test;

View File

@ -1,127 +0,0 @@
use crate::helper::*;
use flowy_test::{event_builder::UserModuleEventBuilder, FlowySDKTest};
use flowy_user::entities::{UpdateUserProfilePayloadPB, UserProfilePB};
use flowy_user::{errors::ErrorCode, event_map::UserEvent::*};
use nanoid::nanoid;
// use serial_test::*;
#[tokio::test]
async fn user_profile_get_failed() {
let sdk = FlowySDKTest::default();
let result = UserModuleEventBuilder::new(sdk)
.event(GetUserProfile)
.assert_error()
.async_send()
.await;
assert!(result.user_profile().is_none())
}
#[tokio::test]
async fn user_profile_get() {
let test = FlowySDKTest::default();
let user_profile = test.init_user().await;
let user = UserModuleEventBuilder::new(test.clone())
.event(GetUserProfile)
.sync_send()
.parse::<UserProfilePB>();
assert_eq!(user_profile, user);
}
#[tokio::test]
async fn user_update_with_name() {
let sdk = FlowySDKTest::default();
let user = sdk.init_user().await;
let new_name = "hello_world".to_owned();
let request = UpdateUserProfilePayloadPB::new(user.id).name(&new_name);
let _ = UserModuleEventBuilder::new(sdk.clone())
.event(UpdateUserProfile)
.payload(request)
.sync_send();
let user_profile = UserModuleEventBuilder::new(sdk.clone())
.event(GetUserProfile)
.assert_error()
.sync_send()
.parse::<UserProfilePB>();
assert_eq!(user_profile.name, new_name,);
}
#[tokio::test]
async fn user_update_with_email() {
let sdk = FlowySDKTest::default();
let user = sdk.init_user().await;
let new_email = format!("{}@gmail.com", nanoid!(6));
let request = UpdateUserProfilePayloadPB::new(user.id).email(&new_email);
let _ = UserModuleEventBuilder::new(sdk.clone())
.event(UpdateUserProfile)
.payload(request)
.sync_send();
let user_profile = UserModuleEventBuilder::new(sdk.clone())
.event(GetUserProfile)
.assert_error()
.sync_send()
.parse::<UserProfilePB>();
assert_eq!(user_profile.email, new_email,);
}
#[tokio::test]
async fn user_update_with_password() {
let sdk = FlowySDKTest::default();
let user = sdk.init_user().await;
let new_password = "H123world!".to_owned();
let request = UpdateUserProfilePayloadPB::new(user.id).password(&new_password);
let _ = UserModuleEventBuilder::new(sdk.clone())
.event(UpdateUserProfile)
.payload(request)
.sync_send()
.assert_success();
}
#[tokio::test]
async fn user_update_with_invalid_email() {
let test = FlowySDKTest::default();
let user = test.init_user().await;
for email in invalid_email_test_case() {
let request = UpdateUserProfilePayloadPB::new(user.id).email(&email);
assert_eq!(
UserModuleEventBuilder::new(test.clone())
.event(UpdateUserProfile)
.payload(request)
.sync_send()
.error()
.code,
ErrorCode::EmailFormatInvalid.value()
);
}
}
#[tokio::test]
async fn user_update_with_invalid_password() {
let test = FlowySDKTest::default();
let user = test.init_user().await;
for password in invalid_password_test_case() {
let request = UpdateUserProfilePayloadPB::new(user.id).password(&password);
UserModuleEventBuilder::new(test.clone())
.event(UpdateUserProfile)
.payload(request)
.sync_send()
.assert_error();
}
}
#[tokio::test]
async fn user_update_with_invalid_name() {
let test = FlowySDKTest::default();
let user = test.init_user().await;
let request = UpdateUserProfilePayloadPB::new(user.id).name("");
UserModuleEventBuilder::new(test.clone())
.event(UpdateUserProfile)
.payload(request)
.sync_send()
.assert_error();
}