Skip to content

removed createdby attributes and enforced expiry time #13

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Dec 22, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 4 additions & 43 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,11 @@ $ cargo add async-mongodb-session
```

## Overview
By default this library utilises the document expiration feature based on [specific clock time](https://docs.mongodb.com/manual/tutorial/expire-data/#expire-documents-at-a-specific-clock-time) supported by mongodb to auto-expire the session.
This library utilises the document expiration feature in mongodb and is based on [specific clock time](https://docs.mongodb.com/manual/tutorial/expire-data/#expire-documents-at-a-specific-clock-time).

For other option to offloading the session expiration to the mongodb layer check the [Advance options](#advance-options).
The expiry index is applied to the collection when a new session object is created.

As document expiration is a [background task](https://docs.mongodb.com/manual/core/index-ttl/#timing-of-the-delete-operation) some stale sessions may be present in the database but won't be returned by this library.

## Example with tide
Create an HTTP server that keep track of user visits in the session.
Expand Down Expand Up @@ -95,47 +97,6 @@ async fn main() -> tide::Result<()> {
Ok(())
}
```
## Advance options
a [specified number of seconds](https://docs.mongodb.com/manual/tutorial/expire-data/#expire-documents-after-a-specified-number-of-seconds) or in a

The specified number of seconds approach is designed to enable the session time out to be managed at the mongodb layer. This approach provides a globally consistent session timeout across multiple processes but has the downside that all services using the same session collection must use the same timeout value.

The specific clock time clock time approach is where you require more flexibility on your session timeouts such as a different session timeout per running service or you would prefer to manage the session time out at the process level. This is more flexible but might lead to some perceived inconsistency in session timeout depending on your upgrade/rollout strategy.

The management of the expiry feature fits into the 12 factor [admin process definintion](https://12factor.net/admin-processes) so it's recommended to use an process outside of your web application to manage the expiry parameters.

## Manual configuration

A `created` property is available on the root of the session document that so the [expiry feature](https://docs.mongodb.com/manual/tutorial/expire-data/#expire-documents-after-a-specified-number-of-seconds) can be used in the configuration.

If your application code to create a session store is something like:
```
let store = MongodbSessionStore::connect("mongodb://127.0.0.1:27017", "db_name", "coll_session").await?;
```

Then the script to create the expiry would be:
```
use db_name;
db.coll_session.createIndex( { "created": 1 } , { expireAfterSeconds: 300 } );
```

If you wish to redefine the session duration then the index must be dropped first using:
```
use db_name;
db.coll_session.dropIndex( { "created": 1 })
db.coll_session.createIndex( { "created": 1 } , { expireAfterSeconds: 300 } );
```

Other way to set create the index is using `index_on_created` passing the amount of seconds to expiry after the session.

Also, an `expireAt` property is available on the root of the session document IFF the session expire is set. Note that [async-session doesn't set by default](https://github.com/http-rs/async-session/blob/main/src/session.rs#L98).

To enable this [expiry feature](https://docs.mongodb.com/manual/tutorial/expire-data/#expire-documents-at-a-specific-clock-time) at `index` for `expireAt` should be created calling `index_on_expiry_at` function or with this script ( following the above example )

```
use db_name;
db.coll_session.createIndex( { "expireAt": 1 } , { expireAfterSeconds: 0 } );
```

## Test

Expand Down
59 changes: 9 additions & 50 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
use async_session::chrono::{Duration, Utc};
use async_session::{async_trait, Result, Session, SessionStore};
use mongodb::bson;
use mongodb::bson::doc;
use mongodb::bson::{doc, Bson};
use mongodb::options::{ReplaceOptions, SelectionCriteria};
use mongodb::Client;

Expand All @@ -28,7 +28,6 @@ pub struct MongodbSessionStore {
client: mongodb::Client,
db: String,
coll_name: String,
ttl: usize,
}

impl MongodbSessionStore {
Expand Down Expand Up @@ -72,7 +71,6 @@ impl MongodbSessionStore {
client,
db: db.to_string(),
coll_name: coll_name.to_string(),
ttl: 1200, // 20 mins by default.
}
}

Expand All @@ -95,34 +93,6 @@ impl MongodbSessionStore {
Ok(())
}

/// Get the default ttl value in seconds.
/// ```rust
/// # fn main() -> async_session::Result { async_std::task::block_on(async {
/// # use async_mongodb_session::MongodbSessionStore;
/// let store =
/// MongodbSessionStore::new("mongodb://127.0.0.1:27017", "db_name", "collection")
/// .await?;
/// let ttl = store.ttl();
/// # Ok(()) }) }
/// ```
pub fn ttl(&self) -> usize {
self.ttl
}

/// Set the default ttl value in seconds.
/// ```rust
/// # fn main() -> async_session::Result { async_std::task::block_on(async {
/// # use async_mongodb_session::MongodbSessionStore;
/// let mut store =
/// MongodbSessionStore::new("mongodb://127.0.0.1:27017", "db_name", "collection")
/// .await?;
/// store.set_ttl(300);
/// # Ok(()) }) }
/// ```
pub fn set_ttl(&mut self, ttl: usize) {
self.ttl = ttl;
}

/// private associated function
/// Create an `expire after seconds` index in the provided field.
/// Testing is covered by initialize test.
Expand Down Expand Up @@ -151,25 +121,6 @@ impl MongodbSessionStore {
Ok(())
}

/// Create a new index for the `created` property and set the expiry ttl (in secods).
/// The session will expire when the number of seconds in the expireAfterSeconds field has passed
/// since the time specified in its created field.
/// https://docs.mongodb.com/manual/tutorial/expire-data/#expire-documents-after-a-specified-number-of-seconds
/// ```rust
/// # fn main() -> async_session::Result { async_std::task::block_on(async {
/// # use async_mongodb_session::MongodbSessionStore;
/// let store =
/// MongodbSessionStore::new("mongodb://127.0.0.1:27017", "db_name", "collection")
/// .await?;
/// store.index_on_created(300).await?;
/// # Ok(()) }) }
/// ```
pub async fn index_on_created(&self, expire_after_seconds: u32) -> Result {
self.create_expire_index("created", expire_after_seconds)
.await?;
Ok(())
}

/// Create a new index for the `expireAt` property, allowing to expire sessions at a specific clock time.
/// If the `expireAt` date field contains a date in the past, mongodb considers the document expired and will be deleted.
/// https://docs.mongodb.com/manual/tutorial/expire-data/#expire-documents-at-a-specific-clock-time
Expand Down Expand Up @@ -220,6 +171,14 @@ impl SessionStore for MongodbSessionStore {
Some(v) => v.clone(),
None => return Ok(None),
};
// mongodb runs the background task that removes expired documents runs every 60 seconds.
// https://docs.mongodb.com/manual/core/index-ttl/#timing-of-the-delete-operation
// This prevents those documents being returned
if let Some(expiry_at) = doc.get("expireAt").and_then(Bson::as_datetime) {
if expiry_at < &Utc::now() {
return Ok(None);
}
}
Ok(Some(bson::from_bson::<Session>(bsession)?))
}
}
Expand Down
4 changes: 1 addition & 3 deletions tests/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,9 +108,7 @@ mod tests {

let cookie_value = store.store_session(session).await?.unwrap();

// mongodb runs the background task that removes expired documents runs every 60 seconds.
// https://docs.mongodb.com/manual/core/index-ttl/#timing-of-the-delete-operation
task::sleep(Duration::from_secs(60)).await;
task::sleep(Duration::from_secs(1)).await;
let session_to_recover = store.load_session(cookie_value).await?;

assert!(&session_to_recover.is_none());
Expand Down