mirror of
				https://github.com/AppFlowy-IO/AppFlowy.git
				synced 2025-10-31 10:03:18 +00:00 
			
		
		
		
	test server api: register user and sign in
This commit is contained in:
		
							parent
							
								
									15f1267956
								
							
						
					
					
						commit
						f05f0c43a3
					
				| @ -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" } | ||||
| @ -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)) | ||||
|         ) | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -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, | ||||
| } | ||||
|  | ||||
| @ -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>, | ||||
|  | ||||
| @ -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
									
								
							
							
						
						
									
										39
									
								
								backend/tests/api/auth.rs
									
									
									
									
									
										Normal 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); | ||||
| } | ||||
							
								
								
									
										77
									
								
								backend/tests/api/helper.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								backend/tests/api/helper.rs
									
									
									
									
									
										Normal 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 | ||||
| } | ||||
							
								
								
									
										2
									
								
								backend/tests/api/main.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								backend/tests/api/main.rs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,2 @@ | ||||
| mod auth; | ||||
| mod helper; | ||||
| @ -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)), | ||||
|         } | ||||
| 
 | ||||
|  | ||||
| @ -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; | ||||
|  | ||||
| @ -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, | ||||
|  | ||||
| @ -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::*}, | ||||
|     }; | ||||
| } | ||||
|  | ||||
| @ -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 { | ||||
|  | ||||
| @ -1 +0,0 @@ | ||||
| mod user_test; | ||||
| @ -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); | ||||
| } | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 appflowy
						appflowy