mirror of
https://github.com/System-End/plura.git
synced 2026-04-19 18:35:12 +00:00
210 lines
5.3 KiB
Rust
Executable file
210 lines
5.3 KiB
Rust
Executable file
use std::str::FromStr;
|
|
|
|
use crate::id;
|
|
|
|
use super::{Trusted, Untrusted, member, system};
|
|
use error_stack::{Result, ResultExt};
|
|
use sqlx::{SqlitePool, prelude::*, sqlite::SqliteQueryResult};
|
|
|
|
id!(
|
|
/// For an ID to be trusted, it must
|
|
///
|
|
/// - Be a valid ID in the database
|
|
/// - Be associated with a valid member or system
|
|
=> Trigger
|
|
);
|
|
|
|
impl Id<Untrusted> {
|
|
#[tracing::instrument(skip(db))]
|
|
pub async fn validate_by_system(
|
|
self,
|
|
system_id: system::Id<Trusted>,
|
|
db: &SqlitePool,
|
|
) -> Result<Id<Trusted>, sqlx::Error> {
|
|
sqlx::query!(
|
|
"SELECT
|
|
id as 'id: Id<Trusted>'
|
|
FROM triggers
|
|
WHERE id = $1 AND system_id = $2",
|
|
self.id,
|
|
system_id.id
|
|
)
|
|
.fetch_one(db)
|
|
.await
|
|
.map(|record| record.id)
|
|
.attach_printable("Error validating trigger")
|
|
}
|
|
}
|
|
|
|
impl Id<Trusted> {
|
|
#[tracing::instrument(skip(db))]
|
|
pub async fn delete(self, db: &SqlitePool) -> Result<SqliteQueryResult, sqlx::Error> {
|
|
sqlx::query!(
|
|
r#"
|
|
DELETE FROM triggers
|
|
WHERE id = $1
|
|
"#,
|
|
self.id
|
|
)
|
|
.execute(db)
|
|
.await
|
|
.attach_printable("Error deleting trigger")
|
|
}
|
|
|
|
#[tracing::instrument(skip(db))]
|
|
pub async fn update(
|
|
self,
|
|
typ: Option<Type>,
|
|
content: Option<String>,
|
|
db: &SqlitePool,
|
|
) -> error_stack::Result<Self, sqlx::Error> {
|
|
sqlx::query!(
|
|
r#"
|
|
UPDATE triggers
|
|
SET
|
|
typ = coalesce($2, typ),
|
|
text = coalesce($3, text)
|
|
WHERE id = $1
|
|
RETURNING
|
|
id as "id: Id<Trusted>"
|
|
"#,
|
|
self,
|
|
typ,
|
|
content
|
|
)
|
|
.fetch_one(db)
|
|
.await
|
|
.attach_printable("Failed to update trigger")
|
|
.map(|record| record.id)
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, sqlx::Type, displaydoc::Display, PartialEq, Eq, clap::ValueEnum, Clone, Copy)]
|
|
#[repr(i64)]
|
|
pub enum Type {
|
|
/// Suffix
|
|
Suffix = 0,
|
|
/// Prefix
|
|
Prefix = 1,
|
|
}
|
|
|
|
impl From<i64> for Type {
|
|
fn from(value: i64) -> Self {
|
|
match value {
|
|
0 => Self::Suffix,
|
|
1 => Self::Prefix,
|
|
_ => unreachable!(
|
|
"Invalid type value. This means the database and rust struct are out of sync"
|
|
),
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, displaydoc::Display)]
|
|
/// Unknown type
|
|
pub struct UnknownType(String);
|
|
|
|
impl FromStr for Type {
|
|
type Err = UnknownType;
|
|
|
|
fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
|
|
match s {
|
|
"suffix" => Ok(Self::Suffix),
|
|
"prefix" => Ok(Self::Prefix),
|
|
_ => Err(UnknownType(s.to_string())),
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(FromRow, Debug)]
|
|
#[allow(dead_code)]
|
|
pub struct Trigger {
|
|
pub id: Id<Trusted>,
|
|
pub member_id: member::Id<Trusted>,
|
|
pub system_id: system::Id<Trusted>,
|
|
pub text: String,
|
|
pub typ: Type,
|
|
}
|
|
|
|
impl Trigger {
|
|
#[tracing::instrument(skip(db))]
|
|
pub async fn fetch_by_system_id(
|
|
system_id: system::Id<Trusted>,
|
|
db: &SqlitePool,
|
|
) -> Result<Vec<Self>, sqlx::Error> {
|
|
sqlx::query_as!(
|
|
Trigger,
|
|
r#"
|
|
SELECT
|
|
id as "id: Id<Trusted>",
|
|
member_id as "member_id: member::Id<Trusted>",
|
|
system_id as "system_id: system::Id<Trusted>",
|
|
text,
|
|
typ
|
|
FROM
|
|
triggers
|
|
WHERE
|
|
system_id = $1
|
|
"#,
|
|
system_id
|
|
)
|
|
.fetch_all(db)
|
|
.await
|
|
.attach_printable("Error fetching triggers")
|
|
}
|
|
|
|
#[tracing::instrument(skip(db))]
|
|
pub async fn fetch_by_member_id(
|
|
member_id: member::Id<Trusted>,
|
|
db: &SqlitePool,
|
|
) -> error_stack::Result<Vec<Self>, sqlx::Error> {
|
|
sqlx::query_as!(
|
|
Trigger,
|
|
r#"
|
|
SELECT
|
|
id as "id: Id<Trusted>",
|
|
member_id as "member_id: member::Id<Trusted>",
|
|
system_id as "system_id: system::Id<Trusted>",
|
|
text,
|
|
typ
|
|
FROM
|
|
triggers
|
|
WHERE member_id = $1
|
|
"#,
|
|
member_id,
|
|
)
|
|
.fetch_all(db)
|
|
.await
|
|
.attach_printable("Error fetching triggers")
|
|
}
|
|
|
|
#[tracing::instrument(skip(db))]
|
|
pub async fn insert(
|
|
member_id: member::Id<Trusted>,
|
|
system_id: system::Id<Trusted>,
|
|
typ: Type,
|
|
content: String,
|
|
db: &SqlitePool,
|
|
) -> error_stack::Result<Self, sqlx::Error> {
|
|
sqlx::query_as!(
|
|
Self,
|
|
r#"
|
|
INSERT INTO triggers (member_id, system_id, typ, text)
|
|
VALUES ($1, $2, $3, $4)
|
|
RETURNING
|
|
id as "id: Id<Trusted>",
|
|
member_id as "member_id: member::Id<Trusted>",
|
|
system_id as "system_id: system::Id<Trusted>",
|
|
typ,
|
|
text
|
|
"#,
|
|
member_id,
|
|
system_id,
|
|
typ,
|
|
content
|
|
)
|
|
.fetch_one(db)
|
|
.await
|
|
.attach_printable("Failed to insert trigger into database")
|
|
}
|
|
}
|