Añade funciones de acceso básico a base de datos

This commit is contained in:
Manuel Cillero 2022-04-24 18:44:37 +02:00
parent d4c6a3b2f3
commit e7f9bf8778
17 changed files with 99 additions and 75 deletions

View file

@ -24,7 +24,7 @@ impl ModuleTrait for NodeModule {
cfg.route("/node", app::web::get().to(node));
}
fn migrations(&self) -> Vec<Box<dyn db::migration::MigrationTrait>> {
fn migrations(&self) -> Vec<Box<dyn db::MigrationTrait>> {
vec![
boxed_migration!(m20220316_000001_create_table_node_type),
boxed_migration!(m20220316_000002_create_table_node),

View file

@ -1,4 +1,4 @@
use pagetop::db::migration::*;
use pagetop::prelude::*;
/// Stores information about all defined {node} types.
#[derive(Iden)]

View file

@ -1,4 +1,4 @@
use pagetop::db::migration::*;
use pagetop::prelude::*;
/// The base table for nodes.
#[derive(Iden)]

View file

@ -1,4 +1,4 @@
use pagetop::db::migration::*;
use pagetop::prelude::*;
// Identifies which realm/grant pairs a user must possess in order to view, update, or delete specific nodes.
#[derive(Iden)]

View file

@ -1,4 +1,4 @@
use pagetop::db::migration::*;
use pagetop::prelude::*;
// Stores information about each saved version of a {node}.
#[derive(Iden)]

View file

@ -23,7 +23,7 @@ impl ModuleTrait for UserModule {
cfg.route("/user/login", app::web::get().to(login));
}
fn migrations(&self) -> Vec<Box<dyn db::migration::MigrationTrait>> {
fn migrations(&self) -> Vec<Box<dyn db::MigrationTrait>> {
vec![
boxed_migration!(m20220312_000001_create_table_role),
boxed_migration!(m20220312_000002_create_table_role_permission),

View file

@ -1,4 +1,4 @@
use pagetop::db::migration::*;
use pagetop::prelude::*;
#[derive(Iden)]
enum Role { Table,
@ -12,49 +12,55 @@ pub struct Migration;
#[async_trait::async_trait]
impl MigrationTrait for Migration {
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.create_table(
// Store user roles.
Table::create()
.table(Role::Table)
.if_not_exists()
// Primary Key: Unique role ID.
.col(ColumnDef::new(Role::Rid)
.unsigned()
.not_null()
.auto_increment()
.primary_key()
)
// Unique role name.
.col(ColumnDef::new(Role::Name)
.string_len(64)
.not_null()
.unique_key()
)
// The weight of this role in listings and the user interface.
.col(ColumnDef::new(Role::Weight)
.integer()
.not_null()
.default(0)
)
// INDEXES.
.index(Index::create()
.name("name-weight")
.col(Role::Name)
.col(Role::Weight)
)
.to_owned()
)
.await
manager.create_table(
// Store user roles.
Table::create()
.table(Role::Table)
.if_not_exists()
// Primary Key: Unique role ID.
.col(ColumnDef::new(Role::Rid)
.unsigned()
.not_null()
.auto_increment()
.primary_key()
)
// Unique role name.
.col(ColumnDef::new(Role::Name)
.string_len(64)
.not_null()
.unique_key()
)
// The weight of this role in listings and the user interface.
.col(ColumnDef::new(Role::Weight)
.integer()
.not_null()
.default(0)
)
// INDEXES.
.index(Index::create()
.name("name-weight")
.col(Role::Name)
.col(Role::Weight)
)
.to_owned()
)
.await?;
app::db::exec::<InsertStatement>(Query::insert()
.into_table(Role::Table)
.columns(vec![Role::Name])
.values_panic(vec!["anonymous".into()])
.values_panic(vec!["authenticated".into()])
)
.await.map(|_| ())
}
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.drop_table(Table::drop()
.table(Role::Table)
.to_owned()
)
.await
manager.drop_table(Table::drop()
.table(Role::Table)
.to_owned()
)
.await
}
}

View file

@ -1,4 +1,4 @@
use pagetop::db::migration::*;
use pagetop::prelude::*;
#[derive(Iden)]
enum RolePermission { Table,

View file

@ -1,4 +1,4 @@
use pagetop::db::migration::*;
use pagetop::prelude::*;
#[derive(Iden)]
enum User { Table,

View file

@ -1,4 +1,4 @@
use pagetop::db::migration::*;
use pagetop::prelude::*;
#[derive(Iden)]
enum UserRole { Table,

View file

@ -21,7 +21,5 @@ default-features = false
actix-web = "3.3.3"
# Si se usa la macro html!:
maud = { version = "0.23.0" }
# Si se usa base de datos:
sea-orm = { version = "0.7.1" }
# Si se requiere serialización de estructuras de datos:
serde = { version = "1.0", features = ["derive"] }

View file

@ -10,7 +10,5 @@ edition = "2021"
pagetop = { path = "../pagetop" }
# Si se usa la macro html!:
maud = { version = "0.23.0" }
# Si se usa base de datos:
sea-orm = { version = "0.7.1" }
# Si se requiere serialización de estructuras de datos:
serde = { version = "1.0", features = ["derive"] }

View file

@ -1,10 +1,11 @@
use crate::{Lazy, db, run_now, trace};
use crate::{Lazy, run_now, trace};
use crate::config::SETTINGS;
use crate::db::*;
use sea_orm::{ConnectOptions, Database};
use sea_orm::{ConnectionTrait, ConnectOptions, Database, DatabaseBackend, Statement};
use tracing_unwrap::ResultExt;
pub static DBCONN: Lazy<db::DbConn> = Lazy::new(|| {
pub static DBCONN: Lazy<DbConn> = Lazy::new(|| {
trace::info!(
"Connecting to database \"{}\" using a pool of {} connections",
&SETTINGS.database.db_name,
@ -13,7 +14,7 @@ pub static DBCONN: Lazy<db::DbConn> = Lazy::new(|| {
let db_uri = match SETTINGS.database.db_type.as_str() {
"mysql" | "postgres" => {
let mut tmp_uri = db::DbUri::parse(format!(
let mut tmp_uri = DbUri::parse(format!(
"{}://{}/{}",
&SETTINGS.database.db_type,
&SETTINGS.database.db_host,
@ -33,7 +34,7 @@ pub static DBCONN: Lazy<db::DbConn> = Lazy::new(|| {
}
tmp_uri
},
"sqlite" => db::DbUri::parse(
"sqlite" => DbUri::parse(
format!("{}://{}",
&SETTINGS.database.db_type,
&SETTINGS.database.db_name
@ -43,7 +44,7 @@ pub static DBCONN: Lazy<db::DbConn> = Lazy::new(|| {
"Unrecognized database type \"{}\"",
&SETTINGS.database.db_type
);
db::DbUri::parse("").unwrap()
DbUri::parse("").unwrap()
}
};
@ -55,3 +56,34 @@ pub static DBCONN: Lazy<db::DbConn> = Lazy::new(|| {
})
).expect_or_log("Failed to connect to database")
});
static DBBACKEND: Lazy<DatabaseBackend> = Lazy::new(|| {
DBCONN.get_database_backend()
});
pub async fn query<Q: QueryStatementWriter>(stmt: &mut Q) -> Result<Vec<QueryResult>, DbErr> {
DBCONN.query_all(Statement::from_string(
*DBBACKEND,
match *DBBACKEND {
DatabaseBackend::MySql => stmt.to_string(MysqlQueryBuilder),
DatabaseBackend::Postgres => stmt.to_string(PostgresQueryBuilder),
DatabaseBackend::Sqlite => stmt.to_string(SqliteQueryBuilder),
}
)).await
}
pub async fn exec<Q: QueryStatementWriter>(stmt: &mut Q) -> Result<Option<QueryResult>, DbErr> {
DBCONN.query_one(Statement::from_string(
*DBBACKEND,
match *DBBACKEND {
DatabaseBackend::MySql => stmt.to_string(MysqlQueryBuilder),
DatabaseBackend::Postgres => stmt.to_string(PostgresQueryBuilder),
DatabaseBackend::Sqlite => stmt.to_string(SqliteQueryBuilder),
}
)).await
}
pub async fn exec_raw(stmt: String) -> Result<ExecResult, DbErr> {
DBCONN.execute(Statement::from_string(*DBBACKEND, stmt)).await
}

View file

@ -1,18 +1,8 @@
pub use url::Url as DbUri;
pub use sea_orm::{
DbErr,
DatabaseConnection as DbConn,
};
pub use sea_orm::{DatabaseConnection as DbConn, ExecResult, QueryResult};
pub mod entity {
pub use sea_orm::entity::prelude::*;
}
pub mod migration {
pub use sea_schema::migration::prelude::*;
pub use crate::module_name;
}
pub use sea_schema::migration::prelude::*;
#[macro_export]
macro_rules! boxed_migration {

View file

@ -1,5 +1,5 @@
use crate::{Lazy, app, run_now, trace};
use crate::db::migration::*;
use crate::db::*;
use super::ModuleTrait;
use std::sync::RwLock;

View file

@ -23,7 +23,7 @@ pub trait ModuleTrait: Send + Sync {
#[cfg(any(feature = "mysql", feature = "postgres", feature = "sqlite"))]
#[allow(unused_variables)]
fn migrations(&self) -> Vec<Box<dyn db::migration::MigrationTrait>> {
fn migrations(&self) -> Vec<Box<dyn db::MigrationTrait>> {
vec![]
}
}

View file

@ -13,7 +13,7 @@ pub use crate::trace;
pub use crate::localize;
#[cfg(any(feature = "mysql", feature = "postgres", feature = "sqlite"))]
pub use crate::{db, boxed_migration};
pub use crate::{db, db::*, boxed_migration};
pub use crate::html::*;
pub use crate::theme::*;