Skip to content

Commit 322ebf4

Browse files
committed
Auto merge of #3280 - Turbo87:session-middleware, r=jtgeibel
Remove `CaptureUserIdFromCookie` middleware in favor accessing cookie directly This PR resolves #2651 Unfortunately for this to work we have to use a few implementation details of `conduit_cookie`, but since we control the crate ourselves I guess this is a reasonable tradeoff. Ideally the `conduit_cookie` crate would export some kind of test helper function though. r? `@jtgeibel` /cc `@jsha`
2 parents 1816846 + f36e757 commit 322ebf4

File tree

7 files changed

+54
-61
lines changed

7 files changed

+54
-61
lines changed

Diff for: src/controllers/user/session.rs

-2
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ use oauth2::reqwest::http_client;
55
use oauth2::{AuthorizationCode, Scope, TokenResponse};
66

77
use crate::github::GithubUser;
8-
use crate::middleware::current_user::TrustedUserId;
98
use crate::models::{NewUser, User};
109
use crate::schema::users;
1110
use crate::util::errors::ReadOnlyMode;
@@ -108,7 +107,6 @@ pub fn authorize(req: &mut dyn RequestExt) -> EndpointResult {
108107
// Log in by setting a cookie and the middleware authentication
109108
req.session_mut()
110109
.insert("user_id".to_string(), user.id.to_string());
111-
req.mut_extensions().insert(TrustedUserId(user.id));
112110

113111
super::me::me(req)
114112
}

Diff for: src/controllers/util.rs

+6-4
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
use chrono::Utc;
2+
use conduit_cookie::RequestSession;
23

34
use super::prelude::*;
45

