test server api: register user and sign in

This commit is contained in:
appflowy 2021-08-23 22:10:36 +08:00
parent 15f1267956
commit f05f0c43a3
15 changed files with 170 additions and 41 deletions

View File

@ -58,4 +58,11 @@ path = "src/lib.rs"
[[bin]]
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" }

View File

@ -34,6 +34,8 @@ impl Application {
}
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> {
@ -64,8 +66,8 @@ fn user_scope() -> Scope {
web::scope("/api")
// authentication
.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))
)
// password
@ -74,7 +76,7 @@ fn user_scope() -> Scope {
)
// register
.service(web::resource("/register")
.route(web::post().to(user_router::register_handler))
.route(web::post().to(user_router::register_user_handler))
)
}

View File

@ -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)]
pub struct User {
pub(crate) id: uuid::Uuid,
pub(crate) email: String,
pub(crate) name: String,
pub(crate) create_time: i64,
pub(crate) create_time: chrono::DateTime<Utc>,
pub(crate) password: String,
}

View File

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

View File

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

39
backend/tests/api/auth.rs Normal file
View File

@ -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: "annie@appflowy.io".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 = "annie@appflowy.io";
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);
}

View File

@ -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
}

View File

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

View File

@ -43,7 +43,7 @@ impl RustStreamSender {
pub fn post(_observable_subject: ObservableSubject) -> Result<(), String> {
#[cfg(feature = "dart")]
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)),
}

View File

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

View File

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

View File

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

View File

@ -26,18 +26,13 @@ pub(crate) fn construct_server() -> Arc<dyn UserServer + Send + Sync> {
}
pub struct UserServerImpl {}
impl UserServerImpl {}
impl UserServerImpl {
pub fn new() -> Self { Self {} }
}
impl UserServer for UserServerImpl {
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> {
@ -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 {}
impl UserServer for UserServerMock {

View File

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

View File

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