summaryrefslogtreecommitdiff
path: root/fs_selfadmin/fs_mailadmin_server
diff options
context:
space:
mode:
Diffstat (limited to 'fs_selfadmin/fs_mailadmin_server')
-rwxr-xr-xfs_selfadmin/fs_mailadmin_server642
1 files changed, 642 insertions, 0 deletions
diff --git a/fs_selfadmin/fs_mailadmin_server b/fs_selfadmin/fs_mailadmin_server
new file mode 100755
index 0000000..ef47885
--- /dev/null
+++ b/fs_selfadmin/fs_mailadmin_server
@@ -0,0 +1,642 @@
+#!/usr/bin/perl -Tw
+#
+# fs_mailadmin_server
+#
+
+use strict;
+use IO::Handle;
+use FS::SSH qw(sshopen2);
+use FS::UID qw(adminsuidsetup);
+use FS::Conf;
+use FS::Record qw( qsearch qsearchs );
+use FS::cust_main_county;
+use FS::cust_main;
+use FS::svc_acct_admin;
+
+use vars qw( $opt $Debug $conf $default_domain );
+
+$Debug = 1;
+
+#my @payby = qw(CARD PREPAY);
+
+my $user = shift or die &usage;
+&adminsuidsetup( $user );
+
+$conf = new FS::Conf;
+$default_domain = $conf->config('domain');
+
+my $machine = shift or die &usage;
+
+my $agentnum = shift or die &usage;
+my $agent = qsearchs( 'agent', { 'agentnum' => $agentnum } ) or die &usage;
+my $pkgpart = $agent->pkgpart_hashref;
+
+my $refnum = shift or die &usage;
+
+#causing trouble for some folks
+#$SIG{CHLD} = sub { wait() };
+
+my($fs_mailadmind)=$conf->config('fs_mailadmind');
+
+while (1) {
+ my($reader,$writer)=(new IO::Handle, new IO::Handle);
+ $writer->autoflush(1);
+ warn "[fs_mailadmin_server] Connecting to $machine...\n" if $Debug;
+ sshopen2($machine,$reader,$writer,$fs_mailadmind);
+
+ my $data;
+
+ warn "[fs_mailadmin_server] Sending locales...\n" if $Debug;
+ my @cust_main_county = qsearch('cust_main_county', {} );
+ print $writer $data = join("\n",
+ ( scalar(@cust_main_county) || die "no tax rates (cust_main_county records)" ),
+ map {
+ $_->taxnum,
+ $_->state,
+ $_->county,
+ $_->country,
+ } @cust_main_county
+ ),"\n";
+ warn "[fs_mailadmin_server] $data\n" if $Debug > 2;
+
+ warn "[fs_mailadmin_server] Sending package definitions...\n" if $Debug;
+ my @part_pkg = grep { $_->svcpart('svc_acct') && $pkgpart->{ $_->pkgpart } }
+ qsearch( 'part_pkg', {} );
+ print $writer $data = join("\n",
+ ( scalar(@part_pkg) || die "no usable package definitions, agent $agentnum" ),
+ map {
+ $_->pkgpart,
+ $_->pkg,
+ } @part_pkg
+ ), "\n";
+ warn "[fs_mailadmin_server] $data\n" if $Debug > 2;
+
+ warn "[fs_mailadmin_server] Sending POPs...\n" if $Debug;
+ my @svc_acct_pop = qsearch ('svc_acct_pop',{} );
+ print $writer $data = join("\n",
+ ( scalar(@svc_acct_pop) || die "No points of presence (svc_acct_pop records)" ),
+ map {
+ $_->popnum,
+ $_->city,
+ $_->state,
+ $_->ac,
+ $_->exch,
+ $_->loc,
+ } @svc_acct_pop
+ ), "\n";
+ warn "[fs_mailadmin_server] $data\n" if $Debug > 2;
+
+ warn "[fs_mailadmin_server] Entering main loop...\n" if $Debug;
+COMMAND: while (1) {
+ warn "[fs_mailadmin_server] Reading (waiting for) command...\n" if $Debug;
+ chop( my($command, $user) = map { scalar(<$reader>) } ( 1 .. 2 ) );
+ my $domain = $default_domain;
+ $user =~ /^([\w\.\-]+)\@(([\w\-]+\.)+\w+)$/;
+ ($user, $domain) = ($1, $2);
+
+ if ($command eq 'authenticate'){
+ warn "[fs_mailadmin_server] Processing authenticate command for $user \n" if $Debug;
+ chop( my($password) = map { scalar(<$reader>) } ( 1 .. 1 ) );
+
+ my $error = '';
+
+ my @svc_domain = qsearchs('svc_domain', { 'domain' => $domain });
+
+ if (scalar(@svc_domain) != 1) {
+ warn "Nonexistant or duplicate service account for \"$domain\"";
+ next COMMAND;
+ }
+
+ my @svc_acct = qsearchs('svc_acct', { 'username' => $user,
+ 'domsvc' => $svc_domain[0]->svcnum });
+ if (scalar(@svc_acct) != 1) {
+ die "Nonexistant or duplicate service account for \"$user\"";
+ next COMMAND;
+ }
+
+ if ($svc_acct[0]->_password eq $password) {
+ $error = "$user\@$domain OK";
+ }else{
+ $error = "$user\@$domain FAILED";
+ }
+ warn "[fs_mailadmin_server] Sending results...\n" if $Debug;
+ print $writer $error, "\n";
+ }
+ elsif ($command eq 'list_packages'){
+ warn "[fs_mailadmin_server] Processing list_packages command for $user \n" if $Debug;
+
+ my $error = '';
+
+ my @packages = eval {find_administrable_packages( $user, $domain )};
+ warn "$@" if $@;
+
+ my %packages;
+ my %accounts;
+
+ foreach my $package (@packages) {
+ $packages{my $pkgnum = $package->getfield('pkgnum')} = $default_domain;
+ $accounts{$pkgnum} = 0;
+ my @services = qsearch('cust_svc', { 'pkgnum' => $pkgnum });
+ foreach my $service (@services) {
+ if ($service->getfield('svcpart') eq '4'){
+ my $account=qsearchs('svc_domain', { 'svcnum' => $service->getfield('svcnum') });
+ $packages{$pkgnum}=$account->getfield('domain');
+ $accounts{$pkgnum}=$account->getfield('svcnum');
+ }
+ }
+ }
+
+ print $writer $data = join("\n",
+ ( scalar(keys(%packages)) ),
+ map {
+ $_,
+ $packages{$_},
+ $accounts{$_},
+ } keys(%packages)
+ ), "\n";
+ warn "[fs_mailadmin_server] $data\n" if $Debug > 2;
+
+ }elsif ($command eq 'list_mailboxes'){
+
+ warn "[fs_mailadmin_server] Processing list_mailboxes command for $user" if $Debug;
+ chop( my($pkgnum) = map { scalar(<$reader>) } ( 1 .. 1 ) );
+ warn "package $pkgnum \n" if $Debug;
+
+ my $error = '';
+
+ my @packages = eval {find_administrable_packages( $user, $domain )};
+ warn "$@" if $@;
+
+ my @accounts;
+
+ foreach my $package (@packages) {
+ next unless ($pkgnum eq $package->getfield('pkgnum'));
+ my @services = qsearch('cust_svc', { 'pkgnum' => $package->getfield('pkgnum') });
+ foreach my $service (@services) {
+ if ($service->getfield('svcpart') eq '2'){
+ my $account=qsearchs('svc_acct', { 'svcnum' => $service->getfield('svcnum') });
+# $accounts[$#accounts+1]=$account->getfield('username');
+ $accounts[$#accounts+1]=$account;
+ }
+ }
+ }
+
+ print $writer $data = join("\n",
+# ( scalar(@accounts) || die "No accounts (svc_acct records)" ),
+ ( scalar(@accounts) ),
+ map {
+ $_->svcnum,
+# $_->username,
+ $_->email,
+# $_->_password,
+ '*****',
+ } @accounts
+ ), "\n";
+ warn "[fs_mailadmin_server] $data\n" if $Debug > 2;
+
+
+ } elsif ($command eq 'delete_mailbox'){
+ warn "[fs_mailadmin_server] Processing delete_mailbox command for $user " if $Debug;
+ chop( my($account) = map { scalar(<$reader>) } ( 1 .. 1 ) );
+ warn "account $account \n" if $Debug;
+
+ my $error = '';
+
+ my @packages = eval { find_administrable_packages($user, $domain) };
+ warn "$@" if $@;
+ $error ||= "$@" if $@;
+
+ my @svc_acct = qsearchs('svc_acct', { 'svcnum' => $account }) unless $error;
+ if (scalar(@svc_acct) != 1) { $error ||= 'Nonexistant or duplicate service account for user.' };
+ if (! $error && check_administrator(\@packages, $svc_acct[0])){
+# not sure about the next three lines... do we delete? or return error
+ foreach my $svc_forward (qsearch('svc_forward', { 'dstsvc' => $svc_acct[0]->getfield('svcnum') })) {
+ $error ||= $svc_forward->delete;
+ }
+ foreach my $svc_forward (qsearch('svc_forward', { 'srcsvc' => $svc_acct[0]->getfield('svcnum') })) {
+ $error ||= $svc_forward->delete;
+ }
+ $error ||= $svc_acct[0]->delete;
+ } else {
+ $error ||= "Illegal attempt to remove service";
+ }
+
+
+ warn "[fs_mailadmin_server] Sending results...\n" if $Debug;
+ print $writer $error, "\n";
+
+ } elsif ($command eq 'password_mailbox'){
+ warn "[fs_mailadmin_server] Processing password_mailbox command for $user " if $Debug;
+ chop( my($account, $_password) = map { scalar(<$reader>) } ( 1 .. 2 ) );
+ warn "account $account with password $_password \n" if $Debug;
+
+ my $error = '';
+
+ my @packages = eval { find_administrable_packages($user, $domain) };
+ warn "$@" if $@;
+ $error ||= "$@" if $@;
+
+ my @svc_acct = qsearchs('svc_acct', { 'svcnum' => $account }) unless $error;
+ if (scalar(@svc_acct) != 1) { $error ||= 'Nonexistant or duplicate service account.' };
+
+ if (! $error && check_administrator(\@packages, $svc_acct[0])){
+ my $new = new FS::svc_acct ({$svc_acct[0]->hash});
+ $new->setfield('_password' => $_password);
+ $error ||= $new->replace($svc_acct[0]);
+ } else {
+ $error ||= "Illegal attempt to change password";
+ }
+
+
+ warn "[fs_mailadmin_server] Sending results...\n" if $Debug;
+ print $writer $error, "\n";
+
+ } elsif ($command eq 'add_mailbox'){
+ warn "[fs_mailadmin_server] Processing add_mailbox command for $user " if $Debug;
+ chop( my($target_package, $account, $_password) = map { scalar(<$reader>) } ( 1 .. 3 ) );
+ warn "in package $target_package account $account with password $_password \n" if $Debug;
+
+ my $found_package;
+ my $domainsvc=0;
+ my $svcpart=2; # this is 'email box'
+ my $svcpartsm=3; # this is 'domain alias'
+ my $error = '';
+ my $found = 0;
+
+ my @packages = eval { find_administrable_packages($user, $domain) };
+ warn "$@" if $@;
+ $error ||= "$@" if $@;
+
+ foreach my $package (@packages) {
+ if ($package->getfield('pkgnum') eq $target_package) {
+ $found = 1;
+ $found_package=$package;
+ my @services = qsearch('cust_svc', { 'pkgnum' => $target_package });
+ foreach my $service (@services) {
+ if ($service->getfield('svcpart') eq '4'){
+ my @svc_domain=qsearchs('svc_domain', { 'svcnum' => $service->getfield('svcnum') });
+ if (scalar(@svc_domain) eq 1) {
+ $domainsvc=$svc_domain[0]->getfield('svcnum');
+ }
+ }
+ }
+ last;
+ }
+ }
+ warn "User $user does not have administration rights to package $target_package\n" unless $found;
+ $error ||= "User $user does not have administration rights to package $target_package\n" unless $found;
+
+ my $part_pkg = qsearchs('part_pkg',{'pkgpart'=>$found_package->getfield('pkgpart')});
+
+ #list of services this pkgpart includes (although at the moment we only care
+ # about $svcpart
+ my $pkg_svc;
+ my %pkg_svc = ();
+ foreach $pkg_svc ( qsearch('pkg_svc',{'pkgpart'=> $found_package->pkgpart }) ) {
+ $pkg_svc{$pkg_svc->svcpart} = $pkg_svc->quantity if $pkg_svc->quantity;
+ }
+
+ my @services = qsearch('cust_svc', {'pkgnum' => $found_package->getfield('pkgnum'),
+ 'svcpart' => $svcpart,
+ });
+
+ if (scalar(@services) >= $pkg_svc{$svcpart}) {
+ $error="Maximum allowed already reached.";
+ }
+
+ my $svc_acct = new FS::svc_acct ( {
+ 'pkgnum' => $found_package->pkgnum,
+ 'svcpart' => $svcpart,
+ 'username' => $account,
+ 'domsvc' => $domainsvc,
+ '_password' => $_password,
+ } );
+
+ my $y = $svc_acct->setdefault; # arguably should be in new method
+ $error ||= $y unless ref($y);
+ #and just in case you were silly
+ $svc_acct->pkgnum($found_package->pkgnum);
+ $svc_acct->svcpart($svcpart);
+ $svc_acct->username($account);
+ $svc_acct->domsvc($domainsvc);
+ $svc_acct->_password($_password);
+
+ $error ||= $svc_acct->check;
+
+ if ( ! $error ) { #in this case, $cust_pkg should always
+ #be definied, but....
+ $error ||= $svc_acct->insert;
+ warn "WARNING: $error on pre-checked svc_acct record!" if $error;
+ }
+
+ warn "[fs_mailadmin_server] Sending results...\n" if $Debug;
+ print $writer $error, "\n";
+
+ }elsif ($command eq 'list_forwards'){
+
+ warn "[fs_mailadmin_server] Processing list_forwards command for $user" if $Debug;
+ chop( my($svcnum) = map { scalar(<$reader>) } ( 1 .. 1 ) );
+ warn "service $svcnum \n" if $Debug;
+
+ my $error = '';
+
+ my @packages = eval {find_administrable_packages( $user, $domain )};
+ warn "$@" if $@;
+
+ my @forwards;
+
+ foreach my $package (@packages) {
+# next unless ($pkgnum eq $package->getfield('pkgnum'));
+ my @services = qsearch('cust_svc', { 'pkgnum' => $package->getfield('pkgnum') });
+ foreach my $service (@services) {
+ if ($service->getfield('svcpart') eq '10'){
+ my $forward=qsearchs('svc_forward', { 'svcnum' => $service->getfield('svcnum') });
+ $forwards[$#forwards+1]=$forward if ($forward->getfield('srcsvc') == $svcnum);
+ }
+ }
+ }
+
+ print $writer $data = join("\n",
+ ( scalar(@forwards) ),
+ map {
+ $_->svcnum,
+ ($_->dstsvc ? qsearchs('svc_acct', {'svcnum' => $_->dstsvc})->email : $_->dst),
+ } @forwards
+ ), "\n";
+ warn "[fs_mailadmin_server] $data\n" if $Debug > 2;
+
+
+ }elsif ($command eq 'list_pkg_forwards'){
+
+ warn "[fs_mailadmin_server] Processing list_pkg_forwards command for $user" if $Debug;
+ chop( my($pkgnum) = map { scalar(<$reader>) } ( 1 .. 1 ) );
+ warn "package $pkgnum \n" if $Debug;
+
+ my $error = '';
+
+ my @packages = eval {find_administrable_packages( $user, $domain )};
+ warn "$@" if $@;
+
+ my @forwards;
+
+ foreach my $package (@packages) {
+ next unless ($pkgnum eq $package->getfield('pkgnum'));
+ my @services = qsearch('cust_svc', { 'pkgnum' => $package->getfield('pkgnum') });
+ foreach my $service (@services) {
+ if ($service->getfield('svcpart') eq '10'){
+ my $forward=qsearchs('svc_forward', { 'svcnum' => $service->getfield('svcnum') });
+ $forwards[$#forwards+1]=$forward;
+ }
+ }
+ }
+
+ print $writer $data = join("\n",
+ ( scalar(@forwards) ),
+ map {
+ $_->svcnum,
+ $_->srcsvc,
+ ($_->dstsvc ? qsearchs('svc_acct', {'svcnum' => $_->dstsvc})->email : $_->dst),
+ } @forwards
+ ), "\n";
+ warn "[fs_mailadmin_server] $data\n" if $Debug > 2;
+
+
+ } elsif ($command eq 'delete_forward'){
+ warn "[fs_mailadmin_server] Processing delete_forward command for $user " if $Debug;
+ chop( my($forward) = map { scalar(<$reader>) } ( 1 .. 1 ) );
+ warn "forward $forward \n" if $Debug;
+
+ my $error = '';
+
+ my @packages = eval { find_administrable_packages($user, $domain) };
+ warn "$@" if $@;
+ $error ||= "$@" if $@;
+
+ my @svc_forward = qsearchs('svc_forward', { 'svcnum' => $forward }) unless $error;
+ if (scalar(@svc_forward) != 1) { $error ||= 'Nonexistant or duplicate service account for user.' };
+ if (! $error && check_administrator(\@packages, $svc_forward[0])){
+# not sure about the next three lines... do we delete? or return error
+ $error ||= $svc_forward[0]->delete;
+ } else {
+ $error ||= "Illegal attempt to remove service";
+ }
+
+
+ warn "[fs_mailadmin_server] Sending results...\n" if $Debug;
+ print $writer $error, "\n";
+
+ } elsif ($command eq 'add_forward'){
+ warn "[fs_mailadmin_server] Processing add_forward command for $user " if $Debug;
+ chop( my($target_package, $source, $dest) = map { scalar(<$reader>) } ( 1 .. 3 ) );
+ warn "in package $target_package source $source with destination $dest \n" if $Debug;
+
+ my $found_package;
+ my $domainsvc=0;
+ my $svcpart=10; # this is 'forward service'
+ my $error = '';
+ my $found = 0;
+
+ my @packages = eval { find_administrable_packages($user, $domain) };
+ warn "$@" if $@;
+ $error ||= "$@" if $@;
+
+ foreach my $package (@packages) {
+ if ($package->getfield('pkgnum') eq $target_package) {
+ $found = 1;
+ $found_package=$package;
+ last;
+ }
+ }
+ warn "User $user does not have administration rights to package $target_package\n" unless $found;
+ $error ||= "User $user does not have administration rights to package $target_package\n" unless $found;
+
+ my $svc_acct = qsearchs('svc_acct', { 'svcnum' => $source });
+ warn "Forwarding source $source does not exist.\n" unless $svc_acct;
+ $error ||= "Forwarding source $source does not exist.\n" unless $svc_acct;
+
+ my $cust_svc = qsearchs('cust_svc', { 'svcnum' => $source });
+ warn "Forwarding source $source not attached to any account.\n" unless $cust_svc;
+ $error ||= "Forwarding source $source not attached to any account.\n" unless $cust_svc;
+
+ if ( ! $error ) {
+ warn "Forwarding source $source is not in package $target_package\n"
+ unless ($cust_svc->getfield('pkgnum') == $target_package);
+ $error ||= "Forwarding source $source is not in package $target_package\n"
+ unless ($cust_svc->getfield('pkgnum') == $target_package);
+ }
+
+ my $part_pkg = qsearchs('part_pkg',{'pkgpart'=>$found_package->getfield('pkgpart')});
+
+ #list of services this pkgpart includes (although at the moment we only care
+ # about $svcpart
+ my $pkg_svc;
+ my %pkg_svc = ();
+ foreach $pkg_svc ( qsearch('pkg_svc',{'pkgpart'=> $found_package->pkgpart }) ) {
+ $pkg_svc{$pkg_svc->svcpart} = $pkg_svc->quantity if $pkg_svc->quantity;
+ }
+
+ my @services = qsearch('cust_svc', {'pkgnum' => $found_package->getfield('pkgnum'),
+ 'svcpart' => $svcpart,
+ });
+
+ if (scalar(@services) >= $pkg_svc{$svcpart}) {
+ $error="Maximum allowed already reached.";
+ }
+
+ my $svc_forward = new FS::svc_forward ( {
+ 'pkgnum' => $found_package->pkgnum,
+ 'svcpart' => $svcpart,
+ 'srcsvc' => $source,
+ 'dstsvc' => 0,
+ 'dst' => $dest,
+ } );
+
+ my $y = $svc_forward->setdefault; # arguably should be in new method
+ $error ||= $y unless ref($y);
+ #and just in case you were silly
+ $svc_forward->pkgnum($found_package->pkgnum);
+ $svc_forward->svcpart($svcpart);
+ $svc_forward->srcsvc($source);
+ $svc_forward->dstsvc(0);
+ $svc_forward->dst($dest);
+
+ $error ||= $svc_forward->check;
+
+ if ( ! $error ) { #in this case, $cust_pkg should always
+ #be definied, but....
+ $error ||= $svc_forward->insert;
+ warn "WARNING: $error on pre-checked svc_forward record!" if $error;
+ }
+
+ warn "[fs_mailadmin_server] Sending results...\n" if $Debug;
+ print $writer $error, "\n";
+
+ } else {
+ warn "[fs_mailadmin_server] Bad command: $command \n" if $Debug;
+ print $writer "Bad command \n";
+ }
+ }
+ close $writer;
+ close $reader;
+ warn "connection to $machine lost! waiting 60 seconds...\n";
+ sleep 60;
+ warn "reconnecting...\n";
+}
+
+sub usage {
+ die "Usage:\n\n fs_mailadmin_server user machine agentnum refnum\n";
+}
+
+#sub find_administrable_packages {
+# my $user = shift;
+#
+# my $error = '';
+#
+# my @svc_acct = qsearchs('svc_acct', { 'username' => $user });
+# if (scalar(@svc_acct) != 1) {
+# die "Nonexistant or duplicate service account for \"$user\"";
+# }
+#
+# my @cust_svc = qsearchs('cust_svc', { 'svcnum' => $svc_acct[0]->getfield('svcnum') });
+# if (scalar(@cust_svc) != 1 ) {
+# die "Nonexistant or duplicate customer service for \"$user\"";
+# }
+#
+# my @cust_pkg = qsearchs('cust_pkg', { 'pkgnum' => $cust_svc[0]->getfield('pkgnum') });
+# if (scalar(@cust_pkg) != 1) {
+# die "Nonexistant or duplicate customer package for \"$user\"";
+# }
+#
+# my @cust_main = qsearchs('cust_main', { 'custnum' => $cust_pkg[0]->getfield('custnum') });
+# if (scalar(@cust_main) != 1 ) {
+# die "Nonexistant or duplicate customer for \"$user\"";
+# }
+#
+# my @packages = $cust_main[0]->ncancelled_pkgs;
+#}
+
+sub find_administrable_packages {
+ my $user = shift;
+ my $domain = shift;
+
+ my @packages;
+ my $error = '';
+
+ my @svc_domain = qsearchs('svc_domain', { 'domain' => $domain });
+
+ if (scalar(@svc_domain) != 1) {
+ die "Nonexistant or duplicate service account for \"$domain\"";
+ }
+
+ my @svc_acct = qsearchs('svc_acct', { 'username' => $user,
+ 'domsvc' => $svc_domain[0]->svcnum });
+ if (scalar(@svc_acct) != 1) {
+ die "Nonexistant or duplicate service account for \"$user\"";
+ }
+
+ my @svc_acct_admin = qsearch('svc_acct_admin', {'adminsvc' => $svc_acct[0]->getfield('svcnum') });
+ die "Nonexistant or duplicate customer service for \"$user\"" unless scalar(@svc_acct_admin);
+
+ foreach my $svc_acct_admin (@svc_acct_admin) {
+ my @cust_svc = qsearchs('cust_svc', { 'svcnum' => $svc_acct_admin->getfield('svcnum') });
+ if (scalar(@cust_svc) != 1 ) {
+ die "Nonexistant or duplicate customer service for admin \"$svc_acct_admin->getfield('svcnum')\"";
+ }
+
+ my @cust_pkg = qsearchs('cust_pkg', { 'pkgnum' => $cust_svc[0]->getfield('pkgnum') });
+ if (scalar(@cust_pkg) != 1) {
+ die "Nonexistant or duplicate customer package for admin \"$user\"";
+ }
+
+ push @packages, $cust_pkg[0] unless $cust_pkg[0]->getfield('cancel');
+
+ }
+ (@packages);
+}
+
+sub check_administrator {
+ my ($allowed_packages_aref, $svc_acct_ref) = @_;
+
+ my $error = '';
+ my $found = 0;
+
+ {
+ my @cust_svc = qsearchs('cust_svc', { 'svcnum' => $svc_acct_ref->getfield('svcnum') });
+ if (scalar(@cust_svc) != 1 ) {
+ warn "Nonexistant or duplicate customer service for \"$svc_acct_ref->getfield('username')\"";
+ last;
+ }
+
+ my @cust_pkg = qsearchs('cust_pkg', { 'pkgnum' => $cust_svc[0]->getfield('pkgnum') });
+ if (scalar(@cust_pkg) != 1) {
+ warn "Nonexistant or duplicate customer package for \"$svc_acct_ref->getfield('username')\"";
+ last;
+ }
+
+ foreach my $package (@$allowed_packages_aref) {
+ if ($package->getfield('pkgnum') eq $cust_pkg[0]->getfield('pkgnum')) {
+ $found = 1;
+ last;
+ }
+ }
+ }
+
+ $found;
+}
+
+sub check_add {
+ my ($allowed_packages_aref, $target_package) = @_;
+
+ my $error = '';
+ my $found = 0;
+
+ foreach my $package (@$allowed_packages_aref) {
+ if ($package->getfield('pkgnum') eq $target_package) {
+ $found = 1;
+ last;
+ }
+ }
+
+ $found;
+}
+