mirror of
https://github.com/actix/actix-extras.git
synced 2024-11-30 10:32:55 +01:00
add support for session access from guards (#234)
This commit is contained in:
parent
8db1088345
commit
4d77e26e1e
@ -1,11 +1,13 @@
|
||||
# Changes
|
||||
|
||||
## Unreleased - 2021-xx-xx
|
||||
### Fixed
|
||||
- Implement `SessionExt` for `GuardContext`. [#234]
|
||||
- Do not leak internal implementation details to callers when errors occur. [#236]
|
||||
|
||||
[#234]: https://github.com/actix/actix-extras/pull/234
|
||||
[#236]: https://github.com/actix/actix-extras/pull/236
|
||||
|
||||
|
||||
## 0.6.1 - 2022-03-21
|
||||
- No significant changes since `0.6.0`.
|
||||
|
||||
|
@ -193,13 +193,14 @@ pub mod test_helpers {
|
||||
*policy,
|
||||
)
|
||||
.await;
|
||||
acceptance_tests::guard(store_builder.clone(), *policy).await;
|
||||
}
|
||||
}
|
||||
|
||||
mod acceptance_tests {
|
||||
use actix_web::{
|
||||
dev::Service,
|
||||
middleware, test,
|
||||
guard, middleware, test,
|
||||
web::{self, get, post, resource, Bytes},
|
||||
App, HttpResponse, Result,
|
||||
};
|
||||
@ -209,7 +210,7 @@ pub mod test_helpers {
|
||||
|
||||
use crate::{
|
||||
middleware::SessionLength, storage::SessionStore, test_helpers::key,
|
||||
CookieContentSecurity, Session, SessionMiddleware,
|
||||
CookieContentSecurity, Session, SessionExt, SessionMiddleware,
|
||||
};
|
||||
|
||||
pub(super) async fn basic_workflow<F, Store>(
|
||||
@ -308,6 +309,91 @@ pub mod test_helpers {
|
||||
assert_eq!(cookie_2.max_age(), Some(Duration::seconds(60)));
|
||||
}
|
||||
|
||||
pub(super) async fn guard<F, Store>(store_builder: F, policy: CookieContentSecurity)
|
||||
where
|
||||
Store: SessionStore + 'static,
|
||||
F: Fn() -> Store + Clone + Send + 'static,
|
||||
{
|
||||
let srv = actix_test::start(move || {
|
||||
App::new()
|
||||
.wrap(
|
||||
SessionMiddleware::builder(store_builder(), key())
|
||||
.cookie_name("test-session".into())
|
||||
.cookie_content_security(policy)
|
||||
.session_length(SessionLength::Predetermined {
|
||||
max_session_length: Some(time::Duration::days(7)),
|
||||
})
|
||||
.build(),
|
||||
)
|
||||
.wrap(middleware::Logger::default())
|
||||
.service(resource("/").route(get().to(index)))
|
||||
.service(resource("/do_something").route(post().to(do_something)))
|
||||
.service(resource("/login").route(post().to(login)))
|
||||
.service(resource("/logout").route(post().to(logout)))
|
||||
.service(
|
||||
web::scope("/protected")
|
||||
.guard(guard::fn_guard(|g| {
|
||||
g.get_session().get::<String>("user_id").unwrap().is_some()
|
||||
}))
|
||||
.service(resource("/count").route(get().to(count))),
|
||||
)
|
||||
});
|
||||
|
||||
// Step 1: GET without session info
|
||||
// - response should be a unsuccessful status
|
||||
let req_1 = srv.get("/protected/count").send();
|
||||
let resp_1 = req_1.await.unwrap();
|
||||
assert!(!resp_1.status().is_success());
|
||||
|
||||
// Step 2: POST to login
|
||||
// - set-cookie actix-session will be in response (session cookie #1)
|
||||
// - updates session state: {"counter": 0, "user_id": "ferris"}
|
||||
let req_2 = srv.post("/login").send_json(&json!({"user_id": "ferris"}));
|
||||
let resp_2 = req_2.await.unwrap();
|
||||
let cookie_1 = resp_2
|
||||
.cookies()
|
||||
.unwrap()
|
||||
.clone()
|
||||
.into_iter()
|
||||
.find(|c| c.name() == "test-session")
|
||||
.unwrap();
|
||||
|
||||
// Step 3: POST to do_something
|
||||
// - adds new session state: {"counter": 1, "user_id": "ferris" }
|
||||
// - set-cookie actix-session should be in response (session cookie #2)
|
||||
// - response should be: {"counter": 1, "user_id": None}
|
||||
let req_3 = srv.post("/do_something").cookie(cookie_1.clone()).send();
|
||||
let mut resp_3 = req_3.await.unwrap();
|
||||
let result_3 = resp_3.json::<IndexResponse>().await.unwrap();
|
||||
assert_eq!(
|
||||
result_3,
|
||||
IndexResponse {
|
||||
user_id: Some("ferris".into()),
|
||||
counter: 1
|
||||
}
|
||||
);
|
||||
let cookie_2 = resp_3
|
||||
.cookies()
|
||||
.unwrap()
|
||||
.clone()
|
||||
.into_iter()
|
||||
.find(|c| c.name() == "test-session")
|
||||
.unwrap();
|
||||
|
||||
// Step 4: GET using a existing user id
|
||||
// - response should be: {"counter": 3, "user_id": "ferris"}
|
||||
let req_4 = srv.get("/protected/count").cookie(cookie_2.clone()).send();
|
||||
let mut resp_4 = req_4.await.unwrap();
|
||||
let result_4 = resp_4.json::<IndexResponse>().await.unwrap();
|
||||
assert_eq!(
|
||||
result_4,
|
||||
IndexResponse {
|
||||
user_id: Some("ferris".into()),
|
||||
counter: 1
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
pub(super) async fn complex_workflow<F, Store>(
|
||||
store_builder: F,
|
||||
is_invalidation_supported: bool,
|
||||
@ -549,6 +635,13 @@ pub mod test_helpers {
|
||||
Ok(HttpResponse::Ok().json(&IndexResponse { user_id, counter }))
|
||||
}
|
||||
|
||||
async fn count(session: Session) -> Result<HttpResponse> {
|
||||
let user_id: Option<String> = session.get::<String>("user_id").unwrap();
|
||||
let counter: i32 = session.get::<i32>("counter").unwrap().unwrap();
|
||||
|
||||
Ok(HttpResponse::Ok().json(&IndexResponse { user_id, counter }))
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct Identity {
|
||||
user_id: String,
|
||||
|
@ -1,5 +1,6 @@
|
||||
use actix_web::{
|
||||
dev::{ServiceRequest, ServiceResponse},
|
||||
guard::GuardContext,
|
||||
HttpMessage, HttpRequest,
|
||||
};
|
||||
|
||||
@ -29,3 +30,9 @@ impl SessionExt for ServiceResponse {
|
||||
self.request().get_session()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> SessionExt for GuardContext<'a> {
|
||||
fn get_session(&self) -> Session {
|
||||
Session::get_session(&mut *self.req_data_mut())
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user