Skip to content
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

WIP: Implement sessions database table #3307

Closed
wants to merge 18 commits into from

Conversation

Turbo87
Copy link
Member

@Turbo87 Turbo87 commented Feb 16, 2021

As discussed in the team meeting last week, this PR implements a sessions table in the database to address #2630.

This is still work-in-progress, but feel free to comment if you have any concerns.

/cc @jsha @jtgeibel

@Turbo87 Turbo87 added C-enhancement ✨ Category: Adding new behavior or a change to the way an existing feature works A-backend ⚙️ labels Feb 16, 2021
@rust-lang rust-lang deleted a comment from rust-highfive Feb 16, 2021
Copy link
Contributor

@jsha jsha left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks awesome! Thanks for writing it. One optimization: If the user's cookie asserts both a session ID and a token, you can avoid having an index on the hashed_token field. Indexes can take up a surprising amount of memory.

Comment on lines +6 to +9
user_id INTEGER NOT NULL
CONSTRAINT sessions_users_id_fk
REFERENCES users
ON UPDATE CASCADE ON DELETE CASCADE,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You'll probably want to delete stale sessions eventually. In a big database, deleting old rows can be relatively expensive. For this, you might want to use partitioning (https://www.postgresql.org/docs/10/ddl-partitioning.html), which lets you drop old, stale partitions cheaply while still treating the partitions as a single table. However, to use partitioning you need to have no foreign keys on the partitioned table. Suggestion: Make user_id not a foreign key. We don't expect that user_ids change, so we don't need ON UPDATE CASCADE. And if the users entry is deleted, we can simply treat the session as invalid. So we don't need ON DELETE CASCADE.

Comment on lines +185 to +190
// try to revoke the session in the database, but explicitly
// ignore failures
let _result: Result<_, Box<dyn AppError>> = req
.db_conn()
.map_err(Into::into)
.and_then(|conn| Session::revoke_by_token(&conn, &token).map_err(Into::into));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps log or increment a stat in this case? Or have a set of expected errors (like timeout) and pass through unexpected errors (like permission denied or malformed SQL).

Comment on lines +62 to +74
// If the database is in read only mode, we can't update these fields.
// Try updating in a new transaction, if that fails, fall back to reading
conn.transaction(|| {
diesel::update(sessions)
.set((
sessions::last_used_at.eq(diesel::dsl::now),
sessions::last_ip_address.eq(IpNetwork::from(ip_address)),
sessions::last_user_agent.eq(user_agent),
))
.get_result(conn)
.optional()
})
.or_else(|_| sessions.first(conn).optional())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's probably a good idea to do the update only if:

  • The IP address has changed, or
  • The User-Agent has changed, or
  • The last_used_at has increased by more than 15 minutes.

This will save you from having to do a DB write on every cookie-authenticated request.

bors added a commit that referenced this pull request Mar 3, 2021
Simplify `authenticate_user()` function

The function was a bit hard to read and difficult to extend (see #3307). This PR simplifies it a little bit by returning early if a suitable authentication method was found.

r? `@jtgeibel`
@bors
Copy link
Contributor

bors commented Mar 3, 2021

☔ The latest upstream changes (presumably #3328) made this pull request unmergeable. Please resolve the merge conflicts.

@pietroalbini
Copy link
Member

Filed a request to the foundation for the additional data collection.

@Turbo87
Copy link
Member Author

Turbo87 commented Oct 1, 2021

closing this for now due to all the conflicts and the foundation not having given us an answer yet wether we can do this or not... 🤷‍♂️

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-backend ⚙️ C-enhancement ✨ Category: Adding new behavior or a change to the way an existing feature works
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants