diff --git a/assets/views/base.html b/assets/views/base.html
index 1167858..d29ea88 100644
--- a/assets/views/base.html
+++ b/assets/views/base.html
@@ -63,7 +63,14 @@
Home
About
Blog
+ {% if logged_in_admin %}
+ Dashboard
+
+ {% else %}
Admin
+ {% endif %}
diff --git a/src/controllers/auth.rs b/src/controllers/auth.rs
index 0d20d8f..57ff777 100644
--- a/src/controllers/auth.rs
+++ b/src/controllers/auth.rs
@@ -14,7 +14,7 @@ use std::sync::OnceLock;
use time::Duration as TimeDuration;
pub static EMAIL_DOMAIN_RE: OnceLock
= OnceLock::new();
-const AUTH_COOKIE: &str = "auth_token";
+pub(crate) const AUTH_COOKIE: &str = "auth_token";
fn get_allow_email_domain_re() -> &'static Regex {
EMAIL_DOMAIN_RE.get_or_init(|| {
diff --git a/src/controllers/frontend.rs b/src/controllers/frontend.rs
index 6c0af91..d3efb9c 100644
--- a/src/controllers/frontend.rs
+++ b/src/controllers/frontend.rs
@@ -5,6 +5,7 @@ use crate::{
users::{self, LoginParams},
},
};
+use axum_extra::extract::cookie::CookieJar;
use chrono::Utc;
use loco_rs::prelude::*;
use sea_orm::{
@@ -87,8 +88,27 @@ async fn article_by_id(ctx: &AppContext, id: Uuid) -> Result bool {
+ let Some(cookie) = jar.get(auth_controller::AUTH_COOKIE) else {
+ return false;
+ };
+ let Ok(jwt_config) = ctx.config.get_jwt_config() else {
+ return false;
+ };
+ let Ok(claims) = loco_rs::auth::jwt::JWT::new(&jwt_config.secret).validate(cookie.value())
+ else {
+ return false;
+ };
+ let Ok(user) = users::Model::find_by_pid(&ctx.db, &claims.claims.pid).await else {
+ return false;
+ };
+
+ admin::is_admin(ctx, &user)
+}
+
#[debug_handler]
async fn home(
+ jar: CookieJar,
ViewEngine(v): ViewEngine,
State(ctx): State,
) -> Result {
@@ -99,19 +119,32 @@ async fn home(
.all(&ctx.db)
.await?;
- format::view(&v, "home/index.html", json!({ "articles": articles }))
+ format::view(
+ &v,
+ "home/index.html",
+ json!({ "articles": articles, "logged_in_admin": logged_in_admin(&ctx, &jar).await }),
+ )
}
#[debug_handler]
async fn about(
+ jar: CookieJar,
ViewEngine(v): ViewEngine,
State(ctx): State,
) -> Result {
- format::view(&v, "pages/about.html", json!({ "page": about_page(&ctx).await? }))
+ format::view(
+ &v,
+ "pages/about.html",
+ json!({
+ "page": about_page(&ctx).await?,
+ "logged_in_admin": logged_in_admin(&ctx, &jar).await,
+ }),
+ )
}
#[debug_handler]
async fn blog_index(
+ jar: CookieJar,
ViewEngine(v): ViewEngine,
State(ctx): State,
) -> Result {
@@ -121,11 +154,16 @@ async fn blog_index(
.all(&ctx.db)
.await?;
- format::view(&v, "blog/index.html", json!({ "articles": articles }))
+ format::view(
+ &v,
+ "blog/index.html",
+ json!({ "articles": articles, "logged_in_admin": logged_in_admin(&ctx, &jar).await }),
+ )
}
#[debug_handler]
async fn blog_show(
+ jar: CookieJar,
ViewEngine(v): ViewEngine,
Path(slug): Path,
State(ctx): State,
@@ -142,12 +180,28 @@ async fn blog_show(
active.view_count = Set(next_count);
let article = active.update(&ctx.db).await?;
- format::view(&v, "blog/show.html", json!({ "article": article }))
+ format::view(
+ &v,
+ "blog/show.html",
+ json!({ "article": article, "logged_in_admin": logged_in_admin(&ctx, &jar).await }),
+ )
}
#[debug_handler]
-async fn admin_login_page(ViewEngine(v): ViewEngine) -> Result {
- format::view(&v, "admin/login.html", json!({ "error": null }))
+async fn admin_login_page(
+ jar: CookieJar,
+ ViewEngine(v): ViewEngine,
+ State(ctx): State,
+) -> Result {
+ if logged_in_admin(&ctx, &jar).await {
+ return format::redirect("/admin/dashboard");
+ }
+
+ format::view(
+ &v,
+ "admin/login.html",
+ json!({ "error": null, "logged_in_admin": false }),
+ )
}
#[debug_handler]
@@ -157,11 +211,19 @@ async fn admin_login(
Form(params): Form,
) -> Result {
let Ok(user) = users::Model::find_by_email(&ctx.db, ¶ms.email).await else {
- return format::view(&v, "admin/login.html", json!({ "error": "Invalid credentials" }));
+ return format::view(
+ &v,
+ "admin/login.html",
+ json!({ "error": "Invalid credentials", "logged_in_admin": false }),
+ );
};
if !user.verify_password(¶ms.password) || !admin::is_admin(&ctx, &user) {
- return format::view(&v, "admin/login.html", json!({ "error": "Invalid credentials" }));
+ return format::view(
+ &v,
+ "admin/login.html",
+ json!({ "error": "Invalid credentials", "logged_in_admin": false }),
+ );
}
let jwt_secret = ctx.config.get_jwt_config()?;