Skip to content

Commit

Permalink
Authentication Middleware
Browse files Browse the repository at this point in the history
  • Loading branch information
lucemans committed Jul 29, 2024
1 parent d25dbd4 commit 6433cbc
Show file tree
Hide file tree
Showing 6 changed files with 64 additions and 53 deletions.
37 changes: 37 additions & 0 deletions engine/src/auth/middleware.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
use std::sync::Arc;

use poem::{
http::StatusCode,
web::{cookie::CookieJar, Data},
Error, FromRequest, Request, RequestBody, Result, Route,
};
use uuid::Uuid;

use crate::state::AppState;

use super::session::SessionState;

pub struct AuthToken {
pub session: SessionState,
}

impl<'a> FromRequest<'a> for AuthToken {
async fn from_request(req: &'a Request, body: &mut RequestBody) -> Result<Self> {
let state = Data::<&Arc<AppState>>::from_request(req, body).await?;

let token = {
let token = req
.headers()
.get("Authorization")
.map(|x| x.to_str().unwrap().replace("Bearer ", ""))
.expect("No token found");
Uuid::parse_str(&token).unwrap()
};

let session = SessionState::get_by_id(token, &state.database)
.await
.unwrap();

Ok(AuthToken { session })
}
}
1 change: 1 addition & 0 deletions engine/src/auth/mod.rs
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
pub mod oauth;
pub mod session;
pub mod middleware;
67 changes: 19 additions & 48 deletions engine/src/routes/auth.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
use crate::{auth::session::SessionState, models::user_data::UserData, state::AppState};
use crate::{
auth::{middleware::AuthToken, session::SessionState},
models::user_data::UserData,
state::AppState,
};
use openid::{Options, Prompt, Token};
use poem::{
handler,
http::HeaderMap,
web::{cookie::CookieJar, Data, Json, Query, RealIp, Redirect},
web::{Data, Json, Query, RealIp, Redirect},
IntoResponse,
};
use serde::Deserialize;
use url::Url;
use std::{collections::HashSet, sync::Arc};
use tracing::info;
use uuid::Uuid;
use url::Url;

#[derive(Deserialize)]
struct LoginQuery {
Expand Down Expand Up @@ -92,7 +94,12 @@ pub async fn callback(

let token = session.id;

let mut redirect_url: Url = query.state.clone().unwrap_or("http://localhost:3000/me".to_string()).parse().unwrap();
let mut redirect_url: Url = query
.state
.clone()
.unwrap_or("http://localhost:3000/me".to_string())
.parse()
.unwrap();

redirect_url.set_query(Some(&format!("token={}", token)));

Expand All @@ -101,62 +108,26 @@ pub async fn callback(
}

#[handler]
pub async fn me(
state: Data<&Arc<AppState>>,
cookies: &CookieJar,
headers: &HeaderMap,
) -> impl IntoResponse {
let token = {
let token = cookies
.get("property.v3x.token")
.map(|x| x.value_str().to_string())
.or(headers
.get("Authorization")
.map(|x| x.to_str().unwrap().replace("Bearer ", "")))
.expect("No token found");
Uuid::parse_str(&token).unwrap()
};

let session = SessionState::get_by_id(token, &state.database)
.await
.unwrap();

let user = UserData::get_by_id(session.user_id, &state.database)
pub async fn me(state: Data<&Arc<AppState>>, token: AuthToken) -> impl IntoResponse {
let user = UserData::get_by_id(token.session.user_id, &state.database)
.await
.unwrap();

Json(user)
}

#[handler]
pub async fn get_sessions(state: Data<&Arc<AppState>>, cookies: &CookieJar) -> impl IntoResponse {
let token = cookies.get("property.v3x.token").unwrap();
let token = Uuid::parse_str(token.value_str()).unwrap();

let session = SessionState::get_by_id(token, &state.database)
.await
.unwrap();

let sessions = SessionState::get_by_user_id(session.user_id, &state.database)
pub async fn get_sessions(state: Data<&Arc<AppState>>, token: AuthToken) -> impl IntoResponse {
let sessions = SessionState::get_by_user_id(token.session.user_id, &state.database)
.await
.unwrap();

Json(sessions)
}

#[handler]
pub async fn delete_sessions(
cookies: &CookieJar,
state: Data<&Arc<AppState>>,
) -> impl IntoResponse {
let token = cookies.get("property.v3x.token").unwrap();
let token = Uuid::parse_str(token.value_str()).unwrap();

let session = SessionState::get_by_id(token, &state.database)
.await
.unwrap();

let sessions = SessionState::invalidate_by_user_id(session.user_id, &state.database)
pub async fn delete_sessions(state: Data<&Arc<AppState>>, token: AuthToken) -> impl IntoResponse {
let sessions = SessionState::invalidate_by_user_id(token.session.user_id, &state.database)
.await
.unwrap();

Expand Down
4 changes: 3 additions & 1 deletion web/src/api/core.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import useSWR from "swr";

const BASE_URL = "http://localhost:3000"

export const useHttp = <K>(url: string, token: string | null) => useSWR(token && url, async (): Promise<K | null> => {
const headers = new Headers();

headers.append("Authorization", "Bearer " + token);

try {
const response = await fetch("http://localhost:3000/api/properties", { headers });
const response = await fetch(BASE_URL + url, { headers });
const data = await response.json() as K;

return data as K;
Expand Down
2 changes: 1 addition & 1 deletion web/src/api/me.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,4 @@ export type ApiMeResponse = {
"nickname": any
}

export const useApiMe = (token: string | null) => useHttp<ApiMeResponse>("/api/me", token);
export const useApiMe = (token: string | null) => useHttp<ApiMeResponse>("/me", token);
6 changes: 3 additions & 3 deletions web/src/components/Navbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export const Navbar = () => {

const login_here_url = LOGIN_URL + "?redirect=" + encodeURIComponent(window.location.href);

console.log({token});
console.log({meData});

return (
<div className="w-full bg-white border-b h-8 flex items-center justify-between">
Expand All @@ -21,9 +21,9 @@ export const Navbar = () => {
meData && <div className="h-full border-l px-2 hover:bg-black/10 relative">
<div className="h-full p-1 flex items-center gap-2">
<div className="h-full aspect-square bg-black/10">
<img src={meData.oauth_data.picture} className="w-full h-full object-contain" />
<img src={meData?.oauth_data?.picture} className="w-full h-full object-contain" />
</div>
<div>{meData.oauth_data.name}</div>
<div>{meData.oauth_data?.name}</div>
<div className="absolute right-0 w-fit top-full bg-white border">
<div className="px-3 py-0.5">
Hello
Expand Down

0 comments on commit 6433cbc

Please sign in to comment.