1
0
mirror of https://github.com/actix/actix-extras.git synced 2024-12-18 01:33:59 +01:00

migrate actix-identity

This commit is contained in:
Nikolay Kim 2019-11-21 10:31:52 +06:00
parent ff62facc0d
commit 3646725cf6
3 changed files with 342 additions and 293 deletions

View File

@ -35,7 +35,7 @@ members = [
#"actix-files", #"actix-files",
#"actix-framed", #"actix-framed",
#"actix-session", #"actix-session",
#"actix-identity", "actix-identity",
#"actix-multipart", #"actix-multipart",
#"actix-web-actors", #"actix-web-actors",
"actix-web-codegen", "actix-web-codegen",

View File

@ -17,14 +17,14 @@ name = "actix_identity"
path = "src/lib.rs" path = "src/lib.rs"
[dependencies] [dependencies]
actix-web = { version = "1.0.9", default-features = false, features = ["secure-cookies"] } actix-web = { version = "2.0.0-alpha.1", default-features = false, features = ["secure-cookies"] }
actix-service = "0.4.2" actix-service = "1.0.0-alpha.1"
futures = "0.3.1" futures = "0.3.1"
serde = "1.0" serde = "1.0"
serde_json = "1.0" serde_json = "1.0"
time = "0.1.42" time = "0.1.42"
[dev-dependencies] [dev-dependencies]
actix-rt = "0.2.2" actix-rt = "1.0.0-alpha.1"
actix-http = "0.2.11" actix-http = "0.3.0-alpha.1"
bytes = "0.4" bytes = "0.4"

View File

@ -47,12 +47,13 @@
//! } //! }
//! ``` //! ```
use std::cell::RefCell; use std::cell::RefCell;
use std::future::Future;
use std::rc::Rc; use std::rc::Rc;
use std::task::{Context, Poll};
use std::time::SystemTime; use std::time::SystemTime;
use actix_service::{Service, Transform}; use actix_service::{Service, Transform};
use futures::future::{ok, Either, FutureResult}; use futures::future::{ok, FutureExt, LocalBoxFuture, Ready};
use futures::{Future, IntoFuture, Poll};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use time::Duration; use time::Duration;
@ -165,21 +166,21 @@ where
impl FromRequest for Identity { impl FromRequest for Identity {
type Config = (); type Config = ();
type Error = Error; type Error = Error;
type Future = Result<Identity, Error>; type Future = Ready<Result<Identity, Error>>;
#[inline] #[inline]
fn from_request(req: &HttpRequest, _: &mut Payload) -> Self::Future { fn from_request(req: &HttpRequest, _: &mut Payload) -> Self::Future {
Ok(Identity(req.clone())) ok(Identity(req.clone()))
} }
} }
/// Identity policy definition. /// Identity policy definition.
pub trait IdentityPolicy: Sized + 'static { pub trait IdentityPolicy: Sized + 'static {
/// The return type of the middleware /// The return type of the middleware
type Future: IntoFuture<Item = Option<String>, Error = Error>; type Future: Future<Output = Result<Option<String>, Error>>;
/// The return type of the middleware /// The return type of the middleware
type ResponseFuture: IntoFuture<Item = (), Error = Error>; type ResponseFuture: Future<Output = Result<(), Error>>;
/// Parse the session from request and load data from a service identity. /// Parse the session from request and load data from a service identity.
fn from_request(&self, request: &mut ServiceRequest) -> Self::Future; fn from_request(&self, request: &mut ServiceRequest) -> Self::Future;
@ -234,7 +235,7 @@ where
type Error = Error; type Error = Error;
type InitError = (); type InitError = ();
type Transform = IdentityServiceMiddleware<S, T>; type Transform = IdentityServiceMiddleware<S, T>;
type Future = FutureResult<Self::Transform, Self::InitError>; type Future = Ready<Result<Self::Transform, Self::InitError>>;
fn new_transform(&self, service: S) -> Self::Future { fn new_transform(&self, service: S) -> Self::Future {
ok(IdentityServiceMiddleware { ok(IdentityServiceMiddleware {
@ -261,46 +262,39 @@ where
type Request = ServiceRequest; type Request = ServiceRequest;
type Response = ServiceResponse<B>; type Response = ServiceResponse<B>;
type Error = Error; type Error = Error;
type Future = Box<dyn Future<Item = Self::Response, Error = Self::Error>>; type Future = LocalBoxFuture<'static, Result<Self::Response, Self::Error>>;
fn poll_ready(&mut self) -> Poll<(), Self::Error> { fn poll_ready(&mut self, cx: &mut Context) -> Poll<Result<(), Self::Error>> {
self.service.borrow_mut().poll_ready() self.service.borrow_mut().poll_ready(cx)
} }
fn call(&mut self, mut req: ServiceRequest) -> Self::Future { fn call(&mut self, mut req: ServiceRequest) -> Self::Future {
let srv = self.service.clone(); let srv = self.service.clone();
let backend = self.backend.clone(); let backend = self.backend.clone();
let fut = self.backend.from_request(&mut req);
Box::new( async move {
self.backend.from_request(&mut req).into_future().then( match fut.await {
move |res| match res { Ok(id) => {
Ok(id) => { req.extensions_mut()
req.extensions_mut() .insert(IdentityItem { id, changed: false });
.insert(IdentityItem { id, changed: false });
Either::A(srv.borrow_mut().call(req).and_then(move |mut res| { let mut res = srv.borrow_mut().call(req).await?;
let id = let id = res.request().extensions_mut().remove::<IdentityItem>();
res.request().extensions_mut().remove::<IdentityItem>();
if let Some(id) = id { if let Some(id) = id {
Either::A( match backend.to_response(id.id, id.changed, &mut res).await {
backend Ok(_) => Ok(res),
.to_response(id.id, id.changed, &mut res) Err(e) => Ok(res.error_response(e)),
.into_future() }
.then(move |t| match t { } else {
Ok(_) => Ok(res), Ok(res)
Err(e) => Ok(res.error_response(e)),
}),
)
} else {
Either::B(ok(res))
}
}))
} }
Err(err) => Either::B(ok(req.error_response(err))), }
}, Err(err) => Ok(req.error_response(err)),
), }
) }
.boxed_local()
} }
} }
@ -547,11 +541,11 @@ impl CookieIdentityPolicy {
} }
impl IdentityPolicy for CookieIdentityPolicy { impl IdentityPolicy for CookieIdentityPolicy {
type Future = Result<Option<String>, Error>; type Future = Ready<Result<Option<String>, Error>>;
type ResponseFuture = Result<(), Error>; type ResponseFuture = Ready<Result<(), Error>>;
fn from_request(&self, req: &mut ServiceRequest) -> Self::Future { fn from_request(&self, req: &mut ServiceRequest) -> Self::Future {
Ok(self.0.load(req).map( ok(self.0.load(req).map(
|CookieValue { |CookieValue {
identity, identity,
login_timestamp, login_timestamp,
@ -603,7 +597,7 @@ impl IdentityPolicy for CookieIdentityPolicy {
} else { } else {
Ok(()) Ok(())
}; };
Ok(()) ok(())
} }
} }
@ -613,7 +607,7 @@ mod tests {
use super::*; use super::*;
use actix_web::http::StatusCode; use actix_web::http::StatusCode;
use actix_web::test::{self, TestRequest}; use actix_web::test::{self, block_on, TestRequest};
use actix_web::{web, App, Error, HttpResponse}; use actix_web::{web, App, Error, HttpResponse};
const COOKIE_KEY_MASTER: [u8; 32] = [0; 32]; const COOKIE_KEY_MASTER: [u8; 32] = [0; 32];
@ -622,115 +616,138 @@ mod tests {
#[test] #[test]
fn test_identity() { fn test_identity() {
let mut srv = test::init_service( block_on(async {
App::new() let mut srv = test::init_service(
.wrap(IdentityService::new( App::new()
CookieIdentityPolicy::new(&COOKIE_KEY_MASTER) .wrap(IdentityService::new(
.domain("www.rust-lang.org") CookieIdentityPolicy::new(&COOKIE_KEY_MASTER)
.name(COOKIE_NAME) .domain("www.rust-lang.org")
.path("/") .name(COOKIE_NAME)
.secure(true), .path("/")
)) .secure(true),
.service(web::resource("/index").to(|id: Identity| { ))
if id.identity().is_some() { .service(web::resource("/index").to(|id: Identity| {
HttpResponse::Created() if id.identity().is_some() {
} else { HttpResponse::Created()
} else {
HttpResponse::Ok()
}
}))
.service(web::resource("/login").to(|id: Identity| {
id.remember(COOKIE_LOGIN.to_string());
HttpResponse::Ok() HttpResponse::Ok()
} }))
})) .service(web::resource("/logout").to(|id: Identity| {
.service(web::resource("/login").to(|id: Identity| { if id.identity().is_some() {
id.remember(COOKIE_LOGIN.to_string()); id.forget();
HttpResponse::Ok() HttpResponse::Ok()
})) } else {
.service(web::resource("/logout").to(|id: Identity| { HttpResponse::BadRequest()
if id.identity().is_some() { }
id.forget(); })),
HttpResponse::Ok() )
} else { .await;
HttpResponse::BadRequest() let resp = test::call_service(
} &mut srv,
})), TestRequest::with_uri("/index").to_request(),
); )
let resp = .await;
test::call_service(&mut srv, TestRequest::with_uri("/index").to_request()); assert_eq!(resp.status(), StatusCode::OK);
assert_eq!(resp.status(), StatusCode::OK);
let resp = let resp = test::call_service(
test::call_service(&mut srv, TestRequest::with_uri("/login").to_request()); &mut srv,
assert_eq!(resp.status(), StatusCode::OK); TestRequest::with_uri("/login").to_request(),
let c = resp.response().cookies().next().unwrap().to_owned(); )
.await;
assert_eq!(resp.status(), StatusCode::OK);
let c = resp.response().cookies().next().unwrap().to_owned();
let resp = test::call_service( let resp = test::call_service(
&mut srv, &mut srv,
TestRequest::with_uri("/index") TestRequest::with_uri("/index")
.cookie(c.clone()) .cookie(c.clone())
.to_request(), .to_request(),
); )
assert_eq!(resp.status(), StatusCode::CREATED); .await;
assert_eq!(resp.status(), StatusCode::CREATED);
let resp = test::call_service( let resp = test::call_service(
&mut srv, &mut srv,
TestRequest::with_uri("/logout") TestRequest::with_uri("/logout")
.cookie(c.clone()) .cookie(c.clone())
.to_request(), .to_request(),
); )
assert_eq!(resp.status(), StatusCode::OK); .await;
assert!(resp.headers().contains_key(header::SET_COOKIE)) assert_eq!(resp.status(), StatusCode::OK);
assert!(resp.headers().contains_key(header::SET_COOKIE))
})
} }
#[test] #[test]
fn test_identity_max_age_time() { fn test_identity_max_age_time() {
let duration = Duration::days(1); block_on(async {
let mut srv = test::init_service( let duration = Duration::days(1);
App::new() let mut srv = test::init_service(
.wrap(IdentityService::new( App::new()
CookieIdentityPolicy::new(&COOKIE_KEY_MASTER) .wrap(IdentityService::new(
.domain("www.rust-lang.org") CookieIdentityPolicy::new(&COOKIE_KEY_MASTER)
.name(COOKIE_NAME) .domain("www.rust-lang.org")
.path("/") .name(COOKIE_NAME)
.max_age_time(duration) .path("/")
.secure(true), .max_age_time(duration)
)) .secure(true),
.service(web::resource("/login").to(|id: Identity| { ))
id.remember("test".to_string()); .service(web::resource("/login").to(|id: Identity| {
HttpResponse::Ok() id.remember("test".to_string());
})), HttpResponse::Ok()
); })),
let resp = )
test::call_service(&mut srv, TestRequest::with_uri("/login").to_request()); .await;
assert_eq!(resp.status(), StatusCode::OK); let resp = test::call_service(
assert!(resp.headers().contains_key(header::SET_COOKIE)); &mut srv,
let c = resp.response().cookies().next().unwrap().to_owned(); TestRequest::with_uri("/login").to_request(),
assert_eq!(duration, c.max_age().unwrap()); )
.await;
assert_eq!(resp.status(), StatusCode::OK);
assert!(resp.headers().contains_key(header::SET_COOKIE));
let c = resp.response().cookies().next().unwrap().to_owned();
assert_eq!(duration, c.max_age().unwrap());
})
} }
#[test] #[test]
fn test_identity_max_age() { fn test_identity_max_age() {
let seconds = 60; block_on(async {
let mut srv = test::init_service( let seconds = 60;
App::new() let mut srv = test::init_service(
.wrap(IdentityService::new( App::new()
CookieIdentityPolicy::new(&COOKIE_KEY_MASTER) .wrap(IdentityService::new(
.domain("www.rust-lang.org") CookieIdentityPolicy::new(&COOKIE_KEY_MASTER)
.name(COOKIE_NAME) .domain("www.rust-lang.org")
.path("/") .name(COOKIE_NAME)
.max_age(seconds) .path("/")
.secure(true), .max_age(seconds)
)) .secure(true),
.service(web::resource("/login").to(|id: Identity| { ))
id.remember("test".to_string()); .service(web::resource("/login").to(|id: Identity| {
HttpResponse::Ok() id.remember("test".to_string());
})), HttpResponse::Ok()
); })),
let resp = )
test::call_service(&mut srv, TestRequest::with_uri("/login").to_request()); .await;
assert_eq!(resp.status(), StatusCode::OK); let resp = test::call_service(
assert!(resp.headers().contains_key(header::SET_COOKIE)); &mut srv,
let c = resp.response().cookies().next().unwrap().to_owned(); TestRequest::with_uri("/login").to_request(),
assert_eq!(Duration::seconds(seconds as i64), c.max_age().unwrap()); )
.await;
assert_eq!(resp.status(), StatusCode::OK);
assert!(resp.headers().contains_key(header::SET_COOKIE));
let c = resp.response().cookies().next().unwrap().to_owned();
assert_eq!(Duration::seconds(seconds as i64), c.max_age().unwrap());
})
} }
fn create_identity_server< async fn create_identity_server<
F: Fn(CookieIdentityPolicy) -> CookieIdentityPolicy + Sync + Send + Clone + 'static, F: Fn(CookieIdentityPolicy) -> CookieIdentityPolicy + Sync + Send + Clone + 'static,
>( >(
f: F, f: F,
@ -754,6 +771,7 @@ mod tests {
web::Json(identity) web::Json(identity)
})), })),
) )
.await
} }
fn legacy_login_cookie(identity: &'static str) -> Cookie<'static> { fn legacy_login_cookie(identity: &'static str) -> Cookie<'static> {
@ -786,15 +804,8 @@ mod tests {
jar.get(COOKIE_NAME).unwrap().clone() jar.get(COOKIE_NAME).unwrap().clone()
} }
fn assert_logged_in(response: &mut ServiceResponse, identity: Option<&str>) { async fn assert_logged_in(response: ServiceResponse, identity: Option<&str>) {
use bytes::BytesMut; let bytes = test::read_body(response).await;
use futures::Stream;
let bytes =
test::block_on(response.take_body().fold(BytesMut::new(), |mut b, c| {
b.extend(c);
Ok::<_, Error>(b)
}))
.unwrap();
let resp: Option<String> = serde_json::from_slice(&bytes[..]).unwrap(); let resp: Option<String> = serde_json::from_slice(&bytes[..]).unwrap();
assert_eq!(resp.as_ref().map(|s| s.borrow()), identity); assert_eq!(resp.as_ref().map(|s| s.borrow()), identity);
} }
@ -874,183 +885,221 @@ mod tests {
#[test] #[test]
fn test_identity_legacy_cookie_is_set() { fn test_identity_legacy_cookie_is_set() {
let mut srv = create_identity_server(|c| c); block_on(async {
let mut resp = let mut srv = create_identity_server(|c| c).await;
test::call_service(&mut srv, TestRequest::with_uri("/").to_request()); let mut resp =
assert_logged_in(&mut resp, None); test::call_service(&mut srv, TestRequest::with_uri("/").to_request())
assert_legacy_login_cookie(&mut resp, COOKIE_LOGIN); .await;
assert_legacy_login_cookie(&mut resp, COOKIE_LOGIN);
assert_logged_in(resp, None).await;
})
} }
#[test] #[test]
fn test_identity_legacy_cookie_works() { fn test_identity_legacy_cookie_works() {
let mut srv = create_identity_server(|c| c); block_on(async {
let cookie = legacy_login_cookie(COOKIE_LOGIN); let mut srv = create_identity_server(|c| c).await;
let mut resp = test::call_service( let cookie = legacy_login_cookie(COOKIE_LOGIN);
&mut srv, let mut resp = test::call_service(
TestRequest::with_uri("/") &mut srv,
.cookie(cookie.clone()) TestRequest::with_uri("/")
.to_request(), .cookie(cookie.clone())
); .to_request(),
assert_logged_in(&mut resp, Some(COOKIE_LOGIN)); )
assert_no_login_cookie(&mut resp); .await;
assert_no_login_cookie(&mut resp);
assert_logged_in(resp, Some(COOKIE_LOGIN)).await;
})
} }
#[test] #[test]
fn test_identity_legacy_cookie_rejected_if_visit_timestamp_needed() { fn test_identity_legacy_cookie_rejected_if_visit_timestamp_needed() {
let mut srv = create_identity_server(|c| c.visit_deadline(Duration::days(90))); block_on(async {
let cookie = legacy_login_cookie(COOKIE_LOGIN); let mut srv =
let mut resp = test::call_service( create_identity_server(|c| c.visit_deadline(Duration::days(90))).await;
&mut srv, let cookie = legacy_login_cookie(COOKIE_LOGIN);
TestRequest::with_uri("/") let mut resp = test::call_service(
.cookie(cookie.clone()) &mut srv,
.to_request(), TestRequest::with_uri("/")
); .cookie(cookie.clone())
assert_logged_in(&mut resp, None); .to_request(),
assert_login_cookie( )
&mut resp, .await;
COOKIE_LOGIN, assert_login_cookie(
LoginTimestampCheck::NoTimestamp, &mut resp,
VisitTimeStampCheck::NewTimestamp, COOKIE_LOGIN,
); LoginTimestampCheck::NoTimestamp,
VisitTimeStampCheck::NewTimestamp,
);
assert_logged_in(resp, None).await;
})
} }
#[test] #[test]
fn test_identity_legacy_cookie_rejected_if_login_timestamp_needed() { fn test_identity_legacy_cookie_rejected_if_login_timestamp_needed() {
let mut srv = create_identity_server(|c| c.login_deadline(Duration::days(90))); block_on(async {
let cookie = legacy_login_cookie(COOKIE_LOGIN); let mut srv =
let mut resp = test::call_service( create_identity_server(|c| c.login_deadline(Duration::days(90))).await;
&mut srv, let cookie = legacy_login_cookie(COOKIE_LOGIN);
TestRequest::with_uri("/") let mut resp = test::call_service(
.cookie(cookie.clone()) &mut srv,
.to_request(), TestRequest::with_uri("/")
); .cookie(cookie.clone())
assert_logged_in(&mut resp, None); .to_request(),
assert_login_cookie( )
&mut resp, .await;
COOKIE_LOGIN, assert_login_cookie(
LoginTimestampCheck::NewTimestamp, &mut resp,
VisitTimeStampCheck::NoTimestamp, COOKIE_LOGIN,
); LoginTimestampCheck::NewTimestamp,
VisitTimeStampCheck::NoTimestamp,
);
assert_logged_in(resp, None).await;
})
} }
#[test] #[test]
fn test_identity_cookie_rejected_if_login_timestamp_needed() { fn test_identity_cookie_rejected_if_login_timestamp_needed() {
let mut srv = create_identity_server(|c| c.login_deadline(Duration::days(90))); block_on(async {
let cookie = login_cookie(COOKIE_LOGIN, None, Some(SystemTime::now())); let mut srv =
let mut resp = test::call_service( create_identity_server(|c| c.login_deadline(Duration::days(90))).await;
&mut srv, let cookie = login_cookie(COOKIE_LOGIN, None, Some(SystemTime::now()));
TestRequest::with_uri("/") let mut resp = test::call_service(
.cookie(cookie.clone()) &mut srv,
.to_request(), TestRequest::with_uri("/")
); .cookie(cookie.clone())
assert_logged_in(&mut resp, None); .to_request(),
assert_login_cookie( )
&mut resp, .await;
COOKIE_LOGIN, assert_login_cookie(
LoginTimestampCheck::NewTimestamp, &mut resp,
VisitTimeStampCheck::NoTimestamp, COOKIE_LOGIN,
); LoginTimestampCheck::NewTimestamp,
VisitTimeStampCheck::NoTimestamp,
);
assert_logged_in(resp, None).await;
})
} }
#[test] #[test]
fn test_identity_cookie_rejected_if_visit_timestamp_needed() { fn test_identity_cookie_rejected_if_visit_timestamp_needed() {
let mut srv = create_identity_server(|c| c.visit_deadline(Duration::days(90))); block_on(async {
let cookie = login_cookie(COOKIE_LOGIN, Some(SystemTime::now()), None); let mut srv =
let mut resp = test::call_service( create_identity_server(|c| c.visit_deadline(Duration::days(90))).await;
&mut srv, let cookie = login_cookie(COOKIE_LOGIN, Some(SystemTime::now()), None);
TestRequest::with_uri("/") let mut resp = test::call_service(
.cookie(cookie.clone()) &mut srv,
.to_request(), TestRequest::with_uri("/")
); .cookie(cookie.clone())
assert_logged_in(&mut resp, None); .to_request(),
assert_login_cookie( )
&mut resp, .await;
COOKIE_LOGIN, assert_login_cookie(
LoginTimestampCheck::NoTimestamp, &mut resp,
VisitTimeStampCheck::NewTimestamp, COOKIE_LOGIN,
); LoginTimestampCheck::NoTimestamp,
VisitTimeStampCheck::NewTimestamp,
);
assert_logged_in(resp, None).await;
})
} }
#[test] #[test]
fn test_identity_cookie_rejected_if_login_timestamp_too_old() { fn test_identity_cookie_rejected_if_login_timestamp_too_old() {
let mut srv = create_identity_server(|c| c.login_deadline(Duration::days(90))); block_on(async {
let cookie = login_cookie( let mut srv =
COOKIE_LOGIN, create_identity_server(|c| c.login_deadline(Duration::days(90))).await;
Some(SystemTime::now() - Duration::days(180).to_std().unwrap()), let cookie = login_cookie(
None, COOKIE_LOGIN,
); Some(SystemTime::now() - Duration::days(180).to_std().unwrap()),
let mut resp = test::call_service( None,
&mut srv, );
TestRequest::with_uri("/") let mut resp = test::call_service(
.cookie(cookie.clone()) &mut srv,
.to_request(), TestRequest::with_uri("/")
); .cookie(cookie.clone())
assert_logged_in(&mut resp, None); .to_request(),
assert_login_cookie( )
&mut resp, .await;
COOKIE_LOGIN, assert_login_cookie(
LoginTimestampCheck::NewTimestamp, &mut resp,
VisitTimeStampCheck::NoTimestamp, COOKIE_LOGIN,
); LoginTimestampCheck::NewTimestamp,
VisitTimeStampCheck::NoTimestamp,
);
assert_logged_in(resp, None).await;
})
} }
#[test] #[test]
fn test_identity_cookie_rejected_if_visit_timestamp_too_old() { fn test_identity_cookie_rejected_if_visit_timestamp_too_old() {
let mut srv = create_identity_server(|c| c.visit_deadline(Duration::days(90))); block_on(async {
let cookie = login_cookie( let mut srv =
COOKIE_LOGIN, create_identity_server(|c| c.visit_deadline(Duration::days(90))).await;
None, let cookie = login_cookie(
Some(SystemTime::now() - Duration::days(180).to_std().unwrap()), COOKIE_LOGIN,
); None,
let mut resp = test::call_service( Some(SystemTime::now() - Duration::days(180).to_std().unwrap()),
&mut srv, );
TestRequest::with_uri("/") let mut resp = test::call_service(
.cookie(cookie.clone()) &mut srv,
.to_request(), TestRequest::with_uri("/")
); .cookie(cookie.clone())
assert_logged_in(&mut resp, None); .to_request(),
assert_login_cookie( )
&mut resp, .await;
COOKIE_LOGIN, assert_login_cookie(
LoginTimestampCheck::NoTimestamp, &mut resp,
VisitTimeStampCheck::NewTimestamp, COOKIE_LOGIN,
); LoginTimestampCheck::NoTimestamp,
VisitTimeStampCheck::NewTimestamp,
);
assert_logged_in(resp, None).await;
})
} }
#[test] #[test]
fn test_identity_cookie_not_updated_on_login_deadline() { fn test_identity_cookie_not_updated_on_login_deadline() {
let mut srv = create_identity_server(|c| c.login_deadline(Duration::days(90))); block_on(async {
let cookie = login_cookie(COOKIE_LOGIN, Some(SystemTime::now()), None); let mut srv =
let mut resp = test::call_service( create_identity_server(|c| c.login_deadline(Duration::days(90))).await;
&mut srv, let cookie = login_cookie(COOKIE_LOGIN, Some(SystemTime::now()), None);
TestRequest::with_uri("/") let mut resp = test::call_service(
.cookie(cookie.clone()) &mut srv,
.to_request(), TestRequest::with_uri("/")
); .cookie(cookie.clone())
assert_logged_in(&mut resp, Some(COOKIE_LOGIN)); .to_request(),
assert_no_login_cookie(&mut resp); )
.await;
assert_no_login_cookie(&mut resp);
assert_logged_in(resp, Some(COOKIE_LOGIN)).await;
})
} }
#[test] #[test]
fn test_identity_cookie_updated_on_visit_deadline() { fn test_identity_cookie_updated_on_visit_deadline() {
let mut srv = create_identity_server(|c| { block_on(async {
c.visit_deadline(Duration::days(90)) let mut srv = create_identity_server(|c| {
.login_deadline(Duration::days(90)) c.visit_deadline(Duration::days(90))
}); .login_deadline(Duration::days(90))
let timestamp = SystemTime::now() - Duration::days(1).to_std().unwrap(); })
let cookie = login_cookie(COOKIE_LOGIN, Some(timestamp), Some(timestamp)); .await;
let mut resp = test::call_service( let timestamp = SystemTime::now() - Duration::days(1).to_std().unwrap();
&mut srv, let cookie = login_cookie(COOKIE_LOGIN, Some(timestamp), Some(timestamp));
TestRequest::with_uri("/") let mut resp = test::call_service(
.cookie(cookie.clone()) &mut srv,
.to_request(), TestRequest::with_uri("/")
); .cookie(cookie.clone())
assert_logged_in(&mut resp, Some(COOKIE_LOGIN)); .to_request(),
assert_login_cookie( )
&mut resp, .await;
COOKIE_LOGIN, assert_login_cookie(
LoginTimestampCheck::OldTimestamp(timestamp), &mut resp,
VisitTimeStampCheck::NewTimestamp, COOKIE_LOGIN,
); LoginTimestampCheck::OldTimestamp(timestamp),
VisitTimeStampCheck::NewTimestamp,
);
assert_logged_in(resp, Some(COOKIE_LOGIN)).await;
})
} }
} }