]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
plugins/push-notification: Rewrite push notification driver config initialization
authorKarl Fleischmann <karl.fleischmann@open-xchange.com>
Thu, 7 Sep 2023 11:35:58 +0000 (13:35 +0200)
committerAki Tuomi <aki.tuomi@open-xchange.com>
Wed, 12 Feb 2025 10:34:10 +0000 (12:34 +0200)
Replace the old config lookup mechanism - a per-driver parsing of a
settings-string and a subsequent creation of a config hash-map - with a
new settings-based mechanism. This way each driver can now access its
native settings directly. For this to work the driver identification and
initialization needs to be adapted, as well.

src/plugins/push-notification/push-notification-driver-dlog.c
src/plugins/push-notification/push-notification-driver-lua.c
src/plugins/push-notification/push-notification-driver-ox.c
src/plugins/push-notification/push-notification-drivers.c
src/plugins/push-notification/push-notification-drivers.h
src/plugins/push-notification/push-notification-plugin.c

index 256340c70f4c0e1f19f3fd09f1caad50e2bf9a05..4063177551cf6490e0c5a925a5c35d865c8c533a 100644 (file)
@@ -2,11 +2,13 @@
 
 #include "lib.h"
 #include "array.h"
+#include "settings.h"
 
 #include "mail-storage-private.h"
 #include "push-notification-plugin.h"
 #include "push-notification-drivers.h"
 #include "push-notification-events.h"
+#include "push-notification-settings.h"
 #include "push-notification-txn-mbox.h"
 #include "push-notification-txn-msg.h"
 
@@ -31,23 +33,16 @@ static struct event *create_dlog_event(struct event *parent)
 
 static int
 push_notification_driver_dlog_init(
-       struct push_notification_driver_config *config,
-       struct mail_user *user, pool_t pool,
-       void **context, const char **error_r ATTR_UNUSED)
+       struct mail_user *user, pool_t pool, ATTR_UNUSED const char *name,
+       void **context_r, ATTR_UNUSED const char **error_r)
 {
        struct event *log_event = create_dlog_event(user->event);
        struct dlog_push_notification_txn_context *ctx = p_new(
                pool, struct dlog_push_notification_txn_context, 1);
        ctx->event = log_event;
-       *context = ctx;
+       *context_r = ctx;
 
        e_debug(log_event, "Called init push_notification plugin hook.");
-       if (config->raw_config != NULL) {
-               e_debug(log_event,
-                       "Config string for dlog push_notification driver: %s",
-                       config->raw_config);
-       }
-
        return 0;
 }
 
index 8cc4cf46dcfb33a665b75e2d4a753c0b1c493cb2..8d536da3a3046d926a1572032a67a05959bbf5bc 100644 (file)
@@ -7,6 +7,7 @@
 #include "hash.h"
 #include "dlua-script.h"
 #include "dlua-script-private.h"
+#include "settings.h"
 
 #include "mail-storage.h"
 #include "mail-user.h"
@@ -17,6 +18,7 @@
 #include "push-notification-drivers.h"
 #include "push-notification-events.h"
 #include "push-notification-event-message-common.h"
+#include "push-notification-settings.h"
 #include "push-notification-txn-mbox.h"
 #include "push-notification-txn-msg.h"
 
