Optimized permissions
This commit is contained in:
parent
701d430742
commit
349c1a24a4
@ -18,10 +18,7 @@ use crate::{
|
|||||||
|
|
||||||
mod error;
|
mod error;
|
||||||
|
|
||||||
pub async fn get_user_from_header(
|
pub async fn get_user_from_header(pool: &PgPool, headers: &HeaderMap) -> Result<User, AuthError> {
|
||||||
pool: &PgPool,
|
|
||||||
headers: &HeaderMap,
|
|
||||||
) -> Result<(Roles, User), AuthError> {
|
|
||||||
let bearer_value = headers.get(header::AUTHORIZATION);
|
let bearer_value = headers.get(header::AUTHORIZATION);
|
||||||
let bearer_value = bearer_value
|
let bearer_value = bearer_value
|
||||||
.ok_or(AuthError::InvalidToken)?
|
.ok_or(AuthError::InvalidToken)?
|
||||||
@ -44,11 +41,7 @@ pub async fn get_user_from_header(
|
|||||||
Err(_) => return Err(AuthError::InvalidToken),
|
Err(_) => return Err(AuthError::InvalidToken),
|
||||||
};
|
};
|
||||||
|
|
||||||
let roles = UserMember::get_roles(pool, &db_user.user_id)
|
Ok(db_user.into())
|
||||||
.await
|
|
||||||
.unwrap_or(Roles::MEMBER);
|
|
||||||
|
|
||||||
Ok((roles, db_user.into()))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_token_from_bearer(bearer: &str) -> Result<String, AuthError> {
|
pub fn get_token_from_bearer(bearer: &str) -> Result<String, AuthError> {
|
||||||
|
@ -8,10 +8,12 @@ pub struct User {
|
|||||||
pub admin: bool,
|
pub admin: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
use crate::auth::AuthError;
|
||||||
use crate::database::model::User as DbUser;
|
use crate::database::model::User as DbUser;
|
||||||
use crate::database::model::UserMember as DbUserMember;
|
use crate::database::model::UserMember as DbUserMember;
|
||||||
use crate::util::convert_vec;
|
use crate::util::convert_vec;
|
||||||
|
|
||||||
|
use super::member::Roles;
|
||||||
use super::Member;
|
use super::Member;
|
||||||
impl From<DbUser> for User {
|
impl From<DbUser> for User {
|
||||||
fn from(db_user: DbUser) -> Self {
|
fn from(db_user: DbUser) -> Self {
|
||||||
@ -40,4 +42,34 @@ impl User {
|
|||||||
|
|
||||||
Ok(convert_vec(related_members))
|
Ok(convert_vec(related_members))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn authorize(
|
||||||
|
&self,
|
||||||
|
pool: &PgPool,
|
||||||
|
required_roles: Option<Roles>,
|
||||||
|
requested_user_id: Option<String>,
|
||||||
|
) -> Result<(), AuthError> {
|
||||||
|
if let Some(user_id) = requested_user_id {
|
||||||
|
let user_uuid = uuid::Uuid::parse_str(&user_id).map_err(|_| AuthError::NoPermssions)?;
|
||||||
|
|
||||||
|
if self.id != user_uuid {
|
||||||
|
return Err(AuthError::NoPermssions);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(roles) = required_roles {
|
||||||
|
let user_roles = DbUserMember::get_roles(pool, &self.id)
|
||||||
|
.await
|
||||||
|
.unwrap_or(Roles::MEMBER);
|
||||||
|
if !user_roles.contains(roles) {
|
||||||
|
return Err(AuthError::NoPermssions);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,7 @@ async fn root(
|
|||||||
State(state): State<AppState>,
|
State(state): State<AppState>,
|
||||||
headers: HeaderMap,
|
headers: HeaderMap,
|
||||||
) -> Result<Json<User>, crate::Error> {
|
) -> Result<Json<User>, crate::Error> {
|
||||||
let (_roles, user) = get_user_from_header(&state.pool, &headers).await?;
|
let user = get_user_from_header(&state.pool, &headers).await?;
|
||||||
|
|
||||||
Ok(Json(user))
|
Ok(Json(user))
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,7 @@ pub struct LoginRequest {
|
|||||||
password: String,
|
password: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn login<'a>(
|
pub async fn login(
|
||||||
State(state): State<AppState>,
|
State(state): State<AppState>,
|
||||||
Json(login_request): Json<LoginRequest>,
|
Json(login_request): Json<LoginRequest>,
|
||||||
) -> Result<String, crate::Error> {
|
) -> Result<String, crate::Error> {
|
||||||
@ -99,7 +99,7 @@ pub async fn change_password(
|
|||||||
headers: HeaderMap,
|
headers: HeaderMap,
|
||||||
Json(request): Json<ChangePasswordRequest>,
|
Json(request): Json<ChangePasswordRequest>,
|
||||||
) -> Result<(), crate::Error> {
|
) -> Result<(), crate::Error> {
|
||||||
let (_, user) = get_user_from_header(&state.pool, &headers).await?;
|
let user = get_user_from_header(&state.pool, &headers).await?;
|
||||||
|
|
||||||
// Verify that password is correct
|
// Verify that password is correct
|
||||||
let db_user: DbUser = user.into();
|
let db_user: DbUser = user.into();
|
||||||
@ -138,7 +138,7 @@ pub async fn change_email(
|
|||||||
headers: HeaderMap,
|
headers: HeaderMap,
|
||||||
Json(request): Json<ChangeEmailRequest>,
|
Json(request): Json<ChangeEmailRequest>,
|
||||||
) -> Result<(), crate::Error> {
|
) -> Result<(), crate::Error> {
|
||||||
let (_, user) = get_user_from_header(&state.pool, &headers).await?;
|
let user = get_user_from_header(&state.pool, &headers).await?;
|
||||||
|
|
||||||
// Verify that password is correct
|
// Verify that password is correct
|
||||||
let db_user: DbUser = user.into();
|
let db_user: DbUser = user.into();
|
||||||
|
@ -20,7 +20,7 @@ pub async fn get_current_members(
|
|||||||
State(state): State<AppState>,
|
State(state): State<AppState>,
|
||||||
headers: HeaderMap,
|
headers: HeaderMap,
|
||||||
) -> Result<Json<Vec<Member>>, crate::Error> {
|
) -> Result<Json<Vec<Member>>, crate::Error> {
|
||||||
let (_roles, user) = get_user_from_header(&state.pool, &headers).await?;
|
let user = get_user_from_header(&state.pool, &headers).await?;
|
||||||
|
|
||||||
let members = user.members(&state.pool).await?;
|
let members = user.members(&state.pool).await?;
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@ use axum::{extract::State, http::HeaderMap, Json};
|
|||||||
use sqlx::PgPool;
|
use sqlx::PgPool;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
auth::{get_user_from_header, AuthError},
|
auth::get_user_from_header,
|
||||||
database::model::Member as DbMember,
|
database::model::Member as DbMember,
|
||||||
model::{
|
model::{
|
||||||
member::{Groups, Name, Roles},
|
member::{Groups, Name, Roles},
|
||||||
@ -14,16 +14,15 @@ use crate::{
|
|||||||
AppState,
|
AppState,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub async fn migrate_request<'a>(
|
pub async fn migrate_request(
|
||||||
State(state): State<AppState>,
|
State(state): State<AppState>,
|
||||||
headers: HeaderMap,
|
headers: HeaderMap,
|
||||||
body: String,
|
body: String,
|
||||||
) -> Result<Json<MigrationResponse>, crate::Error> {
|
) -> Result<Json<MigrationResponse>, crate::Error> {
|
||||||
let (roles, _user) = get_user_from_header(&state.pool, &headers).await?;
|
let user = get_user_from_header(&state.pool, &headers).await?;
|
||||||
|
|
||||||
if !roles.contains(Roles::ADMIN) {
|
user.authorize(&state.pool, Some(Roles::ADMIN), None)
|
||||||
return Err(AuthError::NoPermssions.into());
|
.await?;
|
||||||
}
|
|
||||||
|
|
||||||
tracing::info!("Migration is requested");
|
tracing::info!("Migration is requested");
|
||||||
|
|
||||||
@ -46,10 +45,15 @@ pub async fn migrate_request<'a>(
|
|||||||
Ok(Json(MigrationResponse::from((count, members_diff))))
|
Ok(Json(MigrationResponse::from((count, members_diff))))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn migrate_confirm<'a>(
|
pub async fn migrate_confirm(
|
||||||
State(state): State<AppState>,
|
State(state): State<AppState>,
|
||||||
|
headers: HeaderMap,
|
||||||
body: String,
|
body: String,
|
||||||
) -> Result<(), crate::Error> {
|
) -> Result<(), crate::Error> {
|
||||||
|
let user = get_user_from_header(&state.pool, &headers).await?;
|
||||||
|
user.authorize(&state.pool, Some(Roles::ADMIN), None)
|
||||||
|
.await?;
|
||||||
|
|
||||||
tracing::info!("Migration is confirmed");
|
tracing::info!("Migration is confirmed");
|
||||||
|
|
||||||
let count = match body.trim().parse::<u32>() {
|
let count = match body.trim().parse::<u32>() {
|
||||||
|
@ -1,15 +1,38 @@
|
|||||||
use axum::{extract::State, http::HeaderMap, routing::get, Json, Router};
|
use axum::{
|
||||||
|
extract::{Path, State},
|
||||||
|
http::HeaderMap,
|
||||||
|
routing::{get, post},
|
||||||
|
Json, Router,
|
||||||
|
};
|
||||||
|
|
||||||
use crate::{auth::get_user_from_header, model::User, AppState};
|
use crate::{
|
||||||
|
auth::get_user_from_header,
|
||||||
|
model::{member::Roles, User},
|
||||||
|
AppState,
|
||||||
|
};
|
||||||
|
|
||||||
pub fn routes() -> Router<AppState> {
|
pub fn routes() -> Router<AppState> {
|
||||||
Router::new().route("/user", get(get_current_user))
|
Router::new()
|
||||||
|
.route("/user", get(get_current_user))
|
||||||
|
.route("/user/{user_id}/members", post(members_insert))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_current_user<'a>(
|
pub async fn get_current_user(
|
||||||
State(state): State<AppState>,
|
State(state): State<AppState>,
|
||||||
headers: HeaderMap,
|
headers: HeaderMap,
|
||||||
) -> Result<Json<User>, crate::Error> {
|
) -> Result<Json<User>, crate::Error> {
|
||||||
let (_roles, user) = get_user_from_header(&state.pool, &headers).await?;
|
let user = get_user_from_header(&state.pool, &headers).await?;
|
||||||
Ok(Json(user))
|
Ok(Json(user))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn members_insert(
|
||||||
|
State(state): State<AppState>,
|
||||||
|
Path(user_id): Path<String>,
|
||||||
|
headers: HeaderMap,
|
||||||
|
) -> Result<(), crate::Error> {
|
||||||
|
let user = get_user_from_header(&state.pool, &headers).await?;
|
||||||
|
user.authorize(&state.pool, Some(Roles::ADMIN), Some(user_id))
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user