-
Notifications
You must be signed in to change notification settings - Fork 1
Add client roles to zauth #328
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 6 commits
16c0c40
563d13e
a27fb04
ff4c986
fa8b4b2
00f62f3
ede7341
e37df12
f2ae227
1f203d6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| -- This file should undo anything in `up.sql` | ||
| DROP TABLE users_roles; | ||
| DROP TABLE roles; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| -- Your SQL goes here | ||
| CREATE TABLE roles ( | ||
| id SERIAL PRIMARY KEY, | ||
| name VARCHAR(255) NOT NULL UNIQUE, | ||
| description VARCHAR(255) NOT NULL, | ||
| client_id INTEGER REFERENCES clients(id) | ||
| ); | ||
|
|
||
| CREATE TABLE users_roles ( | ||
| user_id INTEGER REFERENCES users(id) ON DELETE CASCADE, | ||
| role_id INTEGER REFERENCES roles(id) ON DELETE CASCADE, | ||
| PRIMARY KEY (user_id, role_id) | ||
| ) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,179 @@ | ||
| use diesel::result::DatabaseErrorKind; | ||
| use rocket::form::Form; | ||
| use rocket::http::Status; | ||
| use rocket::response::status::Custom; | ||
| use rocket::response::{Redirect, Responder, status}; | ||
| use rocket::serde::json::Json; | ||
| use std::fmt::Debug; | ||
|
|
||
| use crate::DbConn; | ||
| use crate::ephemeral::from_api::Api; | ||
| use crate::ephemeral::session::AdminSession; | ||
| use crate::errors::{Either, InternalError, Result, ZauthError}; | ||
| use crate::models::client::Client; | ||
| use crate::models::role::{NewRole, Role}; | ||
| use crate::models::user::User; | ||
| use crate::views::accepter::Accepter; | ||
|
|
||
| #[get("/roles?<error>")] | ||
| pub async fn list_roles<'r>( | ||
| error: Option<String>, | ||
| db: DbConn, | ||
| session: AdminSession, | ||
| ) -> Result<impl Responder<'r, 'static>> { | ||
| let roles = Role::all(&db).await?; | ||
| let clients = Client::all(&db).await?; | ||
|
|
||
| Ok(Accepter { | ||
| html: template! { | ||
| "roles/index.html"; | ||
| roles: Vec<Role> = roles.clone(), | ||
| clients: Vec<Client> = clients, | ||
| error: Option<String> = error, | ||
| current_user: User = session.admin, | ||
| }, | ||
| json: Json(roles), | ||
| }) | ||
| } | ||
|
|
||
| #[post("/roles", data = "<role>")] | ||
| pub async fn create_role<'r, 'a>( | ||
| role: Api<NewRole>, | ||
| db: DbConn, | ||
| _admin: AdminSession, | ||
| ) -> Result< | ||
| Either<impl Responder<'a, 'static>, impl Responder<'r, 'static> + use<'r>>, | ||
| > { | ||
| let role = Role::create(role.into_inner(), &db).await; | ||
| match role { | ||
| Ok(role) => Ok(Either::Left(Accepter { | ||
| html: Redirect::to(uri!(list_roles(None::<String>))), | ||
| json: status::Created::new(String::from("/role")).body(Json(role)), | ||
| })), | ||
| Err(ZauthError::Internal(InternalError::DatabaseError( | ||
| diesel::result::Error::DatabaseError( | ||
| DatabaseErrorKind::UniqueViolation, | ||
| _, | ||
| ), | ||
| ))) => Ok(Either::Right(Accepter { | ||
| html: Redirect::to(uri!(list_roles(Some( | ||
| "role name already exists" | ||
| )))), | ||
| json: "role name already exists", | ||
| })), | ||
| Err(err) => Err(err), | ||
| } | ||
| } | ||
|
|
||
| #[get("/roles/add?<username>")] | ||
rien marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| pub async fn add_user_page<'r>( | ||
| username: Option<String>, | ||
| db: DbConn, | ||
| session: AdminSession, | ||
| ) -> Result<impl Responder<'r, 'static>> { | ||
| let roles = Role::all(&db).await?; | ||
| Ok(template! { | ||
| "roles/add_user.html"; | ||
| roles: Vec<Role> = roles, | ||
| username: String = username.unwrap_or_default(), | ||
| current_user: User = session.admin | ||
| }) | ||
| } | ||
|
|
||
| #[get("/roles/<id>/show?<error>&<info>")] | ||
| pub async fn show_role_page<'r>( | ||
| id: i32, | ||
| error: Option<String>, | ||
| info: Option<String>, | ||
| session: AdminSession, | ||
| db: DbConn, | ||
| ) -> Result<impl Responder<'r, 'static>> { | ||
| let role = Role::find(id, &db).await?; | ||
| let users = role.clone().users(&db).await?; | ||
|
|
||
| Ok(template! { "roles/show_role.html"; | ||
| current_user: User = session.admin, | ||
| role: Role = role, | ||
| users: Vec<User> = users, | ||
| error: Option<String> = error, | ||
| info: Option<String> = info | ||
| }) | ||
| } | ||
|
|
||
| #[delete("/roles/<id>")] | ||
| pub async fn delete_role<'r>( | ||
| id: i32, | ||
| _session: AdminSession, | ||
| db: DbConn, | ||
| ) -> Result<impl Responder<'r, 'static>> { | ||
| let role = Role::find(id, &db).await?; | ||
| role.delete(&db).await?; | ||
| Ok(Accepter { | ||
| html: Redirect::to(uri!(list_roles(None::<String>))), | ||
| json: Custom(Status::NoContent, ()), | ||
| }) | ||
| } | ||
|
|
||
| #[derive(FromForm)] | ||
| pub struct Mapping { | ||
| username: String, | ||
| role_id: i32, | ||
| } | ||
|
|
||
| #[post("/roles/mapping", data = "<form>")] | ||
|
||
| pub async fn add_user<'r>( | ||
| form: Form<Mapping>, | ||
| db: DbConn, | ||
| _session: AdminSession, | ||
| ) -> Result<impl Responder<'r, 'static>> { | ||
| let role = Role::find(form.role_id, &db).await?; | ||
| let user_result = User::find_by_username(form.username.clone(), &db).await; | ||
| Ok(match user_result { | ||
| Ok(user) => { | ||
| role.add_user(user.id, &db).await?; | ||
| Accepter { | ||
| html: Redirect::to(uri!(show_role_page( | ||
| role.id, | ||
| None::<String>, | ||
| Some("user added") | ||
| ))), | ||
| json: Custom(Status::NoContent, ()), | ||
| } | ||
| }, | ||
| Err(ZauthError::NotFound(_)) => Accepter { | ||
| html: Redirect::to(uri!(show_role_page( | ||
| role.id, | ||
| Some("user not found"), | ||
| None::<String> | ||
| ))), | ||
| json: Custom(Status::NotFound, ()), | ||
| }, | ||
| _ => Accepter { | ||
| html: Redirect::to(uri!(show_role_page( | ||
| role.id, | ||
| Some("error occured"), | ||
| None::<String> | ||
| ))), | ||
| json: Custom(Status::InternalServerError, ()), | ||
| }, | ||
| }) | ||
| } | ||
|
|
||
| #[delete("/roles/<role_id>/mapping/<user_id>")] | ||
|
||
| pub async fn delete_user<'r>( | ||
| role_id: i32, | ||
| user_id: i32, | ||
| _session: AdminSession, | ||
| db: DbConn, | ||
| ) -> Result<impl Responder<'r, 'static>> { | ||
| let role = Role::find(role_id, &db).await?; | ||
| role.remove_user(user_id, &db).await?; | ||
| Ok(Accepter { | ||
| html: Redirect::to(uri!(show_role_page( | ||
| role_id, | ||
| None::<String>, | ||
| Some("user deleted") | ||
| ))), | ||
| json: Custom(Status::Ok, ()), | ||
| }) | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.