feat: define core DB traits to store, check for existence and delete
forges
This commit is contained in:
parent
5af8888936
commit
2a8283acc0
7 changed files with 412 additions and 0 deletions
2
db/db-core/.gitignore
vendored
Normal file
2
db/db-core/.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
/target
|
||||||
|
.env
|
122
db/db-core/Cargo.lock
generated
Normal file
122
db/db-core/Cargo.lock
generated
Normal file
|
@ -0,0 +1,122 @@
|
||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
version = 3
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "async-trait"
|
||||||
|
version = "0.1.53"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ed6aa3524a2dfcf9fe180c51eae2b58738348d819517ceadf95789c51fff7600"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "db-core"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"async-trait",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
"thiserror",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "itoa"
|
||||||
|
version = "1.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro2"
|
||||||
|
version = "1.0.37"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ec757218438d5fda206afc041538b2f6d889286160d649a86a24d37e1235afd1"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-xid",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "quote"
|
||||||
|
version = "1.0.17"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "632d02bff7f874a36f33ea8bb416cd484b90cc66c1194b1a1110d067a7013f58"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ryu"
|
||||||
|
version = "1.0.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde"
|
||||||
|
version = "1.0.136"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ce31e24b01e1e524df96f1c2fdd054405f8d7376249a5110886fb4b658484789"
|
||||||
|
dependencies = [
|
||||||
|
"serde_derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_derive"
|
||||||
|
version = "1.0.136"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "08597e7152fcd306f41838ed3e37be9eaeed2b61c42e2117266a554fab4662f9"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_json"
|
||||||
|
version = "1.0.79"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8e8d9fa5c3b304765ce1fd9c4c8a3de2c8db365a5b91be52f186efc675681d95"
|
||||||
|
dependencies = [
|
||||||
|
"itoa",
|
||||||
|
"ryu",
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "syn"
|
||||||
|
version = "1.0.91"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b683b2b825c8eef438b77c36a06dc262294da3d5a5813fac20da149241dcd44d"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"unicode-xid",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "thiserror"
|
||||||
|
version = "1.0.30"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417"
|
||||||
|
dependencies = [
|
||||||
|
"thiserror-impl",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "thiserror-impl"
|
||||||
|
version = "1.0.30"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-xid"
|
||||||
|
version = "0.2.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
|
25
db/db-core/Cargo.toml
Normal file
25
db/db-core/Cargo.toml
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
[package]
|
||||||
|
name = "db-core"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
homepage = "https://github.com/forgeflux-org/starchart"
|
||||||
|
repository = "https://github.com/forgeflux-org/starchart"
|
||||||
|
documentation = "https://github.con/forgeflux-org/starchart"
|
||||||
|
readme = "https://github.com/forgeflux-org/starchart/blob/master/README.md"
|
||||||
|
license = "AGPLv3 or later version"
|
||||||
|
authors = ["Aravinth Manivannan <realaravinth@batsense.net>"]
|
||||||
|
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
async-trait = "0.1.51"
|
||||||
|
thiserror = "1.0.30"
|
||||||
|
serde = { version = "1", features = ["derive"]}
|
||||||
|
|
||||||
|
[features]
|
||||||
|
default = []
|
||||||
|
test = []
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
serde_json = "1"
|
48
db/db-core/src/errors.rs
Normal file
48
db/db-core/src/errors.rs
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
/*
|
||||||
|
* ForgeFlux StarChart - A federated software forge spider
|
||||||
|
* Copyright (C) 2022 Aravinth Manivannan <realaravinth@batsense.net>
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
//! 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 {
|
||||||
|
/// DNS challenge value is already taken
|
||||||
|
#[error("DNS challenge is already taken")]
|
||||||
|
DuplicateChallengeText,
|
||||||
|
|
||||||
|
/// DNS challenge hostname is already taken
|
||||||
|
#[error("DNS challenge hostname is already taken")]
|
||||||
|
DuplicateChallengeHostname,
|
||||||
|
|
||||||
|
/// forge instance type is unknown
|
||||||
|
#[error("Unknown forge instance specifier {}", _0)]
|
||||||
|
UnknownForgeType(String),
|
||||||
|
|
||||||
|
/// 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<dyn StdError + 'static + Send + Sync>;
|
||||||
|
|
||||||
|
/// Generic result data structure
|
||||||
|
pub type DBResult<V> = std::result::Result<V, DBError>;
|
136
db/db-core/src/lib.rs
Normal file
136
db/db-core/src/lib.rs
Normal file
|
@ -0,0 +1,136 @@
|
||||||
|
/*
|
||||||
|
* ForgeFlux StarChart - A federated software forge spider
|
||||||
|
* Copyright (C) 2022 Aravinth Manivannan <realaravinth@batsense.net>
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#![warn(missing_docs)]
|
||||||
|
//! # `Starchart` database operations
|
||||||
|
//!
|
||||||
|
//! Traits and datastructures used in Starchart to interact with database.
|
||||||
|
//!
|
||||||
|
//! To use an unsupported database with Starchart, 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};
|
||||||
|
|
||||||
|
pub mod errors;
|
||||||
|
pub mod ops;
|
||||||
|
#[cfg(feature = "test")]
|
||||||
|
pub mod tests;
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||||
|
/// create a new forge on the database
|
||||||
|
pub struct CreateForge<'a> {
|
||||||
|
/// hostname of the forge instance: with scheme but remove trailing slash
|
||||||
|
pub hostname: &'a str,
|
||||||
|
/// forge type: which software is the instance running?
|
||||||
|
pub forge_type: ForgeImplementation,
|
||||||
|
}
|
||||||
|
|
||||||
|
use dev::*;
|
||||||
|
#[async_trait]
|
||||||
|
/// Starchart's database requirements. To implement support for $Database, kindly implement this
|
||||||
|
/// trait.
|
||||||
|
pub trait SCDatabase: std::marker::Send + std::marker::Sync + CloneSPDatabase {
|
||||||
|
/// ping DB
|
||||||
|
async fn ping(&self) -> bool;
|
||||||
|
|
||||||
|
/// create forge isntance
|
||||||
|
async fn create_forge_isntance(&self, f: &CreateForge) -> DBResult<()>;
|
||||||
|
|
||||||
|
/// delete forge isntance
|
||||||
|
async fn delete_forge_instance(&self, hostname: &str) -> DBResult<()>;
|
||||||
|
|
||||||
|
/// check if a forge instance exists
|
||||||
|
async fn forge_exists(&self, hostname: &str) -> DBResult<bool>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Trait to clone SCDatabase
|
||||||
|
pub trait CloneSPDatabase {
|
||||||
|
/// clone DB
|
||||||
|
fn clone_db(&self) -> Box<dyn SCDatabase>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> CloneSPDatabase for T
|
||||||
|
where
|
||||||
|
T: SCDatabase + Clone + 'static,
|
||||||
|
{
|
||||||
|
fn clone_db(&self) -> Box<dyn SCDatabase> {
|
||||||
|
Box::new(self.clone())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Clone for Box<dyn SCDatabase> {
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
(**self).clone_db()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Forge type: Gitea, Sourcehut, GitLab, etc. Support is currently only available for Gitea
|
||||||
|
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||||
|
#[serde(rename_all = "lowercase")]
|
||||||
|
pub enum ForgeImplementation {
|
||||||
|
/// [Gitea](https://gitea.io) softare forge
|
||||||
|
Gitea,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ForgeImplementation {
|
||||||
|
/// Convert [ForgeImplementation] to [str]
|
||||||
|
pub const fn to_str(&self) -> &'static str {
|
||||||
|
match self {
|
||||||
|
ForgeImplementation::Gitea => "gitea",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromStr for ForgeImplementation {
|
||||||
|
type Err = DBError;
|
||||||
|
|
||||||
|
/// Convert [str] to [ForgeImplementation]
|
||||||
|
fn from_str(s: &str) -> DBResult<Self> {
|
||||||
|
const GITEA: &str = ForgeImplementation::Gitea.to_str();
|
||||||
|
let s = s.trim();
|
||||||
|
match s {
|
||||||
|
GITEA => Ok(Self::Gitea),
|
||||||
|
_ => Err(DBError::UnknownForgeType(s.to_owned())),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
50
db/db-core/src/ops.rs
Normal file
50
db/db-core/src/ops.rs
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
/*
|
||||||
|
* ForgeFlux StarChart - A federated software forge spider
|
||||||
|
* Copyright (C) 2022 Aravinth Manivannan <realaravinth@batsense.net>
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
//! 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<Self::Conn>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create databse connection
|
||||||
|
#[async_trait]
|
||||||
|
pub trait Connect {
|
||||||
|
/// database specific pool-type
|
||||||
|
type Pool: SCDatabase;
|
||||||
|
/// database specific error-type
|
||||||
|
/// create connection pool
|
||||||
|
async fn connect(self) -> DBResult<Self::Pool>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// database migrations
|
||||||
|
#[async_trait]
|
||||||
|
pub trait Migrate: SCDatabase {
|
||||||
|
/// database specific error-type
|
||||||
|
/// run migrations
|
||||||
|
async fn migrate(&self) -> DBResult<()>;
|
||||||
|
}
|
29
db/db-core/src/tests.rs
Normal file
29
db/db-core/src/tests.rs
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
/*
|
||||||
|
* ForgeFlux StarChart - A federated software forge spider
|
||||||
|
* Copyright (C) 2022 Aravinth Manivannan <realaravinth@batsense.net>
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
//! Test utilities
|
||||||
|
use crate::prelude::*;
|
||||||
|
|
||||||
|
/// adding forge works
|
||||||
|
pub async fn adding_forge_works<T: SCDatabase>(
|
||||||
|
db: &T,
|
||||||
|
create_forge_msg: CreateForge<'static>
|
||||||
|
) {
|
||||||
|
let _ = db.delete_forge_instance(&create_forge_msg.hostname).await;
|
||||||
|
db.create_forge_isntance(&create_forge_msg).await.unwrap();
|
||||||
|
assert!(db.forge_exists(create_forge_msg.hostname).await.unwrap(), "forge creation failed, forge existance check failure");
|
||||||
|
}
|
Loading…
Reference in a new issue