extractor for access token

This commit is contained in:
Fu Zi Xiang 2023-10-10 14:37:12 +08:00
parent 427612b11f
commit b2450419eb
No known key found for this signature in database
8 changed files with 131 additions and 14 deletions

View File

@ -0,0 +1,48 @@
use axum::{
async_trait,
extract::FromRequestParts,
http::request::Parts,
response::{IntoResponse, Redirect},
};
use axum_extra::extract::CookieJar;
pub struct WebAccessToken(pub String);
#[async_trait]
impl<S> FromRequestParts<S> for WebAccessToken
where
S: Send + Sync,
{
type Rejection = AccessTokenRejection;
async fn from_request_parts(parts: &mut Parts, state: &S) -> Result<Self, Self::Rejection> {
let jar = CookieJar::from_request_parts(parts, state)
.await
.map_err(|e| AccessTokenRejection::CookieError(e.to_string()))?;
let token = jar
.get("access_token")
.ok_or(AccessTokenRejection::NoAccessToken)?
.to_string();
Ok(WebAccessToken(token))
}
}
#[derive(Clone, Debug)]
pub enum AccessTokenRejection {
NoAccessToken,
CookieError(String),
}
impl IntoResponse for AccessTokenRejection {
fn into_response(self) -> axum::response::Response {
match self {
AccessTokenRejection::NoAccessToken => Redirect::permanent("/web/login").into_response(),
AccessTokenRejection::CookieError(err) => {
println!("cookie error: {}", err);
Redirect::permanent("/web/login").into_response()
},
}
}
}

View File

@ -1,3 +1,4 @@
mod access_token;
mod error;
mod models;
mod response;

View File

@ -7,3 +7,7 @@ pub struct Login;
#[derive(Template)]
#[template(path = "home.html")]
pub struct Home;
#[derive(Template)]
#[template(path = "admin.html")]
pub struct Admin;

View File

@ -1,3 +1,4 @@
use crate::access_token::WebAccessToken;
use crate::error::RenderError;
use askama::Template;
use axum::response::Result;
@ -11,17 +12,22 @@ pub fn router() -> Router {
.route("/", get(home_handler))
.route("/home", get(home_handler))
.route("/login", get(login_handler))
.route("/admin", get(admin_handler))
.route("/admin/users", get(admin_users_handler))
}
pub async fn home_handler(cookies: CookieJar) -> Result<Html<String>, RenderError> {
let access_token = cookies.get("access_token");
match access_token {
Some(access_token) => {
let s = templates::Home {}.render()?;
Ok(Html(s))
},
None => login_handler().await,
}
pub async fn home_handler(access_token: WebAccessToken) -> Result<Html<String>, RenderError> {
let s = templates::Home {}.render()?;
Ok(Html(s))
}
pub async fn admin_handler(access_token: WebAccessToken) -> Result<Html<String>, RenderError> {
let s = templates::Admin {}.render()?;
Ok(Html(s))
}
pub async fn admin_users_handler(cookies: CookieJar) -> Result<Html<String>, RenderError> {
todo!()
}
pub async fn login_handler() -> Result<Html<String>, RenderError> {

View File

@ -0,0 +1,16 @@
<!doctype html>
<html lang="en">
<body>
<h1>Welcome to the Admin Page</h1>
<button id="usersBtn">Users</button>
<script>
document
.getElementById("usersBtn")
.addEventListener("click", function () {
// Redirect to the users page.
window.location.href = "/web/admin/users";
});
</script>
</body>
</html>

View File

@ -3,18 +3,24 @@
<body>
<h1>Welcome to the Home Page</h1>
<button id="logoutBtn">Logout</button>
<button id="adminBtn">Admin</button>
<script>
document
.getElementById("logoutBtn")
.addEventListener("click", function () {
// Remove the cookie by setting its value to an empty string and its expiry date to the past.
document.cookie =
"access_token=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;";
document.cookie = "access_token=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;";
// Redirect to the login page.
window.location.href = "/web/login";
});
document
.getElementById("adminBtn")
.addEventListener("click", function () {
// Redirect to the admin page.
window.location.href = "/web/admin";
});
</script>
</body>
</html>

View File

@ -1,5 +1,5 @@
<!doctype html>
<html>
<html lang="en">
<body>
<h1>Admin Login</h1>
<form id="loginForm">
@ -52,7 +52,7 @@
// Set the token as a cookie
document.cookie =
"access_token=" + data.data.access_token + "; path=/";
window.location.href = "/";
window.location.href = "/web/home";
})
.catch((error) => {
console.error("Error:", error);

View File

@ -0,0 +1,36 @@
<!DOCTYPE html>
<html lang="en">
<body>
<h1>User List</h1>
<ul id="userList"></ul>
<script>
document.addEventListener("DOMContentLoaded", function () {
// Fetch the user list from the API
fetch('/web-api/users')
.then(response => {
// Check if HTTP status code indicates success
if (!response.ok) {
return Promise.reject('Failed to fetch users');
}
return response.json(); // Parse the JSON response
})
.then(data => {
// Display the users on the page
const userList = document.getElementById('userList');
data.forEach(user => {
const li = document.createElement('li');
li.textContent = `${user.name} (${user.email})`;
userList.appendChild(li);
});
})
.catch(error => {
console.error('Error:', error);
alert('Failed to fetch users');
});
});
</script>
</body>
</html>