...
 
Commits (3)
...@@ -2,5 +2,4 @@ ...@@ -2,5 +2,4 @@
volatile_dir=/tmp/notify/volatile volatile_dir=/tmp/notify/volatile
persistent_dir=/tmp/notify/persistent persistent_dir=/tmp/notify/persistent
plugin_dir=/tmp/notify/plugins plugin_dir=/tmp/notify/plugins
templates_dir=/tmp/notify/templates
cmd_timeout=10 cmd_timeout=10
...@@ -85,12 +85,15 @@ def print_templates(templates): ...@@ -85,12 +85,15 @@ def print_templates(templates):
def list_notifications(notifications): def list_notifications(notifications):
"""Pretty print stored notifications""" """Pretty print stored notifications"""
print("Stored notifications:") if not notifications:
for k, v in notifications.items(): print("No notifications found")
trimmed = ' '.join(v['message'][:80].split()) else:
severity = v['metadata']['severity'] print("Stored notifications:")
for k, v in notifications.items():
trimmed = ' '.join(v['message'][:80].split())
severity = v['metadata']['severity']
print("{} {}\t{}".format(print_severity(severity), k[:8], trimmed)) print("{} {}\t{}".format(print_severity(severity), k[:8], trimmed))
def print_notification(notification): def print_notification(notification):
......
...@@ -27,7 +27,6 @@ class Api: ...@@ -27,7 +27,6 @@ class Api:
config.load_config(conf) config.load_config(conf)
plugin_dir = config.get('settings', 'plugin_dir') plugin_dir = config.get('settings', 'plugin_dir')
templates_dir = config.get('settings', 'templates_dir')
volatile_dir = config.get('settings', 'volatile_dir') volatile_dir = config.get('settings', 'volatile_dir')
persistent_dir = config.get('settings', 'persistent_dir') persistent_dir = config.get('settings', 'persistent_dir')
...@@ -35,10 +34,6 @@ class Api: ...@@ -35,10 +34,6 @@ class Api:
logger.error("Missing plugin directory %s", plugin_dir) logger.error("Missing plugin directory %s", plugin_dir)
raise NotADirectoryError("Missing plugin directory {}".format(plugin_dir)) raise NotADirectoryError("Missing plugin directory {}".format(plugin_dir))
if not os.path.exists(templates_dir):
logger.error("Missing templates directory %s", templates_dir)
raise NotADirectoryError("Missing templates directory {}".format(templates_dir))
if not os.path.exists(volatile_dir): if not os.path.exists(volatile_dir):
logger.error("Missing volatile messages directory %s", volatile_dir) logger.error("Missing volatile messages directory %s", volatile_dir)
raise NotADirectoryError("Missing volatile messages directory {}".format(volatile_dir)) raise NotADirectoryError("Missing volatile messages directory {}".format(volatile_dir))
...@@ -47,7 +42,7 @@ class Api: ...@@ -47,7 +42,7 @@ class Api:
logger.error("Missing persistent messages directory %s", persistent_dir) logger.error("Missing persistent messages directory %s", persistent_dir)
raise NotADirectoryError("Missing persistent messages directory {}".format(persistent_dir)) raise NotADirectoryError("Missing persistent messages directory {}".format(persistent_dir))
self.plugins = PluginStorage(plugin_dir, templates_dir) self.plugins = PluginStorage(plugin_dir)
self.notifications = NotificationStorage(volatile_dir, persistent_dir, self.plugins) self.notifications = NotificationStorage(volatile_dir, persistent_dir, self.plugins)
def get_notifications(self, media_type='simple', lang='en'): def get_notifications(self, media_type='simple', lang='en'):
......
...@@ -14,7 +14,6 @@ class Config: ...@@ -14,7 +14,6 @@ class Config:
self.conf.set("settings", "volatile_dir", "/tmp") self.conf.set("settings", "volatile_dir", "/tmp")
self.conf.set("settings", "persistent_dir", "/srv") self.conf.set("settings", "persistent_dir", "/srv")
self.conf.set("settings", "plugin_dir", "plugins") self.conf.set("settings", "plugin_dir", "plugins")
self.conf.set("settings", "templates_dir", "templates")
self.conf.set("settings", "cmd_timeout", "10") self.conf.set("settings", "cmd_timeout", "10")
def load_config(self, filename): def load_config(self, filename):
......
import gettext import gettext
import os
import yaml import yaml
...@@ -58,7 +59,7 @@ class NotificationSkeleton: ...@@ -58,7 +59,7 @@ class NotificationSkeleton:
def setup_jinja_env(self): def setup_jinja_env(self):
"""Prepare templates for later use""" """Prepare templates for later use"""
self.jinja_message_template = self.jinja_env.get_template(self.template['src']) self.jinja_message_template = self.jinja_env.get_template(os.path.join('templates', self.template['src']))
plugin_template = '{}.yml'.format(self.plugin_name) plugin_template = '{}.yml'.format(self.plugin_name)
self.jinja_plugin_template = self.jinja_env.get_template(plugin_template) self.jinja_plugin_template = self.jinja_env.get_template(plugin_template)
......
...@@ -16,9 +16,9 @@ class Plugin: ...@@ -16,9 +16,9 @@ class Plugin:
# 'notifications' section is intentionally omitted for now # 'notifications' section is intentionally omitted for now
# until mandatory and optional attributes check for 'notifications' is implemented # until mandatory and optional attributes check for 'notifications' is implemented
def __init__(self, name, template_dirs, actions, templates, notifications): def __init__(self, name, template_dir, actions, templates, notifications):
self.name = name self.name = name
self.template_dirs = template_dirs self.template_dir = template_dir
self.actions = {} self.actions = {}
self.templates = {} self.templates = {}
self.notification_types = {} self.notification_types = {}
...@@ -35,7 +35,7 @@ class Plugin: ...@@ -35,7 +35,7 @@ class Plugin:
self.init_jinja_env() self.init_jinja_env()
@classmethod @classmethod
def from_file(cls, filepath, templates_dir): def from_file(cls, filepath):
try: try:
with open(filepath, 'r') as f: with open(filepath, 'r') as f:
data = yaml.safe_load(f) data = yaml.safe_load(f)
...@@ -56,11 +56,10 @@ class Plugin: ...@@ -56,11 +56,10 @@ class Plugin:
path = pathlib.Path(filepath) path = pathlib.Path(filepath)
filename = path.stem filename = path.stem
jinja_template_dirs = [ # use list as workaround to this issue https://github.com/pallets/jinja/issues/870
os.path.join(templates_dir, filename), jinja_template_dir = [path.parent]
path.parent,
] return cls(filename, jinja_template_dir, **data)
return cls(filename, jinja_template_dirs, **data)
@classmethod @classmethod
def valid_schema(cls, data): def valid_schema(cls, data):
...@@ -84,7 +83,7 @@ class Plugin: ...@@ -84,7 +83,7 @@ class Plugin:
return True return True
def init_jinja_env(self): def init_jinja_env(self):
template_loader = jinja2.FileSystemLoader(self.template_dirs) template_loader = jinja2.FileSystemLoader(self.template_dir)
self.jinja_env = jinja2.Environment( self.jinja_env = jinja2.Environment(
loader=template_loader, loader=template_loader,
autoescape=True, autoescape=True,
......
...@@ -14,21 +14,20 @@ class PluginStorage: ...@@ -14,21 +14,20 @@ class PluginStorage:
"""Storage for plugins""" """Storage for plugins"""
META_ATTRS = ['name', 'version', 'timeout', 'severity', 'persistent', 'explicit_dismiss'] META_ATTRS = ['name', 'version', 'timeout', 'severity', 'persistent', 'explicit_dismiss']
def __init__(self, plugin_dir, templates_dir): def __init__(self, plugin_dir):
# print("Constructing new PluginStorage")
self.plugin_dir = plugin_dir self.plugin_dir = plugin_dir
self.templates_dir = templates_dir
self.plugins = {} self.plugins = {}
self.load() self.load()
def load(self): def load(self):
"""Load plugins from FS""" """Load plugins from FS"""
for filepath in glob.glob(os.path.join(self.plugin_dir, '*.yml')): for filepath in glob.glob(os.path.join(self.plugin_dir, '*', '*.yml')):
p = Plugin.from_file(filepath, self.templates_dir) logger.debug("reading plugin file '%s'", filepath)
p = Plugin.from_file(filepath)
if p: if p:
logger.debug("Reading plugin '%s'", p.name)
self.plugins[p.name] = p self.plugins[p.name] = p
def get_plugin(self, name): def get_plugin(self, name):
......
...@@ -48,8 +48,6 @@ class Supervisor: ...@@ -48,8 +48,6 @@ class Supervisor:
def run_proc(self): def run_proc(self):
try: try:
if self.cmd_args: if self.cmd_args:
# due to generic support of command args, args have to be properly formed
# without knowing args structure in advance we can't prevent shell code injection
cmd = f'{self.cmd} {self.cmd_args}' cmd = f'{self.cmd} {self.cmd_args}'
else: else:
cmd = self.cmd cmd = self.cmd
......
...@@ -3,7 +3,7 @@ width = 150 ...@@ -3,7 +3,7 @@ width = 150
omit_header = True omit_header = True
mapping_file = babel.cfg mapping_file = babel.cfg
output_file = messages.pot output_file = messages.pot
input_dirs = templates,plugins input_dirs = plugins
[init_catalog] [init_catalog]
input_file = messages.pot input_file = messages.pot
......