Skip to content

Commit

Permalink
feat(rust): use the any driver for sqlx to add support for postgres
Browse files Browse the repository at this point in the history
  • Loading branch information
etorreborre committed Jun 28, 2024
1 parent a5848f5 commit 859e94d
Show file tree
Hide file tree
Showing 103 changed files with 4,456 additions and 2,901 deletions.
429 changes: 239 additions & 190 deletions .github/workflows/rust.yml

Large diffs are not rendered by default.

23 changes: 8 additions & 15 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 11 additions & 5 deletions NOTICE.md
Original file line number Diff line number Diff line change
Expand Up @@ -192,13 +192,15 @@ This file contains attributions for any 3rd-party open source code used in this
| equivalent | Apache-2.0, MIT | https://crates.io/crates/equivalent |
| errno | MIT, Apache-2.0 | https://crates.io/crates/errno |
| error-code | BSL-1.0 | https://crates.io/crates/error-code |
| etcetera | MIT, Apache-2.0 | https://crates.io/crates/etcetera |
| event-listener | Apache-2.0, MIT | https://crates.io/crates/event-listener |
| event-listener-strategy | Apache-2.0, MIT | https://crates.io/crates/event-listener-strategy |
| fastrand | Apache-2.0, MIT | https://crates.io/crates/fastrand |
| fd-lock | MIT, Apache-2.0 | https://crates.io/crates/fd-lock |
| fdeflate | MIT, Apache-2.0 | https://crates.io/crates/fdeflate |
| ff | MIT, Apache-2.0 | https://crates.io/crates/ff |
| fiat-crypto | MIT, Apache-2.0, BSD-1-Clause | https://crates.io/crates/fiat-crypto |
| finl_unicode | MIT, Apache-2.0 | https://crates.io/crates/finl_unicode |
| flate2 | MIT, Apache-2.0 | https://crates.io/crates/flate2 |
| flexi_logger | MIT, Apache-2.0 | https://crates.io/crates/flexi_logger |
| flume | Apache-2.0, MIT | https://crates.io/crates/flume |
Expand Down Expand Up @@ -487,11 +489,12 @@ This file contains attributions for any 3rd-party open source code used in this
| spin | MIT | https://crates.io/crates/spin |
| spki | Apache-2.0, MIT | https://crates.io/crates/spki |
| sqlformat | MIT, Apache-2.0 | https://crates.io/crates/sqlformat |
| sqlx | MIT, Apache-2.0 | https://crates.io/crates/sqlx |
| sqlx-core | MIT, Apache-2.0 | https://crates.io/crates/sqlx-core |
| sqlx-macros | MIT, Apache-2.0 | https://crates.io/crates/sqlx-macros |
| sqlx-macros-core | MIT, Apache-2.0 | https://crates.io/crates/sqlx-macros-core |
| sqlx-sqlite | MIT, Apache-2.0 | https://crates.io/crates/sqlx-sqlite |
| sqlx | MIT, Apache-2.0 | https://github.com/etorreborre/sqlx?rev=5fec648d2de0cbeed738dcf1c6f5bc9194fc439b |
| sqlx-core | MIT, Apache-2.0 | https://github.com/etorreborre/sqlx?rev=5fec648d2de0cbeed738dcf1c6f5bc9194fc439b |
| sqlx-macros | MIT, Apache-2.0 | https://github.com/etorreborre/sqlx?rev=5fec648d2de0cbeed738dcf1c6f5bc9194fc439b |
| sqlx-macros-core | MIT, Apache-2.0 | https://github.com/etorreborre/sqlx?rev=5fec648d2de0cbeed738dcf1c6f5bc9194fc439b |
| sqlx-postgres | MIT, Apache-2.0 | https://github.com/etorreborre/sqlx?rev=5fec648d2de0cbeed738dcf1c6f5bc9194fc439b |
| sqlx-sqlite | MIT, Apache-2.0 | https://github.com/etorreborre/sqlx?rev=5fec648d2de0cbeed738dcf1c6f5bc9194fc439b |
| stable_deref_trait | MIT, Apache-2.0 | https://crates.io/crates/stable_deref_trait |
| static_assertions | MIT, Apache-2.0 | https://crates.io/crates/static_assertions |
| stm32-device-signature | MIT, Apache-2.0 | https://crates.io/crates/stm32-device-signature |
Expand All @@ -500,6 +503,7 @@ This file contains attributions for any 3rd-party open source code used in this
| stm32h7 | MIT, Apache-2.0 | https://crates.io/crates/stm32h7 |
| stm32h7xx-hal | 0BSD | https://crates.io/crates/stm32h7xx-hal |
| str-buf | BSL-1.0 | https://crates.io/crates/str-buf |
| stringprep | MIT, Apache-2.0 | https://crates.io/crates/stringprep |
| strip-ansi-escapes | Apache-2.0, MIT | https://crates.io/crates/strip-ansi-escapes |
| strsim | MIT | https://crates.io/crates/strsim |
| strum | MIT | https://crates.io/crates/strum |
Expand Down Expand Up @@ -586,6 +590,7 @@ This file contains attributions for any 3rd-party open source code used in this
| waker-fn | Apache-2.0, MIT | https://crates.io/crates/waker-fn |
| walkdir | Unlicense, MIT | https://crates.io/crates/walkdir |
| want | MIT | https://crates.io/crates/want |
| wasite | Apache-2.0, BSL-1.0, MIT | https://crates.io/crates/wasite |
| wasm-bindgen | MIT, Apache-2.0 | https://crates.io/crates/wasm-bindgen |
| wasm-bindgen-backend | MIT, Apache-2.0 | https://crates.io/crates/wasm-bindgen-backend |
| wasm-bindgen-futures | MIT, Apache-2.0 | https://crates.io/crates/wasm-bindgen-futures |
Expand All @@ -604,6 +609,7 @@ This file contains attributions for any 3rd-party open source code used in this
| web-time | MIT, Apache-2.0 | https://crates.io/crates/web-time |
| weezl | MIT, Apache-2.0 | https://crates.io/crates/weezl |
| which | MIT | https://crates.io/crates/which |
| whoami | Apache-2.0, BSL-1.0, MIT | https://crates.io/crates/whoami |
| winapi | MIT, Apache-2.0 | https://crates.io/crates/winapi |
| winapi-i686-pc-windows-gnu | MIT, Apache-2.0 | https://crates.io/crates/winapi-i686-pc-windows-gnu |
| winapi-util | Unlicense, MIT | https://crates.io/crates/winapi-util |
Expand Down
7 changes: 7 additions & 0 deletions implementations/rust/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,13 @@ nextest:
nextest_%:
cargo --locked nextest --config-file $(ROOT_DIR)/tools/nextest/.config/nextest.toml run -E 'package($*)' --no-fail-fast
cargo --locked test --doc
test_postgres:
export OCKAM_POSTGRES_HOST=localhost
export OCKAM_POSTGRES_PORT=5433
export OCKAM_POSTGRES_DATABASE_NAME=test
export OCKAM_POSTGRES_USER=postgres
export OCKAM_POSTGRES_PASSWORD=password
cargo --locked nextest --config-file $(ROOT_DIR)/tools/nextest/.config/nextest.toml run -E 'test(sql) or test(cli_state)' --no-fail-fast --test-threads 1

