certificates ala communigate, RT#7515
[freeside.git] / FS / FS / svc_domain.pm
index 47aa8f3..a97f35b 100644 (file)
@@ -1,7 +1,9 @@
 package FS::svc_domain;
 
 use strict;
-use vars qw( @ISA $whois_hack $conf
+use base qw( FS::svc_Parent_Mixin FS::svc_CGP_Mixin FS::svc_CGPRule_Mixin
+             FS::svc_Common );
+use vars qw( $whois_hack $conf
   @defaultrecords $soadefaultttl $soaemail $soaexpire $soamachine
   $soarefresh $soaretry
 );
@@ -12,8 +14,6 @@ use Date::Format;
 use Net::Domain::TLD qw(tld_exists);
 use FS::Record qw(fields qsearch qsearchs dbh);
 use FS::Conf;
-use FS::svc_Common;
-use FS::svc_Parent_Mixin;
 use FS::cust_svc;
 use FS::svc_acct;
 use FS::cust_pkg;
@@ -21,8 +21,6 @@ use FS::cust_main;
 use FS::domain_record;
 use FS::queue;
 
-@ISA = qw( FS::svc_Parent_Mixin FS::svc_Common );
-
 #ask FS::UID to run this stuff for us later
 $FS::UID::callback{'FS::domain'} = sub { 
   $conf = new FS::Conf;
@@ -89,6 +87,8 @@ FS::svc_Common.  The following fields are currently supported:
 
 =item expiration_date - UNIX timestamp
 
+=item max_accounts
+
 =back
 
 =head1 METHODS
@@ -109,6 +109,173 @@ sub table_info {
     'cancel_weight'  => 60,
     'fields' => {
       'domain' => 'Domain',
+      'parent_svcnum' => { 
+                         label => 'Parent domain / Communigate administrator domain',
+                         type  => 'select',
+                         select_table => 'svc_domain',
+                         select_key => 'svcnum',
+                         select_label => 'domain',
+                         disable_inventory => 1,
+                         disable_select    => 1,
+                       },
+      'max_accounts' => { label => 'Maximum number of accounts',
+                          'disable_inventory' => 1,
+                        },
+      'cgp_aliases' => { 
+                         label => 'Communigate aliases',
+                         type  => 'text',
+                         disable_inventory => 1,
+                         disable_select    => 1,
+                       },
+      'cgp_accessmodes' => { 
+                             label => 'Communigate enabled services',
+                             type  => 'communigate_pro-accessmodes',
+                             disable_inventory => 1,
+                             disable_select    => 1,
+                           },
+      'cgp_certificatetype' => { 
+                             label => 'Communigate PKI services',
+                             type  => 'select',
+                             select_list => __PACKAGE__->cgp_certificatetype_values,
+                             disable_inventory => 1,
+                             disable_select    => 1,
+                           },
+
+      'acct_def_cgp_accessmodes' => { 
+                             label => 'Acct. default Communigate enabled services',
+                             type  => 'communigate_pro-accessmodes',
+                             disable_inventory => 1,
+                             disable_select    => 1,
+                           },
+      'acct_def_password_selfchange' => { label => 'Acct. default Password modification',
+                                 type  => 'checkbox',
+                            disable_inventory => 1,
+                            disable_select    => 1,
+                               },
+      'acct_def_password_recover'    => { label => 'Acct. default Password recovery',
+                                 type  => 'checkbox',
+                            disable_inventory => 1,
+                            disable_select    => 1,
+                               },
+      'acct_def_cgp_deletemode' => { 
+                            label => 'Acct. default Communigate message delete method',
+                            type  => 'select',
+                            select_list => [ 'Move To Trash', 'Immediately', 'Mark' ],
+                            disable_inventory => 1,
+                            disable_select    => 1,
+                          },
+      'acct_def_cgp_emptytrash' => { 
+                            label => 'Acct. default Communigate on logout remove trash',
+                            type        => 'select',
+                            select_list => __PACKAGE__->cgp_emptytrash_values,
+                            disable_inventory => 1,
+                            disable_select    => 1,
+                          },
+      'acct_def_quota'     => { 
+                       label => 'Acct. default Quota', #Mail storage limit
+                       type => 'text',
+                       disable_inventory => 1,
+                       disable_select => 1,
+                     },
+      'acct_def_file_quota'=> { 
+                       label => 'Acct. default File storage limit',
+                       type => 'text',
+                       disable_inventory => 1,
+                       disable_select => 1,
+                     },
+      'acct_def_file_maxnum'=> { 
+                       label => 'Acct. default Number of files limit',
+                       type => 'text',
+                       disable_inventory => 1,
+                       disable_select => 1,
+                     },
+      'acct_def_file_maxsize'=> { 
+                       label => 'Acct. default File size limit',
+                       type => 'text',
+                       disable_inventory => 1,
+                       disable_select => 1,
+                     },
+      'acct_def_cgp_rulesallowed'   => {
+        label       => 'Acct. default Allowed mail rules',
+        type        => 'select',
+        select_list => [ '', 'No', 'Filter Only', 'All But Exec', 'Any' ],
+        disable_inventory => 1,
+        disable_select    => 1,
+      },
+      'acct_def_cgp_rpopallowed'    => {
+        label => 'Acct. default RPOP modifications',
+        type  => 'checkbox',
+      },
+      'acct_def_cgp_mailtoall'      => {
+        label => 'Acct. default Accepts mail to "all"',
+        type  => 'checkbox',
+      },
+      'acct_def_cgp_addmailtrailer' => {
+        label => 'Acct. default Add trailer to sent mail',
+        type  => 'checkbox',
+      },
+      'acct_def_cgp_archiveafter'   => {
+        label       => 'Archive messages after',
+        type        => 'select',
+        select_hash => [ 
+                         -2 => 'default(730 days)',
+                         0 => 'Never',
+                         86400 => '24 hours',
+                         172800 => '2 days',
+                         259200 => '3 days',
+                         432000 => '5 days',
+                         604800 => '7 days',
+                         1209600 => '2 weeks',
+                         2592000 => '30 days',
+                         7776000 => '90 days',
+                         15552000 => '180 days',
+                         31536000 => '365 days',
+                         63072000 => '730 days',
+                       ],
+        disable_inventory => 1,
+        disable_select    => 1,
+      },
+      'trailer' => {
+        label => 'Mail trailer',
+        type  => 'textarea',
+        disable_inventory => 1,
+        disable_select    => 1,
+      },
+      'acct_def_cgp_language' => {
+                            label => 'Acct. default language',
+                            type  => 'select',
+                            select_list => [ '', qw( English Arabic Chinese Dutch French German Hebrew Italian Japanese Portuguese Russian Slovak Spanish Thai ) ],
+                            disable_inventory => 1,
+                            disable_select    => 1,
+                        },
+      'acct_def_cgp_timezone' => {
+                            label       => 'Acct. default time zone',
+                            type        => 'select',
+                            select_list => __PACKAGE__->cgp_timezone_values,
+                            disable_inventory => 1,
+                            disable_select    => 1,
+                        },
+      'acct_def_cgp_skinname' => {
+                            label => 'Acct. default layout',
+                            type  => 'select',
+                            select_list => [ '', '***', 'GoldFleece', 'Skin2' ],
+                            disable_inventory => 1,
+                            disable_select    => 1,
+                        },
+      'acct_def_cgp_prontoskinname' => {
+                            label => 'Acct. default Pronto style',
+                            type  => 'select',
+                            select_list => [ '', 'Pronto', 'Pronto-darkflame', 'Pronto-steel', 'Pronto-twilight', ],
+                            disable_inventory => 1,
+                            disable_select    => 1,
+                        },
+      'acct_def_cgp_sendmdnmode' => {
+        label => 'Acct. default send read receipts',
+        type  => 'select',
+        select_list => [ '', 'Never', 'Manually', 'Automatically' ],
+        disable_inventory => 1,
+        disable_select    => 1,
+      },
     },
   };
 }
@@ -140,11 +307,8 @@ otherwise returns false.
 The additional fields I<pkgnum> and I<svcpart> (see L<FS::cust_svc>) should be 
 defined.  An FS::cust_svc record will be created and inserted.
 
-The additional field I<action> should be set to I<N> for new domains or I<M>
-for transfers.
-
-A registration or transfer email will be submitted unless
-$FS::svc_domain::whois_hack is true.
+The additional field I<action> should be set to I<N> for new domains, I<M>
+for transfers, or I<I> for no action (registered elsewhere).
 
 The additional field I<email> can be used to manually set the admin contact
 email address on this email.  Otherwise, the svc_acct records for this package 
@@ -181,19 +345,36 @@ sub insert {
   local $FS::UID::AutoCommit = 0;
   my $dbh = dbh;
 
-  $error = $self->check;
-  return $error if $error;
-
-  return "Domain in use (here)"
-    if qsearchs( 'svc_domain', { 'domain' => $self->domain } );
-
-
-  $error = $self->SUPER::insert(@_);
+  $error =  $self->SUPER::insert(@_)
+         || $self->insert_defaultrecords;
   if ( $error ) {
     $dbh->rollback if $oldAutoCommit;
     return $error;
   }
 
+  $dbh->commit or die $dbh->errstr if $oldAutoCommit;
+
+  ''; #no error
+}
+
+=item insert_defaultrecords
+
+=cut
+
+sub insert_defaultrecords {
+  my $self = shift;
+
+  local $SIG{HUP} = 'IGNORE';
+  local $SIG{INT} = 'IGNORE';
+  local $SIG{QUIT} = 'IGNORE';
+  local $SIG{TERM} = 'IGNORE';
+  local $SIG{TSTP} = 'IGNORE';
+  local $SIG{PIPE} = 'IGNORE';
+
+  my $oldAutoCommit = $FS::UID::AutoCommit;
+  local $FS::UID::AutoCommit = 0;
+  my $dbh = dbh;
+
   if ( $soamachine ) {
     my $soa = new FS::domain_record {
       'svcnum'  => $self->svcnum,
@@ -203,10 +384,10 @@ sub insert {
       'recdata' => "$soamachine $soaemail ( ". time2str("%Y%m%d", time). "00 ".
                    "$soarefresh $soaretry $soaexpire $soadefaultttl )"
     };
-    $error = $soa->insert;
+    my $error = $soa->insert;
     if ( $error ) {
       $dbh->rollback if $oldAutoCommit;
-      return "couldn't insert SOA record for new domain: $error";
+      return "couldn't insert SOA record: $error";
     }
 
     foreach my $record ( @defaultrecords ) {
@@ -221,7 +402,7 @@ sub insert {
       my $error = $domain_record->insert;
       if ( $error ) {
         $dbh->rollback if $oldAutoCommit;
-        return "couldn't insert record for new domain: $error";
+        return "couldn't insert record: $error";
       }
     }
 
@@ -297,10 +478,11 @@ sub replace {
               : $new->replace_old;
 
   return "Can't change domain - reorder."
-    if $old->getfield('domain') ne $new->getfield('domain'); 
+    if $old->getfield('domain') ne $new->getfield('domain')
+    && ! $conf->exists('svc_domain-edit_domain'); 
 
   # Better to do it here than to force the caller to remember that svc_domain is weird.
-  $new->setfield(action => 'M');
+  $new->setfield(action => 'I');
   my $error = $new->SUPER::replace($old, @_);
   return $error if $error;
 }
@@ -342,6 +524,32 @@ sub check {
 
   my $error = $self->ut_numbern('svcnum')
               || $self->ut_numbern('catchall')
+              || $self->ut_numbern('max_accounts')
+              || $self->ut_anything('trailer') #well
+              || $self->ut_textn('cgp_aliases') #well
+              || $self->ut_enum('acct_def_password_selfchange', [ '', 'Y' ])
+              || $self->ut_enum('acct_def_password_recover',    [ '', 'Y' ])
+              || $self->ut_textn('acct_def_cgp_accessmodes')
+              || $self->ut_alphan('acct_def_quota')
+              || $self->ut_alphan('acct_def_file_quota')
+              || $self->ut_alphan('acct_def_maxnum')
+              || $self->ut_alphan('acct_def_maxsize')
+              #settings
+              || $self->ut_alphasn('acct_def_cgp_rulesallowed')
+              || $self->ut_enum('acct_def_cgp_rpopallowed', [ '', 'Y' ])
+              || $self->ut_enum('acct_def_cgp_mailtoall', [ '', 'Y' ])
+              || $self->ut_enum('acct_def_cgp_addmailtrailer', [ '', 'Y' ])
+              || $self->ut_snumbern('acct_def_cgp_archiveafter')
+              #preferences
+              || $self->ut_alphasn('acct_def_cgp_deletemode')
+              || $self->ut_enum('acct_def_cgp_emptytrash',
+                                   $self->cgp_emptytrash_values )
+              || $self->ut_alphan('acct_def_cgp_language')
+              || $self->ut_textn('acct_def_cgp_timezone')
+              || $self->ut_textn('acct_def_cgp_skinname')
+              || $self->ut_textn('acct_def_cgp_prontoskinname')
+              || $self->ut_alphan('acct_def_cgp_sendmdnmode')
+              #mail
   ;
   return $error if $error;
 
@@ -361,7 +569,7 @@ sub check {
     $recref->{domain} = "$1.$2";
     $recref->{suffix} ||= $2;
   # hmmmmmmmm.
-  } elsif ( $whois_hack && $recref->{domain} =~ /^([\w\-\.]+)\.(\w+)$/ ) {
+  } elsif ( $whois_hack && $recref->{domain} =~ /^([\w\-\.\/]+)\.(\w+)$/ ) {
     $recref->{domain} = "$1.$2";
     # need to match a list of suffixes - no guarantee they're top-level..
     # http://wiki.mozilla.org/TLD_List
@@ -388,11 +596,22 @@ sub check {
     or $self->ut_numbern('setup_date')
     or $self->ut_numbern('renewal_interval')
     or $self->ut_numbern('expiration_date')
-    or $self->ut_textn('purpose')
     or $self->SUPER::check;
 
 }
 
+sub _check_duplicate {
+  my $self = shift;
+
+  $self->lock_table;
+
+  if ( qsearchs( 'svc_domain', { 'domain' => $self->domain } ) ) {
+    return "Domain in use (here)";
+  } else {
+    return '';
+  }
+}
+
 =item domain_record
 
 =cut
@@ -408,6 +627,7 @@ sub domain_record {
     'A'     => 5,
     'TXT'   => 6,
     'PTR'   => 7,
+    'SRV'   => 8,
   );
 
   my %sort = (
@@ -425,6 +645,7 @@ sub domain_record {
     'PTR'   => sub { $_[0]->reczone <=> $_[1]->reczone },
   );
 
+  map { $_ } #return $self->num_domain_record( PARAMS ) unless wantarray;
   sort {    $order{$a->rectype} <=> $order{$b->rectype}
          or &{ $sort{$a->rectype} || sub { 0; } }($a, $b)
        }