Browse Source

test server api: register user and sign in

appflowy 3 years ago
parent
commit
f05f0c43a3

+ 8 - 1
backend/Cargo.toml

@@ -58,4 +58,11 @@ path = "src/lib.rs"
 
 
 [[bin]]
 [[bin]]
 name = "backend"
 name = "backend"
-path = "src/main.rs"
+path = "src/main.rs"
+
+[dev-dependencies]
+once_cell = "1.7.2"
+actix-rt = "2"
+tokio = { version = "1", features = ["macros"] }
+linkify = "0.5.0"
+flowy-user = { path = "../rust-lib/flowy-user" }

+ 5 - 3
backend/src/application.rs

@@ -34,6 +34,8 @@ impl Application {
     }
     }
 
 
     pub async fn run_until_stopped(self) -> Result<(), std::io::Error> { self.server.await }
     pub async fn run_until_stopped(self) -> Result<(), std::io::Error> { self.server.await }
+
+    pub fn port(&self) -> u16 { self.port }
 }
 }
 
 
 pub fn run(listener: TcpListener, app_ctx: AppContext) -> Result<Server, std::io::Error> {
 pub fn run(listener: TcpListener, app_ctx: AppContext) -> Result<Server, std::io::Error> {
@@ -64,8 +66,8 @@ fn user_scope() -> Scope {
     web::scope("/api")
     web::scope("/api")
         // authentication
         // authentication
         .service(web::resource("/auth")
         .service(web::resource("/auth")
-            .route(web::post().to(user_router::login_handler))
-            .route(web::delete().to(user_router::logout_handler))
+            .route(web::post().to(user_router::sign_in_handler))
+            .route(web::delete().to(user_router::sign_out_handler))
             .route(web::get().to(user_router::user_profile))
             .route(web::get().to(user_router::user_profile))
         )
         )
         // password
         // password
@@ -74,7 +76,7 @@ fn user_scope() -> Scope {
         )
         )
         // register
         // register
         .service(web::resource("/register")
         .service(web::resource("/register")
-            .route(web::post().to(user_router::register_handler))
+            .route(web::post().to(user_router::register_user_handler))
         )
         )
 }
 }
 
 

+ 5 - 1
backend/src/entities/user.rs

@@ -1,8 +1,12 @@
+// type mapped https://kotiri.com/2018/01/31/postgresql-diesel-rust-types.html
+
+use chrono::Utc;
+
 #[derive(Debug, Clone, sqlx::FromRow)]
 #[derive(Debug, Clone, sqlx::FromRow)]
 pub struct User {
 pub struct User {
     pub(crate) id: uuid::Uuid,
     pub(crate) id: uuid::Uuid,
     pub(crate) email: String,
     pub(crate) email: String,
     pub(crate) name: String,
     pub(crate) name: String,
-    pub(crate) create_time: i64,
+    pub(crate) create_time: chrono::DateTime<Utc>,
     pub(crate) password: String,
     pub(crate) password: String,
 }
 }

+ 3 - 3
backend/src/routers/user_router.rs

@@ -14,7 +14,7 @@ use flowy_net::errors::ServerError;
 use sqlx::PgPool;
 use sqlx::PgPool;
 use std::sync::Arc;
 use std::sync::Arc;
 
 
-pub async fn login_handler(
+pub async fn sign_in_handler(
     payload: Payload,
     payload: Payload,
     id: Identity,
     id: Identity,
     pool: Data<PgPool>,
     pool: Data<PgPool>,
@@ -24,7 +24,7 @@ pub async fn login_handler(
     Ok(resp.into())
     Ok(resp.into())
 }
 }
 
 
-pub async fn logout_handler(id: Identity) -> Result<HttpResponse, ServerError> {
+pub async fn sign_out_handler(id: Identity) -> Result<HttpResponse, ServerError> {
     id.forget();
     id.forget();
     Ok(HttpResponse::Ok().finish())
     Ok(HttpResponse::Ok().finish())
 }
 }
@@ -37,7 +37,7 @@ pub async fn user_profile(
     unimplemented!()
     unimplemented!()
 }
 }
 
 
