mirror of
https://github.com/actix/actix-extras.git
synced 2024-11-23 15:51:06 +01:00
Add the ability to change the keys (#348)
* feat: add the ability to change the session key store in redis * feat: change everywhere the constants are used * refactor: add formatting with cargo fmt --------- Co-authored-by: Dany Gagnon <danygagnon@Danys-MacBook-Pro.local>
This commit is contained in:
parent
daffc24245
commit
5414e2655b
@ -9,6 +9,9 @@ pub(crate) struct Configuration {
|
||||
pub(crate) on_logout: LogoutBehaviour,
|
||||
pub(crate) login_deadline: Option<Duration>,
|
||||
pub(crate) visit_deadline: Option<Duration>,
|
||||
pub(crate) id_key: &'static str,
|
||||
pub(crate) last_visit_unix_timestamp_key: &'static str,
|
||||
pub(crate) login_unix_timestamp_key: &'static str,
|
||||
}
|
||||
|
||||
impl Default for Configuration {
|
||||
@ -17,6 +20,9 @@ impl Default for Configuration {
|
||||
on_logout: LogoutBehaviour::PurgeSession,
|
||||
login_deadline: None,
|
||||
visit_deadline: None,
|
||||
id_key: "actix_identity.user_id",
|
||||
last_visit_unix_timestamp_key: "actix_identity.last_visited_at",
|
||||
login_unix_timestamp_key: "actix_identity.logged_in_at",
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -58,6 +64,24 @@ impl IdentityMiddlewareBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
/// Set a custom key to identify the user in the session.
|
||||
pub fn id_key(mut self, key: &'static str) -> Self {
|
||||
self.configuration.id_key = key;
|
||||
self
|
||||
}
|
||||
|
||||
/// Set a custom key to store the last visited unix timestamp.
|
||||
pub fn last_visit_unix_timestamp_key(mut self, key: &'static str) -> Self {
|
||||
self.configuration.last_visit_unix_timestamp_key = key;
|
||||
self
|
||||
}
|
||||
|
||||
/// Set a custom key to store the login unix timestamp.
|
||||
pub fn login_unix_timestamp_key(mut self, key: &'static str) -> Self {
|
||||
self.configuration.login_unix_timestamp_key = key;
|
||||
self
|
||||
}
|
||||
|
||||
/// Determines how [`Identity::logout`](crate::Identity::logout) affects the current session.
|
||||
///
|
||||
/// By default, the current session is purged ([`LogoutBehaviour::PurgeSession`]).
|
||||
|
@ -82,6 +82,9 @@ pub(crate) struct IdentityInner {
|
||||
pub(crate) logout_behaviour: LogoutBehaviour,
|
||||
pub(crate) is_login_deadline_enabled: bool,
|
||||
pub(crate) is_visit_deadline_enabled: bool,
|
||||
pub(crate) id_key: &'static str,
|
||||
pub(crate) last_visit_unix_timestamp_key: &'static str,
|
||||
pub(crate) login_unix_timestamp_key: &'static str,
|
||||
}
|
||||
|
||||
impl IdentityInner {
|
||||
@ -101,15 +104,11 @@ impl IdentityInner {
|
||||
/// Retrieve the user id attached to the current session.
|
||||
fn get_identity(&self) -> Result<String, GetIdentityError> {
|
||||
self.session
|
||||
.get::<String>(ID_KEY)?
|
||||
.get::<String>(self.id_key)?
|
||||
.ok_or_else(|| MissingIdentityError.into())
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) const ID_KEY: &str = "actix_identity.user_id";
|
||||
pub(crate) const LAST_VISIT_UNIX_TIMESTAMP_KEY: &str = "actix_identity.last_visited_at";
|
||||
pub(crate) const LOGIN_UNIX_TIMESTAMP_KEY: &str = "actix_identity.logged_in_at";
|
||||
|
||||
impl Identity {
|
||||
/// Return the user id associated to the current session.
|
||||
///
|
||||
@ -130,7 +129,7 @@ impl Identity {
|
||||
pub fn id(&self) -> Result<String, GetIdentityError> {
|
||||
self.0
|
||||
.session
|
||||
.get(ID_KEY)?
|
||||
.get(self.0.id_key)?
|
||||
.ok_or_else(|| LostIdentityError.into())
|
||||
}
|
||||
|
||||
@ -153,13 +152,15 @@ impl Identity {
|
||||
/// ```
|
||||
pub fn login(ext: &Extensions, id: String) -> Result<Self, LoginError> {
|
||||
let inner = IdentityInner::extract(ext);
|
||||
inner.session.insert(ID_KEY, id)?;
|
||||
inner.session.insert(inner.id_key, id)?;
|
||||
let now = OffsetDateTime::now_utc().unix_timestamp();
|
||||
if inner.is_login_deadline_enabled {
|
||||
inner.session.insert(LOGIN_UNIX_TIMESTAMP_KEY, now)?;
|
||||
inner.session.insert(inner.login_unix_timestamp_key, now)?;
|
||||
}
|
||||
if inner.is_visit_deadline_enabled {
|
||||
inner.session.insert(LAST_VISIT_UNIX_TIMESTAMP_KEY, now)?;
|
||||
inner
|
||||
.session
|
||||
.insert(inner.last_visit_unix_timestamp_key, now)?;
|
||||
}
|
||||
inner.session.renew();
|
||||
Ok(Self(inner))
|
||||
@ -191,12 +192,12 @@ impl Identity {
|
||||
self.0.session.purge();
|
||||
}
|
||||
LogoutBehaviour::DeleteIdentityKeys => {
|
||||
self.0.session.remove(ID_KEY);
|
||||
self.0.session.remove(self.0.id_key);
|
||||
if self.0.is_login_deadline_enabled {
|
||||
self.0.session.remove(LOGIN_UNIX_TIMESTAMP_KEY);
|
||||
self.0.session.remove(self.0.login_unix_timestamp_key);
|
||||
}
|
||||
if self.0.is_visit_deadline_enabled {
|
||||
self.0.session.remove(LAST_VISIT_UNIX_TIMESTAMP_KEY);
|
||||
self.0.session.remove(self.0.last_visit_unix_timestamp_key);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -212,7 +213,7 @@ impl Identity {
|
||||
Ok(self
|
||||
.0
|
||||
.session
|
||||
.get(LOGIN_UNIX_TIMESTAMP_KEY)?
|
||||
.get(self.0.login_unix_timestamp_key)?
|
||||
.map(OffsetDateTime::from_unix_timestamp)
|
||||
.transpose()
|
||||
.map_err(SessionExpiryError)?)
|
||||
@ -222,7 +223,7 @@ impl Identity {
|
||||
Ok(self
|
||||
.0
|
||||
.session
|
||||
.get(LAST_VISIT_UNIX_TIMESTAMP_KEY)?
|
||||
.get(self.0.last_visit_unix_timestamp_key)?
|
||||
.map(OffsetDateTime::from_unix_timestamp)
|
||||
.transpose()
|
||||
.map_err(SessionExpiryError)?)
|
||||
@ -230,7 +231,9 @@ impl Identity {
|
||||
|
||||
pub(crate) fn set_last_visited_at(&self) -> Result<(), LoginError> {
|
||||
let now = OffsetDateTime::now_utc().unix_timestamp();
|
||||
self.0.session.insert(LAST_VISIT_UNIX_TIMESTAMP_KEY, now)?;
|
||||
self.0
|
||||
.session
|
||||
.insert(self.0.last_visit_unix_timestamp_key, now)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -114,6 +114,9 @@ where
|
||||
logout_behaviour: configuration.on_logout.clone(),
|
||||
is_login_deadline_enabled: configuration.login_deadline.is_some(),
|
||||
is_visit_deadline_enabled: configuration.visit_deadline.is_some(),
|
||||
id_key: configuration.id_key,
|
||||
last_visit_unix_timestamp_key: configuration.last_visit_unix_timestamp_key,
|
||||
login_unix_timestamp_key: configuration.login_unix_timestamp_key,
|
||||
};
|
||||
req.extensions_mut().insert(identity_inner);
|
||||
enforce_policies(&req, &configuration);
|
||||
|
@ -28,6 +28,33 @@ async fn login_works() {
|
||||
assert!(response.status().is_success());
|
||||
}
|
||||
|
||||
#[actix_web::test]
|
||||
async fn custom_keys_work_as_expected() {
|
||||
let custom_id_key = "custom.user_id";
|
||||
let custom_last_visited_key = "custom.last_visited_at";
|
||||
let custom_logged_in_key = "custom.logged_in_at";
|
||||
|
||||
let app = TestApp::spawn_with_config(
|
||||
IdentityMiddleware::builder()
|
||||
.id_key(custom_id_key)
|
||||
.last_visit_unix_timestamp_key(custom_last_visited_key)
|
||||
.login_unix_timestamp_key(custom_logged_in_key),
|
||||
);
|
||||
let user_id = user_id();
|
||||
|
||||
let body = app.post_login(user_id.clone()).await;
|
||||
assert_eq!(body.user_id, Some(user_id.clone()));
|
||||
|
||||
let response = app.get_identity_required().await;
|
||||
assert!(response.status().is_success());
|
||||
|
||||
let response = app.post_logout().await;
|
||||
assert!(response.status().is_success());
|
||||
|
||||
let response = app.get_identity_required().await;
|
||||
assert_eq!(response.status(), StatusCode::UNAUTHORIZED);
|
||||
}
|
||||
|
||||
#[actix_web::test]
|
||||
async fn logging_in_again_replaces_the_current_identity() {
|
||||
let app = TestApp::spawn();
|
||||
|
Loading…
Reference in New Issue
Block a user