Skip to content

Commit

Permalink
Introduce redirect url & basic frontend
Browse files Browse the repository at this point in the history
  • Loading branch information
lucemans committed Jul 29, 2024
1 parent ccc1120 commit 5c2694f
Show file tree
Hide file tree
Showing 17 changed files with 2,804 additions and 70 deletions.
60 changes: 60 additions & 0 deletions engine/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions engine/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ edition = "2021"
async-std = { version = "1.12.0", features = ["attributes", "tokio1"] }
bigdecimal = { version = "0.4.5", features = ["serde"] }
chrono = "0.4.38"
color-eyre = "0.6.3"
dotenv = "0.15.0"
dotenvy = "0.15.7"
openid = "0.14.0"
Expand Down
17 changes: 15 additions & 2 deletions engine/src/auth/session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ impl SessionState {
Ok(session)
}

/// Get all sessions for a user that are valid
pub async fn get_by_user_id(user_id: i32, database: &Database) -> Result<Vec<Self>, sqlx::Error> {
let sessions = sqlx::query_as::<_, SessionState>(
"SELECT * FROM sessions WHERE user_id = $1 AND valid = TRUE",
Expand All @@ -57,8 +58,8 @@ impl SessionState {
Ok(sessions)
}

// Set every session to invalid
pub async fn delete_by_user_id(user_id: i32, database: &Database) -> Result<Vec<Self>, sqlx::Error> {
/// Set every session to invalid
pub async fn invalidate_by_user_id(user_id: i32, database: &Database) -> Result<Vec<Self>, sqlx::Error> {
let sessions = sqlx::query_as::<_, SessionState>(
"UPDATE sessions SET valid = FALSE WHERE user_id = $1",
)
Expand All @@ -68,4 +69,16 @@ impl SessionState {

Ok(sessions)
}

/// Invalidate all sessions for a user that are older than the given time
pub async fn invalidate_by_user_id_by_time(user_id: i32, database: &Database, invalidate_before: chrono::DateTime<chrono::Utc>) -> Result<Vec<Self>, sqlx::Error> {
let sessions = sqlx::query_as::<_, SessionState>(
"UPDATE sessions SET valid = FALSE WHERE user_id = $1 AND last_access < $2",
)
.bind(user_id)
.fetch_all(&database.pool)
.await?;

Ok(sessions)
}
}
42 changes: 34 additions & 8 deletions engine/src/routes/auth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,18 @@ use poem::{
IntoResponse,
};
use serde::Deserialize;
use url::Url;
use std::{collections::HashSet, sync::Arc};
use tracing::info;
use uuid::Uuid;

#[derive(Deserialize)]
struct LoginQuery {
redirect: Option<String>,
}

#[handler]
pub async fn login(state: Data<&Arc<AppState>>) -> impl IntoResponse {
pub async fn login(query: Query<LoginQuery>, state: Data<&Arc<AppState>>) -> impl IntoResponse {
// let discovery_url = "http://localhost:8080/realms/master/.well-known/openid-configuration";

// let http_client = reqwest::Client::new();
Expand All @@ -27,6 +34,7 @@ pub async fn login(state: Data<&Arc<AppState>>) -> impl IntoResponse {

let options = Options {
scope: Some(scope),
state: query.redirect.clone(),
prompt: Some(HashSet::from([Prompt::SelectAccount])),
..Default::default()
};
Expand All @@ -42,8 +50,10 @@ pub async fn login(state: Data<&Arc<AppState>>) -> impl IntoResponse {

#[derive(Deserialize)]
pub struct MyQuery {
pub session_state: Option<String>,
pub iss: Option<String>,
pub state: Option<String>,
pub scope: Option<String>,
pub hd: Option<String>,
pub authuser: Option<String>,
pub code: String,
pub prompt: Option<String>,
}
Expand Down Expand Up @@ -82,14 +92,30 @@ pub async fn callback(

let token = session.id;

Redirect::temporary("http://localhost:3000/me")
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)));

Redirect::temporary(redirect_url)
.with_header("Set-Cookie", format!("property.v3x.token={}", token))
}

#[handler]
pub async fn me(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();
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
Expand Down Expand Up @@ -130,7 +156,7 @@ pub async fn delete_sessions(
.await
.unwrap();

let sessions = SessionState::delete_by_user_id(session.user_id, &state.database)
let sessions = SessionState::invalidate_by_user_id(session.user_id, &state.database)
.await
.unwrap();

Expand Down
3 changes: 2 additions & 1 deletion engine/src/routes/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::sync::Arc;
use poem::{
get, handler,
listener::TcpListener,
middleware::CookieJarManager,
middleware::{CookieJarManager, Cors},
web::{Data, Html, Path},
EndpointExt, Route, Server,
};
Expand Down Expand Up @@ -95,6 +95,7 @@ pub async fn serve(state: AppState) -> Result<(), poem::Error> {
.nest("/openapi.json", spec)
.at("/", get(ui))
.with(CookieJarManager::new())
.with(Cors::new())
.data(state);

let listener = TcpListener::bind("0.0.0.0:3000");
Expand Down
19 changes: 19 additions & 0 deletions web/.eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaVersion": 2021
},
"extends": [
"plugin:v3xlabs/recommended"
],
"ignorePatterns": [
"!**/*"
],
"plugins": [
"v3xlabs"
],
"env": {
"node": true
},
"rules": {}
}
5 changes: 5 additions & 0 deletions web/.prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"tabWidth": 4,
"useTabs": false,
"singleQuote": true
}
6 changes: 4 additions & 2 deletions web/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>v3x.property</title>
<link rel="stylesheet" href="./src/index.css" />
<script type="module" src="./src/index.tsx"></script>
</head>
<body>
<div class="w-full max-w-xl mx-auto p-4 space-y-4 pb-32">
<div id="root"></div>
<!-- <div class="w-full max-w-xl mx-auto p-4 space-y-4 pb-32">
<div>
<div class="bg-black text-white px-2 py-0.5 font-bold">
v3x.property
Expand Down Expand Up @@ -70,6 +72,6 @@ <h1 class="font-bold text-2xl">Battery Pack</h1>
<div>Re-print Tag</div>
</div>
</div>
</div>
</div> -->
</body>
</html>
52 changes: 33 additions & 19 deletions web/package.json
Original file line number Diff line number Diff line change
@@ -1,20 +1,34 @@
{
"name": "web",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"dev": "vite",
"build": "vite build"
},
"keywords": [],
"author": "",
"license": "GPL-3",
"dependencies": {
"autoprefixer": "^10.4.19",
"postcss": "^8.4.38",
"tailwindcss": "^3.4.3",
"vite": "^5.2.10"
}
}
"name": "web",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"dev": "vite",
"build": "vite build",
"lint": "eslint -c .eslintrc.json --ext .ts ./src"
},
"keywords": [],
"author": "",
"license": "GPL-3",
"dependencies": {
"@vitejs/plugin-react": "^4.3.1",
"autoprefixer": "^10.4.19",
"postcss": "^8.4.38",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"swr": "^2.2.5",
"tailwindcss": "^3.4.3",
"vite": "^5.2.10",
"zustand": "^4.5.4"
},
"devDependencies": {
"@types/react": "^18.3.3",
"@types/react-dom": "^18.3.0",
"@typescript-eslint/parser": "^7.17.0",
"eslint": "^9.8.0",
"eslint-plugin-v3xlabs": "^1.6.5",
"typescript": "^5.5.4"
}
}
Loading

0 comments on commit 5c2694f

Please sign in to comment.