-pub async fn register_handler(
+pub async fn register_user_handler(
     _request: HttpRequest,
     _request: HttpRequest,
     payload: Payload,
     payload: Payload,
     pool: Data<PgPool>,
     pool: Data<PgPool>,

+ 1 - 1
backend/src/user_service/auth_service.rs

@@ -116,7 +116,7 @@ async fn insert_user(
         params.email,
         params.email,
         params.name,
         params.name,
         Utc::now(),
         Utc::now(),
-        "123".to_string()
+        password,
     )
     )
     .execute(transaction)
     .execute(transaction)
     .await
     .await

+ 39 - 0
backend/tests/api/auth.rs

@@ -0,0 +1,39 @@
+use crate::helper::spawn_app;
+use flowy_user::entities::{SignInParams, SignInResponse, SignUpParams};
+
+#[actix_rt::test]
+async fn user_register() {
+    let app = spawn_app().await;
+    let params = SignUpParams {
+        email: "[email protected]".to_string(),
+        name: "annie".to_string(),
+        password: "123".to_string(),
+    };
+
+    let response = app.register_user(params).await;
+    log::info!("{:?}", response);
+}
+
+#[actix_rt::test]
+async fn user_sign_in() {
+    let app = spawn_app().await;
+    let email = "[email protected]";
+    let password = "123";
+
+    let _ = app
+        .register_user(SignUpParams {
+            email: email.to_string(),
+            name: "annie".to_string(),
+            password: password.to_string(),
+        })
+        .await;
+
+    let response = app
+        .sign_in(SignInParams {
+            email: email.to_string(),
+            password: password.to_string(),
+        })
+        .await;
+
+    log::info!("{:?}", response);
+}

+ 77 - 0
backend/tests/api/helper.rs

@@ -0,0 +1,77 @@
+use backend::{
+    application::{get_connection_pool, Application},
+    config::{get_configuration, DatabaseSettings},
+};
+use flowy_net::request::HttpRequestBuilder;
+use flowy_user::prelude::*;
+use sqlx::{Connection, Executor, PgConnection, PgPool};
+use uuid::Uuid;
+
+pub struct TestApp {
+    pub address: String,
+    pub port: u16,
+    pub pg_pool: PgPool,
+}
+
+impl TestApp {
+    pub async fn register_user(&self, params: SignUpParams) -> SignUpResponse {
+        let url = format!("{}/api/register", self.address);
+        let resp = user_sign_up(params, &url).await.unwrap();
+        resp
+    }
+
+    pub async fn sign_in(&self, params: SignInParams) -> SignInResponse {
+        let url = format!("{}/api/auth", self.address);
+        let resp = user_sign_in(params, &url).await.unwrap();
+        resp
+    }
+}
+
+pub async fn spawn_app() -> TestApp {
+    let configuration = {
+        let mut c = get_configuration().expect("Failed to read configuration.");
+        c.database.database_name = Uuid::new_v4().to_string();
+        // Use a random OS port
+        c.application.port = 0;
+        c
+    };
+
+    let _ = configure_database(&configuration.database).await;
+    let application = Application::build(configuration.clone())
+        .await
+        .expect("Failed to build application.");
+    let application_port = application.port();
+
+    let _ = tokio::spawn(application.run_until_stopped());
+
+    TestApp {
+        address: format!("http://localhost:{}", application_port),
+        port: application_port,
+        pg_pool: get_connection_pool(&configuration.database)
+            .await
+            .expect("Failed to connect to the database"),
+    }
+}
+
+async fn configure_database(config: &DatabaseSettings) -> PgPool {
+    // Create database
+    let mut connection = PgConnection::connect_with(&config.without_db())
+        .await
+        .expect("Failed to connect to Postgres");
+    connection
+        .execute(&*format!(r#"CREATE DATABASE "{}";"#, config.database_name))
+        .await
+        .expect("Failed to create database.");
+
+    // Migrate database
+    let connection_pool = PgPool::connect_with(config.with_db())
+        .await
+        .expect("Failed to connect to Postgres.");
+
+    sqlx::migrate!("./migrations")
+        .run(&connection_pool)
+        .await
+        .expect("Failed to migrate the database");
+
+    connection_pool
+}

+ 2 - 0
backend/tests/api/main.rs

@@ -0,0 +1,2 @@
+mod auth;
+mod helper;

+ 1 - 1
rust-lib/flowy-observable/src/dart/stream_sender.rs

@@ -43,7 +43,7 @@ impl RustStreamSender {
     pub fn post(_observable_subject: ObservableSubject) -> Result<(), String> {
     pub fn post(_observable_subject: ObservableSubject) -> Result<(), String> {
         #[cfg(feature = "dart")]
         #[cfg(feature = "dart")]
         match R2F_STREAM_SENDER.read() {
         match R2F_STREAM_SENDER.read() {
-            Ok(stream) => stream.inner_post(observable_subject),
+            Ok(stream) => stream.inner_post(_observable_subject),
             Err(e) => Err(format!("Get rust to flutter stream lock fail. {:?}", e)),
             Err(e) => Err(format!("Get rust to flutter stream lock fail. {:?}", e)),
         }
         }
 
 

+ 1 - 1
rust-lib/flowy-user/src/entities/mod.rs

@@ -4,6 +4,6 @@ pub use user_detail::*;
 pub use user_update::*;
 pub use user_update::*;
 mod parser;
 mod parser;
 mod sign_in;
 mod sign_in;
-mod sign_up;
+pub mod sign_up;
 mod user_detail;
 mod user_detail;
 mod user_update;
 mod user_update;

+ 1 - 1
rust-lib/flowy-user/src/entities/sign_in.rs

@@ -20,7 +20,7 @@ pub struct SignInParams {
     pub password: String,
     pub password: String,
 }
 }
 
 
-#[derive(Default, ProtoBuf)]
+#[derive(Debug, Default, ProtoBuf)]
 pub struct SignInResponse {
 pub struct SignInResponse {
     #[pb(index = 1)]
     #[pb(index = 1)]
     pub uid: String,
     pub uid: String,

+ 5 - 5
rust-lib/flowy-user/src/lib.rs

@@ -1,11 +1,12 @@
+mod event;
+mod handlers;
+mod sql_tables;
+
 pub mod entities;
 pub mod entities;
 pub mod errors;
 pub mod errors;
-pub mod event;
-mod handlers;
 pub mod module;
 pub mod module;
 pub mod protobuf;
 pub mod protobuf;
-mod services;
-pub mod sql_tables;
+pub mod services;
 
 
 #[macro_use]
 #[macro_use]
 extern crate flowy_database;
 extern crate flowy_database;
@@ -13,7 +14,6 @@ extern crate flowy_database;
 pub mod prelude {
 pub mod prelude {
     pub use crate::{
     pub use crate::{
         entities::*,
         entities::*,
-        handlers::*,
         services::{user::*, workspace::*},
         services::{user::*, workspace::*},
     };
     };
 }
 }

+ 22 - 9
rust-lib/flowy-user/src/services/user/user_server.rs

@@ -26,18 +26,13 @@ pub(crate) fn construct_server() -> Arc<dyn UserServer + Send + Sync> {
 }
 }
 
 
 pub struct UserServerImpl {}
 pub struct UserServerImpl {}
-impl UserServerImpl {}
+impl UserServerImpl {
+    pub fn new() -> Self { Self {} }
+}
 
 
 impl UserServer for UserServerImpl {
 impl UserServer for UserServerImpl {
     fn sign_up(&self, params: SignUpParams) -> ResultFuture<SignUpResponse, UserError> {
     fn sign_up(&self, params: SignUpParams) -> ResultFuture<SignUpResponse, UserError> {
-        ResultFuture::new(async move {
-            let response = HttpRequestBuilder::post(SIGN_UP_URL.as_ref())
-                .protobuf(params)?
-                .send()
-                .await?
-                .response()?;
-            Ok(response)
-        })
+        ResultFuture::new(async move { user_sign_up(params, SIGN_UP_URL.as_ref()).await })
     }
     }
 
 
     fn sign_in(&self, _params: SignInParams) -> ResultFuture<SignInResponse, UserError> {
     fn sign_in(&self, _params: SignInParams) -> ResultFuture<SignInResponse, UserError> {
@@ -60,6 +55,24 @@ impl UserServer for UserServerImpl {
     }
     }
 }
 }
 
 
+pub async fn user_sign_up(params: SignUpParams, url: &str) -> Result<SignUpResponse, UserError> {
+    let response = HttpRequestBuilder::post(&url.to_owned())
+        .protobuf(params)?
+        .send()
+        .await?
+        .response()?;
+    Ok(response)
+}
+
+pub async fn user_sign_in(params: SignInParams, url: &str) -> Result<SignInResponse, UserError> {
+    let response = HttpRequestBuilder::post(&url.to_owned())
+        .protobuf(params)?
+        .send()
+        .await?
+        .response()?;
+    Ok(response)
+}
+
 pub struct UserServerMock {}
 pub struct UserServerMock {}
 
 
 impl UserServer for UserServerMock {
 impl UserServer for UserServerMock {

+ 0 - 1
rust-lib/flowy-user/tests/server/main.rs

@@ -1 +0,0 @@
-mod user_test;

+ 0 - 14
rust-lib/flowy-user/tests/server/user_test.rs

@@ -1,14 +0,0 @@
-use flowy_user::prelude::*;
-
-#[tokio::test]
-async fn user_register_test() {
-    let server = UserServerImpl {};
-
-    let params = SignUpParams {
-        email: "[email protected]".to_string(),
-        name: "annie".to_string(),
-        password: "1233333".to_string(),
-    };
-    let result = server.sign_up(params).await.unwrap();
-    println!("{:?}", result);
-}