From 02abffd63aeada45482a80fca74bc81a31e82b37 Mon Sep 17 00:00:00 2001 From: realaravinth Date: Sun, 8 May 2022 20:01:13 +0530 Subject: [PATCH] feat: init and define database ops as interfaces to support multiple DBs --- db/db-core/.gitignore | 2 + db/db-core/Cargo.toml | 22 ++++++++++ db/db-core/src/errors.rs | 35 ++++++++++++++++ db/db-core/src/lib.rs | 88 ++++++++++++++++++++++++++++++++++++++++ db/db-core/src/ops.rs | 49 ++++++++++++++++++++++ db/db-core/src/tests.rs | 24 +++++++++++ 6 files changed, 220 insertions(+) create mode 100644 db/db-core/.gitignore create mode 100644 db/db-core/Cargo.toml create mode 100644 db/db-core/src/errors.rs create mode 100644 db/db-core/src/lib.rs create mode 100644 db/db-core/src/ops.rs create mode 100644 db/db-core/src/tests.rs diff --git a/db/db-core/.gitignore b/db/db-core/.gitignore new file mode 100644 index 00000000..4fffb2f8 --- /dev/null +++ b/db/db-core/.gitignore @@ -0,0 +1,2 @@ +/target +/Cargo.lock diff --git a/db/db-core/Cargo.toml b/db/db-core/Cargo.toml new file mode 100644 index 00000000..3a7c6ee0 --- /dev/null +++ b/db/db-core/Cargo.toml @@ -0,0 +1,22 @@ +[package] +name = "db-core" +version = "0.1.0" +edition = "2021" +homepage = "https://mcaptcha.org" +repository = "https://github.com/mCaptcha/mCaptcha" +documentation = "https://mcaptcha.org/docs/" +license = "AGPLv3 or later version" +authors = ["realaravinth "] + +[dependencies] +async-trait = "0.1.51" +thiserror = "1.0.30" +serde = { version = "1", features = ["derive"]} +url = { version = "2.2.2", features = ["serde"] } + +[features] +default = [] +test = [] + +[dev-dependencies] +serde_json = "1" diff --git a/db/db-core/src/errors.rs b/db/db-core/src/errors.rs new file mode 100644 index 00000000..c3f18e23 --- /dev/null +++ b/db/db-core/src/errors.rs @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2022 Aravinth Manivannan + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +//! represents all the ways a trait can fail using this crate +use std::error::Error as StdError; + +//use derive_more::{error, Error as DeriveError}; +use thiserror::Error; + +/// Error data structure grouping various error subtypes +#[derive(Debug, Error)] +pub enum DBError { + /// errors that are specific to a database implementation + #[error("{0}")] + DBError(#[source] BoxDynError), +} + +/// Convenience type alias for grouping driver-specific errors +pub type BoxDynError = Box; + +/// Generic result data structure +pub type DBResult = std::result::Result; diff --git a/db/db-core/src/lib.rs b/db/db-core/src/lib.rs new file mode 100644 index 00000000..1287379c --- /dev/null +++ b/db/db-core/src/lib.rs @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2022 Aravinth Manivannan + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#![warn(missing_docs)] +//! # `mCaptcha` database operations +//! +//! Traits and datastructures used in mCaptcha to interact with database. +//! +//! To use an unsupported database with mCaptcha, traits present within this crate should be +//! implemented. +//! +//! +//! ## Organisation +//! +//! Database functionallity is divided accross various modules: +//! +//! - [errors](crate::auth): error data structures used in this crate +//! - [ops](crate::ops): meta operations like connection pool creation, migrations and getting +//! connection from pool +use std::str::FromStr; + +use serde::{Deserialize, Serialize}; +use url::Url; + +pub mod errors; +pub mod ops; +#[cfg(feature = "test")] +pub mod tests; + +use dev::*; +pub use ops::GetConnection; + +pub mod prelude { + //! useful imports for users working with a supported database + + pub use super::errors::*; + pub use super::ops::*; + pub use super::*; +} + +pub mod dev { + //! useful imports for supporting a new database + pub use super::prelude::*; + pub use async_trait::async_trait; +} + +#[async_trait] +/// mCaptcha's database requirements. To implement support for $Database, kindly implement this +/// trait. +pub trait MCDatabase: std::marker::Send + std::marker::Sync + CloneSPDatabase { + /// ping DB + async fn ping(&self) -> bool; +} + +/// Trait to clone MCDatabase +pub trait CloneSPDatabase { + /// clone DB + fn clone_db(&self) -> Box; +} + +impl CloneSPDatabase for T +where + T: MCDatabase + Clone + 'static, +{ + fn clone_db(&self) -> Box { + Box::new(self.clone()) + } +} + +impl Clone for Box { + fn clone(&self) -> Self { + (**self).clone_db() + } +} diff --git a/db/db-core/src/ops.rs b/db/db-core/src/ops.rs new file mode 100644 index 00000000..680225a9 --- /dev/null +++ b/db/db-core/src/ops.rs @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2022 Aravinth Manivannan + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +//! meta operations like migration and connecting to a database +use crate::dev::*; + +/// Database operations trait(migrations, pool creation and fetching connection from pool) +pub trait DBOps: GetConnection + Migrate {} + +/// Get database connection +#[async_trait] +pub trait GetConnection { + /// database connection type + type Conn; + /// database specific error-type + /// get connection from connection pool + async fn get_conn(&self) -> DBResult; +} + +/// Create databse connection +#[async_trait] +pub trait Connect { + /// database specific pool-type + type Pool: MCDatabase; + /// database specific error-type + /// create connection pool + async fn connect(self) -> DBResult; +} + +/// database migrations +#[async_trait] +pub trait Migrate: MCDatabase { + /// database specific error-type + /// run migrations + async fn migrate(&self) -> DBResult<()>; +} diff --git a/db/db-core/src/tests.rs b/db/db-core/src/tests.rs new file mode 100644 index 00000000..da9de2d1 --- /dev/null +++ b/db/db-core/src/tests.rs @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2022 Aravinth Manivannan + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +//! Test utilities +use crate::prelude::*; + +pub async fn database_works<'a, T: MCDatabase>( + db: &T, +) { + unimplemented!("database tests"); +}