Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/linters.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ concurrency:

env:
CARGO_TERM_COLOR: always
rust_min: 1.89.0
rust_min: 1.90.0

jobs:
rustfmt:
Expand Down
49 changes: 32 additions & 17 deletions src/assignment/backends/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,30 +40,45 @@ pub enum AssignmentDatabaseError {
source: RoleBuilderError,
},

#[error(transparent)]
Database { source: sea_orm::DbErr },

/// Conflict
#[error("{0}")]
Conflict(String),
#[error("{message}")]
Conflict { message: String, context: String },

/// SqlError
#[error("{0}")]
Sql(String),
#[error("{message}")]
Sql { message: String, context: String },

/// Database error
#[error("Database error while {context}")]
Database {
source: sea_orm::DbErr,
context: String,
},

#[error("{0}")]
InvalidAssignmentType(String),
}

impl From<sea_orm::DbErr> for AssignmentDatabaseError {
fn from(err: sea_orm::DbErr) -> Self {
err.sql_err().map_or_else(
|| Self::Database { source: err },
|err| match err {
SqlErr::UniqueConstraintViolation(descr) => Self::Conflict(descr),
SqlErr::ForeignKeyConstraintViolation(descr) => Self::Conflict(descr),
other => Self::Sql(other.to_string()),
/// Convert the DB error into the [AssignmentDatabaseError] with the context information.
pub fn db_err(e: sea_orm::DbErr, context: &str) -> AssignmentDatabaseError {
e.sql_err().map_or_else(
|| AssignmentDatabaseError::Database {
source: e,
context: context.to_string(),
},
|err| match err {
SqlErr::UniqueConstraintViolation(descr) => AssignmentDatabaseError::Conflict {
message: descr.to_string(),
context: context.to_string(),
},
SqlErr::ForeignKeyConstraintViolation(descr) => AssignmentDatabaseError::Conflict {
message: descr.to_string(),
context: context.to_string(),
},
other => AssignmentDatabaseError::Sql {
message: other.to_string(),
context: context.to_string(),
},
)
}
},
)
}
32 changes: 24 additions & 8 deletions src/assignment/backends/sql/assignment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use sea_orm::prelude::Expr;
use sea_orm::query::*;
use std::collections::{BTreeMap, HashMap};

use crate::assignment::backends::error::AssignmentDatabaseError;
use crate::assignment::backends::error::{AssignmentDatabaseError, db_err};
use crate::assignment::types::*;
use crate::config::Config;
use crate::db::entity::{
Expand Down Expand Up @@ -71,15 +71,19 @@ pub async fn list(
}

let results: Result<Vec<Assignment>, _> = if let Some(true) = &params.include_names {
let db_assignments: Vec<(db_assignment::Model, Option<db_role::Model>)> =
select_assignment.find_also_related(DbRole).all(db).await?;
let db_assignments: Vec<(db_assignment::Model, Option<db_role::Model>)> = select_assignment
.find_also_related(DbRole)
.all(db)
.await
.map_err(|err| db_err(err, "fetching role assignments with roles"))?;
let db_system_assignments: Vec<(db_system_assignment::Model, Option<db_role::Model>)> =
if params.project_id.is_none() && params.domain_id.is_none() {
// get system scope assignments only when no project or domain is specified
select_system_assignment
.find_also_related(DbRole)
.all(db)
.await?
.await
.map_err(|err| db_err(err, "fetching system role assignments with roles"))?
} else {
Vec::new()
};
Expand All @@ -93,11 +97,17 @@ pub async fn list(
)
.collect()
} else {
let db_assignments: Vec<db_assignment::Model> = select_assignment.all(db).await?;
let db_assignments: Vec<db_assignment::Model> = select_assignment
.all(db)
.await
.map_err(|err| db_err(err, "fetching role assignments"))?;
let db_system_assignments: Vec<db_system_assignment::Model> =
if params.project_id.is_none() && params.domain_id.is_none() {
// get system scope assignments only when no project or domain is specified
select_system_assignment.all(db).await?
select_system_assignment
.all(db)
.await
.map_err(|err| db_err(err, "fetching system role assignments"))?
} else {
Vec::new()
};
Expand Down Expand Up @@ -153,7 +163,12 @@ pub async fn list_for_multiple_actors_and_targets(

let mut db_assignments: BTreeMap<String, db_assignment::Model> = BTreeMap::new();
// Get assignments resolving the roles inference
for assignment in select.all(db).await? {
for assignment in select.all(db).await.map_err(|err| {
db_err(
err,
"fetching role assignments for multiple actors and targets",
)
})? {
db_assignments.insert(assignment.role_id.clone(), assignment.clone());
if let Some(implies) = imply_rules.get(&assignment.role_id) {
let mut implied_assignment = assignment.clone();
Expand All @@ -173,7 +188,8 @@ pub async fn list_for_multiple_actors_and_targets(
.filter(Expr::col(db_role::Column::Id).is_in(db_assignments.keys()))
.into_tuple()
.all(db)
.await?,
.await
.map_err(|err| db_err(err, "fetching roles by ids"))?,
);
let results: Result<Vec<Assignment>, _> = db_assignments
.values()
Expand Down
8 changes: 6 additions & 2 deletions src/assignment/backends/sql/implied_role.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use sea_orm::DatabaseConnection;
use sea_orm::entity::*;
use std::collections::{BTreeMap, BTreeSet};

use crate::assignment::backends::error::AssignmentDatabaseError;
use crate::assignment::backends::error::{AssignmentDatabaseError, db_err};
use crate::db::entity::prelude::ImpliedRole as DbImpliedRole;

/// Build a resolved tree of role inference
Expand Down Expand Up @@ -52,7 +52,11 @@ pub async fn list_rules(
resolve: bool,
) -> Result<BTreeMap<String, BTreeSet<String>>, AssignmentDatabaseError> {
let mut implied_rules: BTreeMap<String, BTreeSet<String>> = BTreeMap::new();
for imply in DbImpliedRole::find().all(db).await? {
for imply in DbImpliedRole::find()
.all(db)
.await
.map_err(|err| db_err(err, "fetching implied roles"))?
{
implied_rules
.entry(imply.prior_role_id)
.and_modify(|x| {
Expand Down
12 changes: 9 additions & 3 deletions src/assignment/backends/sql/role.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use sea_orm::entity::*;
use sea_orm::query::*;
use serde_json::Value;

use crate::assignment::backends::error::AssignmentDatabaseError;
use crate::assignment::backends::error::{AssignmentDatabaseError, db_err};
use crate::assignment::types::*;
use crate::config::Config;
use crate::db::entity::{prelude::Role as DbRole, role as db_role};
Expand All @@ -31,7 +31,10 @@ pub async fn get<I: AsRef<str>>(
) -> Result<Option<Role>, AssignmentDatabaseError> {
let role_select = DbRole::find_by_id(id.as_ref());

let entry: Option<db_role::Model> = role_select.one(db).await?;
let entry: Option<db_role::Model> = role_select
.one(db)
.await
.map_err(|err| db_err(err, "fetching role by id"))?;
entry.map(TryInto::try_into).transpose()
}

Expand All @@ -49,7 +52,10 @@ pub async fn list(
select = select.filter(db_role::Column::Name.eq(name));
}

let db_roles: Vec<db_role::Model> = select.all(db).await?;
let db_roles: Vec<db_role::Model> = select
.all(db)
.await
.map_err(|err| db_err(err, "listing roles"))?;
let results: Result<Vec<Role>, _> = db_roles
.into_iter()
.map(TryInto::<Role>::try_into)
Expand Down
2 changes: 1 addition & 1 deletion src/assignment/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ pub enum AssignmentProviderError {
impl From<AssignmentDatabaseError> for AssignmentProviderError {
fn from(source: AssignmentDatabaseError) -> Self {
match source {
AssignmentDatabaseError::Conflict(x) => Self::Conflict(x),
AssignmentDatabaseError::Conflict { message, .. } => Self::Conflict(message),
AssignmentDatabaseError::RoleNotFound(x) => Self::RoleNotFound(x),
AssignmentDatabaseError::Serde { source } => Self::Serde { source },
_ => Self::AssignmentDatabaseError { source },
Expand Down
46 changes: 30 additions & 16 deletions src/catalog/backends/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,27 +41,41 @@ pub enum CatalogDatabaseError {
ServiceNotFound(String),

/// Conflict
#[error("{0}")]
Conflict(String),
#[error("{message}")]
Conflict { message: String, context: String },

/// SqlError
#[error("{0}")]
Sql(String),
#[error("{message}")]
Sql { message: String, context: String },

/// Database error
#[error(transparent)]
Database { source: sea_orm::DbErr },
#[error("Database error while {context}")]
Database {
source: sea_orm::DbErr,
context: String,
},
}

impl From<sea_orm::DbErr> for CatalogDatabaseError {
fn from(err: sea_orm::DbErr) -> Self {
err.sql_err().map_or_else(
|| Self::Database { source: err },
|err| match err {
SqlErr::UniqueConstraintViolation(descr) => Self::Conflict(descr),
SqlErr::ForeignKeyConstraintViolation(descr) => Self::Conflict(descr),
other => Self::Sql(other.to_string()),
/// Convert the DB error into the [CatalogDatabaseError] with the context information.
pub fn db_err(e: sea_orm::DbErr, context: &str) -> CatalogDatabaseError {
e.sql_err().map_or_else(
|| CatalogDatabaseError::Database {
source: e,
context: context.to_string(),
},
|err| match err {
SqlErr::UniqueConstraintViolation(descr) => CatalogDatabaseError::Conflict {
message: descr.to_string(),
context: context.to_string(),
},
SqlErr::ForeignKeyConstraintViolation(descr) => CatalogDatabaseError::Conflict {
message: descr.to_string(),
context: context.to_string(),
},
other => CatalogDatabaseError::Sql {
message: other.to_string(),
context: context.to_string(),
},
)
}
},
)
}
5 changes: 3 additions & 2 deletions src/catalog/backends/sql.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use sea_orm::query::*;

use super::super::types::*;
use crate::catalog::CatalogProviderError;
use crate::catalog::backends::error::CatalogDatabaseError;
use crate::catalog::backends::error::{CatalogDatabaseError, db_err};
use crate::config::Config;
use crate::db::entity::{
endpoint as db_endpoint,
Expand Down Expand Up @@ -104,7 +104,8 @@ async fn get_catalog(
.find_with_related(DbEndpoint)
.filter(db_endpoint::Column::Enabled.eq(enabled))
.all(db)
.await?;
.await
.map_err(|err| db_err(err, "fetching catalog"))?;

let mut res: Vec<(Service, Vec<Endpoint>)> = Vec::new();
for (srv, db_endpoints) in db_entities.into_iter() {
Expand Down
12 changes: 9 additions & 3 deletions src/catalog/backends/sql/endpoint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use sea_orm::entity::*;
use sea_orm::query::*;
use serde_json::Value;

use crate::catalog::backends::error::CatalogDatabaseError;
use crate::catalog::backends::error::{CatalogDatabaseError, db_err};
use crate::catalog::types::*;
use crate::config::Config;
use crate::db::entity::{endpoint as db_endpoint, prelude::Endpoint as DbEndpoint};
Expand All @@ -29,7 +29,10 @@ pub async fn get<I: AsRef<str>>(
) -> Result<Option<Endpoint>, CatalogDatabaseError> {
let select = DbEndpoint::find_by_id(id.as_ref());

let entry: Option<db_endpoint::Model> = select.one(db).await?;
let entry: Option<db_endpoint::Model> = select
.one(db)
.await
.map_err(|err| db_err(err, "fetching service endpoint by id"))?;
entry.map(TryInto::try_into).transpose()
}

Expand All @@ -50,7 +53,10 @@ pub async fn list(
select = select.filter(db_endpoint::Column::RegionId.eq(val));
}

let db_entities: Vec<db_endpoint::Model> = select.all(db).await?;
let db_entities: Vec<db_endpoint::Model> = select
.all(db)
.await
.map_err(|err| db_err(err, "fetching endpoints"))?;
let results: Result<Vec<Endpoint>, _> = db_entities
.into_iter()
.map(TryInto::<Endpoint>::try_into)
Expand Down
12 changes: 9 additions & 3 deletions src/catalog/backends/sql/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use sea_orm::entity::*;
use sea_orm::query::*;
use serde_json::Value;

use crate::catalog::backends::error::CatalogDatabaseError;
use crate::catalog::backends::error::{CatalogDatabaseError, db_err};
use crate::catalog::types::*;
use crate::config::Config;
use crate::db::entity::{prelude::Service as DbService, service as db_service};
Expand All @@ -29,7 +29,10 @@ pub async fn get<I: AsRef<str>>(
) -> Result<Option<Service>, CatalogDatabaseError> {
let select = DbService::find_by_id(id.as_ref());

let entry: Option<db_service::Model> = select.one(db).await?;
let entry: Option<db_service::Model> = select
.one(db)
.await
.map_err(|err| db_err(err, "fetching service by ID"))?;
entry.map(TryInto::try_into).transpose()
}

Expand All @@ -44,7 +47,10 @@ pub async fn list(
select = select.filter(db_service::Column::Type.eq(typ));
}

let db_services: Vec<db_service::Model> = select.all(db).await?;
let db_services: Vec<db_service::Model> = select
.all(db)
.await
.map_err(|err| db_err(err, "fetching services"))?;
let results: Result<Vec<Service>, _> = db_services
.into_iter()
.map(TryInto::<Service>::try_into)
Expand Down
Loading
Loading