From: ivan useradd -d $dir -m -s $shell -u $uid $username
is the default. If this option is set but empty, cp -pr /etc/skel $dir; chown -R $uid.$gid $dir
is the default instead. Otherwise the value is evaluated as a double-quoted perl string, with the following variables available: $username
, $uid
, $gid
, $dir
, and $shell
.',
+ 'section' => 'deprecated',
+ 'description' => 'DEPRECATED, add a cp export instead. This option used to contain command(s) to run on shellmachine when an account is created. If the shellmachine option is set but this option is not, useradd -d $dir -m -s $shell -u $uid $username
is the default. If this option is set but empty, cp -pr /etc/skel $dir; chown -R $uid.$gid $dir
is the default instead. Otherwise the value is evaluated as a double-quoted perl string, with the following variables available: $username
, $uid
, $gid
, $dir
, and $shell
.',
'type' => [qw( checkbox text )],
},
{
'key' => 'shellmachine-userdel',
- 'section' => 'shell',
- 'description' => 'The command(s) to run on shellmachine when an account is deleted. If the shellmachine option is set but this option is not, userdel $username
is the default. If this option is set but empty, rm -rf $dir
is the default instead. Otherwise the value is evaluated as a double-quoted perl string, with the following variables available: $username
and $dir
.',
+ 'section' => 'deprecated',
+ 'description' => 'DEPRECATED, add a cp export instead. This option used to contain command(s) to run on shellmachine when an account is deleted. If the shellmachine option is set but this option is not, userdel $username
is the default. If this option is set but empty, rm -rf $dir
is the default instead. Otherwise the value is evaluated as a double-quoted perl string, with the following variables available: $username
and $dir
.',
'type' => [qw( checkbox text )],
},
{
'key' => 'shellmachine-usermod',
- 'section' => 'shell',
- 'description' => 'The command(s) to run on shellmachine when an account is modified. If the shellmachine option is set but this option is empty, [ -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 )
is the default. Otherwise the contents of the file are treated as a double-quoted perl string, with the following variables available: $old_dir
, $new_dir
, $uid
and $gid
.',
+ 'section' => 'deprecated',
+ 'description' => 'DEPRECATED, add a cp export instead. This option used to contain command(s) to run on shellmachine when an account is modified. If the shellmachine option is set but this option is empty, [ -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 )
is the default. Otherwise the contents of the file are treated as a double-quoted perl string, with the following variables available: $old_dir
, $new_dir
, $uid
and $gid
.',
#'type' => [qw( checkbox text )],
'type' => 'text',
},
diff --git a/FS/FS/part_export.pm b/FS/FS/part_export.pm
index 7ae00f00c..82503c4ee 100644
--- a/FS/FS/part_export.pm
+++ b/FS/FS/part_export.pm
@@ -489,14 +489,37 @@ sub exporttype2svcdb {
# 'Batch export of /etc/global/passwd and /etc/global/shadow for NIS ',
# 'options' => {},
# },
- 'bsdshell' => {
- 'desc' =>
- 'Batch export of /etc/passwd and /etc/master.passwd files (BSD)',
- 'options' => {},
- },
'textradius' => {
'desc' => 'Batch export of a text /etc/raddb/users file (Livingston, Cistron)',
},
+
+ 'shellcommands' => {
+ 'desc' => 'Real-time export via arbitrary commands on a remote machine (i.e. useradd, userdel, etc.)',
+ 'options' => {
+ 'machine' => { label=>'Remote machine' },
+ 'user' => { label=>'Remote username', default=>'root' },
+ 'useradd' => { label=>'Insert command',
+ default=>'useradd -d $dir -m -s $shell -u $uid $username'
+ #default=>'cp -pr /etc/skel $dir; chown -R $uid.$gid $dir'
+ },
+ 'userdel' => { label=>'Delete command',
+ default=>'userdel $username',
+ #default=>'rm -rf $dir',
+ },
+ 'usermod' => { label=>'Modify command',
+ default=>'usermod -d $new_dir -l $new_username -s $new_shell -u $new_uid $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'.
+ #')'
+ },
+ },
+ 'nodomain' => 'Y',
+ 'notes' => 'shellcommandsnotes... (this one is the nodomain one)',
+ },
+
'sqlradius' => {
'desc' => 'Real-time export to SQL-backed RADIUS (ICRADIUS, FreeRADIUS)',
'options' => {
@@ -507,9 +530,18 @@ sub exporttype2svcdb {
'nodomain' => 'Y',
'notes' => 'Real-time export of radcheck, radreply and usergroup tables to any SQL database for FreeRADIUS or ICRADIUS. Use freeside-sqlradius-reset to delete and repopulate the tables from the Freeside database.',
},
+
'cyrus' => {
'desc' => 'Real-time export to Cyrus IMAP server',
+ 'options' => {
+ 'server' => { label=>'IMAP server' },
+ 'username' => { label=>'Admin username' },
+ 'password' => { label=>'Admin password' },
+ },
+ 'nodomain' => 'Y',
+ 'notes' => 'Integration with Cyrus IMAP Server. Cyrus::IMAP::Admin should be installed locally and the connection to the server secured. svc_acct.quota is used to set the Cyrus quota if available. '
},
+
'cp' => {
'desc' => 'Real-time export to Critical Path Account Provisioning Protocol',
'options' => {
@@ -522,6 +554,7 @@ sub exporttype2svcdb {
},
'notes' => 'Real-time export to Critial Path Account Provisioning Protocol. Requires installation of Net::APP from CPAN.',
},
+
'infostreet' => {
'desc' => 'Real-time export to InfoStreet streetSmartAPI',
'options' => {
@@ -532,7 +565,8 @@ sub exporttype2svcdb {
},
'nodomain' => 'Y',
'notes' => 'Real-time export to InfoStreet streetSmartAPI. Requires installation of Frontier::Client from CPAN.',
- }
+ },
+
},
'svc_domain' => {},
diff --git a/FS/FS/part_export/cp.pm b/FS/FS/part_export/cp.pm
index 58ac85e8a..d998c1d95 100644
--- a/FS/FS/part_export/cp.pm
+++ b/FS/FS/part_export/cp.pm
@@ -69,22 +69,17 @@ sub cp_command { #subroutine, not method
);
}
+ my $other = 'F';
if ( $new_password =~ /^\*SUSPENDED\* (.*)$/ ) {
$new_password = $1;
- cp_command($host, $port, $username, $password, 'set_mailbox_status',
- Domain => $domain,
- Mailbox => $new_username,
- Other => 'T',
- Other_Bounce => 'T',
- );
- } else {
- cp_command($host, $port, $username, $password, 'set_mailbox_status',
- Domain => $domain,
- Mailbox => $new_username,
- Other => 'F',
- Other_Bounce => 'F',
- );
+ $other = 'T';
}
+ cp_command($host, $port, $username, $password, 'set_mailbox_status',
+ Domain => $domain,
+ Mailbox => $new_username,
+ Other => $other,
+ Other_Bounce => $other,
+ );
if ( $old_password ne $new_password ) {
cp_command($host, $port, $username, $password, 'change_mailbox',
diff --git a/FS/FS/part_export/cyrus.pm b/FS/FS/part_export/cyrus.pm
new file mode 100644
index 000000000..110ff198f
--- /dev/null
+++ b/FS/FS/part_export/cyrus.pm
@@ -0,0 +1,98 @@
+package FS::part_export::cyrus;
+
+use vars qw(@ISA);
+use FS::part_export;
+
+@ISA = qw(FS::part_export);
+
+sub rebless { shift; }
+
+sub _export_insert {
+ my($self, $svc_acct) = (shift, shift);
+ $self->cyrus_queue( $svc_acct->svcnum, 'insert',
+ $svc_acct->username, $svc_acct->quota );
+}
+
+sub _export_replace {
+ my( $self, $new, $old ) = (shift, shift, shift);
+ return "can't change username using Cyrus"
+ if $old->username ne $new->username;
+ return '';
+# #return '' unless $old->_password ne $new->_password;
+# $self->cyrus_queue( $new->svcnum,
+# 'replace', $new->username, $new->_password );
+}
+
+sub _export_delete {
+ my( $self, $svc_acct ) = (shift, shift);
+ $self->cyrus_queue( $svc_acct->svcnum, 'delete',
+ $svc_acct->username );
+}
+
+#a good idea to queue anything that could fail or take any time
+sub cyrus_queue {
+ my( $self, $svcnum, $method ) = (shift, shift, shift);
+ my $queue = new FS::queue {
+ 'svcnum' => $svcnum,
+ 'job' => "FS::part_export::cyrus::cyrus_$method",
+ };
+ $queue->insert(
+ $self->option('server'),
+ $self->option('username'),
+ $self->option('password'),
+ @_
+ );
+}
+
+sub cyrus_insert { #subroutine, not method
+ my $client = cyrus_connect(shift, shift, shift);
+ my( $username, $quota ) = @_;
+ my $rc = $client->create("user.$username");
+ my $error = $client->error;
+ die "creating user.$username: $error" if $error;
+
+ $rc = $client->setacl("user.$username", $username => 'all' );
+ $error = $client->error;
+ die "setacl user.$username: $error" if $error;
+
+ if ( $quota ) {
+ $rc = $client->setquota("user.$username", 'STORAGE' => $quota );
+ $error = $client->error;
+ die "setquota user.$username: $error" if $error;
+ }
+
+}
+
+sub cyrus_delete { #subroutine, not method
+ my ( $server, $admin_username, $password_username, $username ) = @_;
+ my $client = cyrus_connect($server, $admin_username, $password_username);
+
+ my $rc = $client->setacl("user.$username", $admin_username => 'all' );
+ my $error = $client->error;
+ die $error if $error;
+
+ $rc = $client->delete("user.$username");
+ $error = $client->error;
+ die $error if $error;
+}
+
+sub cyrus_connect {
+
+ my( $server, $admin_username, $admin_password ) = @_;
+
+ eval "use Cyrus::IMAP::Admin;";
+
+ my $client = Cyrus::IMAP::Admin->new($server);
+ $client->authenticate(
+ -user => $admin_username,
+ -mechanism => "login",
+ -password => $admin_password,
+ );
+ $client;
+
+}
+
+#sub cyrus_replace { #subroutine, not method
+#}
+
+
diff --git a/FS/FS/part_export/infostreet.pm b/FS/FS/part_export/infostreet.pm
index c2386adb7..e86e82a66 100644
--- a/FS/FS/part_export/infostreet.pm
+++ b/FS/FS/part_export/infostreet.pm
@@ -10,7 +10,7 @@ sub rebless { shift; }
sub _export_insert {
my( $self, $svc_acct ) = (shift, shift);
$self->infostreet_queue( $svc_acct->svcnum,
- 'createUser', $svc_acct->username, $svc_acct->password );
+ 'createUser', $svc_acct->username, $svc_acct->_password );
}
sub _export_replace {
@@ -19,7 +19,7 @@ sub _export_replace {
if $old->username ne $new->username;
return '' unless $old->_password ne $new->_password;
$self->infostreet_queue( $new->svcnum,
- 'passwd', $new->username, $new->password );
+ 'passwd', $new->username, $new->_password );
}
sub _export_delete {
diff --git a/FS/FS/part_export/shellcommands.pm b/FS/FS/part_export/shellcommands.pm
new file mode 100644
index 000000000..e99c382a4
--- /dev/null
+++ b/FS/FS/part_export/shellcommands.pm
@@ -0,0 +1,59 @@
+package FS::part_export::shellcommands;
+
+use vars qw(@ISA);
+use FS::part_export;
+
+@ISA = qw(FS::part_export);
+
+sub rebless { shift; }
+
+sub _export_insert {
+ my($self) = shift;
+ $self->_export_command($self, 'useradd', @_);
+}
+
+sub _export_delete {
+ my($self) = shift;
+ $self->_export_command($self, 'userdel', @_);
+}
+
+sub _export_command {
+ my ( $self, $action, $svc_acct) = (shift, shift, shift);
+ my $command = $self->option($action);
+ no strict 'refs';
+ ${$_} = $svc_acct->getfield($_) foreach $svc_acct->fields;
+ $self->shellcommands_queue(
+ $self->options('user')||'root'. "\@". $self->options('machine'),
+ eval(qq("$command"))
+ );
+}
+
+sub _export_replace {
+ my($self, $new, $old ) = (shift, shift, shift);
+ my $command = $self->option('usermod');
+ no strict 'refs';
+ ${"old_$_"} = $old->getfield($_) foreach $old->fields;
+ ${"new_$_"} = $new->getfield($_) foreach $new->fields;
+ $self->shellcommands_queue(
+ $self->options('user')||'root'. "\@". $self->options('machine'),
+ eval(qq("$command"))
+ );
+}
+
+#a good idea to queue anything that could fail or take any time
+sub shellcommands_queue {
+ my( $self, $svcnum ) = (shift, shift);
+ my $queue = new FS::queue {
+ 'svcnum' => $svcnum,
+ 'job' => "Net::SSH::ssh_cmd", #freeside-queued pre-uses...
+ };
+ $queue->insert( @_ );
+}
+
+#sub shellcommands_insert { #subroutine, not method
+#}
+#sub shellcommands_replace { #subroutine, not method
+#}
+#sub shellcommands_delete { #subroutine, not method
+#}
+
diff --git a/FS/FS/part_export/vpopmail.pm b/FS/FS/part_export/vpopmail.pm
new file mode 100644
index 000000000..7a59f3259
--- /dev/null
+++ b/FS/FS/part_export/vpopmail.pm
@@ -0,0 +1,47 @@
+package FS::part_export::myexport;
+
+use vars qw(@ISA);
+use FS::part_export;
+
+@ISA = qw(FS::part_export);
+
+sub rebless { shift; }
+
+sub _export_insert {
+ my($self, $svc_acct) = (shift, shift);
+ $self->myexport_queue( $svc_acct->svcnum, 'insert',
+ $svc_acct->username, $svc_acct->_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_acct ) = (shift, shift);
+ $self->myexport_queue( $svc_acct->svcnum,
+ 'delete', $svc_acct->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
+}
+
diff --git a/FS/FS/svc_acct.pm b/FS/FS/svc_acct.pm
index 1e1cbb019..ea1107823 100644
--- a/FS/FS/svc_acct.pm
+++ b/FS/FS/svc_acct.pm
@@ -6,8 +6,7 @@ use vars qw( @ISA $nossh_hack $noexport_hack $conf
$usernamemax $passwordmin $passwordmax
$username_ampersand $username_letter $username_letterfirst
$username_noperiod $username_uppercase
- $shellmachine $useradd $usermod $userdel $mydomain
- $cyrus_server $cyrus_admin_user $cyrus_admin_pass
+ $mydomain
$dirhash
@saltset @pw_set
$rsync $ssh $exportdir $vpopdir);
@@ -38,47 +37,16 @@ $FS::UID::callback{'FS::svc_acct'} = sub {
$conf = new FS::Conf;
$dir_prefix = $conf->config('home');
@shells = $conf->config('shells');
- $shellmachine = $conf->config('shellmachine');
$usernamemin = $conf->config('usernamemin') || 2;
$usernamemax = $conf->config('usernamemax');
$passwordmin = $conf->config('passwordmin') || 6;
$passwordmax = $conf->config('passwordmax') || 8;
- if ( $shellmachine ) {
- if ( $conf->exists('shellmachine-useradd') ) {
- $useradd = join("\n", $conf->config('shellmachine-useradd') )
- || 'cp -pr /etc/skel $dir; chown -R $uid.$gid $dir';
- } else {
- $useradd = 'useradd -d $dir -m -s $shell -u $uid $username';
- }
- if ( $conf->exists('shellmachine-userdel') ) {
- $userdel = join("\n", $conf->config('shellmachine-userdel') )
- || 'rm -rf $dir';
- } else {
- $userdel = 'userdel $username';
- }
- $usermod = join("\n", $conf->config('shellmachine-usermod') )
- || '[ -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'.
- ')';
- }
$username_letter = $conf->exists('username-letter');
$username_letterfirst = $conf->exists('username-letterfirst');
$username_noperiod = $conf->exists('username-noperiod');
$username_uppercase = $conf->exists('username-uppercase');
$username_ampersand = $conf->exists('username-ampersand');
$mydomain = $conf->config('domain');
- if ( $conf->exists('cyrus') ) {
- ($cyrus_server, $cyrus_admin_user, $cyrus_admin_pass) =
- $conf->config('cyrus');
- eval "use Cyrus::IMAP::Admin;"
- } else {
- $cyrus_server = '';
- $cyrus_admin_user = '';
- $cyrus_admin_pass = '';
- }
$dirhash = $conf->config('dirhash') || 0;
$exportdir = "/usr/local/etc/freeside/export." . datasrc;
@@ -94,8 +62,6 @@ $FS::UID::callback{'FS::svc_acct'} = sub {
@saltset = ( 'a'..'z' , 'A'..'Z' , '0'..'9' , '.' , '/' );
@pw_set = ( 'a'..'z', 'A'..'Z', '0'..'9', '(', ')', '#', '!', '.', ',' );
-#not needed in 5.004 #srand($$|time);
-
sub _cache {
my $self = shift;
my ( $hashref, $cache ) = @_;
@@ -228,7 +194,7 @@ is the default instead. Otherwise the contents of the file are treated as
a double-quoted perl string, with the following variables available:
$username, $uid, $gid, $dir, and $shell.
-(TODOC: cyrus config file, L