@@ -71,18 +73,26 @@ static const char *push_notification_driver_lua_to_fn(const char *evname);
 
 static int
 push_notification_driver_lua_init(
-       struct push_notification_driver_config *config, struct mail_user *user,
-       pool_t pool, void **context, const char **error_r)
+               struct mail_user *user, pool_t pool, const char *name,
+               void **context, const char **error_r)
 {
        struct dlua_push_notification_context *ctx;
        const char *path;
 
+       struct push_notification_lua_settings *lua_settings;
+       if (settings_get_filter(user->event, PUSH_NOTIFICATION_SETTINGS_FILTER_NAME,
+                               name, &push_notification_lua_setting_parser_info,
+                               0, &lua_settings, error_r) < 0)
+               return -1;
+
        struct event *event = event_create(user->event);
        event_add_category(event, push_notification_get_event_category());
        event_set_append_log_prefix(event, "lua: ");
 
        if ((path = mail_user_plugin_getenv(user, DLUA_LOG_USERENV_KEY)) == NULL)
-               path = hash_table_lookup(config->config, (const char *)"path");
+               path = t_strdup(lua_settings->path);
+
+       settings_free(lua_settings);
 
        if (path == NULL) {
                struct dlua_script *script;
index 8e88ad60375dbe93bed07c7949717b03e9bba15c..82c75c359dce5ba24b66db8b57f1a352fcd3d04b 100644 (file)
 #include "json-ostream.h"
 #include "mailbox-attribute.h"
 #include "mail-storage-private.h"
+#include "settings.h"
 #include "str.h"
 #include "strescape.h"
+#include "strnum.h"
 #include "str-parse.h"
 #include "iostream-ssl.h"
 
+#include "push-notification-settings.h"
 #include "push-notification-plugin.h"
 #include "push-notification-drivers.h"
 #include "push-notification-event-messagenew.h"
@@ -28,7 +31,6 @@
 /* Default values. */
 static const char *const default_events[] = { "MessageNew", NULL };
 static const char *const default_mboxes[] = { "INBOX", NULL };
-#define DEFAULT_CACHE_LIFETIME_SECS 60
 
 /* This is data that is shared by all plugin users. */
 struct push_notification_driver_ox_global {
@@ -70,53 +72,46 @@ push_notification_driver_ox_init_global(struct mail_user *user) {
 }
 
 static int
-push_notification_driver_ox_init(struct push_notification_driver_config *config,
-                                struct mail_user *user, pool_t pool,
-                                void **context, const char **error_r)
+push_notification_driver_ox_init(struct mail_user *user, pool_t pool,
+                                const char *name, void **context,
+                                const char **error_r)
 {
        struct push_notification_driver_ox_config *dconfig;
-       const char *error, *tmp;
 
-       /* Valid config keys: cache_lifetime, url */
-       tmp = hash_table_lookup(config->config, (const char *)"url");
-       if (tmp == NULL) {
-               *error_r = "Driver requires the url parameter";
+       struct push_notification_ox_settings *ox_settings;
+       if (settings_get_filter(user->event, PUSH_NOTIFICATION_SETTINGS_FILTER_NAME,
+                               name, &push_notification_ox_setting_parser_info,
+                               0, &ox_settings, error_r) < 0)
                return -1;
-       }
 
        dconfig = p_new(pool, struct push_notification_driver_ox_config, 1);
        dconfig->event = event_create(user->event);
        event_add_category(dconfig->event, &event_category_push_notification);
        event_set_append_log_prefix(dconfig->event, "push-notification-ox: ");
 
-       if (http_url_parse(tmp, NULL, HTTP_URL_ALLOW_USERINFO_PART, pool,
-                          &dconfig->http_url, &error) < 0) {
-               event_unref(&dconfig->event);
-               *error_r = t_strdup_printf("Failed to parse OX REST URL %s: %s",
-                                          tmp, error);
-               return -1;
-       }
-       dconfig->use_unsafe_username =
-               hash_table_lookup(config->config,
-                                 (const char *)"user_from_metadata") != NULL;
-
-       e_debug(dconfig->event, "Using URL %s", tmp);
-
-       tmp = hash_table_lookup(config->config, (const char *)"cache_lifetime");
-       if (tmp == NULL) {
-               dconfig->cached_ox_metadata_lifetime_secs =
-                       DEFAULT_CACHE_LIFETIME_SECS;
-       } else if (str_parse_get_interval(
-               tmp, &dconfig->cached_ox_metadata_lifetime_secs, &error) < 0) {
-               event_unref(&dconfig->event);
-               *error_r = t_strdup_printf(
-                       "Failed to parse OX cache_lifetime %s: %s", tmp, error);
-               return -1;
+       /* The settings check is deliberately only validating a url if it is   
+          given in the settings. Otherwise any file that does not contain     
+          push-notification specific settings would fail the validation.      
+          Thus we need to check here, whether the parsed url exists. */       
+       if (ox_settings->parsed_url == NULL) {                            
+               *error_r = "push_notification_ox_url is missing or empty";
+               event_unref(&dconfig->event);                                  
+               settings_free(ox_settings);                               
+               return -1;                                                     
        }
+       
+       dconfig->http_url = http_url_clone_with_userinfo(pool, ox_settings->parsed_url);
+       e_debug(dconfig->event, "Using URL %s",
+               http_url_create(dconfig->http_url));
 
+       dconfig->cached_ox_metadata_lifetime_secs = ox_settings->cache_ttl;
        e_debug(dconfig->event, "Using cache lifetime: %u",
                dconfig->cached_ox_metadata_lifetime_secs);
 
+       dconfig->use_unsafe_username = ox_settings->user_from_metadata;
+       e_debug(dconfig->event, "Using user %s",
+               dconfig->use_unsafe_username ? "stored in METADATA" : "sent by OX endpoint");
+
        if (ox_global == NULL) {
                ox_global = i_new(struct push_notification_driver_ox_global, 1);
                ox_global->refcount = 0;
@@ -125,6 +120,7 @@ push_notification_driver_ox_init(struct push_notification_driver_config *config,
        ++ox_global->refcount;
        *context = dconfig;
 
+       settings_free(ox_settings);
        return 0;
 }
 
index 175ac74f09e30d505513f5c296f2f7279583088a..d3ec7028fb2739f144edb5d0f69b0ad50bec2447 100644 (file)
@@ -4,9 +4,11 @@
 #include "array.h"
 #include "hash.h"
 #include "mail-user.h"
+#include "settings.h"
 
 #include "push-notification-drivers.h"
 #include "push-notification-events.h"
+#include "push-notification-settings.h"
 
 static ARRAY(const struct push_notification_driver *) push_notification_drivers;
 
@@ -27,47 +29,29 @@ push_notification_driver_find(const char *name, unsigned int *idx_r)
        return FALSE;
 }
 
-static const struct push_notification_driver *
-push_notification_driver_find_class(const char *driver)
+static bool
+push_notification_driver_identify(struct mail_user *user, const char *name,
+                                 const struct push_notification_driver **driver_r,
+                                 const char **error_r)
 {
+       struct push_notification_settings *set;
        unsigned int idx;
-
-       if (!push_notification_driver_find(driver, &idx))
-               return NULL;
-
-       return array_idx_elem(&push_notification_drivers, idx);
-}
-
-static struct push_notification_driver_config *
-push_notification_driver_parse_config(const char *p)
-{
-       const char **args, *key, *p2, *value;
-       struct push_notification_driver_config *config;
-
-       config = t_new(struct push_notification_driver_config, 1);
-       config->raw_config = p;
-
-       hash_table_create(&config->config, unsafe_data_stack_pool, 0,
-                         str_hash, strcmp);
-
-       if (p == NULL)
-               return config;
-
-       args = t_strsplit_spaces(p, " ");
-
-       for (; *args != NULL; args++) {
-               p2 = strchr(*args, '=');
-               if (p2 != NULL) {
-                       key = t_strdup_until(*args, p2);
-                       value = t_strdup(p2 + 1);
-               } else {
-                       key = *args;
-                       value = "";
-               }
-               hash_table_update(config->config, key, value);
+       if (settings_get_filter(user->event, PUSH_NOTIFICATION_SETTINGS_FILTER_NAME,
+                               name, &push_notification_setting_parser_info,
+                               0, &set, error_r) < 0)
+               return FALSE;
+
+       bool ret = FALSE;
+       if (push_notification_driver_find(set->driver, &idx)) {
+               *driver_r = array_idx_elem(&push_notification_drivers, idx);
+               ret = TRUE;
        }
+       settings_free(set);
 
-       return config;
+       if (!ret)
+               *error_r = "Name does not match any registered drivers";
+
+       return ret;
 }
 
 int push_notification_driver_init(
@@ -76,40 +60,30 @@ int push_notification_driver_init(
 {
        void *context = NULL;
        const struct push_notification_driver *driver;
-       const char *driver_name, *error_r, *p;
+       const char *error;
        struct push_notification_driver_user *duser;
        int ret;
 
-       /* <driver>[:<driver config>] */
-       p = strchr(config_in, ':');
-       if (p == NULL)
-               driver_name = config_in;
-       else
-               driver_name = t_strdup_until(config_in, p);
-
-       driver = push_notification_driver_find_class(driver_name);
-       if (driver == NULL) {
+       bool found_driver = push_notification_driver_identify(user, config_in,
+                                                             &driver, &error);
+       if (!found_driver) {
                e_error(user->event,
-                       "Unknown push notification driver: %s", driver_name);
+                       "Unable to identify push notification driver '%s': %s",
+                       config_in, error);
                return -1;
        }
 
        if (driver->v.init != NULL) {
                T_BEGIN {
-                       struct push_notification_driver_config *config;
-
-                       config = push_notification_driver_parse_config(
-                                       (p == NULL) ? p : p + 1);
-                       ret = driver->v.init(config, user, pool,
-                                            &context, &error_r);
-                       if (ret < 0)
-                               e_error(user->event, "%s: %s",
-                                       driver_name, error_r);
-                       hash_table_destroy(&config->config);
-               } T_END;
-
-               if (ret < 0)
+                       ret = driver->v.init(user, pool, config_in, &context,
+                                            &error);
+               } T_END_PASS_STR_IF(ret < 0, &error);
+
+               if (ret < 0) {
+                       e_error(user->event, "%s: %s", driver->name,
+                               error);
                        return -1;
+               }
        }
 
        duser = p_new(pool, struct push_notification_driver_user, 1);
index 07b570fac59a3b182a63dea6e44da371e6a15038..67d17c0fb5cba296566e19e273d368b4efc7f1ff 100644 (file)
@@ -7,7 +7,6 @@
 #include "push-notification-triggers.h"
 
 struct mail_user;
-struct push_notification_driver_config;
 struct push_notification_driver_txn;
 struct push_notification_driver_user;
 struct push_notification_txn_mbox;
@@ -18,12 +17,11 @@ HASH_TABLE_DEFINE_TYPE(push_notification_msgs, void *,
                                           struct push_notification_txn_msg *);
 
 struct push_notification_driver_vfuncs {
-       /* Init driver. Config (from plugin configuration) is parsed once (no
-          user variable substitutions). Return 0 on success, or -1 if this
-          driver should be disabled (or on error). */
-       int (*init)(struct push_notification_driver_config *config,
-                   struct mail_user *user, pool_t pool, void **context,
-                   const char **error_r);
+       /* Init driver. Config should be read from settings via the name
+          parameter. Return 0 on success, or -1 if this driver should be
+          disabled (or on error). */
+       int (*init)(struct mail_user *user, pool_t pool, const char *name,
+                   void **context, const char **error_r);
        /* Called at the beginning of a notification transaction. Return TRUE on
           success, or FALSE if this driver should be ignored for this
           transaction. */
@@ -48,11 +46,6 @@ struct push_notification_driver {
        struct push_notification_driver_vfuncs v;
 };
 
-struct push_notification_driver_config {
-       HASH_TABLE_TYPE(push_notification_config) config;
-       const char *raw_config;
-};
-
 struct push_notification_driver_user {
        const struct push_notification_driver *driver;
        void *context;
index 75fcfc7f77c233c7997e12c0d4d08cb0d5028887..6b12e2998947ab9beedfd69f074cd002203ba72d 100644 (file)
@@ -7,17 +7,18 @@
 #include "mail-storage.h"
 #include "mail-storage-private.h"
 #include "notify-plugin.h"
+#include "settings.h"
 #include "str.h"
 
 #include "push-notification-drivers.h"
 #include "push-notification-events.h"
 #include "push-notification-events-rfc5423.h"
+#include "push-notification-settings.h"
 #include "push-notification-plugin.h"
 #include "push-notification-triggers.h"
 #include "push-notification-txn-mbox.h"
 #include "push-notification-txn-msg.h"
 
-#define PUSH_NOTIFICATION_CONFIG "push_notification_driver"
 #define PUSH_NOTIFICATION_EVENT_FINISHED "push_notification_finished"
 
 #define PUSH_NOTIFICATION_USER_CONTEXT(obj) \
@@ -248,32 +249,33 @@ static void push_notification_transaction_rollback(void *txn)
 }
 
 static void
-push_notification_config_init(const char *config_name, struct mail_user *user,
+push_notification_config_init(struct mail_user *user,
                              struct push_notification_driver_list *dlist)
 {
+       const struct push_notification_settings *set;
        struct push_notification_driver_user *duser;
-       const char *env;
-       unsigned int i;
-       string_t *root_name;
+       const char *error, *name;
 
-       root_name = t_str_new(32);
-       str_append(root_name, config_name);
-
-       for (i = 2;; i++) {
-               env = mail_user_plugin_getenv(user, str_c(root_name));
-               if ((env == NULL) || (*env == '\0'))
-                       break;
+       if (settings_get(user->event, &push_notification_setting_parser_info,
+                        0, &set, &error) < 0) {
+               e_error(user->event, "Failed to get push_notification settings: %s",
+                       error);
+               return;
+       }
 
-               if (push_notification_driver_init(
-                       user, env, user->pool, &duser) < 0)
-                       break;
+       if (array_is_created(&set->push_notifications)) {
+               array_foreach_elem(&set->push_notifications, name) {
+                       if (push_notification_driver_init(
+                                       user, name, user->pool,
+                                       &duser) < 0)
+                               break;
 
-               /* Add driver. */
-               array_push_back(&dlist->drivers, &duser);
+                       /* Add driver. */
+                       array_push_back(&dlist->drivers, &duser);
+               }
 
-               str_truncate(root_name, strlen(config_name));
-               str_printfa(root_name, "%d", i);
        }
+       settings_free(set);
 }
 
 static struct push_notification_driver_list *
@@ -284,7 +286,7 @@ push_notification_driver_list_init(struct mail_user *user)
        dlist = p_new(user->pool, struct push_notification_driver_list, 1);
        p_array_init(&dlist->drivers, user->pool, 4);
 
-       push_notification_config_init(PUSH_NOTIFICATION_CONFIG, user, dlist);
+       push_notification_config_init(user, dlist);
        return dlist;
 }