Skip to content

Commit

Permalink
Add project separation by UUID
Browse files Browse the repository at this point in the history
  • Loading branch information
GamePad64 committed Sep 22, 2024
1 parent 867feca commit cc7c5e7
Show file tree
Hide file tree
Showing 11 changed files with 117 additions and 32 deletions.
4 changes: 3 additions & 1 deletion notifico-core/src/credentials.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use crate::error::EngineError;
use serde::{Deserialize, Serialize};
use serde_json::Value;
use uuid::Uuid;

#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct Credential {
Expand All @@ -10,5 +11,6 @@ pub struct Credential {
}

pub trait Credentials: Send + Sync {
fn get_credential(&self, r#type: &str, name: &str) -> Result<Value, EngineError>;
fn get_credential(&self, project: Uuid, r#type: &str, name: &str)
-> Result<Value, EngineError>;
}
2 changes: 2 additions & 0 deletions notifico-core/src/engine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,15 @@ use serde_json::{Map, Value};
use std::any::Any;
use std::borrow::Cow;
use std::collections::HashMap;
use uuid::Uuid;

#[derive(Debug, Default, Serialize, Deserialize)]
#[serde(transparent)]
pub struct EventContext(pub Map<String, Value>);

#[derive(Default, Debug)]
pub struct PipelineContext {
pub project_id: Uuid,
pub recipient: Option<Recipient>,
pub event_context: EventContext,
pub plugin_contexts: HashMap<Cow<'static, str>, Value>,
Expand Down
2 changes: 2 additions & 0 deletions notifico-core/src/error.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::templater::TemplaterError;
use std::borrow::Cow;
use uuid::Uuid;

#[derive(Debug)]
pub enum EngineError {
Expand All @@ -12,6 +13,7 @@ pub enum EngineError {
InvalidContactFormat,
RecipientNotSet,
TemplateNotSet,
ProjectNotFound(Uuid),
}

impl From<TemplaterError> for EngineError {
Expand Down
6 changes: 6 additions & 0 deletions notifico-core/src/pipeline.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
use crate::error::EngineError;
use serde::{Deserialize, Serialize};
use serde_json::Value;
use uuid::Uuid;

#[derive(Serialize, Deserialize, Default, Clone, Debug)]
pub struct Pipeline {
Expand Down Expand Up @@ -28,3 +30,7 @@ impl SerializedStep {
Value::Object(self.into_inner())
}
}

pub trait PipelineStorage {
fn get_pipelines(&self, project: Uuid, event_name: &str) -> Result<Vec<Pipeline>, EngineError>;
}
4 changes: 4 additions & 0 deletions notifico-core/src/recipient.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,7 @@ impl Contact {
self.0
}
}

pub trait RecipientDirectory {
fn get_recipient(&self, id: Uuid) -> Option<Recipient>;
}
2 changes: 1 addition & 1 deletion notifico-smtp/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ impl EnginePlugin for EmailPlugin {
let smtpcred: SmtpServerCredentials = match cred_selector {
CredentialSelector::SmtpName { smtp_name } => self
.credentials
.get_credential("smtp_server", &smtp_name)?
.get_credential(context.project_id, "smtp_server", &smtp_name)?
.try_into()?,
};

Expand Down
2 changes: 1 addition & 1 deletion notifico-telegram/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ impl EnginePlugin for TelegramPlugin {
let tgcred: TelegramBotCredentials = match cred_selector {
CredentialSelector::BotName { bot_name } => self
.credentials
.get_credential("telegram_token", &bot_name)?
.get_credential(context.project_id, "telegram_token", &bot_name)?
.try_into()?,
};

Expand Down
93 changes: 86 additions & 7 deletions src/config.rs
Original file line number Diff line number Diff line change
@@ -1,31 +1,62 @@
use notifico_core::credentials::{Credential, Credentials};
use notifico_core::error::EngineError;
use notifico_core::pipeline::Pipeline;
use notifico_core::pipeline::{Pipeline, PipelineStorage};
use notifico_core::recipient::Recipient;
use serde::Deserialize;
use serde_json::Value;
use std::collections::HashMap;
use std::sync::Arc;
use uuid::Uuid;

#[derive(Debug, Deserialize)]
pub(crate) struct Config {
pub project: String,
pub projects: Vec<Project>,
}

#[derive(Debug, Deserialize)]
pub struct Project {
#[serde(default = "Uuid::nil")]
pub id: Uuid,
pub pipelines: Vec<Pipeline>,
pub credentials: Vec<Credential>,
pub recipients: Vec<Recipient>,
}

#[derive(Default)]
pub struct SimpleCredentials {
creds: Vec<Credential>,
creds: HashMap<Uuid, Vec<Credential>>,
}

impl SimpleCredentials {
pub fn new(creds: Vec<Credential>) -> Self {
SimpleCredentials { creds }
pub fn from_config(config: &Config) -> Self {
let mut slf = Self::default();
for project in config.projects.iter() {
slf.add_project(project.id, project.credentials.clone());
}
slf
}

fn add_project(&mut self, project: Uuid, pipelines: Vec<Credential>) {
if self.creds.get(&project).is_some() {
panic!("Project already exists: {}", project);
}

self.creds.insert(project, pipelines);
}
}

impl Credentials for SimpleCredentials {
fn get_credential(&self, r#type: &str, name: &str) -> Result<Value, EngineError> {
for cred in self.creds.iter() {
fn get_credential(
&self,
project: Uuid,
r#type: &str,
name: &str,
) -> Result<Value, EngineError> {
let Some(creds) = self.creds.get(&project) else {
return Err(EngineError::ProjectNotFound(project));
};

for cred in creds.iter() {
if cred.r#type == r#type && cred.name == name {
return Ok(cred.value.clone());
}
Expand All @@ -36,3 +67,51 @@ impl Credentials for SimpleCredentials {
))
}
}

#[derive(Default)]
pub struct SimplePipelineStorage {
eventmap: HashMap<Uuid, HashMap<String, Vec<Arc<Pipeline>>>>,
}

impl SimplePipelineStorage {
pub fn from_config(config: &Config) -> Self {
let mut slf = Self::default();
for project in config.projects.iter() {
slf.add_project(project.id, project.pipelines.clone());
}
slf
}

pub fn add_project(&mut self, project: Uuid, pipelines: Vec<Pipeline>) {
if self.eventmap.get(&project).is_some() {
panic!("Project already exists: {}", project);
}

let mut eventmap = HashMap::new();

for pipeline in pipelines.into_iter().map(|p| Arc::new(p)) {
for event in pipeline.events.iter().cloned() {
eventmap
.entry(event)
.or_insert_with(Vec::new)
.push(pipeline.clone());
}
}

self.eventmap.insert(project, eventmap);
}
}

impl PipelineStorage for SimplePipelineStorage {
fn get_pipelines(&self, project: Uuid, event_name: &str) -> Result<Vec<Pipeline>, EngineError> {
let Some(eventmap) = self.eventmap.get(&project) else {
return Err(EngineError::ProjectNotFound(project));
};

if let Some(pipelines) = eventmap.get(event_name) {
Ok(pipelines.iter().map(|p| p.as_ref().clone()).collect())
} else {
Ok(vec![])
}
}
}
2 changes: 1 addition & 1 deletion src/engine/mod.rs → src/engine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ impl Engine {

#[instrument]
pub(crate) async fn execute_step(
&mut self,
&self,
context: &mut PipelineContext,
step: &SerializedStep,
) -> Result<(), EngineError> {
Expand Down
26 changes: 10 additions & 16 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,15 @@ pub mod engine;
pub mod recipients;
pub mod templater;

use crate::config::{Config, SimpleCredentials};
use crate::config::{Config, SimpleCredentials, SimplePipelineStorage};
use crate::engine::Engine;
use clap::Parser;
use figment::{
providers::{Env, Format, Yaml},
Figment,
};
use notifico_core::engine::{EventContext, PipelineContext};
use notifico_core::pipeline::PipelineStorage;
use notifico_core::recipient::Recipient;
use notifico_smtp::EmailPlugin;
use notifico_telegram::TelegramPlugin;
Expand Down Expand Up @@ -62,36 +63,29 @@ async fn main() {
info!("Received context: {:?}", event_context);

let templater = Arc::new(TemplaterService::new("http://127.0.0.1:8000"));
let credentials = Arc::new(SimpleCredentials::new(config.credentials.clone()));
let credentials = Arc::new(SimpleCredentials::from_config(&config));
let pipelines = SimplePipelineStorage::from_config(&config);

let mut engine = Engine::new();

engine.add_plugin(TelegramPlugin::new(templater.clone(), credentials.clone()));
engine.add_plugin(EmailPlugin::new(templater, credentials));

let pipelines = {
let mut eventmap = HashMap::new();
for pipeline in config.pipelines.iter() {
for event in pipeline.events.iter() {
eventmap
.entry(event)
.or_insert_with(Vec::new)
.push(pipeline);
}
}
eventmap
};
let pipelines = pipelines
.get_pipelines(config.projects[0].id, &args.event)
.unwrap();

let recipinents: HashMap<Uuid, &Recipient> =
HashMap::from_iter(config.recipients.iter().map(|r| (r.id, r)));
HashMap::from_iter(config.projects[0].recipients.iter().map(|r| (r.id, r)));

// Pipeline;
{
let mut context = PipelineContext::default();
context.project_id = config.projects[0].id;
context.recipient = Some(recipinents[&args.recipient].clone());
context.event_context = event_context;

for pipeline in pipelines.get(&args.event).unwrap() {
for pipeline in pipelines {
for step in pipeline.steps.iter() {
engine.execute_step(&mut context, step).await.unwrap()
}
Expand Down
6 changes: 1 addition & 5 deletions src/recipients.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
use notifico_core::recipient::Recipient;
use notifico_core::recipient::{Recipient, RecipientDirectory};
use std::collections::HashMap;
use uuid::Uuid;

pub trait RecipientDirectory {
fn get_recipient(&self, id: Uuid) -> Option<Recipient>;
}

pub struct MemoryRecipientDirectory {
directory: HashMap<Uuid, Recipient>,
}
Expand Down

0 comments on commit cc7c5e7

Please sign in to comment.