Merge branch 'master' of ssh://git.freeside.biz/home/git/freeside
authorChristopher Burger <burgerc@freeside.biz>
Fri, 1 Dec 2017 22:11:10 +0000 (17:11 -0500)
committerChristopher Burger <burgerc@freeside.biz>
Fri, 1 Dec 2017 22:11:10 +0000 (17:11 -0500)
FS/FS/part_export/passwdfile.pm
FS/FS/part_export/shellcommands.pm
FS/FS/part_export/shellcommands_withdomain.pm
FS/FS/svc_acct.pm
rt/etc/RT_SiteConfig.pm
rt/etc/initialdata
rt/lib/RT/Condition/StatusChangeQuietResolve.pm [new file with mode: 0644]

index 2978d25..6713c8d 100644 (file)
@@ -9,8 +9,8 @@ use FS::part_export::null;
 
 tie %options, 'Tie::IxHash',
   'crypt' => { label=>'Password encryption',
-               type=>'select', options=>[qw(crypt md5)],
-               default=>'crypt',
+               type=>'select', options=>[qw(crypt md5 sha512)],
+               default=>'md5',
              },
 ;
 
index 775af17..7c280e5 100644 (file)
@@ -97,8 +97,8 @@ tie my %options, 'Tie::IxHash',
                         },
 
   'crypt' => { label   => 'Default password encryption',
-               type=>'select', options=>[qw(crypt md5)],
-               default => 'crypt',
+               type=>'select', options=>[qw(crypt md5 sha512)],
+               default => 'md5',
              },
   'groups_susp_reason' => { label =>
                              'Radius group mapping to reason (via template user)',
index 29715b7..b307133 100644 (file)
@@ -63,8 +63,8 @@ tie my %options, 'Tie::IxHash',
                  type  => 'checkbox',
            },
   'crypt' => { label   => 'Default password encryption',
-               type=>'select', options=>[qw(crypt md5)],
-               default => 'crypt',
+               type=>'select', options=>[qw(crypt md5 sha512)],
+               default => 'md5',
              },
   'fail_on_output' => {
       label => 'Treat any output from the command as an error',
index 0894980..de9199d 100644 (file)
@@ -2542,6 +2542,11 @@ sub crypt_password {
       );
     } elsif ( $encryption eq 'md5' ) {
       return unix_md5_crypt( $self->_password );
+    } elsif ( $encryption eq 'sha512' ) {
+      return crypt(
+        $self->_password,
+        '$6$rounds=15420$'. join('', map $saltset[int(rand(64))], (1..16) )
+      );
     } elsif ( $encryption eq 'sha1_base64' ) { #for acct_sql
       my $pass = sha1_base64( $self->_password );
       $pass .= '=' x (4 - length($pass) % 4); #properly padded base64
index d22da42..6420d11 100644 (file)
@@ -58,4 +58,193 @@ Set($MessageBoxRichTextHeight, 368);
 
 #Set(@Plugins,(qw(Extension::QuickDelete RT::FM)));
 
+
+# Define default lifecycle to include resolved_quiet status workflow
+Set(%Lifecycles,
+  default => {
+    initial         => [qw(new)], # loc_qw
+    active          => [qw(open stalled)], # loc_qw
+    inactive        => [qw(resolved resolved_quiet rejected deleted)], # loc_qw
+
+    defaults => {
+        on_create => 'new',
+        on_merge  => 'resolved',
+        approved  => 'open',
+        denied    => 'rejected',
+        reminder_on_open     => 'open',
+        reminder_on_resolve  => 'resolved',
+    },
+
+    transitions => {
+        ""       => [qw(new open resolved)],
+
+        # from   => [ to list ],
+        new       => [qw(open stalled resolved resolved_quiet rejected  deleted)],
+        open      => [qw(new stalled resolved resolved_quiet rejected  deleted)],
+        stalled   => [qw(new open rejected resolved resolved_quiet deleted)],
+        resolved  => [qw(new open stalled rejected deleted)],
+        resolved_quiet => [qw(resolved)],
+        rejected  => [qw(new open stalled resolved resolved_quiet deleted)],
+        deleted   => [qw(new open stalled rejected resolved resolved_quiet)],
+    },
+
+    rights => {
+        '* -> deleted'  => 'DeleteTicket',
+        '* -> *'        => 'ModifyTicket',
+    },
+    actions => [
+        'new -> open'            => { label  => 'Open It',       update => 'Respond' },
+        'new -> resolved'        => { label  => 'Resolve',       update => 'Comment' },
+        'new -> resolved_quiet'  => { label  => 'Quiet Resolve', update => 'Comment' },
+        'new -> rejected'        => { label  => 'Reject',        update => 'Respond' },
+        'new -> deleted'         => { label  => 'Delete',                            },
+        'open -> stalled'        => { label  => 'Stall',         update => 'Comment' },
+        'open -> resolved'       => { label  => 'Resolve',       update => 'Comment' },
+        'open -> resolved_quiet' => { label  => 'Quiet Resolve', update => 'Comment' },
+        'open -> rejected'       => { label  => 'Reject',        update => 'Respond' },
+        'stalled -> open'        => { label  => 'Open It',                           },
+        'resolved -> open'       => { label  => 'Re-open',       update => 'Comment' },
+        'rejected -> open'       => { label  => 'Re-open',       update => 'Comment' },
+        'deleted -> open'        => { label  => 'Undelete',                          },
+    ],
+  },
+# don't change lifecyle of the approvals, they are not capable to deal with
+# custom statuses
+  approvals => {
+    initial         => [ 'new' ],
+    active          => [ 'open', 'stalled' ],
+    inactive        => [ 'resolved', 'rejected', 'deleted' ],
+
+    defaults => {
+      on_create => 'new',
+      on_merge => 'resolved',
+      reminder_on_open     => 'open',
+      reminder_on_resolve  => 'resolved',
+    },
+
+    transitions => {
+      ''       => [qw(new open resolved)],
+
+      # from   => [ to list ],
+      new      => [qw(open stalled resolved rejected deleted)],
+      open     => [qw(new stalled resolved rejected deleted)],
+      stalled  => [qw(new open rejected resolved deleted)],
+      resolved => [qw(new open stalled rejected deleted)],
+      rejected => [qw(new open stalled resolved deleted)],
+      deleted  => [qw(new open stalled rejected resolved)],
+    },
+    rights => {
+      '* -> deleted'  => 'DeleteTicket',
+      '* -> rejected' => 'ModifyTicket',
+      '* -> *'        => 'ModifyTicket',
+    },
+    actions => [
+      'new -> open'      => { label  => 'Open It', update => 'Respond' },
+      'new -> resolved'  => { label  => 'Resolve', update => 'Comment' },
+      'new -> rejected'  => { label  => 'Reject',  update => 'Respond' },
+      'new -> deleted'   => { label  => 'Delete',                      },
+      'open -> stalled'  => { label  => 'Stall',   update => 'Comment' },
+      'open -> resolved' => { label  => 'Resolve', update => 'Comment' },
+      'open -> rejected' => { label  => 'Reject',  update => 'Respond' },
+      'stalled -> open'  => { label  => 'Open It',                     },
+      'resolved -> open' => { label  => 'Re-open', update => 'Comment' },
+      'rejected -> open' => { label  => 'Re-open', update => 'Comment' },
+      'deleted -> open'  => { label  => 'Undelete',                    },
+    ],
+  },
+);
+
+# Lifecycle 'default' from RT_Config.pm
+# Customer may set the lifecycle on their ticket queue as 'hide_resolve_quiet'
+# to suppress the 'resolve_quiet' ticket status
+Set(%Lifecycles,
+    hide_resolve_quiet => {
+        initial         => [qw(new)], # loc_qw
+        active          => [qw(open stalled)], # loc_qw
+        inactive        => [qw(resolved rejected deleted)], # loc_qw
+
+        defaults => {
+            on_create => 'new',
+            on_merge  => 'resolved',
+            approved  => 'open',
+            denied    => 'rejected',
+            reminder_on_open     => 'open',
+            reminder_on_resolve  => 'resolved',
+        },
+
+        transitions => {
+            ""       => [qw(new open resolved)],
+
+            # from   => [ to list ],
+            new      => [qw(    open stalled resolved rejected deleted)],
+            open     => [qw(new      stalled resolved rejected deleted)],
+            stalled  => [qw(new open         rejected resolved deleted)],
+            resolved => [qw(new open stalled          rejected deleted)],
+            rejected => [qw(new open stalled resolved          deleted)],
+            deleted  => [qw(new open stalled rejected resolved        )],
+        },
+        rights => {
+            '* -> deleted'  => 'DeleteTicket',
+            '* -> *'        => 'ModifyTicket',
+        },
+        actions => [
+            'new -> open'      => { label  => 'Open It', update => 'Respond' }, # loc{label}
+            'new -> resolved'  => { label  => 'Resolve', update => 'Comment' }, # loc{label}
+            'new -> rejected'  => { label  => 'Reject',  update => 'Respond' }, # loc{label}
+            'new -> deleted'   => { label  => 'Delete',                      }, # loc{label}
+            'open -> stalled'  => { label  => 'Stall',   update => 'Comment' }, # loc{label}
+            'open -> resolved' => { label  => 'Resolve', update => 'Comment' }, # loc{label}
+            'open -> rejected' => { label  => 'Reject',  update => 'Respond' }, # loc{label}
+            'stalled -> open'  => { label  => 'Open It',                     }, # loc{label}
+            'resolved -> open' => { label  => 'Re-open', update => 'Comment' }, # loc{label}
+            'rejected -> open' => { label  => 'Re-open', update => 'Comment' }, # loc{label}
+            'deleted -> open'  => { label  => 'Undelete',                    }, # loc{label}
+        ],
+    },
+# don't change lifecyle of the approvals, they are not capable to deal with
+# custom statuses
+    approvals => {
+        initial         => [ 'new' ],
+        active          => [ 'open', 'stalled' ],
+        inactive        => [ 'resolved', 'rejected', 'deleted' ],
+
+        defaults => {
+            on_create => 'new',
+            on_merge => 'resolved',
+            reminder_on_open     => 'open',
+            reminder_on_resolve  => 'resolved',
+        },
+
+        transitions => {
+            ''       => [qw(new open resolved)],
+
+            # from   => [ to list ],
+            new      => [qw(open stalled resolved rejected deleted)],
+            open     => [qw(new stalled resolved rejected deleted)],
+            stalled  => [qw(new open rejected resolved deleted)],
+            resolved => [qw(new open stalled rejected deleted)],
+            rejected => [qw(new open stalled resolved deleted)],
+            deleted  => [qw(new open stalled rejected resolved)],
+        },
+        rights => {
+            '* -> deleted'  => 'DeleteTicket',
+            '* -> rejected' => 'ModifyTicket',
+            '* -> *'        => 'ModifyTicket',
+        },
+        actions => [
+            'new -> open'      => { label  => 'Open It', update => 'Respond' }, # loc{label}
+            'new -> resolved'  => { label  => 'Resolve', update => 'Comment' }, # loc{label}
+            'new -> rejected'  => { label  => 'Reject',  update => 'Respond' }, # loc{label}
+            'new -> deleted'   => { label  => 'Delete',                      }, # loc{label}
+            'open -> stalled'  => { label  => 'Stall',   update => 'Comment' }, # loc{label}
+            'open -> resolved' => { label  => 'Resolve', update => 'Comment' }, # loc{label}
+            'open -> rejected' => { label  => 'Reject',  update => 'Respond' }, # loc{label}
+            'stalled -> open'  => { label  => 'Open It',                     }, # loc{label}
+            'resolved -> open' => { label  => 'Re-open', update => 'Comment' }, # loc{label}
+            'rejected -> open' => { label  => 'Re-open', update => 'Comment' }, # loc{label}
+            'deleted -> open'  => { label  => 'Undelete',                    }, # loc{label}
+        ],
+    },
+);
+
 1;
index aa2010f..8769fed 100644 (file)
     #   ExecModule           => 'CustomFieldChange',
     #   ApplicableTransTypes => 'Any',
     #},
-
+    {  Name                 => 'On Resolve Allow Quiet',
+       Description          => 'Whenever a ticket is resolved, '.
+                               'except with resolve_quiet',
+       ApplicableTransTypes => 'Status',
+       ExecModule           => 'StatusChangeQuietResolve',
+    },
 );
 
 @Templates = (
@@ -931,8 +936,12 @@ Hour:         { $SubscriptionObj->SubValue('Hour') }
        ScripCondition => 'On Owner Change',
        ScripAction    => 'Notify Owner',
        Template       => 'Transaction in HTML' },
