use actix_web_sql_identity::SqlIdentityBuilder;
use actix_web::client::{ClientRequest, ClientRequestBuilder};
use actix_web::http::StatusCode;
use actix_web::middleware::identity::{IdentityService, RequestIdentity};
use actix_web::test::TestServer;
use actix_web::{HttpMessage, HttpRequest, HttpResponse};
use dotenv;
const RESPONSE_HEADER: &'static str = "test-auth";
pub enum SqlVariant {
Sqlite,
MySql,
Postgres,
}
pub fn build_test_server_from_env(variant: SqlVariant) -> TestServer {
dotenv::from_filename("tests/test.env").ok();
let uri = match variant {
SqlVariant::Sqlite => format!(
"{}/{}",
dotenv::var("SQLITE_PATH").unwrap(),
dotenv::var("SQLITE_DB").unwrap(),
),
SqlVariant::MySql => format!(
"mysql://{}:{}@{}/{}",
dotenv::var("MYSQL_USER").unwrap(),
dotenv::var("MYSQL_PASS").unwrap(),
dotenv::var("MYSQL_HOST").unwrap(),
dotenv::var("MYSQL_DB").unwrap()
),
SqlVariant::Postgres => format!(
"postgres://{}:{}@{}/{}",
dotenv::var("PG_USER").unwrap(),
dotenv::var("PG_PASS").unwrap(),
dotenv::var("PG_HOST").unwrap(),
dotenv::var("PG_DB").unwrap()
),
};
build_test_server(uri)
}
pub fn build_test_server<S: Into<String>>(uri: S) -> TestServer {
let uri = uri.into();
println!("Connecting to: {}", uri);
TestServer::new(move |app| {
let policy = SqlIdentityBuilder::new(uri.clone()).response_header(RESPONSE_HEADER);
app.middleware(IdentityService::new(
policy.finish().expect("failed to connect to database"),
)).resource("/", |r| r.get().f(|_| HttpResponse::Ok()))
.resource("/login", |r| {
r.post().f(|req: &HttpRequest| {
req.remember("mike".to_string());
HttpResponse::Ok()
})
})
.resource("/profile", |r| {
r.get().f(|req: &HttpRequest| match req.identity() {
Some(_) => HttpResponse::Ok(),
None => HttpResponse::Unauthorized(),
})
})
.resource("/logout", |r| {
r.post().f(|req: &HttpRequest| {
req.forget();
HttpResponse::Ok()
})
});
})
}
pub fn add_token_to_request(req: &mut ClientRequestBuilder, token: &str) {
req.header("Authorization", format!("Bearer {}", token));
}
pub fn check_response(srv: &mut TestServer, req: ClientRequest, exp: StatusCode) -> bool {
println!("{:?}", req);
let resp = srv.execute(req.send()).unwrap();
println!("{:?}", resp);
resp.status() == exp
}
pub fn login(srv: &mut TestServer, _username: &str) -> Option<String> {
let request = srv.post().uri(srv.url("/login")).finish().unwrap();
println!("{:?}", request);
let response = srv.execute(request.send()).unwrap();
println!("{:?}", response);
assert!(response.status() == StatusCode::OK, "Login Failed");
match response.headers().get(RESPONSE_HEADER) {
Some(token) => Some(token.to_str().unwrap().to_string()),
None => None,
}
}
pub fn logout(srv: &mut TestServer, token: Option<&str>, code: StatusCode) {
let mut request = srv.post();
let mut request = request.uri(srv.url("/logout"));
if token.is_some() {
add_token_to_request(&mut request, token.unwrap());
}
let request = request.finish().unwrap();
assert!(check_response(srv, request, code));
}
fn build_get(srv: &mut TestServer, uri: &str, token: Option<&str>) -> ClientRequest {
let mut request = srv.get();
let mut request = request.uri(srv.url(uri));
match token {
Some(t) => add_token_to_request(&mut request, t),
None => (),
}
request.finish().unwrap()
}
pub fn index(srv: &mut TestServer, token: Option<&str>) {
let request = build_get(srv, "/", token);
assert!(
check_response(srv, request, StatusCode::OK),
"Failed to GET /index!"
);
}
pub fn profile(srv: &mut TestServer, token: Option<&str>, code: StatusCode) {
let request = build_get(srv, "/profile", token);
assert!(check_response(srv, request, code));
}