X-Git-Url: http://git.freeside.biz/gitweb/?p=freeside.git;a=blobdiff_plain;f=FS%2FFS%2Fpart_export%2Fcommunigate_pro.pm;h=07281f1403fccf0c6a3614e545c1d66af37738fa;hp=a9d9591ca505493a9ccecf96663262f4891df4f6;hb=7a8c7b6f64ac14d555d866f93300e64c47b74a98;hpb=972ef71fa13cf9a76cb6453a98ece950e1776f1a diff --git a/FS/FS/part_export/communigate_pro.pm b/FS/FS/part_export/communigate_pro.pm index a9d9591ca..07281f140 100644 --- a/FS/FS/part_export/communigate_pro.pm +++ b/FS/FS/part_export/communigate_pro.pm @@ -1,91 +1,837 @@ package FS::part_export::communigate_pro; -use vars qw(@ISA); +use strict; +use vars qw(@ISA %info %options %quotas $DEBUG); +use Data::Dumper; +use Tie::IxHash; use FS::part_export; use FS::queue; @ISA = qw(FS::part_export); +$DEBUG = 1; + +tie %options, 'Tie::IxHash', + 'port' => { label =>'Port number', default=>'106', }, + 'login' => { label =>'The administrator account name. The name can contain a domain part.', }, + 'password' => { label =>'The administrator account password.', }, + 'accountType' => { label => 'Type for newly-created accounts (default when not specified in service)', + type => 'select', + options => [qw(MultiMailbox TextMailbox MailDirMailbox AGrade BGrade CGrade)], + default => 'MultiMailbox', + }, + 'externalFlag' => { label => 'Create accounts with an external (visible for legacy mailers) INBOX.', + type => 'checkbox', + }, + 'AccessModes' => { label => 'Access modes (default when not specified in service)', + default => 'Mail POP IMAP PWD WebMail WebSite', + }, + 'create_domain' => { label => 'Domain creation API call', + type => 'select', + options => [qw( CreateDomain CreateSharedDomain )], + } +; + +%info = ( + 'svc' => [qw( svc_acct svc_domain svc_forward svc_mailinglist )], + 'desc' => 'Real-time export of accounts, domains, mail forwards and mailing lists to a CommuniGate Pro mail server', + 'options' => \%options, + 'notes' => <<'END' +Real time export of accounts, domains, mail forwards and mailing lists to a +CommuniGate Pro +mail server. The +CommuniGate Pro Perl Interface +must be installed as CGP::CLI. +END +); + +%quotas = ( + 'quota' => 'MaxAccountSize', + 'file_quota' => 'MaxWebSize', + 'file_maxnum' => 'MaxWebFiles', + 'file_maxsize' => 'MaxFileSize', +); + sub rebless { shift; } +sub export_username { + my($self, $svc_acct) = (shift, shift); + $svc_acct->email; +} + sub _export_insert { + my( $self, $svc_x ) = (shift, shift); + + my $table = $svc_x->table; + my $method = "_export_insert_$table"; + $self->$method($svc_x, @_); +} + +sub _export_insert_svc_acct { my( $self, $svc_acct ) = (shift, shift); - my @options = ( $svc_acct->svcnum, 'CreateAccount', - 'accountName' => $svc_acct->email, - 'accountType' => $self->option('accountType'), - 'AccessModes' => $self->option('AccessModes'), + + my %settings = ( + 'AccessModes' => [ split(' ', ( $svc_acct->cgp_accessmodes + || $self->option('AccessModes') ) + ) + ], 'RealName' => $svc_acct->finger, 'Password' => $svc_acct->_password, + + 'PasswordRecovery' => ($svc_acct->password_recover ? 'YES':'NO'), + + 'RulesAllowed' => $svc_acct->cgp_rulesallowed, + 'RPOPAllowed' =>($svc_acct->cgp_rpopallowed ?'YES':'NO'), + 'MailToAll' =>($svc_acct->cgp_mailtoall ?'YES':'NO'), + 'AddMailTrailer' =>($svc_acct->cgp_addmailtrailer ?'YES':'NO'), + + map { $quotas{$_} => $svc_acct->$_() } + grep $svc_acct->$_(), keys %quotas ); - push @options, 'MaxAccountSize' => $svc_acct->quota if $svc_acct->quota; + #XXX phase 3: archive messages, mailing lists + + my @options = ( 'CreateAccount', + 'accountName' => $self->export_username($svc_acct), + 'accountType' => ( $svc_acct->cgp_type + || $self->option('accountType') ), + 'settings' => \%settings + ); + push @options, 'externalFlag' => $self->option('externalFlag') if $self->option('externalFlag'); - $self->communigate_pro_queue( @options ); + #let's do the create realtime too, for much the same reasons, and to avoid + #pain of trying to queue w/dep the prefs & aliases + eval { $self->communigate_pro_runcommand( @options ) }; + return $@ if $@; + + #preferences + my %prefs = (); + $prefs{'DeleteMode'} = $svc_acct->cgp_deletemode if $svc_acct->cgp_deletemode; + $prefs{'EmptyTrash'} = $svc_acct->cgp_emptytrash if $svc_acct->cgp_emptytrash; + $prefs{'Language'} = $svc_acct->cgp_language if $svc_acct->cgp_language; + $prefs{'TimeZone'} = $svc_acct->cgp_timezone if $svc_acct->cgp_timezone; + $prefs{'SkinName'} = $svc_acct->cgp_skinname if $svc_acct->cgp_skinname; + $prefs{'ProntoSkinName'} = $svc_acct->cgp_prontoskinname if $svc_acct->cgp_prontoskinname; + $prefs{'SendMDNMode'} = $svc_acct->cgp_sendmdnmode if $svc_acct->cgp_sendmdnmode; + if ( keys %prefs ) { + my $pref_err = $self->communigate_pro_queue( $svc_acct->svcnum, + 'UpdateAccountPrefs', + $self->export_username($svc_acct), + %prefs, + ); + warn "WARNING: error queueing UpdateAccountPrefs job: $pref_err" + if $pref_err; + } + + #aliases + if ( $svc_acct->cgp_aliases ) { + my $alias_err = $self->communigate_pro_queue( $svc_acct->svcnum, + 'SetAccountAliases', + $self->export_username($svc_acct), + [ split(/\s*[,\s]\s*/, $svc_acct->cgp_aliases) ], + ); + warn "WARNING: error queueing SetAccountAliases job: $alias_err" + if $alias_err; + } + + ''; + +} + +sub _export_insert_svc_domain { + my( $self, $svc_domain ) = (shift, shift); + + my $create = $self->option('create_domain') || 'CreateDomain'; + + my %settings = ( + 'DomainAccessModes' => [ split(' ', $svc_domain->cgp_accessmodes ) ], + ); + $settings{'AccountsLimit'} = $svc_domain->max_accounts + if $svc_domain->max_accounts; + $settings{'AdminDomainName'} = $svc_domain->parent_svc_x->domain + if $svc_domain->parent_svcnum; + $settings{'TrailerText'} = $svc_domain->trailer + if $svc_domain->trailer; + + my @options = ( $create, $svc_domain->domain, \%settings ); + + eval { $self->communigate_pro_runcommand( @options ) }; + return $@ if $@; + + #aliases + if ( $svc_domain->cgp_aliases ) { + my $alias_err = $self->communigate_pro_queue( $svc_domain->svcnum, + 'SetDomainAliases', + $svc_domain->domain, + split(/\s*[,\s]\s*/, $svc_domain->cgp_aliases), + ); + warn "WARNING: error queueing SetDomainAliases job: $alias_err" + if $alias_err; + } + + #account defaults + my $def_err = $self->communigate_pro_queue( $svc_domain->svcnum, + 'SetAccountDefaults', + $svc_domain->domain, + 'PWDAllowed' =>($svc_domain->acct_def_password_selfchange ? 'YES':'NO'), + 'PasswordRecovery' => ($svc_domain->acct_def_password_recover ? 'YES':'NO'), + 'AccessModes' => $svc_domain->acct_def_cgp_accessmodes, + 'MaxAccountSize' => $svc_domain->acct_def_quota, + 'MaxWebSize' => $svc_domain->acct_def_file_quota, + 'MaxWebFile' => $svc_domain->acct_def_file_maxnum, + 'MaxFileSize' => $svc_domain->acct_def_file_maxsize, + 'RulesAllowed' => $svc_domain->acct_def_cgp_rulesallowed, + 'RPOPAllowed' =>($svc_domain->acct_def_cgp_rpopallowed ?'YES':'NO'), + 'MailToAll' =>($svc_domain->acct_def_cgp_mailtoall ?'YES':'NO'), + 'AddMailTrailer' =>($svc_domain->acct_def_cgp_addmailtrailer ?'YES':'NO'), + ); + warn "WARNING: error queueing SetAccountDefaults job: $def_err" + if $def_err; + + #account defaults prefs + my $pref_err = $self->communigate_pro_queue( $svc_domain->svcnum, + 'SetAccountDefaultPrefs', + $svc_domain->domain, + 'DeleteMode' => $svc_domain->acct_def_cgp_deletemode, + 'EmptyTrash' => $svc_domain->acct_def_cgp_emptytrash, + 'Language' => $svc_domain->acct_def_cgp_language, + 'TimeZone' => $svc_domain->acct_def_cgp_timezone, + 'SkinName' => $svc_domain->acct_def_cgp_skinname, + 'ProntoSkinName' => $svc_domain->acct_def_cgp_prontoskinname, + 'SendMDNMode' => $svc_domain->acct_def_cgp_sendmdnmode, + ); + warn "WARNING: error queueing SetAccountDefaultPrefs job: $pref_err" + if $pref_err; + + ''; + +} + +sub _export_insert_svc_forward { + my( $self, $svc_forward ) = (shift, shift); + + my $src = $svc_forward->src || $svc_forward->srcsvc_acct->email; + my $dst = $svc_forward->dst || $svc_forward->dstsvc_acct->email; + + #real-time here, presuming CGP does some dup detection? + eval { $self->communigate_pro_runcommand( 'CreateForwarder', $src, $dst); }; + return $@ if $@; + + ''; +} + +sub _export_insert_svc_mailinglist { + my( $self, $svc_mlist ) = (shift, shift); + + my @members = map $_->email_address, + $svc_mlist->mailinglist->mailinglistmember; + + #real-time here, presuming CGP does some dup detection + eval { $self->communigate_pro_runcommand( + 'CreateGroup', + $svc_mlist->username.'@'.$svc_mlist->domain, + { 'RealName' => $svc_mlist->listname, + 'SetReplyTo' => ( $svc_mlist->reply_to ? 'YES' : 'NO' ), + 'RemoveAuthor' => ( $svc_mlist->remove_from ? 'YES' : 'NO' ), + 'RejectAuto' => ( $svc_mlist->reject_auto ? 'YES' : 'NO' ), + 'RemoveToAndCc' => ( $svc_mlist->remove_to_and_cc ? 'YES' : 'NO' ), + 'Members' => \@members, + } + ); + }; + return $@ if $@; + + ''; + } sub _export_replace { my( $self, $new, $old ) = (shift, shift, shift); - return "can't (yet) change domain with CommuniGate Pro" - if $old->domain ne $new->domain; - return "can't (yet) change username with CommuniGate Pro" - if $old->username ne $new->username; - return "can't (yet) change GECOS with CommuniGate Pro" + + my $table = $new->table; + my $method = "_export_replace_$table"; + $self->$method($new, $old, @_); +} + +sub _export_replace_svc_acct { + my( $self, $new, $old ) = (shift, shift, shift); + + #let's just do the rename part realtime rather than trying to queue + #w/dependencies. we don't want FS winding up out-of-sync with the wrong + #username and a queued job anyway. right?? + if ( $self->export_username($old) ne $self->export_username($new) ) { + eval { $self->communigate_pro_runcommand( + 'RenameAccount', + $self->export_username($old), + $self->export_username($new), + ) }; + return $@ if $@; + } + + if ( $new->_password ne $old->_password + && '*SUSPENDED* '.$old->_password ne $new->_password + ) { + $self->communigate_pro_queue( $new->svcnum, 'SetAccountPassword', + $self->export_username($new), $new->_password + ); + } + + my %settings = (); + + $settings{'RealName'} = $new->finger if $old->finger ne $new->finger; - return "can't (yet) change quota with CommuniGate Pro" - if $old->quota ne $new->quota; - return '' unless $old->username ne $new->username - || $old->_password ne $new->_password - || $old->finger ne $new->finger - || $old->quota ne $new->quota; + $settings{$quotas{$_}} = $new->$_() + foreach grep $old->$_() ne $new->$_(), keys %quotas; + $settings{'accountType'} = $new->cgp_type + if $old->cgp_type ne $new->cgp_type; + $settings{'AccessModes'} = $new->cgp_accessmodes + if $old->cgp_accessmodes ne $new->cgp_accessmodes + || $old->cgp_type ne $new->cgp_type; + + $settings{'PasswordRecovery'} = ( $new->password_recover ? 'YES':'NO' ) + if $old->password_recover ne $new->password_recover; + + $settings{'RulesAllowed'} = $new->cgp_rulesallowed + if $old->cgp_rulesallowed ne $new->cgp_rulesallowed; + $settings{'RPOPAllowed'} = ( $new->cgp_rpopallowed ? 'YES':'NO' ) + if $old->cgp_rpopallowed ne $new->cgp_rpopallowed; + $settings{'MailToAll'} = ( $new->cgp_mailtoall ? 'YES':'NO' ) + if $old->cgp_mailtoall ne $new->cgp_mailtoall; + $settings{'AddMailTrailer'} = ( $new->cgp_addmailtrailer ? 'YES':'NO' ) + if $old->cgp_addmailtrailer ne $new->cgp_addmailtrailer; + + #XXX phase 3: archive messages, mailing lists + + if ( keys %settings ) { + my $error = $self->communigate_pro_queue( + $new->svcnum, + 'UpdateAccountSettings', + $self->export_username($new), + %settings, + ); + return $error if $error; + } + + #preferences + my %prefs = (); + $prefs{'DeleteMode'} = $new->cgp_deletemode + if $old->cgp_deletemode ne $new->cgp_deletemode; + $prefs{'EmptyTrash'} = $new->cgp_emptytrash + if $old->cgp_emptytrash ne $new->cgp_emptytrash; + $prefs{'Language'} = $new->cgp_language + if $old->cgp_language ne $new->cgp_language; + $prefs{'TimeZone'} = $new->cgp_timezone + if $old->cgp_timezone ne $new->cgp_timezone; + $prefs{'SkinName'} = $new->cgp_skinname + if $old->cgp_skinname ne $new->cgp_skinname; + $prefs{'ProntoSkinName'} = $new->cgp_prontoskinname + if $old->cgp_prontoskinname ne $new->cgp_prontoskinname; + $prefs{'SendMDNMode'} = $new->cgp_sendmdnmode + if $old->cgp_sendmdnmode ne $new->cgp_sendmdnmode; + if ( keys %prefs ) { + my $pref_err = $self->communigate_pro_queue( $new->svcnum, + 'UpdateAccountPrefs', + $self->export_username($new), + %prefs, + ); + warn "WARNING: error queueing UpdateAccountPrefs job: $pref_err" + if $pref_err; + } + + if ( $old->cgp_aliases ne $new->cgp_aliases ) { + my $error = $self->communigate_pro_queue( + $new->svcnum, + 'SetAccountAliases', + $self->export_username($new), + [ split(/\s*[,\s]\s*/, $new->cgp_aliases) ], + ); + return $error if $error; + } + + ''; + +} + +sub _export_replace_svc_domain { + my( $self, $new, $old ) = (shift, shift, shift); + + if ( $old->domain ne $new->domain ) { + my $error = $self->communigate_pro_queue( $new->svcnum, 'RenameDomain', + $old->domain, $new->domain, + ); + return $error if $error; + } + my %settings = (); + $settings{'AccountsLimit'} = $new->max_accounts + if $old->max_accounts ne $new->max_accounts; + $settings{'TrailerText'} = $new->trailer + if $old->trailer ne $new->trailer; + $settings{'DomainAccessModes'} = $new->cgp_accessmodes + if $old->cgp_accessmodes ne $new->cgp_accessmodes; + $settings{'AdminDomainName'} = + $new->parent_svcnum ? $new->parent_svc_x->domain : '' + if $old->parent_svcnum != $new->parent_svcnum; - return '' if '*SUSPENDED* '. $old->_password eq $new->_password; + if ( keys %settings ) { + my $error = $self->communigate_pro_queue( $new->svcnum, + 'UpdateDomainSettings', + $new->domain, + %settings, + ); + return $error if $error; + } - #my $err_or_queue = $self->communigate_pro_queue( $new->svcnum,'RenameAccount', - # $old->email, $new->email ); - #return $err_or_queue unless ref($err_or_queue); - #my $jobnum = $err_or_queue->jobnum; + if ( $old->cgp_aliases ne $new->cgp_aliases ) { + my $error = $self->communigate_pro_queue( $new->svcnum, + 'SetDomainAliases', + $new->domain, + split(/\s*[,\s]\s*/, $new->cgp_aliases), + ); + return $error if $error; + } - $self->communigate_pro_queue( $new->svcnum, 'SetAccountPassword', - $new->email, $new->_password ) - if $new->_password ne $old->_password; + #below this identical to insert... any value to doing an Update here? + #not seeing any big one... i guess it would be nice to avoid the update + #when things haven't changed + + #account defaults + my $def_err = $self->communigate_pro_queue( $new->svcnum, + 'SetAccountDefaults', + $new->domain, + 'PWDAllowed' => ( $new->acct_def_password_selfchange ? 'YES' : 'NO' ), + 'PasswordRecovery' => ( $new->acct_def_password_recover ? 'YES' : 'NO' ), + 'AccessModes' => $new->acct_def_cgp_accessmodes, + 'MaxAccountSize' => $new->acct_def_quota, + 'MaxWebSize' => $new->acct_def_file_quota, + 'MaxWebFile' => $new->acct_def_file_maxnum, + 'MaxFileSize' => $new->acct_def_file_maxsize, + 'RulesAllowed' => $new->acct_def_cgp_rulesallowed, + 'RPOPAllowed' => ( $new->acct_def_cgp_rpopallowed ? 'YES' : 'NO' ), + 'MailToAll' => ( $new->acct_def_cgp_mailtoall ? 'YES' : 'NO' ), + 'AddMailTrailer' => ( $new->acct_def_cgp_addmailtrailer ? 'YES' : 'NO' ), + ); + warn "WARNING: error queueing SetAccountDefaults job: $def_err" + if $def_err; + + #account defaults prefs + my $pref_err = $self->communigate_pro_queue( $new->svcnum, + 'SetAccountDefaultPrefs', + $new->domain, + 'DeleteMode' => $new->acct_def_cgp_deletemode, + 'EmptyTrash' => $new->acct_def_cgp_emptytrash, + 'Language' => $new->acct_def_cgp_language, + 'TimeZone' => $new->acct_def_cgp_timezone, + 'SkinName' => $new->acct_def_cgp_skinname, + 'ProntoSkinName' => $new->acct_def_cgp_prontoskinname, + 'SendMDNMode' => $new->acct_def_cgp_sendmdnmode, + ); + warn "WARNING: error queueing SetAccountDefaultPrefs job: $pref_err" + if $pref_err; + + ''; +} + +sub _export_replace_svc_forward { + my( $self, $new, $old ) = (shift, shift, shift); + + my $osrc = $old->src || $old->srcsvc_acct->email; + my $nsrc = $new->src || $new->srcsvc_acct->email; + my $odst = $old->dst || $old->dstsvc_acct->email; + my $ndst = $new->dst || $new->dstsvc_acct->email; + + if ( $odst ne $ndst ) { + + #no change command, so delete and create (real-time) + eval { $self->communigate_pro_runcommand('DeleteForwarder', $osrc) }; + return $@ if $@; + eval { $self->communigate_pro_runcommand('CreateForwarder', $nsrc, $ndst)}; + return $@ if $@; + + } elsif ( $osrc ne $nsrc ) { + + #real-time here, presuming CGP does some dup detection? + eval { $self->communigate_pro_runcommand( 'RenameForwarder', $osrc, $nsrc)}; + return $@ if $@; + + } else { + warn "communigate replace called for svc_forward with no changes\n";#confess + } + + ''; +} + +sub _export_replace_svc_mailinglist { + my( $self, $new, $old ) = (shift, shift, shift); + + my $oldGroupName = $old->username.'@'.$old->domain; + my $newGroupName = $new->username.'@'.$new->domain; + + if ( $oldGroupName ne $newGroupName ) { + eval { $self->communigate_pro_runcommand( + 'RenameGroup', $oldGroupName, $newGroupName ); }; + return $@ if $@; + } + + my @members = map $_->email_address, + $new->mailinglist->mailinglistmember; + + #real-time here, presuming CGP does some dup detection + eval { $self->communigate_pro_runcommand( + 'SetGroup', $newGroupName, + { 'RealName' => $new->listname, + 'SetReplyTo' => ( $new->reply_to ? 'YES' : 'NO' ), + 'RemoveAuthor' => ( $new->remove_from ? 'YES' : 'NO' ), + 'RejectAuto' => ( $new->reject_auto ? 'YES' : 'NO' ), + 'RemoveToAndCc' => ( $new->remove_to_and_cc ? 'YES' : 'NO' ), + 'Members' => \@members, + } + ); + }; + return $@ if $@; + + ''; } sub _export_delete { + my( $self, $svc_x ) = (shift, shift); + + my $table = $svc_x->table; + my $method = "_export_delete_$table"; + $self->$method($svc_x, @_); +} + +sub _export_delete_svc_acct { my( $self, $svc_acct ) = (shift, shift); + $self->communigate_pro_queue( $svc_acct->svcnum, 'DeleteAccount', - $svc_acct->email, + $self->export_username($svc_acct), + ); +} + +sub _export_delete_svc_domain { + my( $self, $svc_domain ) = (shift, shift); + + $self->communigate_pro_queue( $svc_domain->svcnum, 'DeleteDomain', + $svc_domain->domain, + #XXX turn on force option for domain deletion? + ); +} + +sub _export_delete_svc_forward { + my( $self, $svc_forward ) = (shift, shift); + + $self->communigate_pro_queue( $svc_forward->svcnum, 'DeleteForwarder', + ($svc_forward->src || $svc_forward->srcsvc_acct->email), ); } +sub _export_delete_svc_mailinglist { + my( $self, $svc_mailinglist ) = (shift, shift); + + #real-time here, presuming CGP does some dup detection + eval { $self->communigate_pro_runcommand( + 'DeleteGroup', + $svc_mailinglist->username.'@'.$svc_mailinglist->domain, + ); + }; + return $@ if $@; + + ''; + +} + sub _export_suspend { + my( $self, $svc_x ) = (shift, shift); + + my $table = $svc_x->table; + my $method = "_export_suspend_$table"; + $self->$method($svc_x, @_); + +} + +sub _export_suspend_svc_acct { my( $self, $svc_acct ) = (shift, shift); - $self->communigate_pro_queue( $svc_acct->svcnum, 'UpdateAccountSettings', - 'accountName' => $svc_acct->email, + + #XXX is this the desired suspnsion action? + + $self->communigate_pro_queue( + $svc_acct->svcnum, + 'UpdateAccountSettings', + $self->export_username($svc_acct), 'AccessModes' => 'Mail', ); + +} + +sub _export_suspend_svc_domain { + my( $self, $svc_domain) = (shift, shift); + + #XXX domain operations + ''; + } sub _export_unsuspend { + my( $self, $svc_x ) = (shift, shift); + + my $table = $svc_x->table; + my $method = "_export_unsuspend_$table"; + $self->$method($svc_x, @_); + +} + +sub _export_unsuspend_svc_acct { my( $self, $svc_acct ) = (shift, shift); - $self->communigate_pro_queue( $svc_acct->svcnum, 'UpdateAccountSettings', - 'accountName' => $svc_acct->email, - 'AccessModes' => $self->option('AccessModes'), + + $self->communigate_pro_queue( + $svc_acct->svcnum, + 'UpdateAccountSettings', + $self->export_username($svc_acct), + 'AccessModes' => ( $svc_acct->cgp_accessmodes + || $self->option('AccessModes') ), + ); + +} + +sub _export_unsuspend_svc_domain { + my( $self, $svc_domain) = (shift, shift); + + #XXX domain operations + ''; + +} + +sub export_mailinglistmember_insert { + my( $self, $svc_mailinglist, $mailinglistmember ) = (shift, shift, shift); + $svc_mailinglist->replace(); +} + +sub export_mailinglistmember_replace { + my( $self, $svc_mailinglist, $new, $old ) = (shift, shift, shift, shift); + die "no way to do this from the UI right now"; +} + +sub export_mailinglistmember_delete { + my( $self, $svc_mailinglist, $mailinglistmember ) = (shift, shift, shift); + $svc_mailinglist->replace(); +} + +sub export_getsettings { + my($self, $svc_x) = (shift, shift); + + my $table = $svc_x->table; + my $method = "export_getsettings_$table"; + + $self->can($method) ? $self->$method($svc_x, @_) : ''; + +} + +sub export_getsettings_svc_domain { + my($self, $svc_domain, $settingsref, $defaultref ) = @_; + + my $settings = eval { $self->communigate_pro_runcommand( + 'GetDomainSettings', + $svc_domain->domain + ) }; + return $@ if $@; + + my $effective_settings = eval { $self->communigate_pro_runcommand( + 'GetDomainEffectiveSettings', + $svc_domain->domain + ) }; + return $@ if $@; + + my $acct_defaults = eval { $self->communigate_pro_runcommand( + 'GetAccountDefaults', + $svc_domain->domain + ) }; + return $@ if $@; + + my $acct_defaultprefs = eval { $self->communigate_pro_runcommand( + 'GetAccountDefaultPrefs', + $svc_domain->domain + ) }; + return $@ if $@; + + %$effective_settings = ( + %$effective_settings, + ( map { ("Acct. Default $_" => $acct_defaults->{$_}); } + keys(%$acct_defaults) + ), + ( map { ("Acct. Default $_" => $acct_defaultprefs->{$_}); } #diff label?? + keys(%$acct_defaultprefs) + ), + ); + %$settings = ( + %$settings, + ( map { ("Acct. Default $_" => $acct_defaults->{$_}); } + keys(%$acct_defaults) + ), + ( map { ("Acct. Default $_" => $acct_defaultprefs->{$_}); } #diff label?? + keys(%$acct_defaultprefs) + ), ); + + #aliases too + my $aliases = eval { $self->communigate_pro_runcommand( + 'GetDomainAliases', + $svc_domain->domain + ) }; + return $@ if $@; + + $effective_settings->{'Aliases'} = join(', ', @$aliases); + $settings->{'Aliases'} = join(', ', @$aliases); + + + #false laziness w/below + + my %defaults = map { $_ => 1 } + grep !exists(${$settings}{$_}), keys %$effective_settings; + + foreach my $key ( grep ref($effective_settings->{$_}), + keys %$effective_settings ) + { + my $value = $effective_settings->{$key}; + if ( ref($value) eq 'ARRAY' ) { + $effective_settings->{$key} = join(' ', @$value); + } else { + #XXX + warn "serializing ". ref($value). " for table display not yet handled"; + } + } + + %{$settingsref} = %$effective_settings; + %{$defaultref} = %defaults; + + ''; +} + +sub export_getsettings_svc_acct { + my($self, $svc_acct, $settingsref, $defaultref ) = @_; + + my $settings = eval { $self->communigate_pro_runcommand( + 'GetAccountSettings', + $svc_acct->email + ) }; + return $@ if $@; + + delete($settings->{'Password'}); + + my $effective_settings = eval { $self->communigate_pro_runcommand( + 'GetAccountEffectiveSettings', + $svc_acct->email + ) }; + return $@ if $@; + + delete($effective_settings->{'Password'}); + + #prefs/effectiveprefs too + + my $prefs = eval { $self->communigate_pro_runcommand( + 'GetAccountPrefs', + $svc_acct->email + ) }; + return $@ if $@; + + my $effective_prefs = eval { $self->communigate_pro_runcommand( + 'GetAccountEffectivePrefs', + $svc_acct->email + ) }; + return $@ if $@; + + %$effective_settings = ( %$effective_settings, + map { ("Pref $_" => $effective_prefs->{$_}); } + keys(%$effective_prefs) + ); + %$settings = ( %$settings, + map { ("Pref $_" => $prefs->{$_}); } + keys(%$prefs) + ); + + #aliases too + + my $aliases = eval { $self->communigate_pro_runcommand( + 'GetAccountAliases', + $svc_acct->email + ) }; + return $@ if $@; + + $effective_settings->{'Aliases'} = join(', ', @$aliases); + $settings->{'Aliases'} = join(', ', @$aliases); + + #false laziness w/above + + my %defaults = map { $_ => 1 } + grep !exists(${$settings}{$_}), keys %$effective_settings; + + foreach my $key ( grep ref($effective_settings->{$_}), + keys %$effective_settings ) + { + my $value = $effective_settings->{$key}; + if ( ref($value) eq 'ARRAY' ) { + $effective_settings->{$key} = join(' ', @$value); + } else { + #XXX + warn "serializing ". ref($value). " for table display not yet handled"; + } + } + + %{$settingsref} = %$effective_settings; + %{$defaultref} = %defaults; + + ''; + +} + +sub export_getsettings_svc_mailinglist { + my($self, $svc_mailinglist, $settingsref, $defaultref ) = @_; + + my $settings = eval { $self->communigate_pro_runcommand( + 'GetGroup', + $svc_mailinglist->username.'@'.$svc_mailinglist->domain, + ) }; + return $@ if $@; + + $settings->{'Members'} = join(', ', @{ $settings->{'Members'} } ); + + %{$settingsref} = %$settings; + + ''; } sub communigate_pro_queue { my( $self, $svcnum, $method ) = (shift, shift, shift); - my @kludge_methods = qw(CreateAccount UpdateAccountSettings); - my $sub = grep { $method eq $_ } @kludge_methods - ? $method + my $jobnum = ''; #don't actually care + $self->communigate_pro_queue_dep( \$jobnum, $svcnum, $method, @_); +} + +sub communigate_pro_queue_dep { + my( $self, $jobnumref, $svcnum, $method ) = splice(@_,0,4); + + my %kludge_methods = ( + #'CreateAccount' => 'CreateAccount', + 'UpdateAccountSettings' => 'UpdateAccountSettings', + 'UpdateAccountPrefs' => 'cp_Scalar_Hash', + #'CreateDomain' => 'cp_Scalar_Hash', + #'CreateSharedDomain' => 'cp_Scalar_Hash', + 'UpdateDomainSettings' => 'cp_Scalar_settingsHash', + 'SetDomainAliases' => 'cp_Scalar_Array', + 'SetAccountDefaults' => 'cp_Scalar_settingsHash', + 'UpdateAccountDefaults' => 'cp_Scalar_settingsHash', + 'SetAccountDefaultPrefs' => 'cp_Scalar_settingsHash', + 'UpdateAccountDefaultPrefs' => 'cp_Scalar_settingsHash', + ); + my $sub = exists($kludge_methods{$method}) + ? $kludge_methods{$method} : 'communigate_pro_command'; + my $queue = new FS::queue { 'svcnum' => $svcnum, 'job' => "FS::part_export::communigate_pro::$sub", }; - $queue->insert( + my $error = $queue->insert( $self->machine, $self->option('port'), $self->option('login'), @@ -93,31 +839,76 @@ sub communigate_pro_queue { $method, @_, ); + $$jobnumref = $queue->jobnum unless $error; + return $error; } -sub CreateAccount { - my( $machine, $port, $login, $password, $method, %args ) = @_; - my $accountName = delete $args{'accountName'}; - my $accountType = delete $args{'accountType'}; - my $externalFlag = delete $args{'externalFlag'}; - $args{'AccessModes'} = [ split(' ', $args{'AccessModes'}) ]; - my @args = ( accountName => $accountName, - accountType => $accountType, - settings => \%args, - ); - #externalFlag => $externalFlag, - push @args, externalFlag => $externalFlag if $externalFlag; +sub communigate_pro_runcommand { + my( $self, $method ) = (shift, shift); + + communigate_pro_command( + $self->machine, + $self->option('port'), + $self->option('login'), + $self->option('password'), + $method, + @_, + ); + +} +#XXX one sub per arg prototype is lame. more magic? i suppose queue needs +# to store data strctures properly instead of just an arg list. right. + +sub cp_Scalar_Hash { + my( $machine, $port, $login, $password, $method, $scalar, %hash ) = @_; + my @args = ( $scalar, \%hash ); + communigate_pro_command( $machine, $port, $login, $password, $method, @args ); +} + +sub cp_Scalar_Array { + my( $machine, $port, $login, $password, $method, $scalar, @array ) = @_; + my @args = ( $scalar, \@array ); communigate_pro_command( $machine, $port, $login, $password, $method, @args ); +} + +#sub cp_Hash { +# my( $machine, $port, $login, $password, $method, %hash ) = @_; +# my @args = ( \%hash ); +# communigate_pro_command( $machine, $port, $login, $password, $method, @args ); +#} +sub cp_Scalar_settingsHash { + my( $machine, $port, $login, $password, $method, $domain, %settings ) = @_; + for (qw( AccessModes DomainAccessModes )) { + $settings{$_} = [split(' ',$settings{$_})] if $settings{$_}; + } + my @args = ( 'domain' => $domain, 'settings' => \%settings ); + communigate_pro_command( $machine, $port, $login, $password, $method, @args ); } +#sub CreateAccount { +# my( $machine, $port, $login, $password, $method, %args ) = @_; +# my $accountName = delete $args{'accountName'}; +# my $accountType = delete $args{'accountType'}; +# my $externalFlag = delete $args{'externalFlag'}; +# $args{'AccessModes'} = [ split(' ', $args{'AccessModes'}) ]; +# my @args = ( accountName => $accountName, +# accountType => $accountType, +# settings => \%args, +# ); +# #externalFlag => $externalFlag, +# push @args, externalFlag => $externalFlag if $externalFlag; +# +# communigate_pro_command( $machine, $port, $login, $password, $method, @args ); +# +#} + sub UpdateAccountSettings { - my( $machine, $port, $login, $password, $method, %args ) = @_; - my $accountName = delete $args{'accountName'}; + my( $machine, $port, $login, $password, $method, $accountName, %args ) = @_; $args{'AccessModes'} = [ split(' ', $args{'AccessModes'}) ]; - @args = ( $accountName, \%args ); + my @args = ( $accountName, \%args ); communigate_pro_command( $machine, $port, $login, $password, $method, @args ); } @@ -125,6 +916,7 @@ sub communigate_pro_command { #subroutine, not method my( $machine, $port, $login, $password, $method, @args ) = @_; eval "use CGP::CLI"; + die $@ if $@; my $cli = new CGP::CLI( { 'PeerAddr' => $machine, @@ -133,8 +925,16 @@ sub communigate_pro_command { #subroutine, not method 'password' => $password, } ) or die "Can't login to CGPro: $CGP::ERR_STRING\n"; - $cli->$method(@args) or die "CGPro error: ". $cli->getErrMessage; + #warn "$method ". Dumper(@args) if $DEBUG; + + my $return = $cli->$method(@args) + or die "Communigate Pro error: ". $cli->getErrMessage. "\n"; - $cli->Logout or die "Can't logout of CGPro: $CGP::ERR_STRING\n"; + $cli->Logout; # or die "Can't logout of CGPro: $CGP::ERR_STRING\n"; + + $return; } + +1; +