re-uploading work
This commit is contained in:
465
crates/common/src/repositories/event.rs
Normal file
465
crates/common/src/repositories/event.rs
Normal file
@@ -0,0 +1,465 @@
|
||||
//! Event and Enforcement repository for database operations
|
||||
//!
|
||||
//! This module provides CRUD operations and queries for Event and Enforcement entities.
|
||||
|
||||
use crate::models::{
|
||||
enums::{EnforcementCondition, EnforcementStatus},
|
||||
event::*,
|
||||
Id, JsonDict,
|
||||
};
|
||||
use crate::Result;
|
||||
use sqlx::{Executor, Postgres, QueryBuilder};
|
||||
|
||||
use super::{Create, Delete, FindById, List, Repository, Update};
|
||||
|
||||
/// Repository for Event operations
|
||||
pub struct EventRepository;
|
||||
|
||||
impl Repository for EventRepository {
|
||||
type Entity = Event;
|
||||
|
||||
fn table_name() -> &'static str {
|
||||
"event"
|
||||
}
|
||||
}
|
||||
|
||||
/// Input for creating a new event
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct CreateEventInput {
|
||||
pub trigger: Option<Id>,
|
||||
pub trigger_ref: String,
|
||||
pub config: Option<JsonDict>,
|
||||
pub payload: Option<JsonDict>,
|
||||
pub source: Option<Id>,
|
||||
pub source_ref: Option<String>,
|
||||
pub rule: Option<Id>,
|
||||
pub rule_ref: Option<String>,
|
||||
}
|
||||
|
||||
/// Input for updating an event
|
||||
#[derive(Debug, Clone, Default)]
|
||||
pub struct UpdateEventInput {
|
||||
pub config: Option<JsonDict>,
|
||||
pub payload: Option<JsonDict>,
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl FindById for EventRepository {
|
||||
async fn find_by_id<'e, E>(executor: E, id: i64) -> Result<Option<Self::Entity>>
|
||||
where
|
||||
E: Executor<'e, Database = Postgres> + 'e,
|
||||
{
|
||||
let event = sqlx::query_as::<_, Event>(
|
||||
r#"
|
||||
SELECT id, trigger, trigger_ref, config, payload, source, source_ref,
|
||||
rule, rule_ref, created, updated
|
||||
FROM event
|
||||
WHERE id = $1
|
||||
"#,
|
||||
)
|
||||
.bind(id)
|
||||
.fetch_optional(executor)
|
||||
.await?;
|
||||
|
||||
Ok(event)
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl List for EventRepository {
|
||||
async fn list<'e, E>(executor: E) -> Result<Vec<Self::Entity>>
|
||||
where
|
||||
E: Executor<'e, Database = Postgres> + 'e,
|
||||
{
|
||||
let events = sqlx::query_as::<_, Event>(
|
||||
r#"
|
||||
SELECT id, trigger, trigger_ref, config, payload, source, source_ref,
|
||||
rule, rule_ref, created, updated
|
||||
FROM event
|
||||
ORDER BY created DESC
|
||||
LIMIT 1000
|
||||
"#,
|
||||
)
|
||||
.fetch_all(executor)
|
||||
.await?;
|
||||
|
||||
Ok(events)
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl Create for EventRepository {
|
||||
type CreateInput = CreateEventInput;
|
||||
|
||||
async fn create<'e, E>(executor: E, input: Self::CreateInput) -> Result<Self::Entity>
|
||||
where
|
||||
E: Executor<'e, Database = Postgres> + 'e,
|
||||
{
|
||||
let event = sqlx::query_as::<_, Event>(
|
||||
r#"
|
||||
INSERT INTO event (trigger, trigger_ref, config, payload, source, source_ref, rule, rule_ref)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
|
||||
RETURNING id, trigger, trigger_ref, config, payload, source, source_ref,
|
||||
rule, rule_ref, created, updated
|
||||
"#,
|
||||
)
|
||||
.bind(input.trigger)
|
||||
.bind(&input.trigger_ref)
|
||||
.bind(&input.config)
|
||||
.bind(&input.payload)
|
||||
.bind(input.source)
|
||||
.bind(&input.source_ref)
|
||||
.bind(input.rule)
|
||||
.bind(&input.rule_ref)
|
||||
.fetch_one(executor)
|
||||
.await?;
|
||||
|
||||
Ok(event)
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl Update for EventRepository {
|
||||
type UpdateInput = UpdateEventInput;
|
||||
|
||||
async fn update<'e, E>(executor: E, id: i64, input: Self::UpdateInput) -> Result<Self::Entity>
|
||||
where
|
||||
E: Executor<'e, Database = Postgres> + 'e,
|
||||
{
|
||||
// Build update query
|
||||
|
||||
let mut query = QueryBuilder::new("UPDATE event SET ");
|
||||
let mut has_updates = false;
|
||||
|
||||
if let Some(config) = &input.config {
|
||||
query.push("config = ");
|
||||
query.push_bind(config);
|
||||
has_updates = true;
|
||||
}
|
||||
|
||||
if let Some(payload) = &input.payload {
|
||||
if has_updates {
|
||||
query.push(", ");
|
||||
}
|
||||
query.push("payload = ");
|
||||
query.push_bind(payload);
|
||||
has_updates = true;
|
||||
}
|
||||
|
||||
if !has_updates {
|
||||
// No updates requested, fetch and return existing entity
|
||||
return Self::get_by_id(executor, id).await;
|
||||
}
|
||||
|
||||
query.push(", updated = NOW() WHERE id = ");
|
||||
query.push_bind(id);
|
||||
query.push(" RETURNING id, trigger, trigger_ref, config, payload, source, source_ref, rule, rule_ref, created, updated");
|
||||
|
||||
let event = query.build_query_as::<Event>().fetch_one(executor).await?;
|
||||
|
||||
Ok(event)
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl Delete for EventRepository {
|
||||
async fn delete<'e, E>(executor: E, id: i64) -> Result<bool>
|
||||
where
|
||||
E: Executor<'e, Database = Postgres> + 'e,
|
||||
{
|
||||
let result = sqlx::query("DELETE FROM event WHERE id = $1")
|
||||
.bind(id)
|
||||
.execute(executor)
|
||||
.await?;
|
||||
|
||||
Ok(result.rows_affected() > 0)
|
||||
}
|
||||
}
|
||||
|
||||
impl EventRepository {
|
||||
/// Find events by trigger ID
|
||||
pub async fn find_by_trigger<'e, E>(executor: E, trigger_id: Id) -> Result<Vec<Event>>
|
||||
where
|
||||
E: Executor<'e, Database = Postgres> + 'e,
|
||||
{
|
||||
let events = sqlx::query_as::<_, Event>(
|
||||
r#"
|
||||
SELECT id, trigger, trigger_ref, config, payload, source, source_ref,
|
||||
rule, rule_ref, created, updated
|
||||
FROM event
|
||||
WHERE trigger = $1
|
||||
ORDER BY created DESC
|
||||
LIMIT 1000
|
||||
"#,
|
||||
)
|
||||
.bind(trigger_id)
|
||||
.fetch_all(executor)
|
||||
.await?;
|
||||
|
||||
Ok(events)
|
||||
}
|
||||
|
||||
/// Find events by trigger ref
|
||||
pub async fn find_by_trigger_ref<'e, E>(executor: E, trigger_ref: &str) -> Result<Vec<Event>>
|
||||
where
|
||||
E: Executor<'e, Database = Postgres> + 'e,
|
||||
{
|
||||
let events = sqlx::query_as::<_, Event>(
|
||||
r#"
|
||||
SELECT id, trigger, trigger_ref, config, payload, source, source_ref,
|
||||
rule, rule_ref, created, updated
|
||||
FROM event
|
||||
WHERE trigger_ref = $1
|
||||
ORDER BY created DESC
|
||||
LIMIT 1000
|
||||
"#,
|
||||
)
|
||||
.bind(trigger_ref)
|
||||
.fetch_all(executor)
|
||||
.await?;
|
||||
|
||||
Ok(events)
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Enforcement Repository
|
||||
// ============================================================================
|
||||
|
||||
/// Repository for Enforcement operations
|
||||
pub struct EnforcementRepository;
|
||||
|
||||
impl Repository for EnforcementRepository {
|
||||
type Entity = Enforcement;
|
||||
|
||||
fn table_name() -> &'static str {
|
||||
"enforcement"
|
||||
}
|
||||
}
|
||||
|
||||
/// Input for creating a new enforcement
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct CreateEnforcementInput {
|
||||
pub rule: Option<Id>,
|
||||
pub rule_ref: String,
|
||||
pub trigger_ref: String,
|
||||
pub config: Option<JsonDict>,
|
||||
pub event: Option<Id>,
|
||||
pub status: EnforcementStatus,
|
||||
pub payload: JsonDict,
|
||||
pub condition: EnforcementCondition,
|
||||
pub conditions: serde_json::Value,
|
||||
}
|
||||
|
||||
/// Input for updating an enforcement
|
||||
#[derive(Debug, Clone, Default)]
|
||||
pub struct UpdateEnforcementInput {
|
||||
pub status: Option<EnforcementStatus>,
|
||||
pub payload: Option<JsonDict>,
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl FindById for EnforcementRepository {
|
||||
async fn find_by_id<'e, E>(executor: E, id: i64) -> Result<Option<Self::Entity>>
|
||||
where
|
||||
E: Executor<'e, Database = Postgres> + 'e,
|
||||
{
|
||||
let enforcement = sqlx::query_as::<_, Enforcement>(
|
||||
r#"
|
||||
SELECT id, rule, rule_ref, trigger_ref, config, event, status, payload,
|
||||
condition, conditions, created, updated
|
||||
FROM enforcement
|
||||
WHERE id = $1
|
||||
"#,
|
||||
)
|
||||
.bind(id)
|
||||
.fetch_optional(executor)
|
||||
.await?;
|
||||
|
||||
Ok(enforcement)
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl List for EnforcementRepository {
|
||||
async fn list<'e, E>(executor: E) -> Result<Vec<Self::Entity>>
|
||||
where
|
||||
E: Executor<'e, Database = Postgres> + 'e,
|
||||
{
|
||||
let enforcements = sqlx::query_as::<_, Enforcement>(
|
||||
r#"
|
||||
SELECT id, rule, rule_ref, trigger_ref, config, event, status, payload,
|
||||
condition, conditions, created, updated
|
||||
FROM enforcement
|
||||
ORDER BY created DESC
|
||||
LIMIT 1000
|
||||
"#,
|
||||
)
|
||||
.fetch_all(executor)
|
||||
.await?;
|
||||
|
||||
Ok(enforcements)
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl Create for EnforcementRepository {
|
||||
type CreateInput = CreateEnforcementInput;
|
||||
|
||||
async fn create<'e, E>(executor: E, input: Self::CreateInput) -> Result<Self::Entity>
|
||||
where
|
||||
E: Executor<'e, Database = Postgres> + 'e,
|
||||
{
|
||||
let enforcement = sqlx::query_as::<_, Enforcement>(
|
||||
r#"
|
||||
INSERT INTO enforcement (rule, rule_ref, trigger_ref, config, event, status,
|
||||
payload, condition, conditions)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)
|
||||
RETURNING id, rule, rule_ref, trigger_ref, config, event, status, payload,
|
||||
condition, conditions, created, updated
|
||||
"#,
|
||||
)
|
||||
.bind(input.rule)
|
||||
.bind(&input.rule_ref)
|
||||
.bind(&input.trigger_ref)
|
||||
.bind(&input.config)
|
||||
.bind(input.event)
|
||||
.bind(input.status)
|
||||
.bind(&input.payload)
|
||||
.bind(input.condition)
|
||||
.bind(&input.conditions)
|
||||
.fetch_one(executor)
|
||||
.await?;
|
||||
|
||||
Ok(enforcement)
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl Update for EnforcementRepository {
|
||||
type UpdateInput = UpdateEnforcementInput;
|
||||
|
||||
async fn update<'e, E>(executor: E, id: i64, input: Self::UpdateInput) -> Result<Self::Entity>
|
||||
where
|
||||
E: Executor<'e, Database = Postgres> + 'e,
|
||||
{
|
||||
// Build update query
|
||||
|
||||
let mut query = QueryBuilder::new("UPDATE enforcement SET ");
|
||||
let mut has_updates = false;
|
||||
|
||||
if let Some(status) = input.status {
|
||||
query.push("status = ");
|
||||
query.push_bind(status);
|
||||
has_updates = true;
|
||||
}
|
||||
|
||||
if let Some(payload) = &input.payload {
|
||||
if has_updates {
|
||||
query.push(", ");
|
||||
}
|
||||
query.push("payload = ");
|
||||
query.push_bind(payload);
|
||||
has_updates = true;
|
||||
}
|
||||
|
||||
if !has_updates {
|
||||
// No updates requested, fetch and return existing entity
|
||||
return Self::get_by_id(executor, id).await;
|
||||
}
|
||||
|
||||
query.push(", updated = NOW() WHERE id = ");
|
||||
query.push_bind(id);
|
||||
query.push(" RETURNING id, rule, rule_ref, trigger_ref, config, event, status, payload, condition, conditions, created, updated");
|
||||
|
||||
let enforcement = query
|
||||
.build_query_as::<Enforcement>()
|
||||
.fetch_one(executor)
|
||||
.await?;
|
||||
|
||||
Ok(enforcement)
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl Delete for EnforcementRepository {
|
||||
async fn delete<'e, E>(executor: E, id: i64) -> Result<bool>
|
||||
where
|
||||
E: Executor<'e, Database = Postgres> + 'e,
|
||||
{
|
||||
let result = sqlx::query("DELETE FROM enforcement WHERE id = $1")
|
||||
.bind(id)
|
||||
.execute(executor)
|
||||
.await?;
|
||||
|
||||
Ok(result.rows_affected() > 0)
|
||||
}
|
||||
}
|
||||
|
||||
impl EnforcementRepository {
|
||||
/// Find enforcements by rule ID
|
||||
pub async fn find_by_rule<'e, E>(executor: E, rule_id: Id) -> Result<Vec<Enforcement>>
|
||||
where
|
||||
E: Executor<'e, Database = Postgres> + 'e,
|
||||
{
|
||||
let enforcements = sqlx::query_as::<_, Enforcement>(
|
||||
r#"
|
||||
SELECT id, rule, rule_ref, trigger_ref, config, event, status, payload,
|
||||
condition, conditions, created, updated
|
||||
FROM enforcement
|
||||
WHERE rule = $1
|
||||
ORDER BY created DESC
|
||||
"#,
|
||||
)
|
||||
.bind(rule_id)
|
||||
.fetch_all(executor)
|
||||
.await?;
|
||||
|
||||
Ok(enforcements)
|
||||
}
|
||||
|
||||
/// Find enforcements by status
|
||||
pub async fn find_by_status<'e, E>(
|
||||
executor: E,
|
||||
status: EnforcementStatus,
|
||||
) -> Result<Vec<Enforcement>>
|
||||
where
|
||||
E: Executor<'e, Database = Postgres> + 'e,
|
||||
{
|
||||
let enforcements = sqlx::query_as::<_, Enforcement>(
|
||||
r#"
|
||||
SELECT id, rule, rule_ref, trigger_ref, config, event, status, payload,
|
||||
condition, conditions, created, updated
|
||||
FROM enforcement
|
||||
WHERE status = $1
|
||||
ORDER BY created DESC
|
||||
"#,
|
||||
)
|
||||
.bind(status)
|
||||
.fetch_all(executor)
|
||||
.await?;
|
||||
|
||||
Ok(enforcements)
|
||||
}
|
||||
|
||||
/// Find enforcements by event ID
|
||||
pub async fn find_by_event<'e, E>(executor: E, event_id: Id) -> Result<Vec<Enforcement>>
|
||||
where
|
||||
E: Executor<'e, Database = Postgres> + 'e,
|
||||
{
|
||||
let enforcements = sqlx::query_as::<_, Enforcement>(
|
||||
r#"
|
||||
SELECT id, rule, rule_ref, trigger_ref, config, event, status, payload,
|
||||
condition, conditions, created, updated
|
||||
FROM enforcement
|
||||
WHERE event = $1
|
||||
ORDER BY created DESC
|
||||
"#,
|
||||
)
|
||||
.bind(event_id)
|
||||
.fetch_all(executor)
|
||||
.await?;
|
||||
|
||||
Ok(enforcements)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user