Skip to content

Commit 7f756dd

Browse files
committed
fix auth bootstrap and consolidate live dashboard work
1 parent c0e1f22 commit 7f756dd

11 files changed

Lines changed: 8998 additions & 181 deletions

File tree

api/src/auth/handlers.rs

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,11 @@ pub struct MeResponse {
4545
pub created_at: String,
4646
}
4747

48+
#[derive(Debug, Serialize)]
49+
pub struct SessionResponse {
50+
pub user: Option<MeResponse>,
51+
}
52+
4853
#[derive(Debug, Serialize)]
4954
pub struct ErrorResponse {
5055
pub error: String,
@@ -243,6 +248,14 @@ pub async fn refresh(
243248
State(state): State<AppState>,
244249
jar: CookieJar,
245250
) -> Result<impl IntoResponse, (StatusCode, Json<ErrorResponse>)> {
251+
let (jar, user) = rotate_refresh_token(&state, jar).await?;
252+
Ok((jar, Json(as_user_response(&user))))
253+
}
254+
255+
async fn rotate_refresh_token(
256+
state: &AppState,
257+
jar: CookieJar,
258+
) -> Result<(CookieJar, crate::models::UserRow), (StatusCode, Json<ErrorResponse>)> {
246259
let raw_refresh = jar
247260
.get("refresh_token")
248261
.ok_or_else(|| json_error(StatusCode::UNAUTHORIZED, "missing refresh token"))?
@@ -298,7 +311,7 @@ pub async fn refresh(
298311
let jar = jar
299312
.add(access_cookie(&new_access))
300313
.add(refresh_cookie(&new_refresh));
301-
Ok((jar, Json(as_user_response(&user))))
314+
Ok((jar, user))
302315
}
303316

304317
pub async fn logout(
@@ -338,3 +351,32 @@ pub async fn me(
338351
created_at: user.created_at.to_rfc3339(),
339352
}))
340353
}
354+
355+
pub async fn session(
356+
State(state): State<AppState>,
357+
jar: CookieJar,
358+
Extension(auth_user): Extension<Option<AuthUser>>,
359+
) -> Result<impl IntoResponse, (StatusCode, Json<ErrorResponse>)> {
360+
let (jar, user) = if let Some(auth_user) = auth_user {
361+
let user = users::find_user_by_id(&state.pool, auth_user.id)
362+
.await
363+
.map_err(|_| json_error(StatusCode::INTERNAL_SERVER_ERROR, "database error"))?;
364+
(jar, user)
365+
} else if jar.get("refresh_token").is_some() {
366+
let (jar, user) = rotate_refresh_token(&state, jar).await?;
367+
(jar, Some(user))
368+
} else {
369+
(jar, None)
370+
};
371+
372+
let user = user.map(|user| MeResponse {
373+
id: user.id.to_string(),
374+
email: user.email,
375+
display_name: user.display_name,
376+
role: user.role,
377+
stripe_customer_id: user.stripe_customer_id,
378+
created_at: user.created_at.to_rfc3339(),
379+
});
380+
381+
Ok((jar, Json(SessionResponse { user })))
382+
}

api/src/main.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
8787
.route("/login", post(auth::handlers::login))
8888
.route("/refresh", post(auth::handlers::refresh))
8989
.route("/logout", post(auth::handlers::logout))
90+
.route("/session", get(auth::handlers::session))
9091
.route("/me", get(auth::handlers::me));
9192

9293
let billing_routes = Router::new()

dashboard/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
"@urql/core": "^6.0.1",
1515
"graphql": "^16.13.2",
1616
"maplibre-gl": "^5.21.1",
17+
"proj4": "^2.20.9",
1718
"react": "^19.2.4",
1819
"react-dom": "^19.2.4",
1920
"react-router-dom": "^7.18.1",

dashboard/pnpm-lock.yaml

Lines changed: 26 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)