Start role based access

This commit is contained in:
Chris Jean-Marie 2024-09-27 12:22:23 +00:00
parent 754cac54e2
commit 038990ff85
5 changed files with 64 additions and 4 deletions

View File

@ -0,0 +1 @@
-- Add down migration script here

View File

@ -0,0 +1,23 @@
-- Add up migration script here
CREATE TABLE IF NOT EXISTS roles (
"id" integer NOT NULL PRIMARY KEY AUTOINCREMENT,
"created_at" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updated_at" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"name" TEXT NOT NULL,
"description" TEXT
);
CREATE TABLE IF NOT EXISTS user_roles (
"user_id" integer NOT NULL,
"role_id" integer NOT NULL,
"created_at" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updated_at" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
);
create TABLE IF NOT EXISTS role_permissions (
"role_id" integer NOT NULL,
"item" text NOT NULL,
"created_at" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updated_at" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
);

View File

@ -83,16 +83,16 @@ async fn main() {
// build our application with some routes
let app = Router::new()
//Routes that require authentication
.route("/logout", get(logout))
.route("/profile", get(profile))
.route("/useradmin", get(useradmin))
.route_layer(middleware::from_fn_with_state(app_state.clone(), check_auth))
.route_layer(middleware::from_fn_with_state(app_state.db_pool.clone(), check_auth))
//Routes that don't require authentication
.nest_service("/assets", ServeDir::new("templates/assets")
.fallback(get_service(ServeDir::new("templates/assets"))))
.route("/", get(index))
.route("/login", get(login))
.route("/logout", get(logout))
.route("/google_auth", get(google_auth))
.route("/google_auth_return", get(google_auth_return))
.route_layer(middleware::from_fn_with_state(app_state.db_pool.clone(), inject_user_data))

View File

@ -65,15 +65,52 @@ pub async fn inject_user_data(
Ok(next.run(request).await)
}
pub async fn check_auth(request: Request<Body>, next: Next) -> Result<impl IntoResponse, AppError> {
pub async fn check_auth(State(app_state): State<SqlitePool>, request: Request<Body>, next: Next) -> Result<impl IntoResponse, AppError> {
if request
.extensions()
.get::<Option<UserData>>()
.ok_or("check_auth: extensions have no UserData")?
.is_some()
{
let path = &*request.uri().to_string();
println!("{}", path);
println!("{}",&*request.extensions().get::<Option<UserData>>().unwrap().as_ref().unwrap().email);
let query: Result<(i64,), _> = match path {
"/profile" =>
sqlx::query_as(r#"select u.id from users u where email =?"#)
.bind(request.extensions().get::<Option<UserData>>().unwrap().as_ref().unwrap().email.as_str())
.fetch_one(&app_state)
.await,
_ => sqlx::query_as(r#"select u.id from role_permissions r join user_roles ur on ur.role_id = r.role_id join users u on u.id = ur.user_id where item = ? and email =?"#)
.bind(&*request.uri().to_string())
.bind(request.extensions().get::<Option<UserData>>().unwrap().as_ref().unwrap().email.as_str())
.fetch_one(&app_state)
.await,
};
// user is logged in
// check if user has the proper role
// if not, display banner and return to home page
let user_id = if let Ok(query) = query {
query.0
} else {
// user does not have the proper role
0
};
println!("{}", user_id);
if user_id == 0 {
// user does not have the proper role
// display banner and return to home page
return Ok(Redirect::to("/").into_response());
}
Ok(next.run(request).await)
} else {
// user is not logged in
// redirect to login page with return_url
let login_url = "/login?return_url=".to_owned() + &*request.uri().to_string();
Ok(Redirect::to(login_url.as_str()).into_response())
}

View File

@ -154,7 +154,6 @@ pub async fn google_auth_return(
.map_err(|_| "OAuth: reqwest received invalid userinfo")?;
let mut body: serde_json::Value =
serde_json::from_str(body.as_str()).map_err(|_| "OAuth: Serde failed to parse userinfo")?;
println!("body: {}", body);
let email = body["email"]
.take()
.as_str()