-    {  Description    => 'On Resolve Notify Requestors',
-       ScripCondition => 'On Resolve',
+#    {  Description    => 'On Resolve Notify Requestors',
+#       ScripCondition => 'On Resolve',
+#       ScripAction    => 'Notify Requestors',
+#       Template       => 'Resolved in HTML' },
+    {  Description    => 'On Resolve Notify Requestors, Allow Quiet Resolve',
+       ScripCondition => 'On Resolve Allow Quiet',
        ScripAction    => 'Notify Requestors',
        Template       => 'Resolved in HTML' },
     {  Description    => "On transaction, add any tags in the transaction's subject to the ticket's subject",
@@ -1068,6 +1077,10 @@ Hour:         { $SubscriptionObj->SubValue('Hour') }
     # superseded by "notify owner and adminccs"
     'notify adminccs'           => { 'transaction' => 1 },
   },
+  'on resolve' => {
+    # superseded by "On Resolve Notify Requestors, Allow Quiet Resolve"
+    'notify requestors' => { 'resolved in html' => 1 },
+  },
 );
 
 # -*- perl -*-
diff --git a/rt/lib/RT/Condition/StatusChangeQuietResolve.pm b/rt/lib/RT/Condition/StatusChangeQuietResolve.pm
new file mode 100644 (file)
index 0000000..8426141
--- /dev/null
@@ -0,0 +1,48 @@
+package RT::Condition::StatusChangeQuietResolve;
+use base 'RT::Condition';
+use strict;
+use warnings;
+
+=head2 DESCRIPTION
+
+This condition allows for muting of resolution notifications when
+combined with the ticket status 'resolved_quiet'
+
+If status has been updated as 'resolved_quiet', this condition
+will block notification, and update ticket status to 'resolved'
+
+If status has been updated as 'resolved', this condition
+will block notification only if the previous ticket status
+had been 'resolved_quiet'
+
+=cut
+
+sub IsApplicable {
+  my $self = shift;
+  my $txn = $self->TransactionObj;
+  my ($type, $field) = ($txn->Type, $txn->Field);
+
+  return 0
+    unless $type eq 'Status'
+    || ($type eq 'Set' && $field eq 'Status');
+
+  return 0
+    unless $txn->NewValue eq 'resolved'
+    || $txn->NewValue eq 'resolved_quiet';
+
+  my $ticket = $self->TicketObj;
+
+  if ($txn->NewValue eq 'resolved_quiet') {
+    $ticket->SetStatus('resolved');
+    return 0;
+  }
+  elsif ($txn->NewValue eq 'resolved' && $txn->OldValue eq 'resolved_quiet') {
+    return 0;
+  }
+
+  return 1;
+}
+
+RT::Base->_ImportOverlays();
+
+1;