5-
use crate::middleware::current_user::TrustedUserId;
66
use crate::middleware::log_request;
77
use crate::models::{ApiToken, User};
88
use crate::util::errors::{
@@ -62,9 +62,11 @@ fn verify_origin(req: &dyn RequestExt) -> AppResult<()> {
6262

6363
fn authenticate_user(req: &dyn RequestExt) -> AppResult<AuthenticatedUser> {
6464
let conn = req.db_conn()?;
65-
let (user_id, token_id) = if let Some(id) =
66-
req.extensions().find::<TrustedUserId>().map(|x| x.0)
67-
{
65+
66+
let session = req.session();
67+
let user_id_from_session = session.get("user_id").and_then(|s| s.parse::<i32>().ok());
68+
69+
let (user_id, token_id) = if let Some(id) = user_id_from_session {
6870
(id, None)
6971
} else {
7072
// Otherwise, look for an `Authorization` header on the request

Diff for: src/middleware.rs

-5
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ mod prelude {
44
}
55

66
use self::app::AppMiddleware;
7-
use self::current_user::CaptureUserIdFromCookie;
87
use self::debug::*;
98
use self::ember_html::EmberHtml;
109
use self::head::Head;
@@ -14,7 +13,6 @@ use self::static_or_continue::StaticOrContinue;
1413
pub mod app;
1514
mod balance_capacity;
1615
mod block_traffic;
17-
pub mod current_user;
1816
mod debug;
1917
mod ember_html;
2018
mod ensure_well_formed_500;
@@ -70,9 +68,6 @@ pub fn build_middleware(app: Arc<App>, endpoints: R404) -> MiddlewareBuilder {
7068

7169
m.add(AppMiddleware::new(app));
7270

73-
// Parse and save the user_id from the session cookie as part of the authentication logic
74-
m.add(CaptureUserIdFromCookie);
75-
7671
// Note: The following `m.around()` middleware is run from bottom to top
7772

7873
// This is currently the final middleware to run. If a middleware layer requires a database

Diff for: src/middleware/current_user.rs

-37
This file was deleted.

Diff for: src/middleware/log_request.rs

+2-5
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@
22
//! information that we care about like User-Agent
33
44
use super::prelude::*;
5-
use crate::middleware::current_user::TrustedUserId;
65
use crate::util::request_header;
76

87
use conduit::{header, Host, RequestExt, Scheme, StatusCode};
8+
use conduit_cookie::RequestSession;
99
use sentry::Level;
1010

1111
use std::fmt::{self, Display, Formatter};
@@ -86,10 +86,7 @@ fn report_to_sentry(req: &dyn RequestExt, res: &AfterResult, response_time: u64)
8686
let url = format!("{}://{}{}", scheme, host, path).parse().ok();
8787

8888
{
89-
let id = req
90-
.extensions()
91-
.find::<TrustedUserId>()
92-
.map(|x| x.0.to_string());
89+
let id = req.session().get("user_id").map(|str| str.to_string());
9390

9491
let user = sentry::User {
9592
id,

Diff for: src/tests/authentication.rs

+7-4
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
use crate::{util::RequestHelper, TestApp};
22

3-
use cargo_registry::middleware::current_user::TrustedUserId;
4-
5-
use conduit::{header, Handler, HandlerResult, Method, RequestExt, StatusCode};
3+
use crate::util::encode_session_header;
4+
use conduit::{header, Handler, HandlerResult, Method, StatusCode};
65
use conduit_test::MockRequest;
76

87
static URL: &str = "/api/v1/me/updates";
@@ -49,8 +48,12 @@ fn token_auth_cannot_find_token() {
4948
#[test]
5049
fn cookie_auth_cannot_find_user() {
5150
let (app, anon) = TestApp::init().empty();
51+
52+
let session_key = &app.as_inner().session_key;
53+
let cookie = encode_session_header(session_key, -1);
54+
5255
let mut request = anon.request_builder(Method::GET, URL);
53-
request.mut_extensions().insert(TrustedUserId(-1));
56+
request.header(header::COOKIE, &cookie);
5457

5558
let response = call(&app, request);
5659
let log_message = response.map(|_| ()).unwrap_err().to_string();

Diff for: src/tests/util.rs

+39-4
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ use cargo_registry::{
2727
background_jobs::Environment,
2828
db::DieselPool,
2929
git::{Credentials, RepositoryConfig},
30-
middleware::current_user::TrustedUserId,
3130
models::{ApiToken, CreatedApiToken, User},
3231
util::AppResponse,
3332
App, Config,
@@ -37,7 +36,8 @@ use serde_json::Value;
3736
use std::{marker::PhantomData, rc::Rc, sync::Arc, time::Duration};
3837
use swirl::Runner;
3938

40-
use conduit::{Handler, HandlerResult, Method, RequestExt};
39+
use conduit::{Handler, HandlerResult, Method};
40+
use conduit_cookie::SessionMiddleware;
4141
use conduit_test::MockRequest;
4242

4343
use cargo_registry::git::Repository as WorkerRepository;
@@ -46,6 +46,8 @@ use git2::Repository as UpstreamRepository;
4646
use url::Url;
4747

4848
pub use conduit::{header, StatusCode};
49+
use cookie::Cookie;
50+
use std::collections::HashMap;
4951

5052
pub fn init_logger() {
5153
let _ = tracing_subscriber::fmt()
@@ -209,6 +211,37 @@ impl TestApp {
209211
}
210212
}
211213

214+
/// This function can be used to create a `Cookie` header for mock requests that
215+
/// include cookie-based authentication.
216+
///
217+
/// ```
218+
/// let cookie = encode_session_header(session_key, user_id);
219+
/// request.header(header::COOKIE, &cookie);
220+
/// ```
221+
///
222+
/// The implementation matches roughly what is happening inside of the
223+
/// `SessionMiddleware` from `conduit_cookie`.
224+
pub fn encode_session_header(session_key: &str, user_id: i32) -> String {
225+
let cookie_name = "cargo_session";
226+
let cookie_key = cookie::Key::derive_from(session_key.as_bytes());
227+
228+
// build session data map
229+
let mut map = HashMap::new();
230+
map.insert("user_id".into(), user_id.to_string());
231+
232+
// encode the map into a cookie value string
233+
let session_middleware = SessionMiddleware::new(cookie_name, cookie_key.clone(), false);
234+
let encoded = session_middleware.encode(&map);
235+
236+
// put the cookie into a signed cookie jar
237+
let cookie = Cookie::build(cookie_name, encoded).finish();
238+
let mut jar = cookie::CookieJar::new();
239+
jar.signed(&cookie_key).add(cookie);
240+
241+
// read the raw cookie from the cookie jar
242+
jar.get(&cookie_name).unwrap().to_string()
243+
}
244+
212245
pub struct TestAppBuilder {
213246
config: Config,
214247
proxy: Option<String>,
@@ -463,9 +496,11 @@ pub struct MockCookieUser {
463496

464497
impl RequestHelper for MockCookieUser {
465498
fn request_builder(&self, method: Method, path: &str) -> MockRequest {
499+
let session_key = &self.app.as_inner().session_key;
500+
let cookie = encode_session_header(session_key, self.user.id);
501+
466502
let mut request = req(method, path);
467-
let id = TrustedUserId(self.user.id);
468-
request.mut_extensions().insert(id);
503+
request.header(header::COOKIE, &cookie);
469504
request
470505
}
471506

0 commit comments

Comments
 (0)