diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2007-09-06 13:05:56 +0000 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2007-09-06 13:05:56 +0000 |
commit | 747e41693d7f2a808b3314cf82b3af38f98daf2d (patch) | |
tree | a023fea0ac96b2abdc2c98141d90a841544dbbf9 /src | |
parent | afd4995c30c273a02f81e80a972688936907853a (diff) | |
download | wydawca-747e41693d7f2a808b3314cf82b3af38f98daf2d.tar.gz wydawca-747e41693d7f2a808b3314cf82b3af38f98daf2d.tar.bz2 |
Redo mail notifications
git-svn-id: file:///svnroot/wydawca/trunk@316 6bb4bd81-ecc2-4fd4-a2d4-9571d19c0d33
Diffstat (limited to 'src')
-rw-r--r-- | src/config.c | 167 | ||||
-rw-r--r-- | src/mail.c | 172 | ||||
-rw-r--r-- | src/mail.h | 4 | ||||
-rw-r--r-- | src/wydawca.h | 18 | ||||
-rw-r--r-- | src/wydawca.rc | 141 |
5 files changed, 262 insertions, 240 deletions
diff --git a/src/config.c b/src/config.c index 13f90ce..ed0bafd 100644 --- a/src/config.c +++ b/src/config.c @@ -832,6 +832,26 @@ static void cfg_mail_admin_stat (gsc_config_file_t *file, char *kw, char *val, void *unused) { + char *word; + + if (!val) + { + file->error_msg (file->file_name, file->line, + "missing message template identifier"); + file->error_count++; + return; + } + + word = get_word (&val); + + admin_stat_message_template = find_message_template (word); + if (!admin_stat_message_template) + { + file->error_msg (file->file_name, file->line, + "no such message template: %s", word); + file->error_count++; + return; + } _cfg_statmask (file, val, &mail_admin_mask); } @@ -918,16 +938,43 @@ _cfg_raw_read (gsc_config_file_t *file, char *val, struct obstack *stk) file->error_count++; } } - + static void -cfg_admin_stat_message (gsc_config_file_t *file, char *kw, char *val, - void *unused) +cfg_define_message (gsc_config_file_t *file, char *kw, char *val, void *unused) { + char *word; + if (!val) + { + file->error_msg (file->file_name, file->line, + "missing message identifier"); + file->error_count++; + return; + } + + word = xstrdup (get_word (&val)); if (_cfg_raw_read (file, val, &cfg_stk) == 0) - admin_stat_message_template = obstack_finish (&cfg_stk); + register_message_template (word, obstack_finish (&cfg_stk)); } +int +string_to (char *what, char *str, + const char **args, int *vals, + int *pret, + gsc_config_file_t *file) +{ + ptrdiff_t x = ARGMATCH (str, args, vals); + + if (x == (ptrdiff_t)-1) + { + file->error_msg (file->file_name, file->line, + "unknown %s: %s", what, str); + file->error_count++; + return 1; + } + *pret = vals[x]; + return 0; +} static const char *event_args[] = { "success", @@ -937,7 +984,7 @@ static const char *event_args[] = { NULL }; -static enum notification_event event_types[] = { +static int event_types[] = { ev_success, ev_bad_ownership, ev_bad_directive_signature, @@ -946,30 +993,69 @@ static enum notification_event event_types[] = { ARGMATCH_VERIFY (event_args, event_types); +const char * +notification_event_str (enum notification_event evt) +{ + return event_args[evt]; +} + int string_to_notification_event (gsc_config_file_t *file, char *val, enum notification_event *pret) { - ptrdiff_t x = ARGMATCH (val, event_args, event_types); - - if (x == (ptrdiff_t)-1) - { - file->error_msg (file->file_name, file->line, - "unknown notification type: %s", val); - file->error_count++; - return 1; - } - *pret = event_types[x]; - return 0; + int rc, res; + rc = string_to ("notification event", val, + event_args, event_types, + &res, + file); + *pret = res; + return rc; +} + +static const char *target_args[] = { + "admin", + "user", + "owner", + NULL +}; + +static int target_types[] = { + notify_admin, /* System administrator */ + notify_owner, /* Project admin */ + notify_user /* User (uploader) */ +}; + +ARGMATCH_VERIFY (target_args, target_types); + +const char * +notification_target_str (enum notification_target tgt) +{ + return target_args[tgt]; +} + +int +string_to_notification_target (gsc_config_file_t *file, char *val, + enum notification_target *pret) +{ + int rc, res; + rc = string_to ("notification target", val, + target_args, target_types, + &res, + file); + *pret = res; + return rc; } static void -cfg_mail_user (gsc_config_file_t *file, char *kw, char *val, void *unused) +cfg_notify_event (gsc_config_file_t *file, char *kw, char *val, void *unused) { - int i; int argc; char **argv; - + enum notification_event evt; + enum notification_target tgt; + struct message_template *msg; + int rc; + if (argcv_get (val, NULL, NULL, &argc, &argv)) { file->error_msg (file->file_name, file->line, @@ -978,38 +1064,32 @@ cfg_mail_user (gsc_config_file_t *file, char *kw, char *val, void *unused) return; } - for (i = 0; i < argc; i++) + if (argc != 3) { - enum notification_event evt; - - if (string_to_notification_event (file, argv[i], &evt)) - break; - owner_notification_flags |= STAT_MASK (evt); + file->error_msg (file->file_name, file->line, + "wrong number of arguments"); + file->error_count++; + argcv_free (argc, argv); + return; } - argcv_free (argc, argv); -} - -static void -cfg_user_message (gsc_config_file_t *file, char *kw, char *val, void *unused) -{ - enum notification_event evt; - char *word = get_word (&val); - if (!*word) + rc = string_to_notification_event (file, argv[0], &evt) + | string_to_notification_target (file, argv[1], &tgt); + if ((msg = find_message_template (argv[2])) == NULL) { + rc = 1; file->error_msg (file->file_name, file->line, - "not enough arguments"); + "undefined message: %s", argv[2]); file->error_count++; - return; } - - if (string_to_notification_event (file, word, &evt)) - return; - if (_cfg_raw_read (file, val, &cfg_stk) == 0) - user_message_template[evt] = obstack_finish (&cfg_stk); + if (rc == 0) + register_notification (evt, tgt, msg); + + argcv_free (argc, argv); } + static struct gsc_config_keyword kw_handler[] = { @@ -1032,9 +1112,8 @@ static struct gsc_config_keyword kw_handler[] = { { "admin-address", cfg_admin_address }, { "from-address", cfg_from_address }, { "mail-admin-stat", cfg_mail_admin_stat }, - { "admin-stat-message", cfg_admin_stat_message }, - { "mail-user", cfg_mail_user }, - { "user-message", cfg_user_message }, + { "define-message", cfg_define_message }, + { "notify-event", cfg_notify_event }, { NULL } }; @@ -22,7 +22,7 @@ mu_mailer_t mailer; mu_address_t admin_address; mu_address_t from_address; unsigned long mail_admin_mask; -char *admin_stat_message_template; +struct message_template *admin_stat_message_template; unsigned long owner_notification_flags; char *user_message_template[MAX_EVENT]; @@ -98,6 +98,70 @@ mail_send_message (mu_address_t rcpt, const char *text) } void +mail_finish () +{ + if (mailer_opened) + mu_mailer_close (mailer); +} + + +struct message_template +{ + struct message_template *next; + char *name; + char *text; + /* int mime; for future use */ +}; + +static struct message_template *message_list; + +void +register_message_template (char *name, char *text) +{ + struct message_template *newp = xmalloc (sizeof *newp); + newp->name = name; + newp->text = text; + newp->next = message_list; + message_list = newp; +} + +struct message_template * +find_message_template (char *name) +{ + struct message_template *p; + + for (p = message_list; p; p = p->next) + if (strcmp (p->name, name) == 0) + break; + return p; +} + + +struct notification +{ + struct notification *next; + enum notification_event ev; + enum notification_target tgt; + struct message_template *msg; +}; + +static struct notification *notification_list; + +void +register_notification (enum notification_event ev, + enum notification_target tgt, + struct message_template *msg) +{ + struct notification *newp = xmalloc (sizeof *newp); + newp->ev = ev; + newp->tgt = tgt; + newp->msg = msg; + newp->next = notification_list; + notification_list = newp; +} + + +void mail_stats () { struct kw_expansion exp[MAX_STAT + 1]; @@ -129,7 +193,7 @@ mail_stats () make_stat_expansion (exp + 1); - text = expand_param (admin_stat_message_template, + text = expand_param (admin_stat_message_template->text, exp, sizeof (exp) / sizeof (exp[0]), NULL); mail_send_message (admin_address, text); @@ -138,53 +202,26 @@ mail_stats () free_kwexp (exp, sizeof (exp) / sizeof (exp[0])); } -void -mail_finish () +mu_address_t +get_recipient (struct access_method *method, struct file_triplet *trp, + char **errp) { - if (mailer_opened) - mu_mailer_close (mailer); -} - -void -notify_owner (struct file_triplet *trp, enum notification_event ev) -{ - int rc; - struct access_method *method; - char *text; - mu_address_t rcpt = NULL; unsigned nrows, ncols, i; struct kw_expansion kwexp[4]; - - switch (ev) - { - case ev_success: - case ev_bad_directive_signature: - case ev_bad_detached_signature: - method = trp->dpair->user_data_method; - break; - - case ev_bad_ownership: - method = trp->dpair->project_owner_method; - break; - - default: - abort (); - } + mu_address_t rcpt = NULL; + char *text; + int rc; if (method->type == method_none) { - logmsg (LOG_NOTICE, - "NOT notifying project admins: project-owner not configured in " - "[%s, %s]", trp->dpair->source_dir, trp->dpair->dest_dir); - return; + *errp = "access method is not configured"; + return NULL; } if (method_init (method)) { - logmsg (LOG_ERR, - "failed to initialize project-owner method: " - "NOT notifying project admins"); - return; + *errp = "failed to initialize access method"; + return NULL; } make_default_kwexp (kwexp, trp->user, trp->project); @@ -195,9 +232,8 @@ notify_owner (struct file_triplet *trp, enum notification_event ev) free (text); if (rc) { - logmsg (LOG_ERR, "cannot obtain owner emails for %s", - trp->project); - return; + *errp = "cannot obtain recipient emails"; + return NULL; } nrows = method_num_rows (method); @@ -205,9 +241,8 @@ notify_owner (struct file_triplet *trp, enum notification_event ev) if (nrows == 0) { - logmsg (LOG_ERR, "cannot obtain owner emails for %s", - trp->project); - return; + *errp = "cannot obtain recipient emails"; + return NULL; } for (i = 0; i < nrows; i++) @@ -226,6 +261,40 @@ notify_owner (struct file_triplet *trp, enum notification_event ev) mu_address_destroy (&addr); } + return rcpt; +} + +void +do_notify (struct file_triplet *trp, enum notification_event ev, + struct notification *ntf) +{ + int rc; + mu_address_t rcpt = NULL; + char *errp; + + switch (ntf->tgt) + { + case notify_admin: + rcpt = admin_address; + break; + + case notify_user: + rcpt = get_recipient (trp->dpair->user_data_method, trp, &errp); + break; + + case notify_owner: + rcpt = get_recipient (trp->dpair->project_owner_method, trp, &errp); + } + + if (!rcpt) + { + logmsg (LOG_ERR, "not notifying %s (project %s) about %s: %s", + notification_target_str (ntf->tgt), + trp->project, + notification_event_str (ev), errp); + return; + } + if (debug_level) { size_t size; @@ -233,14 +302,14 @@ notify_owner (struct file_triplet *trp, enum notification_event ev) mu_address_to_string (rcpt, NULL, 0, &size); buf = xmalloc (size + 1); mu_address_to_string (rcpt, buf, size + 1, NULL); - logmsg (LOG_DEBUG, "Notifying admins of %s: %s", trp->project, - buf); + logmsg (LOG_DEBUG, "notifying %s (project %s) about %s", + buf, trp->project, notification_event_str (ev)); free (buf); } if (!dry_run_mode) { - text = triplet_expand_param (user_message_template[ev], trp); + char *text = triplet_expand_param (ntf->msg->text, trp); mail_send_message (rcpt, text); free (text); } @@ -251,8 +320,11 @@ notify_owner (struct file_triplet *trp, enum notification_event ev) void notify (struct file_triplet *trp, enum notification_event ev) { + struct notification *p; + fill_project_name (trp); - if (owner_notification_flags & STAT_MASK (ev)) - notify_owner (trp, ev); + for (p = notification_list; p; p = p->next) + if (p->ev == ev) + do_notify (trp, ev, p); /* FIXME */ } @@ -20,9 +20,7 @@ extern mu_mailer_t mailer; extern mu_address_t admin_address; extern mu_address_t from_address; extern unsigned long mail_admin_mask; -extern char *admin_stat_message_template; -extern unsigned long owner_notification_flags; -extern char *user_message_template[MAX_EVENT]; +extern struct message_template *admin_stat_message_template; void mail_init (void); void mail_finish (void); diff --git a/src/wydawca.h b/src/wydawca.h index 0d38bd3..2de86f0 100644 --- a/src/wydawca.h +++ b/src/wydawca.h @@ -197,10 +197,24 @@ enum notification_event MAX_EVENT }; -void notify_project_owner (struct file_triplet *, enum notification_event); -void notify_admin (struct file_triplet *, enum notification_event); +enum notification_target + { + notify_admin, /* System administrator */ + notify_owner, /* Project admin */ + notify_user /* User (uploader) */ + }; + +struct message_template; +struct message_template *find_message_template (char *name); +void register_notification (enum notification_event ev, + enum notification_target tgt, + struct message_template *msg); + void notify (struct file_triplet *, enum notification_event); +const char *notification_event_str (enum notification_event evt); +const char *notification_target_str (enum notification_target tgt); + struct kw_expansion { diff --git a/src/wydawca.rc b/src/wydawca.rc deleted file mode 100644 index 5deba03..0000000 --- a/src/wydawca.rc +++ /dev/null @@ -1,141 +0,0 @@ -syslog-facility local1 -syslog-tag wydawca -syslog-print-priority yes -statistics all - -file-sweep-time 1 hour - -sql default - host localhost:/tmp/mysql.sock - database savane - user savane - password guessme -end - -umask 022 -tar-program /bin/tar - -admin-address gray@localhost -from-address wydawca@localhost -mail-admin-stat all - -admin-stat-message -Subject: Wydawca stats - -This is to notify you that the run of wydawca on %{date} -caused the following results: - -errors ............................. %{stat:errors} -warning ............................ %{stat:warnings} -bad signatures ..................... %{stat:bad_signatures} -access violation attempts .......... %{stat:access_violations} -complete triplets .................. %{stat:complete_triplets} -incomplete triplets ................ %{stat:incomplete_triplets} -bad triplets ....................... %{stat:bad_triplets} -expired triplets ................... %{stat:expired_triplets} -triplet successes .................. %{stat:triplet_success} -files uploaded ..................... %{stat:uploads} -files archived ..................... %{stat:archives} -symlinks created ................... %{stat:symlinks} -symlinks removed ................... %{stat:rmsymlinks} - -Regards, -Wydawca -end - -mail-user success bad-ownership bad-directive-signature bad-detached-signature - -user-message success -Subject: Upload of %{project} successful - -Upload of %{project} to %{dir} finished successfully. Files uploaded: - -%{triplet:upload} - -Regards, -Wydawca -The Project Submission Robot -end - -user-message bad-ownership -Subject: Suspicious upload of %{project} - -Someone not authorized to make releases for %{project} has attempted to upload -the following files to %{dir}: - -%{triplet:full} - -This upload has been ignored and the files removed. The person who attempted -the upload was %{user:real-name}, user name %{user:name}, email %{user:email}. -If you think this is an error and wish this user to be authorized to make -releases for %{project}, please contact <puszcza-hackers@gnu.org.ua>. -Otherwise, let us know so we could undertake appropriate measures. - -Regards, -Wydawca -The Project Submission Robot -end - -user-message bad-directive-signature -Subject: Suspicious upload of %{project} - -Someone (apparently you), has tried to make a release for %{project}. -However, the signature of the directive file was wrong, which looks -suspicious. The person uploaded the following files: - -%{triplet:full} - -This upload has been ignored and the files removed. If it was you who -attempted this upload, please make sure you use the right PGP key and -try again. If not, please let us know as soon as possible, so we can -track down the person trying to make believe he is you. -Regards, -Wydawca -The Project Submission Robot -end - -user-message bad-detached-signature -Subject: Suspicious upload of %{project} - -Someone (apparently you), has tried to make a release for %{project}. -However, the detached signature signature was wrong, which looks -suspicious. The person uploaded the following files: - -%{triplet:full} - -This upload has been ignored and the files removed. If it was you who -attempted this upload, please make sure you use the right PGP key and -try again. If not, please let us know as soon as possible, so we can -track down the person trying to make believe he is you. -Regards, -Wydawca -The Project Submission Robot -end - -project-owner sql default SELECT user.email, user.realname \ - FROM user,user_group,groups \ - WHERE user_group.user_id=user.user_id \ - AND user_group.group_id=groups.group_id \ - AND user_group.admin_flags = 'A' \ - AND groups.unix_group_name='%p' - -user-data sql default SELECT email, realname \ - FROM user \ - WHERE user_name='%{user}' - -directory - source /home/ftp/incoming/ftp - destination /home/ftp/gnu - verify-user sql default SELECT user.user_name \ - FROM user,user_group,groups \ - WHERE user_group.user_id=user.user_id \ - AND user_group.group_id=groups.group_id \ - AND user_group.admin_flags = 'A' \ - AND groups.unix_group_name='%p' \ - AND user.user_name='%u' - gpg-key sql default SELECT gpg_key FROM user WHERE user_name='%u' - archive directory .archive - #archive directory .archive numbered - #archive directory /var/spool/archive - #archive tar /var/spool/archive.tar -end |