lint: lint_cargo_fmt_check lint_cargo_deny lint_cargo_clippy
lint_cargo_fmt_check:
Expand Down
2 changes: 1 addition & 1 deletion implementations/rust/ockam/ockam_abac/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ ockam_executor = { version = "0.80.0", path = "../ockam_executor", default-featu
regex = { version = "1.10.5", default-features = false, optional = true }
rustyline = { version = "14.0.0", optional = true }
rustyline-derive = { version = "0.10.0", optional = true }
sqlx = { version = "0.7.4", optional = true }
sqlx = { git = "https://github.com/etorreborre/sqlx", rev = "5fec648d2de0cbeed738dcf1c6f5bc9194fc439b", optional = true }
str-buf = "3.0.3"
tokio = { version = "1.38", default-features = false, optional = true, features = ["sync", "time", "rt", "rt-multi-thread", "macros"] }
tracing = { version = "0.1", default-features = false, features = ["attributes"] }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use tracing::debug;
use ockam_core::async_trait;
use ockam_core::compat::vec::Vec;
use ockam_core::Result;
use ockam_node::database::{FromSqlxError, SqlxDatabase, SqlxType, ToSqlxType, ToVoid};
use ockam_node::database::{FromSqlxError, SqlxDatabase, ToVoid};

use crate::{Action, Expr, ResourceName, ResourcePoliciesRepository, ResourcePolicy};

Expand Down Expand Up @@ -43,13 +43,15 @@ impl ResourcePoliciesRepository for ResourcePolicySqlxDatabase {
expression: &Expr,
) -> Result<()> {
let query = query(
r#"INSERT OR REPLACE INTO resource_policy
VALUES (?, ?, ?, ?)"#,
r#"INSERT INTO resource_policy (resource_name, action, expression, node_name)
VALUES ($1, $2, $3, $4)
ON CONFLICT (resource_name, action, node_name)
DO UPDATE SET expression = $3"#,
)
.bind(resource_name.to_sql())
.bind(action.to_sql())
.bind(expression.to_string().to_sql())
.bind(self.node_name.to_sql());
.bind(resource_name)
.bind(action)
.bind(expression)
.bind(&self.node_name);
query.execute(&*self.database.pool).await.void()
}

Expand All @@ -61,11 +63,11 @@ impl ResourcePoliciesRepository for ResourcePolicySqlxDatabase {
let query = query_as(
r#"SELECT resource_name, action, expression
FROM resource_policy
WHERE node_name=$1 and resource_name=$2 and action=$3"#,
WHERE node_name = $1 and resource_name = $2 and action = $3"#,
)
.bind(self.node_name.to_sql())
.bind(resource_name.to_sql())
.bind(action.to_sql());
.bind(&self.node_name)
.bind(resource_name)
.bind(action);
let row: Option<PolicyRow> = query
.fetch_optional(&*self.database.pool)
.await
Expand All @@ -77,9 +79,9 @@ impl ResourcePoliciesRepository for ResourcePolicySqlxDatabase {
let query = query_as(
r#"SELECT resource_name, action, expression
FROM resource_policy
WHERE node_name=$1"#,
WHERE node_name = $1"#,
)
.bind(self.node_name.to_sql());
.bind(&self.node_name);
let row: Vec<PolicyRow> = query.fetch_all(&*self.database.pool).await.into_core()?;
row.into_iter()
.map(|r| r.try_into())
Expand All @@ -93,10 +95,10 @@ impl ResourcePoliciesRepository for ResourcePolicySqlxDatabase {
let query = query_as(
r#"SELECT resource_name, action, expression
FROM resource_policy
WHERE node_name=$1 and resource_name=$2"#,
WHERE node_name = $1 and resource_name = $2"#,
)
.bind(self.node_name.to_sql())
.bind(resource_name.to_sql());
.bind(&self.node_name)
.bind(resource_name);
let row: Vec<PolicyRow> = query.fetch_all(&*self.database.pool).await.into_core()?;
row.into_iter()
.map(|r| r.try_into())
Expand All @@ -106,29 +108,15 @@ impl ResourcePoliciesRepository for ResourcePolicySqlxDatabase {
async fn delete_policy(&self, resource_name: &ResourceName, action: &Action) -> Result<()> {
let query = query(
r#"DELETE FROM resource_policy
WHERE node_name=? and resource_name=? and action=?"#,
WHERE node_name = $1 and resource_name = $2 and action = $3"#,
)
.bind(self.node_name.to_sql())
.bind(resource_name.to_sql())
.bind(action.to_sql());
.bind(&self.node_name)
.bind(resource_name)
.bind(action);
query.execute(&*self.database.pool).await.void()
}
}

// Database serialization / deserialization

impl ToSqlxType for ResourceName {
fn to_sql(&self) -> SqlxType {
SqlxType::Text(self.as_str().to_string())
}
}

impl ToSqlxType for Action {
fn to_sql(&self) -> SqlxType {
SqlxType::Text(self.to_string())
}
}

/// Low-level representation of a row in the resource_policy table
#[derive(FromRow)]
struct PolicyRow {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
use core::str::FromStr;
use sqlx::database::HasArguments;
use sqlx::encode::IsNull;
use sqlx::*;
use tracing::debug;

use ockam_core::async_trait;
use ockam_core::Result;
use ockam_node::database::{FromSqlxError, SqlxDatabase, ToSqlxType, ToVoid};
use ockam_node::database::{FromSqlxError, SqlxDatabase, ToVoid};

use crate::{Resource, ResourceName, ResourceType, ResourcesRepository};

Expand Down Expand Up @@ -37,23 +39,25 @@ impl ResourcesSqlxDatabase {
impl ResourcesRepository for ResourcesSqlxDatabase {
async fn store_resource(&self, resource: &Resource) -> Result<()> {
let query = query(
r#"INSERT OR REPLACE INTO resource
VALUES (?, ?, ?)"#,
r#"
INSERT INTO resource (resource_name, resource_type, node_name)
VALUES ($1, $2, $3)
ON CONFLICT DO NOTHING"#,
)
.bind(resource.resource_name.to_sql())
.bind(resource.resource_type.to_sql())
.bind(self.node_name.to_sql());
.bind(&resource.resource_name)
.bind(&resource.resource_type)
.bind(&self.node_name);
query.execute(&*self.database.pool).await.void()
}

async fn get_resource(&self, resource_name: &ResourceName) -> Result<Option<Resource>> {
let query = query_as(
r#"SELECT resource_name, resource_type
FROM resource
WHERE node_name=$1 and resource_name=$2"#,
WHERE node_name = $1 and resource_name = $2"#,
)
.bind(self.node_name.to_sql())
.bind(resource_name.to_sql());
.bind(&self.node_name)
.bind(resource_name);
let row: Option<ResourceRow> = query
.fetch_optional(&*self.database.pool)
.await
Expand All @@ -66,24 +70,38 @@ impl ResourcesRepository for ResourcesSqlxDatabase {

let query = query(
r#"DELETE FROM resource
WHERE node_name=? and resource_name=?"#,
WHERE node_name = $1 and resource_name = $2"#,
)
.bind(self.node_name.to_sql())
.bind(resource_name.to_sql());
.bind(&self.node_name)
.bind(resource_name);
query.execute(&mut *transaction).await.void()?;

let query = sqlx::query(
r#"DELETE FROM resource_policy
WHERE node_name=? and resource_name=?"#,
WHERE node_name = $1 and resource_name = $2"#,
)
.bind(self.node_name.to_sql())
.bind(resource_name.to_sql());
.bind(&self.node_name)
.bind(resource_name);
query.execute(&mut *transaction).await.void()?;

transaction.commit().await.void()
}
}

// Database serialization / deserialization

impl Type<Any> for ResourceName {
fn type_info() -> <Any as Database>::TypeInfo {
<String as Type<Any>>::type_info()
}
}

impl sqlx::Encode<'_, Any> for ResourceName {
fn encode_by_ref(&self, buf: &mut <Any as HasArguments>::ArgumentBuffer) -> IsNull {
<String as sqlx::Encode<'_, Any>>::encode_by_ref(&self.to_string(), buf)
}
}

/// Low-level representation of a row in the resource_type_policy table
#[derive(FromRow)]
#[allow(dead_code)]
Expand Down
Loading

0 comments on commit 859e94d

Please sign in to comment.