diff --git a/src/auth.rs b/src/auth.rs index 4742dfad596..19ddaa98b7d 100644 --- a/src/auth.rs +++ b/src/auth.rs @@ -9,6 +9,7 @@ use crate::util::errors::{ account_locked, forbidden, internal, AppError, AppResult, InsecurelyGeneratedTokenRevoked, }; use chrono::Utc; +use diesel::PgConnection; use http::header; #[derive(Debug, Clone)] @@ -56,7 +57,7 @@ impl AuthCheck { } pub fn check(&self, request: &T) -> AppResult { - let auth = authenticate_user(request)?; + let auth = authenticate(request)?; if let Some(token) = auth.api_token() { if !self.allow_token { @@ -152,50 +153,71 @@ impl Authentication { } } -fn authenticate_user(req: &T) -> AppResult { - controllers::util::verify_origin(req)?; - - let conn = req.app().db_write()?; - +fn authenticate_via_cookie( + req: &T, + conn: &PgConnection, +) -> AppResult> { let user_id_from_session = req .session_get("user_id") .and_then(|s| s.parse::().ok()); - if let Some(id) = user_id_from_session { - let user = User::find(&conn, id) - .map_err(|err| err.chain(internal("user_id from cookie not found in database")))?; + let Some(id) = user_id_from_session else { return Ok(None) }; - ensure_not_locked(&user)?; + let user = User::find(conn, id) + .map_err(|err| err.chain(internal("user_id from cookie not found in database")))?; - req.add_custom_metadata("uid", id); + ensure_not_locked(&user)?; - return Ok(Authentication::Cookie(CookieAuthentication { user })); - } + req.add_custom_metadata("uid", id); - // Otherwise, look for an `Authorization` header on the request + Ok(Some(CookieAuthentication { user })) +} + +fn authenticate_via_token( + req: &T, + conn: &PgConnection, +) -> AppResult> { let maybe_authorization = req .headers() .get(header::AUTHORIZATION) .and_then(|h| h.to_str().ok()); - if let Some(header_value) = maybe_authorization { - let token = ApiToken::find_by_api_token(&conn, header_value).map_err(|e| { - if e.is::() { - e - } else { - e.chain(internal("invalid token")).chain(forbidden()) - } - })?; + let Some(header_value) = maybe_authorization else { return Ok(None) }; - let user = User::find(&conn, token.user_id) - .map_err(|err| err.chain(internal("user_id from token not found in database")))?; + let token = ApiToken::find_by_api_token(conn, header_value).map_err(|e| { + if e.is::() { + e + } else { + e.chain(internal("invalid token")).chain(forbidden()) + } + })?; - ensure_not_locked(&user)?; + let user = User::find(conn, token.user_id) + .map_err(|err| err.chain(internal("user_id from token not found in database")))?; - req.add_custom_metadata("uid", token.user_id); - req.add_custom_metadata("tokenid", token.id); + ensure_not_locked(&user)?; + + req.add_custom_metadata("uid", token.user_id); + req.add_custom_metadata("tokenid", token.id); + + Ok(Some(TokenAuthentication { user, token })) +} + +fn authenticate(req: &T) -> AppResult { + controllers::util::verify_origin(req)?; + + let conn = req.app().db_write()?; + + match authenticate_via_cookie(req, &conn) { + Ok(None) => {} + Ok(Some(auth)) => return Ok(Authentication::Cookie(auth)), + Err(err) => return Err(err), + } - return Ok(Authentication::Token(TokenAuthentication { user, token })); + match authenticate_via_token(req, &conn) { + Ok(None) => {} + Ok(Some(auth)) => return Ok(Authentication::Token(auth)), + Err(err) => return Err(err), } // Unable to authenticate the user