package FS::part_export;
use strict;
-use vars qw( @ISA );
+use vars qw( @ISA @EXPORT_OK %exports );
+use Exporter;
+use Tie::IxHash;
use FS::Record qw( qsearch qsearchs dbh );
use FS::part_svc;
use FS::part_export_option;
+use FS::export_svc;
@ISA = qw(FS::Record);
+@EXPORT_OK = qw(export_info);
=head1 NAME
$record = new FS::part_export \%hash;
$record = new FS::part_export { 'column' => 'value' };
- ($new_record, $options) = $template_recored->clone( $svcpart );
+ #($new_record, $options) = $template_recored->clone( $svcpart );
$error = $record->insert( { 'option' => 'value' } );
$error = $record->insert( \%options );
=item exportnum - primary key
-=item svcpart - Service definition (see L<FS::part_svc>) to which this export applies
-
=item machine - Machine name
=item exporttype - Export type
sub table { 'part_export'; }
-=item clone SVCPART
-
-An alternate constructor. Creates a new export by duplicating an existing
-export. The given svcpart is assigned to the new export.
-
-Returns a list consisting of the new export object and a hashref of options.
-
=cut
-sub clone {
- my $self = shift;
- my $class = ref($self);
- my %hash = $self->hash;
- $hash{'exportnum'} = '';
- $hash{'svcpart'} = shift;
- ( $class->new( \%hash ),
- { map { $_->optionname => $_->optionvalue }
- qsearch('part_export_option', { 'exportnum' => $self->exportnum } )
- }
- );
-}
+#=item clone SVCPART
+#
+#An alternate constructor. Creates a new export by duplicating an existing
+#export. The given svcpart is assigned to the new export.
+#
+#Returns a list consisting of the new export object and a hashref of options.
+#
+#=cut
+#
+#sub clone {
+# my $self = shift;
+# my $class = ref($self);
+# my %hash = $self->hash;
+# $hash{'exportnum'} = '';
+# $hash{'svcpart'} = shift;
+# ( $class->new( \%hash ),
+# { map { $_->optionname => $_->optionvalue }
+# qsearch('part_export_option', { 'exportnum' => $self->exportnum } )
+# }
+# );
+#}
=item insert HASHREF
'';
-};
+}
=item delete
}
}
+ foreach my $export_svc ( $self->export_svc ) {
+ my $error = $export_svc->delete;
+ if ( $error ) {
+ $dbh->rollback if $oldAutoCommit;
+ return $error;
+ }
+ }
+
$dbh->commit or die $dbh->errstr if $oldAutoCommit;
'';
my $error =
$self->ut_numbern('exportnum')
|| $self->ut_domain('machine')
- || $self->ut_number('svcpart')
|| $self->ut_alpha('exporttype')
;
return $error if $error;
- return "Unknown svcpart: ". $self->svcpart
- unless qsearchs( 'part_svc', { 'svcpart' => $self->svcpart } );
-
$self->machine =~ /^([\w\-\.]*)$/
or return "Illegal machine: ". $self->machine;
$self->machine($1);
$self->nodomain =~ /^(Y?)$/ or return "Illegal nodomain: ". $self->nodomain;
$self->nodomain($1);
+ $self->deprecated(1); #BLAH
+
#check exporttype?
''; #no error
}
-=item part_svc
+#=item part_svc
+#
+#Returns the service definition (see L<FS::part_svc>) for this export.
+#
+#=cut
+#
+#sub part_svc {
+# my $self = shift;
+# qsearchs('part_svc', { svcpart => $self->svcpart } );
+#}
+
+sub part_svc {
+ use Carp;
+ croak "FS::part_export::part_svc deprecated";
+ #confess "FS::part_export::part_svc deprecated";
+}
+
+=item export_svc
-Returns the service definition (see L<FS::part_svc>) for this export.
+Returns a list of associated FS::export_svc records.
=cut
-sub part_svc {
+sub export_svc {
my $self = shift;
- qsearchs('part_svc', { svcpart => $self->svcpart } );
+ qsearch('export_svc', { 'exportnum' => $self->exportnum } );
}
=item part_export_option
sub rebless {
my $self = shift;
my $exporttype = $self->exporttype;
- my $class = ref($self);
- bless($self, $class."::$exporttype");
+ my $class = ref($self). "::$exporttype";
+ eval "use $class;";
+ die $@ if $@;
+ bless($self, $class);
}
=item export_insert SVC_OBJECT
$self->_export_delete(@_);
}
-#fallbacks providing useful error messages intead of infinite loops
-sub _export_insert {
- my $self = shift;
- return "_export_insert: unknown export type ". $self->exporttype;
-}
+=item export_suspend
-sub _export_replace {
- my $self = shift;
- return "_export_replace: unknown export type ". $self->exporttype;
-}
+=cut
-sub _export_delete {
+sub export_suspend {
my $self = shift;
- return "_export_delete: unknown export type ". $self->exporttype;
+ $self->rebless;
+ $self->_export_suspend(@_);
}
-=back
+=item export_unsuspend
=cut
-#infostreet
-
-package FS::part_export::infostreet;
-use vars qw(@ISA);
-@ISA = qw(FS::part_export);
+sub export_unsuspend {
+ my $self = shift;
+ $self->rebless;
+ $self->_export_unsuspend(@_);
+}
+#fallbacks providing useful error messages intead of infinite loops
sub _export_insert {
- my( $self, $svc_acct ) = (shift, shift);
- $self->infostreet_queue( $svc_acct->svcnum,
- 'createUser', $svc_acct->username, $svc_acct->password );
+ my $self = shift;
+ return "_export_insert: unknown export type ". $self->exporttype;
}
sub _export_replace {
- my( $self, $new, $old ) = (shift, shift, shift);
- return "can't change username with InfoStreet"
- if $old->username ne $new->username;
- return '' unless $old->_password ne $new->_password;
- $self->infostreet_queue( $new->svcnum,
- 'passwd', $new->username, $new->password );
+ my $self = shift;
+ return "_export_replace: unknown export type ". $self->exporttype;
}
sub _export_delete {
- my( $self, $svc_acct ) = (shift, shift);
- $self->infostreet_queue( $svc_acct->svcnum,
- 'purgeAccount,releaseUsername', $svc_acct->username );
-}
-
-sub infostreet_queue {
- my( $self, $svcnum, $method ) = (shift, shift, shift);
- my $queue = new FS::queue {
- 'svcnum' => $svcnum,
- 'job' => 'FS::part_export::infostreet::infostreet_command',
- };
- $queue->insert(
- $self->option('url'),
- $self->option('login'),
- $self->option('password'),
- $self->option('groupID'),
- $method,
- @_,
- );
-}
-
-sub infostreet_command { #subroutine, not method
- my($url, $username, $password, $groupID, $method, @args) = @_;
-
- #quelle hack
- if ( $method =~ /,/ ) {
- foreach my $part ( split(/,\s*/, $method) ) {
- infostreet_command($url, $username, $password, $groupID, $part, @args);
- }
- return;
- }
-
- eval "use Frontier::Client;";
-
- my $conn = Frontier::Client->new( url => $url );
- my $key_result = $conn->call( 'authenticate', $username, $password, $groupID);
- my %key_result = _infostreet_parse($key_result);
- die $key_result{error} unless $key_result{success};
- my $key = $key_result{data};
-
- my $result = $conn->call($method, $key, @args);
- my %result = _infostreet_parse($result);
- die $result{error} unless $result{success};
-
-}
-
-sub _infostreet_parse { #subroutine, not method
- my $arg = shift;
- map {
- my $value = $arg->{$_};
- #warn ref($value);
- $value = $value->value()
- if ref($value) && $value->isa('Frontier::RPC2::DataType');
- $_=>$value;
- } keys %$arg;
+ my $self = shift;
+ return "_export_delete: unknown export type ". $self->exporttype;
}
-#sqlradius
+#fallbacks providing null operations
-package FS::part_export::sqlradius;
-use vars qw(@ISA);
-@ISA = qw(FS::part_export);
-
-sub _export_insert {
- my($self, $svc_acct) = (shift, shift);
-
- foreach my $table (qw(reply check)) {
- my $method = "radius_$table";
- my %attrib = $svc_acct->$method;
- next unless keys %attrib;
- my $error = $self->sqlradius_queue( $svc_acct->svcnum, 'insert',
- $table, $svc_acct->username, %attrib );
- return $error if $error;
- }
- my @groups = $svc_acct->radius_groups;
- if ( @groups ) {
- my $error = $self->sqlradius_queue( $svc_acct->svcnum, 'usergroup_insert',
- $svc_acct->username, @groups );
- return $error if $error;
- }
+sub _export_suspend {
+ my $self = shift;
+ #warn "warning: _export_suspened unimplemented for". ref($self);
'';
}
-sub _export_replace {
- my( $self, $new, $old ) = (shift, shift, shift);
-
- #return "can't (yet) change username with sqlradius"
- # if $old->username ne $new->username;
- if ( $old->username ne $new->username ) {
- my $error = $self->sqlradius_queue( $new->svcnum, 'rename',
- $new->username, $old->username );
- return $error if $error;
- }
-
- foreach my $table (qw(reply check)) {
- my $method = "radius_$table";
- my %new = $new->$method;
- my %old = $old->$method;
- if ( grep { !exists $old{$_} #new attributes
- || $new{$_} ne $old{$_} #changed
- } keys %new
- ) {
- my $error = $self->sqlradius_queue( $new->svcnum, 'insert',
- $table, $new->username, %new );
- return $error if $error;
- }
-
- my @del = grep { !exists $new{$_} } keys %old;
- if ( @del ) {
- my $error = $self->sqlradius_queue( $new->svcnum, 'attrib_delete',
- $table, $new->username, @del );
- return $error if $error;
- }
- }
-
- # (sorta) false laziness with FS::svc_acct::replace
- my @oldgroups = @{$old->usergroup}; #uuuh
- my @newgroups = $new->radius_groups;
- my @delgroups = ();
- foreach my $oldgroup ( @oldgroups ) {
- if ( grep { $oldgroup eq $_ } @newgroups ) {
- @newgroups = grep { $oldgroup ne $_ } @newgroups;
- next;
- }
- push @delgroups, $oldgroup;
- }
-
- if ( @delgroups ) {
- my $error = $self->sqlradius_queue( $new->svcnum, 'usergroup_delete',
- $new->username, @delgroups );
- return $error if $error;
- }
-
- if ( @newgroups ) {
- my $error = $self->sqlradius_queue( $new->svcnum, 'usergroup_insert',
- $new->username, @newgroups );
- return $error if $error;
- }
-
+sub _export_unsuspend {
+ my $self = shift;
+ #warn "warning: _export_unsuspend unimplemented for ". ref($self);
'';
}
-sub _export_delete {
- my( $self, $svc_acct ) = (shift, shift);
- $self->sqlradius_queue( $svc_acct->svcnum, 'delete',
- $svc_acct->username );
-}
-
-sub sqlradius_queue {
- my( $self, $svcnum, $method ) = (shift, shift, shift);
- my $queue = new FS::queue {
- 'svcnum' => $svcnum,
- 'job' => "FS::part_export::sqlradius::sqlradius_$method",
- };
- $queue->insert(
- $self->option('datasrc'),
- $self->option('username'),
- $self->option('password'),
- @_,
- );
-}
-
-sub sqlradius_insert { #subroutine, not method
- my $dbh = sqlradius_connect(shift, shift, shift);
- my( $replycheck, $username, %attributes ) = @_;
-
- foreach my $attribute ( keys %attributes ) {
- my $u_sth = $dbh->prepare(
- "UPDATE rad$replycheck SET Value = ? WHERE UserName = ? AND Attribute = ?" ) or die $dbh->errstr;
- my $i_sth = $dbh->prepare(
- "INSERT INTO rad$replycheck ( id, UserName, Attribute, Value ) ".
- "VALUES ( ?, ?, ?, ? )"
- ) or die $dbh->errstr;
- $u_sth->execute($attributes{$attribute}, $username, $attribute) > 0
- or $i_sth->execute( '', $username, $attribute, $attributes{$attribute} )
- or die "can't insert into rad$replycheck table: ". $i_sth->errstr;
- }
- $dbh->disconnect;
-}
+=back
-sub sqlradius_usergroup_insert { #subroutine, not method
- my $dbh = sqlradius_connect(shift, shift, shift);
- my( $username, @groups ) = @_;
+=head1 SUBROUTINES
- my $sth = $dbh->prepare(
- "INSERT INTO usergroup ( id, UserName, GroupName ) VALUES ( ?, ?, ? )"
- ) or die $dbh->errstr;
- foreach my $group ( @groups ) {
- $sth->execute( '', $username, $group )
- or die "can't insert into groupname table: ". $sth->errstr;
- }
- $dbh->disconnect;
-}
+=over 4
-sub sqlradius_usergroup_delete { #subroutine, not method
- my $dbh = sqlradius_connect(shift, shift, shift);
- my( $username, @groups ) = @_;
+=item export_info [ SVCDB ]
- my $sth = $dbh->prepare(
- "DELETE FROM usergroup ( id, UserName, GroupName ) VALUES ( ?, ?, ? )"
- ) or die $dbh->errstr;
- foreach my $group ( @groups ) {
- $sth->execute( '', $username, $group )
- or die "can't delete from groupname table: ". $sth->errstr;
- }
- $dbh->disconnect;
-}
+Returns a hash reference of the exports for the given I<svcdb>, or if no
+I<svcdb> is specified, for all exports. The keys of the hash are
+I<exporttype>s and the values are again hash references containing information
+on the export:
-sub sqlradius_rename { #subroutine, not method
- my $dbh = sqlradius_connect(shift, shift, shift);
- my($new_username, $old_username) = @_;
- foreach my $table (qw(radreply radcheck usergroup )) {
- my $sth = $dbh->prepare("UPDATE $table SET Username = ? WHERE UserName = ?")
- or die $dbh->errstr;
- $sth->execute($new_username, $old_username)
- or die "can't update $table: ". $sth->errstr;
- }
- $dbh->disconnect;
-}
+ 'desc' => 'Description',
+ 'options' => {
+ 'option' => { label=>'Option Label' },
+ 'option2' => { label=>'Another label' },
+ },
+ 'nodomain' => 'Y', #or ''
+ 'notes' => 'Additional notes',
-sub sqlradius_attrib_delete { #subroutine, not method
- my $dbh = sqlradius_connect(shift, shift, shift);
- my( $replycheck, $username, @attrib ) = @_;
+=cut
- foreach my $attribute ( @attrib ) {
- my $sth = $dbh->prepare(
- "DELETE FROM rad$replycheck WHERE UserName = ? AND Attribute = ?" )
- or die $dbh->errstr;
- $sth->execute($username,$attribute)
- or die "can't delete from rad$replycheck table: ". $sth->errstr;
- }
- $dbh->disconnect;
+sub export_info {
+ #warn $_[0];
+ return $exports{$_[0]} if @_;
+ #{ map { %{$exports{$_}} } keys %exports };
+ my $r = { map { %{$exports{$_}} } keys %exports };
}
-sub sqlradius_delete { #subroutine, not method
- my $dbh = sqlradius_connect(shift, shift, shift);
- my $username = shift;
+#=item exporttype2svcdb EXPORTTYPE
+#
+#Returns the applicable I<svcdb> for an I<exporttype>.
+#
+#=cut
+#
+#sub exporttype2svcdb {
+# my $exporttype = $_[0];
+# foreach my $svcdb ( keys %exports ) {
+# return $svcdb if grep { $exporttype eq $_ } keys %{$exports{$svcdb}};
+# }
+# '';
+#}
- foreach my $table (qw( radcheck radreply usergroup )) {
- my $sth = $dbh->prepare( "DELETE FROM $table WHERE UserName = ?" );
- $sth->execute($username)
- or die "can't delete from $table table: ". $sth->errstr;
- }
- $dbh->disconnect;
-}
+tie my %sysvshell_options, 'Tie::IxHash',
+ 'crypt' => { label=>'Password encryption',
+ type=>'select', options=>[qw(crypt md5)],
+ default=>'crypt',
+ },
+;
+
+tie my %bsdshell_options, 'Tie::IxHash',
+ 'crypt' => { label=>'Password encryption',
+ type=>'select', options=>[qw(crypt md5)],
+ default=>'crypt',
+ },
+;
+
+tie my %shellcommands_options, 'Tie::IxHash',
+ #'machine' => { label=>'Remote machine' },
+ 'user' => { label=>'Remote username', default=>'root' },
+ 'useradd' => { label=>'Insert command',
+ default=>'useradd -d $dir -m -s $shell -u $uid -p $crypt_password $username'
+ #default=>'cp -pr /etc/skel $dir; chown -R $uid.$gid $dir'
+ },
+ 'useradd_stdin' => { label=>'Insert command STDIN',
+ type =>'textarea',
+ default=>'',
+ },
+ 'userdel' => { label=>'Delete command',
+ default=>'userdel -r $username',
+ #default=>'rm -rf $dir',
+ },
+ 'userdel_stdin' => { label=>'Delete command STDIN',
+ type =>'textarea',
+ default=>'',
+ },
+ 'usermod' => { label=>'Modify command',
+ default=>'usermod -d $new_dir -m -l $new_username -s $new_shell -u $new_uid -p $new_crypt_password $old_username',
+ #default=>'[ -d $old_dir ] && mv $old_dir $new_dir || ( '.
+ # 'chmod u+t $old_dir; mkdir $new_dir; cd $old_dir; '.
+ # 'find . -depth -print | cpio -pdm $new_dir; '.
+ # 'chmod u-t $new_dir; chown -R $uid.$gid $new_dir; '.
+ # 'rm -rf $old_dir'.
+ #')'
+ },
+ 'usermod_stdin' => { label=>'Modify command STDIN',
+ type =>'textarea',
+ default=>'',
+ },
+ 'suspend' => { label=>'Suspension command',
+ default=>'',
+ },
+ 'suspend_stdin' => { label=>'Suspension command STDIN',
+ default=>'',
+ },
+ 'unsuspend' => { label=>'Unsuspension command',
+ default=>'',
+ },
+ 'unsuspend_stdin' => { label=>'Unsuspension command STDIN',
+ default=>'',
+ },
+;
+
+tie my %shellcommands_withdomain_options, 'Tie::IxHash',
+ 'user' => { label=>'Remote username', default=>'root' },
+ 'useradd' => { label=>'Insert command',
+ #default=>''
+ },
+ 'useradd_stdin' => { label=>'Insert command STDIN',
+ type =>'textarea',
+ #default=>"$_password\n$_password\n",
+ },
+ 'userdel' => { label=>'Delete command',
+ #default=>'',
+ },
+ 'userdel_stdin' => { label=>'Delete command STDIN',
+ type =>'textarea',
+ #default=>'',
+ },
+ 'usermod' => { label=>'Modify command',
+ default=>'',
+ },
+ 'usermod_stdin' => { label=>'Modify command STDIN',
+ type =>'textarea',
+ #default=>"$_password\n$_password\n",
+ },
+ 'suspend' => { label=>'Suspension command',
+ default=>'',
+ },
+ 'suspend_stdin' => { label=>'Suspension command STDIN',
+ default=>'',
+ },
+ 'unsuspend' => { label=>'Unsuspension command',
+ default=>'',
+ },
+ 'unsuspend_stdin' => { label=>'Unsuspension command STDIN',
+ default=>'',
+ },
+;
+
+tie my %www_shellcommands_options, 'Tie::IxHash',
+ 'user' => { lable=>'Remote username', default=>'root' },
+ 'useradd' => { label=>'Insert command',
+ default=>'mkdir /var/www/$zone; chown $username /var/www/$zone; ln -s /var/www/$zone $homedir/$zone',
+ },
+ 'userdel' => { label=>'Delete command',
+ default=>'[ -n "$zone" ] && rm -rf /var/www/$zone; rm $homedir/$zone',
+ },
+ 'usermod' => { label=>'Modify command',
+ default=>'[ -n "$old_zone" ] && rm $old_homedir/$old_zone; [ "$old_zone" != "$new_zone" -a -n "$new_zone" ] && mv /var/www/$old_zone /var/www/$new_zone; [ "$old_username" != "$new_username" ] && chown -R $new_username /var/www/$new_zone; ln -s /var/www/$new_zone $new_homedir/$new_zone',
+ },
+;
+
+tie my %domain_shellcommands_options, 'Tie::IxHash',
+ 'user' => { lable=>'Remote username', default=>'root' },
+ 'useradd' => { label=>'Insert command',
+ default=>'',
+ },
+ 'userdel' => { label=>'Delete command',
+ default=>'',
+ },
+ 'usermod' => { label=>'Modify command',
+ default=>'',
+ },
+;
+
+tie my %textradius_options, 'Tie::IxHash',
+ 'user' => { label=>'Remote username', default=>'root' },
+ 'users' => { label=>'users file location', default=>'/etc/raddb/users' },
+;
+
+tie my %sqlradius_options, 'Tie::IxHash',
+ 'datasrc' => { label=>'DBI data source ' },
+ 'username' => { label=>'Database username' },
+ 'password' => { label=>'Database password' },
+;
+
+tie my %cyrus_options, 'Tie::IxHash',
+ 'server' => { label=>'IMAP server' },
+ 'username' => { label=>'Admin username' },
+ 'password' => { label=>'Admin password' },
+;
+
+tie my %cp_options, 'Tie::IxHash',
+ 'host' => { label=>'Hostname' },
+ 'port' => { label=>'Port number' },
+ 'username' => { label=>'Username' },
+ 'password' => { label=>'Password' },
+ 'domain' => { label=>'Domain' },
+ 'workgroup' => { label=>'Default Workgroup' },
+;
+
+tie my %infostreet_options, 'Tie::IxHash',
+ 'url' => { label=>'XML-RPC Access URL', },
+ 'login' => { label=>'InfoStreet login', },
+ 'password' => { label=>'InfoStreet password', },
+ 'groupID' => { label=>'InfoStreet groupID', },
+;
+
+tie my %vpopmail_options, 'Tie::IxHash',
+ #'machine' => { label=>'vpopmail machine', },
+ 'dir' => { label=>'directory', }, # ?more info? default?
+ 'uid' => { label=>'vpopmail uid' },
+ 'gid' => { label=>'vpopmail gid' },
+ 'restart' => { label=> 'vpopmail restart command',
+ default=> 'cd /home/vpopmail/domains; for domain in *; do /home/vpopmail/bin/vmkpasswd $domain; done; /var/qmail/bin/qmail-newu; killall -HUP qmail-send',
+ },
+;
+
+tie my %bind_options, 'Tie::IxHash',
+ #'machine' => { label=>'named machine' },
+ 'named_conf' => { label => 'named.conf location',
+ default=> '/etc/bind/named.conf' },
+ 'zonepath' => { label => 'path to zone files',
+ default=> '/etc/bind/', },
+;
+
+tie my %bind_slave_options, 'Tie::IxHash',
+ #'machine' => { label=> 'Slave machine' },
+ 'master' => { label=> 'Master IP address(s) (semicolon-separated)' },
+ 'named_conf' => { label => 'named.conf location',
+ default => '/etc/bind/named.conf' },
+;
+
+tie my %http_options, 'Tie::IxHash',
+ 'method' => { label =>'Method',
+ type =>'select',
+ #options =>[qw(POST GET)],
+ options =>[qw(POST)],
+ default =>'POST' },
+ 'url' => { label => 'URL', default => 'http://', },
+ 'insert_data' => {
+ label => 'Insert data',
+ type => 'textarea',
+ default => join("\n",
+ 'DomainName $svc_x->domain',
+ 'Email ( grep { $_ ne "POST" } $svc_x->cust_svc->cust_pkg->cust_main->invoicing_list)[0]',
+ 'test 1',
+ 'reseller $svc_x->cust_svc->cust_pkg->part_pkg->pkg =~ /reseller/i',
+ ),
+ },
+ 'delete_data' => {
+ label => 'Delete data',
+ type => 'textarea',
+ default => join("\n",
+ ),
+ },
+ 'replace_data' => {
+ label => 'Replace data',
+ type => 'textarea',
+ default => join("\n",
+ ),
+ },
+;
+
+tie my %sqlmail_options, 'Tie::IxHash',
+ 'datasrc' => { label=>'DBI data source' },
+ 'username' => { label=>'Database username' },
+ 'password' => { label=>'Database password' },
+;
+
+tie my %ldap_options, 'Tie::IxHash',
+ 'dn' => { label=>'Root DN' },
+ 'password' => { label=>'Root DN password' },
+ 'userdn' => { label=>'User DN' },
+ 'attributes' => { label=>'Attributes',
+ type=>'textarea',
+ default=>join("\n",
+ 'uid $username',
+ 'mail $username\@$domain',
+ 'uidno $uid',
+ 'gidno $gid',
+ 'cn $first',
+ 'sn $last',
+ 'mailquota $quota',
+ 'vmail',
+ 'location',
+ 'mailtag',
+ 'mailhost',
+ 'mailmessagestore $dir',
+ 'userpassword $crypt_password',
+ 'hint',
+ 'answer $sec_phrase',
+ 'objectclass top,person,inetOrgPerson',
+ ),
+ },
+ 'radius' => { label=>'Export RADIUS attributes', type=>'checkbox', },
+;
+
+
+#export names cannot have dashes...
+%exports = (
+ 'svc_acct' => {
+ 'sysvshell' => {
+ 'desc' =>
+ 'Batch export of /etc/passwd and /etc/shadow files (Linux/SysV).',
+ 'options' => \%sysvshell_options,
+ 'nodomain' => 'Y',
+ 'notes' => 'MD5 crypt requires installation of <a href="http://search.cpan.org/search?dist=Crypt-PasswdMD5">Crypt::PasswdMD5</a> from CPAN. Run bin/sysvshell.export to export the files.',
+ },
+ 'bsdshell' => {
+ 'desc' =>
+ 'Batch export of /etc/passwd and /etc/master.passwd files (BSD).',
+ 'options' => \%bsdshell_options,
+ 'nodomain' => 'Y',
+ 'notes' => 'MD5 crypt requires installation of <a href="http://search.cpan.org/search?dist=Crypt-PasswdMD5">Crypt::PasswdMD5</a> from CPAN. Run bin/bsdshell.export to export the files.',
+ },
+# 'nis' => {
+# 'desc' =>
+# 'Batch export of /etc/global/passwd and /etc/global/shadow for NIS ',
+# 'options' => {},
+# },
+ 'textradius' => {
+ 'desc' => 'Real-time export to a text /etc/raddb/users file (Livingston, Cistron)',
+ 'options' => \%textradius_options,
+ 'notes' => 'This will edit a text RADIUS users file in place on a remote server. Requires installation of <a href="http://search.cpan.org/search?dist=RADIUS-UserFile">RADIUS::UserFile</a> from CPAN. If using RADIUS::UserFile 1.01, make sure to apply <a href="http://rt.cpan.org/NoAuth/Bug.html?id=1210">this patch</a>. Also make sure <a href="http://rsync.samba.org/">rsync</a> is installed on the remote machine, and <a href="../docs/ssh.html">SSH is setup for unattended operation</a>.',
+ },
+
+ 'shellcommands' => {
+ 'desc' => 'Real-time export via remote SSH (i.e. useradd, userdel, etc.)',
+ 'options' => \%shellcommands_options,
+ 'nodomain' => 'Y',
+ 'notes' => 'Run remote commands via SSH. Usernames are considered unique (also see shellcommands_withdomain). You probably want this if the commands you are running will not accept a domain as a parameter. You will need to <a href="../docs/ssh.html">setup SSH for unattended operation</a>.<BR><BR>Use these buttons for some useful presets:<UL><LI><INPUT TYPE="button" VALUE="Linux/NetBSD" onClick=\'this.form.useradd.value = "useradd -c $finger -d $dir -m -s $shell -u $uid -p $crypt_password $username"; this.form.useradd_stdin.value = ""; this.form.userdel.value = "userdel -r $username"; this.form.userdel_stdin.value=""; this.form.usermod.value = "usermod -c $new_finger -d $new_dir -m -l $new_username -s $new_shell -u $new_uid -p $new_crypt_password $old_username"; this.form.usermod_stdin.value = "";\'><LI><INPUT TYPE="button" VALUE="FreeBSD" onClick=\'this.form.useradd.value = "pw useradd $username -d $dir -m -s $shell -u $uid -g $gid -c $finger -h 0"; this.form.useradd_stdin.value = "$_password\n"; this.form.userdel.value = "pw userdel $username -r"; this.form.userdel_stdin.value=""; this.form.usermod.value = "pw usermod $old_username -d $new_dir -m -l $new_username -s $new_shell -u $new_uid -c $new_finger -h 0"; this.form.usermod_stdin.value = "$new__password\n";\'><LI><INPUT TYPE="button" VALUE="Just maintain directories (use with sysvshell or bsdshell)" onClick=\'this.form.useradd.value = "cp -pr /etc/skel $dir; chown -R $uid.$gid $dir"; this.form.useradd_stdin.value = ""; this.form.usermod.value = "[ -d $old_dir ] && mv $old_dir $new_dir || ( chmod u+t $old_dir; mkdir $new_dir; cd $old_dir; find . -depth -print | cpio -pdm $new_dir; chmod u-t $new_dir; chown -R $uid.$gid $new_dir; rm -rf $old_dir )"; this.form.usermod_stdin.value = ""; this.form.userdel.value = "rm -rf $dir"; this.form.userdel_stdin.value="";\'></UL>',
+ },
+
+ 'shellcommands_withdomain' => {
+ 'desc' => 'Real-time export via remote SSH.',
+ 'options' => \%shellcommands_withdomain_options,
+ 'notes' => 'Run remote commands via SSH. username@domain (rather than just usernames) are considered unique (also see shellcommands). You probably want this if the commands you are running will accept a domain as a parameter, and will allow the same username with different domains. You will need to <a href="../docs/ssh.html">setup SSH for unattended operation</a>.',
+ },
+
+ 'ldap' => {
+ 'desc' => 'Real-time export to LDAP',
+ 'options' => \%ldap_options,
+ 'notes' => 'Real-time export to arbitrary LDAP attributes. Requires installation of <a href="http://search.cpan.org/search?dist=Net-LDAP">Net::LDAP</a> from CPAN.',
+ },
+
+ 'sqlradius' => {
+ 'desc' => 'Real-time export to SQL-backed RADIUS (ICRADIUS, FreeRADIUS)',
+ 'options' => \%sqlradius_options,
+ 'nodomain' => 'Y',
+ 'notes' => 'Real-time export of radcheck, radreply and usergroup tables to any SQL database for <a href="http://www.freeradius.org/">FreeRADIUS</a> or <a href="http://radius.innercite.com/">ICRADIUS</a>. An existing RADIUS database will be updated in realtime, but you can use <a href="../docs/man/bin/freeside-sqlradius-reset">freeside-sqlradius-reset</a> to delete the entire RADIUS database and repopulate the tables from the Freeside database. See the <a href="http://search.cpan.org/doc/TIMB/DBI-1.23/DBI.pm">DBI documentation</a> and the <a href="http://search.cpan.org/search?mode=module&query=DBD%3A%3A">documentation for your DBD</a> for the exact syntax of a DBI data source. If using <a href="http://www.freeradius.org/">FreeRADIUS</a> 0.5 or above, make sure your <b>op</b> fields are set to allow NULL values.',
+ },
+
+ 'sqlmail' => {
+ 'desc' => 'Real-time export to SQL-backed mail server',
+ 'options' => \%sqlmail_options,
+ 'nodomain' => 'Y',
+ 'notes' => 'Database schema can be made to work with Courier IMAP and Exim. Others could work but are untested. (...extended description from pc-intouch?...)',
+ },
+
+ 'cyrus' => {
+ 'desc' => 'Real-time export to Cyrus IMAP server',
+ 'options' => \%cyrus_options,
+ 'nodomain' => 'Y',
+ 'notes' => 'Integration with <a href="http://asg.web.cmu.edu/cyrus/imapd/">Cyrus IMAP Server</a>. Cyrus::IMAP::Admin should be installed locally and the connection to the server secured. <B>svc_acct.quota</B>, if available, is used to set the Cyrus quota. '
+ },
+
+ 'cp' => {
+ 'desc' => 'Real-time export to Critical Path Account Provisioning Protocol',
+ 'options' => \%cp_options,
+ 'notes' => 'Real-time export to <a href="http://www.cp.net/">Critial Path Account Provisioning Protocol</a>. Requires installation of <a href="http://search.cpan.org/search?dist=Net-APP">Net::APP</a> from CPAN.',
+ },
+
+ 'infostreet' => {
+ 'desc' => 'Real-time export to InfoStreet streetSmartAPI',
+ 'options' => \%infostreet_options,
+ 'nodomain' => 'Y',
+ 'notes' => 'Real-time export to <a href="http://www.infostreet.com/">InfoStreet</a> streetSmartAPI. Requires installation of <a href="http://search.cpan.org/search?dist=Frontier-Client">Frontier::Client</a> from CPAN.',
+ },
+
+ 'vpopmail' => {
+ 'desc' => 'Real-time export to vpopmail text files',
+ 'options' => \%vpopmail_options,
+ 'notes' => 'Real time export to <a href="http://inter7.com/vpopmail/">vpopmail</a> text files. <a href="http://search.cpan.org/search?dist=File-Rsync">File::Rsync</a> must be installed, and you will need to <a href="../docs/ssh.html">setup SSH for unattended operation</a> to <b>vpopmail</b>@<i>export.host</i>.',
+ },
+
+ },
+
+ 'svc_domain' => {
+
+ 'bind' => {
+ 'desc' =>'Batch export to BIND named',
+ 'options' => \%bind_options,
+ 'notes' => 'Batch export of BIND zone and configuration files to primary nameserver. <a href="http://search.cpan.org/search?dist=File-Rsync">File::Rsync</a> must be installed. Run bin/bind.export to export the files.',
+ },
+
+ 'bind_slave' => {
+ 'desc' =>'Batch export to slave BIND named',
+ 'options' => \%bind_slave_options,
+ 'notes' => 'Batch export of BIND configuration file to a secondary nameserver. Zones are slaved from the listed masters. <a href="http://search.cpan.org/search?dist=File-Rsync">File::Rsync</a> must be installed. Run bin/bind.export to export the files.',
+ },
+
+ 'http' => {
+ 'desc' => 'Send an HTTP or HTTPS GET or POST request',
+ 'options' => \%http_options,
+ 'notes' => 'Send an HTTP or HTTPS GET or POST to the specified URL. <a href="http://search.cpan.org/search?dist=libwww-perl">libwww-perl</a> must be installed. For HTTPS support, <a href="http://search.cpan.org/search?dist=Crypt-SSLeay">Crypt::SSLeay</a> or <a href="http://search.cpan.org/search?dist=IO-Socket-SSL">IO::Socket::SSL</a> is required.',
+ },
+
+ 'sqlmail' => {
+ 'desc' => 'Real-time export to SQL-backed mail server',
+ 'options' => \%sqlmail_options,
+ #'nodomain' => 'Y',
+ 'notes' => 'Database schema can be made to work with Courier IMAP and Exim. Others could work but are untested. (...extended description from pc-intouch?...)',
+ },
+
+ 'domain_shellcommands' => {
+ 'desc' => 'Run remote commands via SSH, for domains.',
+ 'options' => \%domain_shellcommands_options,
+ 'notes' => 'Run remote commands via SSH, for domains. You will need to <a href="../docs/ssh.html">setup SSH for unattended operation</a>.',
+ },
+
+
+ },
+
+ 'svc_forward' => {
+ 'sqlmail' => {
+ 'desc' => 'Real-time export to SQL-backed mail server',
+ 'options' => \%sqlmail_options,
+ #'nodomain' => 'Y',
+ 'notes' => 'Database schema can be made to work with Courier IMAP and Exim. Others could work but are untested. (...extended description from pc-intouch?...)',
+ },
+ },
+
+ 'svc_www' => {
+ 'www_shellcommands' => {
+ 'desc' => 'Run remote commands via SSH, for virtual web sites.',
+ 'options' => \%www_shellcommands_options,
+ 'notes' => 'Run remote commands via SSH, for virtual web sites. You will need to <a href="../docs/ssh.html">setup SSH for unattended operation</a>.',
+ },
+
+ },
+
+ 'svc_broadband' => {
+ },
+
+);
-sub sqlradius_connect {
- #my($datasrc, $username, $password) = @_;
- #DBI->connect($datasrc, $username, $password) or die $DBI::errstr;
- DBI->connect(@_) or die $DBI::errstr;
-}
+=back
=head1 NEW EXPORT CLASSES
- #myexport
-
- package FS::part_export::myexport;
- use vars qw(@ISA);
- @ISA = qw(FS::part_export);
-
- sub _export_insert {
- my($self, $svc_something) = (shift, shift);
- $self->myexport_queue( $svc_acct->svcnum, 'insert',
- $svc_something->username, $svc_something->password );
- }
-
- sub _export_replace {
- my( $self, $new, $old ) = (shift, shift, shift);
- #return "can't change username with myexport"
- # if $old->username ne $new->username;
- #return '' unless $old->_password ne $new->_password;
- $self->myexport_queue( $new->svcnum,
- 'replace', $new->username, $new->password );
- }
-
- sub _export_delete {
- my( $self, $svc_something ) = (shift, shift);
- $self->myexport_queue( $svc_acct->svcnum,
- 'delete', $svc_something->username );
- }
-
- #a good idea to queue anything that could fail or take any time
- sub myexport_queue {
- my( $self, $svcnum, $method ) = (shift, shift, shift);
- my $queue = new FS::queue {
- 'svcnum' => $svcnum,
- 'job' => "FS::part_export::myexport::myexport_$method",
- };
- $queue->insert( @_ );
- }
-
- sub myexport_insert { #subroutine, not method
- }
- sub myexport_replace { #subroutine, not method
- }
- sub myexport_delete { #subroutine, not method
- }
+Should be added to the %export hash here, and a module should be added in
+FS/FS/part_export/ (an example may be found in eg/export_template.pm)
=head1 BUGS
-Probably.
+All the stuff in the %exports hash should be generated from the specific
+export modules.
+
+Hmm... cust_export class (not necessarily a database table...) ... ?
-Hmm, export code has wound up in here. Move those sub-classes out into their
-own files, at least. Also hmm... cust_export class (not necessarily a
-database table...) ... ?
+deprecated column...
=head1 SEE ALSO
-L<FS::part_export_option>, L<FS::part_svc>, L<FS::svc_acct>, L<FS::svc_domain>,
+L<FS::part_export_option>, L<FS::export_svc>, L<FS::svc_acct>,
+L<FS::svc_domain>,
L<FS::svc_forward>, L<FS::Record>, schema.html from the base documentation.
=cut