diff options
| -rw-r--r-- | FS/FS/Schema.pm | 19 | ||||
| -rw-r--r-- | FS/FS/log.pm | 35 | ||||
| -rw-r--r-- | FS/FS/log_email.pm | 108 | ||||
| -rw-r--r-- | FS/FS/msg_template.pm | 6 | ||||
| -rw-r--r-- | httemplate/browse/log_email.html | 92 | ||||
| -rw-r--r-- | httemplate/edit/log_email.html | 45 | ||||
| -rw-r--r-- | httemplate/edit/process/log_email.html | 18 | ||||
| -rw-r--r-- | httemplate/elements/menu.html | 4 | ||||
| -rw-r--r-- | httemplate/elements/tr-select-msg_template.html | 12 | ||||
| -rw-r--r-- | httemplate/misc/delete-log_email.html | 20 | ||||
| -rw-r--r-- | httemplate/search/log.html | 4 | 
11 files changed, 359 insertions, 4 deletions
| diff --git a/FS/FS/Schema.pm b/FS/FS/Schema.pm index 447a6bcad..ecd071e49 100644 --- a/FS/FS/Schema.pm +++ b/FS/FS/Schema.pm @@ -4658,6 +4658,25 @@ sub tables_hashref {        'index' => [],      }, +    'log_email' => { +      'columns' => [ +        'logemailnum', 'serial', '', '', '', '', +        'context', 'varchar', 'NULL', $char_d, '', '', +        'min_level', 'int',  'NULL', '', '', '', +        'msgnum', 'int', '',  '', '', '', +        'to_addr', 'varchar', 'NULL',     255, '', '', +      ], +      'primary_key'  => 'logemailnum', +      'unique'       => [], +      'index'        => [ ['context'], ['min_level'] ], +      'foreign_keys' => [ +                          { columns    => [ 'msgnum' ], +                            table      => 'msg_template', +                            references => [ 'msgnum' ], +                          }, +                        ], +    }, +      'svc_alarm' => {        'columns' => [  #       name               type        null   length   default local diff --git a/FS/FS/log.pm b/FS/FS/log.pm index 547beb7d0..18ba7c936 100644 --- a/FS/FS/log.pm +++ b/FS/FS/log.pm @@ -5,6 +5,7 @@ use base qw( FS::Record );  use FS::Record qw( qsearch qsearchs dbdef );  use FS::UID qw( dbh driver_name );  use FS::log_context; +use FS::log_email;  =head1 NAME @@ -71,6 +72,8 @@ otherwise returns false.  CONTEXT may be a list of context tags to attach to this record. +Will send emails according to the conditions in L<FS::log_email>. +  =cut  sub insert { @@ -78,6 +81,7 @@ sub insert {    my $self = shift;    my $error = $self->SUPER::insert;    return $error if $error; +  my $contexts = {}; #for quick checks when sending emails    foreach ( @_ ) {      my $context = FS::log_context->new({          'lognum'  => $self->lognum, @@ -85,11 +89,40 @@ sub insert {      });      $error = $context->insert;      return $error if $error; +    $contexts->{$_} = 1; +  } +  foreach my $log_email ( +    qsearch('log_email', +      { +        'disabled' => '', +        'min_level' => { +          'op' => '<=', +          'value' => $self->level, +        }, +      } +    ) +  ) { +    # shouldn't be a lot of these, so not packing this into the qsearch +    next if $log_email->context && !$contexts->{$log_email->context}; +    my $msg_template = qsearchs('msg_template',{ 'msgnum' => $log_email->msgnum }); +    unless ($msg_template) { +      warn "Could not send email when logging, could not load message template for logemailnum " . $log_email->logemailnum; +      next; +    } +    my $emailerror = $msg_template->send( +      'to'            => $log_email->to_addr, +      'substitutions' => { +        'loglevel'   => $FS::Log::LEVELS[$self->level], # which has hopefully been loaded... +        'logcontext' => $log_email->context, # use the one that triggered the email +        'logmessage' => $self->message, +      }, +    ); +    warn "Could not send email when logging: $emailerror" if $emailerror;    }    '';  } -# the insert method can be inherited from FS::Record +# these methods can be inherited from FS::Record  sub delete  { die "Log entries can't be modified." }; diff --git a/FS/FS/log_email.pm b/FS/FS/log_email.pm new file mode 100644 index 000000000..9c53c230a --- /dev/null +++ b/FS/FS/log_email.pm @@ -0,0 +1,108 @@ +package FS::log_email; + +use strict; +use base qw( FS::Record ); +use FS::Record qw( qsearch qsearchs dbdef ); +use FS::UID qw( dbh driver_name ); + +=head1 NAME + +FS::log_email - Object methods for log email records + +=head1 SYNOPSIS + +  use FS::log_email; + +  $record = new FS::log_email \%hash; +  $record = new FS::log_email { 'column' => 'value' }; + +  $error = $record->insert; + +  $error = $new_record->replace($old_record); + +  $error = $record->delete; + +  $error = $record->check; + +=head1 DESCRIPTION + +An FS::log object represents the conditions for sending an email +when a log entry is created.  FS::log inherits from FS::Record.   +The following fields are currently supported: + +=over 4 + +=item logemailnum - primary key + +=item context - the context that will trigger the email (all contexts if unspecified) + +=item min_level - the minimum log level that will trigger the email (all levels if unspecified) + +=item msgnum - the msg_template that will be used to send the email + +=item to_addr - who the email will be sent to (in addition to any bcc on the template) + +=back + +=head1 METHODS + +=over 4 + +=item new HASHREF + +Creates a new log_email entry. + +=cut + +sub table { 'log_email'; } + +=item insert + +Adds this record to the database.  If there is an error, returns the error, +otherwise returns false. + +=item delete + +Delete this record from the database. + +=item replace OLD_RECORD + +Replaces the OLD_RECORD with this one in the database.  If there is an error, +returns the error, otherwise returns false. + +=item check + +Checks all fields to make sure this is a valid record.  If there is +an error, returns the error, otherwise returns false.  Called by the insert +and replace methods. + +=cut + +sub check { +  my $self = shift; + +  my $error =  +    $self->ut_numbern('logemailnum') +    || $self->ut_textn('context') # not validating against list of contexts in log_context, +                                  # because not even log_context check currently does so +    || $self->ut_number('min_level') +    || $self->ut_foreign_key('msgnum', 'msg_template', 'msgnum') +    || $self->ut_textn('to_addr') +  ; +  return $error if $error; + +  $self->SUPER::check; +} + +=back + +=head1 BUGS + +=head1 SEE ALSO + +L<FS::Record>, schema.html from the base documentation. + +=cut + +1; + diff --git a/FS/FS/msg_template.pm b/FS/FS/msg_template.pm index 50a9b3f27..2388aba69 100644 --- a/FS/FS/msg_template.pm +++ b/FS/FS/msg_template.pm @@ -239,7 +239,7 @@ Options are passed as a list of name/value pairs:  =item cust_main -Customer object (required). +Customer object  =item object @@ -277,8 +277,8 @@ A hash reference of additional substitutions  sub prepare {    my( $self, %opt ) = @_; -  my $cust_main = $opt{'cust_main'} or die 'cust_main required'; -  my $object = $opt{'object'} or die 'object required'; +  my $cust_main = $opt{'cust_main'}; # or die 'cust_main required'; +  my $object = $opt{'object'}; # or die 'object required';    # localization    my $locale = $cust_main->locale || ''; diff --git a/httemplate/browse/log_email.html b/httemplate/browse/log_email.html new file mode 100644 index 000000000..0f64dd454 --- /dev/null +++ b/httemplate/browse/log_email.html @@ -0,0 +1,92 @@ +<% include('/elements/init_overlib.html') %> +<% include('/browse/elements/browse.html', +     'title'         => 'Log email condition configuration', +     'name_singular' => 'condition', +     'html_init'     => '<P STYLE="margin-top: 0">' +                        . $add_condition_link +                        . ' | ' +                        . $system_log_link +                        . '</P>' +                        . '<SCRIPT>' +                        . $areyousure +                        . '</SCRIPT>', +     'query'         => $query, +     'count_query'   => $count_query, +     'header'      => [ '#', +                        'Context',  +                        'Min. Level',  +                        'Template',  +                        'To', +                        '', +                      ], +     'fields'      => [ 'logemailnum', +                        sub { $_[0]->context || '(all)' }, +                        sub { $FS::Log::LEVELS[$_[0]->min_level] }, +                        'msgname', +                        'to_addr', +                        $actions, +                      ], +     'sort_fields' => [ 'logemailnum', +                        'context', +                        'min_level', +                        'msgname', +                        'to_addr', +                        '', +                      ], +     'links'       => [ $editlink, +                        $editlink, +                        $editlink, +                        $editlink, +                        $editlink, +                        '', +                      ], + +   ) %> + +<%init> + +my $curuser = $FS::CurrentUser::CurrentUser; + +die "access denied" +  unless $curuser->access_right([ 'View system logs', 'Configuration' ]); + +my $add_condition_link = include('/elements/popup_link.html', +  'action' => $p.'edit/log_email.html?popup=1', +  'label'  => 'Add log email condition', +  'actionlabel' => 'Add log email condition', +); + +my $system_log_link = qq(<A HREF="${p}search/log.html">System Log</A>); + +my $query = { +  'table'   => 'log_email', +  'select'  => '*', +  'addl_from' => 'LEFT JOIN msg_template USING (msgnum)', +  'hashref' => { }, +}; + +my $count_query = "SELECT COUNT(*) FROM log_email"; + +my $actions = sub { +  my $log_email = shift; +  my $logemailnum = $log_email->logemailnum; +  qq!<A HREF="javascript:areyousure_delete_log_email($logemailnum)">(delete)</A>!; +}; + +my $areyousure_onclick = include('/elements/popup_link_onclick.html', +  'js_action' => q(') . $p . q(misc/delete-log_email.html?logemailnum=' + logemailnum), +  'actionlabel' => 'Delete log email condition', +); + +my $areyousure = <<EOF; +function areyousure_delete_log_email(logemailnum) { +  if (confirm('Are you sure you want to delete log email condition #'+logemailnum+'?')) { +${areyousure_onclick} +  } +} +EOF + +my $editlink = [ $p.'edit/log_email.html?logemailnum=', 'logemailnum' ]; + +</%init> + diff --git a/httemplate/edit/log_email.html b/httemplate/edit/log_email.html new file mode 100644 index 000000000..bbce7c708 --- /dev/null +++ b/httemplate/edit/log_email.html @@ -0,0 +1,45 @@ +<% include( 'elements/edit.html', +              'name_singular' => 'log email condition', +              'table'  => 'log_email', +              'fields' => [ +                            { 'field' => 'context', +                              'type' => 'select', +                              'options' => [ '', @contexts ], +                              'labels' => { '' => '(all)', map { $_ => $_ } @contexts }, +                              'curr_value' => scalar($cgi->param('context')), +                            }, +                            { 'field' => 'min_level', +                              'type'  => 'select', +                              'options' => [ 0..7 ], +                              'labels' => { map {$_ => $FS::Log::LEVELS[$_]} 0..7 }, +                              'curr_value' => scalar($cgi->param('min_level')), +                            }, +                            'to_addr', +                            { 'field' => 'msgnum', +                              'type' => 'select-msg_template', +                              'empty_label' => 'Select template', +                              'required' => 1, +                            }, +                          ], +              'labels' => {  +                            'context' => 'Context', +                            'min_level' => 'Min. Level', +                            'to_addr' => 'To', +                            'msgnum' => 'Message', +                          }, +              'viewall_dir' => 'browse', +              'popup' => $opts{'popup'}, +              'form_init' => $opts{'popup'} ? q(<INPUT TYPE="hidden" NAME="popup" VALUE="1">) : '', +           ) +%> +<%once> +my @contexts = sort FS::log_context->contexts; +</%once> +<%init> + +my %opts = @_; + +die "access denied" +  unless $FS::CurrentUser::CurrentUser->access_right([ 'View system logs', 'Configuration' ]); + +</%init> diff --git a/httemplate/edit/process/log_email.html b/httemplate/edit/process/log_email.html new file mode 100644 index 000000000..769e180a8 --- /dev/null +++ b/httemplate/edit/process/log_email.html @@ -0,0 +1,18 @@ +<% include('elements/process.html', +    'table' => 'log_email', +    %processopts +   ) %> +<%init> + +my %opts = @_; + +my $curuser = $FS::CurrentUser::CurrentUser; + +die "access denied" +  unless $curuser->access_right([ 'View system logs', 'Configuration' ]); + +my %processopts = $opts{'popup'} +  ? ( 'popup_reload' => 'Logging email added' ) +  : ( 'redirect' => $fsurl.'browse/log_email.html?' ); # id will be needlessly appended, should be harmless + +</%init> diff --git a/httemplate/elements/menu.html b/httemplate/elements/menu.html index 9b30b6cd0..759ae338c 100644 --- a/httemplate/elements/menu.html +++ b/httemplate/elements/menu.html @@ -801,6 +801,10 @@ $config_misc{'Inventory classes and inventory'} = [ $fsurl.'browse/inventory_cla  $config_misc{'Upload targets'} = [ $fsurl.'browse/upload_target.html', 'Billing and payment upload destinations' ]    if $curuser->access_right('Configuration'); +$config_misc{'System log emails'} = [ $fsurl.'browse/log_email.html', 'Configure conditions for sending email when logging' ] +  if $curuser->access_right('View system logs') +  || $curuser->access_right('Configuration'); +  tie my %config_menu, 'Tie::IxHash';  if ( $curuser->access_right('Configuration' ) ) {    %config_menu = ( diff --git a/httemplate/elements/tr-select-msg_template.html b/httemplate/elements/tr-select-msg_template.html new file mode 100644 index 000000000..1f899e01c --- /dev/null +++ b/httemplate/elements/tr-select-msg_template.html @@ -0,0 +1,12 @@ +<% include('/elements/tr-td-label.html', +     'label'    => $opt{'label'} || 'Message template: ', +     'required' => $opt{'required'} ) %> +  <TD><% include('select-msg_template.html', %opt) %></TD> +</TR> + +<%init> + +my %opt = @_; + +</%init> + diff --git a/httemplate/misc/delete-log_email.html b/httemplate/misc/delete-log_email.html new file mode 100644 index 000000000..cc17b15a0 --- /dev/null +++ b/httemplate/misc/delete-log_email.html @@ -0,0 +1,20 @@ +% if ($error) { +<P STYLE="color: red"><% $error %></P> +% } else { +<H1>Log email condition deleted</H1> +<SCRIPT> +window.top.location.reload(); +</SCRIPT> +% } + +<%init> +die "access denied" +  unless $FS::CurrentUser::CurrentUser->access_right([ 'View system logs', 'Configuration' ]); + +my $logemailnum = $cgi->param('logemailnum'); +$logemailnum =~ /^\d+$/ or die "bad logemailnum '$logemailnum'"; +my $log_email = FS::log_email->by_key($logemailnum) +  or die "logemailnum '$logemailnum' not found"; +my $error = $log_email->delete; +</%init> + diff --git a/httemplate/search/log.html b/httemplate/search/log.html index 9aa37365d..9a61a71e1 100644 --- a/httemplate/search/log.html +++ b/httemplate/search/log.html @@ -1,6 +1,7 @@  <& elements/search.html,     'title'         => 'System Log',    'name_singular' => 'event', +  'menubar'       => \@menubar,    'html_init'     => include('.head'),    'query'         => $query,    'count_query'   => $count_query, @@ -210,6 +211,9 @@ my $curuser = $FS::CurrentUser::CurrentUser;  die "access denied"    unless $curuser->access_right([ 'View system logs', 'Configuration' ]); +my @menubar = (); +push @menubar, qq(<A HREF="${fsurl}browse/log_email.html" STYLE="text-decoration: underline;">Configure conditions for sending email when logging</A>), +  $cgi->param('min_level', 0) unless defined($cgi->param('min_level'));  $cgi->param('max_level', 7) unless defined($cgi->param('max_level')); | 
