From a5bbbed61e09dffffc5d7022cddb3f9ff62a955a Mon Sep 17 00:00:00 2001 From: ivan Date: Mon, 3 Oct 2005 01:42:22 +0000 Subject: [PATCH] update account view and edit: convert to proper templates, make sure usage information displays for any usage-capable export, add ability to edit uid/gid --- FS/FS/Conf.pm | 17 +- FS/FS/cust_svc.pm | 6 +- FS/FS/part_svc.pm | 16 +- FS/FS/svc_acct.pm | 9 +- httemplate/edit/svc_acct.cgi | 449 +++++++++++++++++++++----------- httemplate/elements/small_custview.html | 2 +- httemplate/view/svc_acct.cgi | 224 +++++++++------- 7 files changed, 462 insertions(+), 261 deletions(-) diff --git a/FS/FS/Conf.pm b/FS/FS/Conf.pm index 37d649bf9..237ab1e58 100644 --- a/FS/FS/Conf.pm +++ b/FS/FS/Conf.pm @@ -668,7 +668,7 @@ httemplate/docs/config.html { 'key' => 'invoice_send_receipts', - 'section' => 'deprecated',q + 'section' => 'deprecated', 'description' => 'DEPRECATED, this used to send an invoice copy on payments and credits. See the payment_receipt_email and XXXX instead.', 'type' => 'checkbox', }, @@ -1569,6 +1569,21 @@ httemplate/docs/config.html 'type' => 'checkbox', }, + { + 'key' => 'svc_acct-edit_uid', + 'section' => 'shell', + 'description' => 'Allow UID editing.', + 'type' => 'checkbox', + }, + + { + 'key' => 'svc_acct-edit_gid', + 'section' => 'shell', + 'description' => 'Allow GID editing.', + 'type' => 'checkbox', + }, + + ); 1; diff --git a/FS/FS/cust_svc.pm b/FS/FS/cust_svc.pm index 2e349f6bd..e69befca2 100644 --- a/FS/FS/cust_svc.pm +++ b/FS/FS/cust_svc.pm @@ -384,10 +384,8 @@ sub seconds_since_sqlradacct { my $svc_x = $self->svc_x; - my @part_export = $self->part_svc->part_export('sqlradius'); - push @part_export, $self->part_svc->part_export('sqlradius_withdomain'); - die "no sqlradius or sqlradius_withdomain export configured for this". - "service type" + my @part_export = $self->part_svc->part_export_usage; + die "no usage-capable export configured for this service type" unless @part_export; #or return undef; diff --git a/FS/FS/part_svc.pm b/FS/FS/part_svc.pm index 2bb8ab59e..0ece185f7 100644 --- a/FS/FS/part_svc.pm +++ b/FS/FS/part_svc.pm @@ -393,8 +393,8 @@ sub all_part_svc_column { =item part_export [ EXPORTTYPE ] -Returns all exports (see L) for this service, or, if an -export type is specified, only returns exports of the given type. +Returns a list of all exports (see L) for this service, or, +if an export type is specified, only returns exports of the given type. =cut @@ -406,6 +406,18 @@ sub part_export { qsearch('export_svc', { 'svcpart' => $self->svcpart } ); } +=item part_export_usage + +Returns a list of any exports (see L) for this service that +are capable of reporting usage information. + +=cut + +sub part_export_usage { + my $self = shift; + grep $_->can('usage_sessions'), $self->part_export; +} + =item cust_svc Returns a list of associated FS::cust_svc records. diff --git a/FS/FS/svc_acct.pm b/FS/FS/svc_acct.pm index 4a618108f..167fcee88 100644 --- a/FS/FS/svc_acct.pm +++ b/FS/FS/svc_acct.pm @@ -467,7 +467,14 @@ sub replace { { #no warnings 'numeric'; #alas, a 5.006-ism local($^W) = 0; - return "Can't change uid!" if $old->uid != $new->uid; + + foreach my $xid (qw( uid gid )) { + + return "Can't change $xid!" + if ! $conf->exists("svc_acct-edit_$xid") + && $old->$xid() != $new->$xid(); + } + } #change homdir when we change username diff --git a/httemplate/edit/svc_acct.cgi b/httemplate/edit/svc_acct.cgi index a730531f5..bc5d96aab 100755 --- a/httemplate/edit/svc_acct.cgi +++ b/httemplate/edit/svc_acct.cgi @@ -1,4 +1,3 @@ - <% my $conf = new FS::Conf; @@ -6,6 +5,7 @@ my @shells = $conf->config('shells'); my($svcnum, $pkgnum, $svcpart, $part_svc, $svc_acct, @groups); if ( $cgi->param('error') ) { + $svc_acct = new FS::svc_acct ( { map { $_, scalar($cgi->param($_)) } fields('svc_acct') } ); @@ -15,7 +15,9 @@ if ( $cgi->param('error') ) { $part_svc = qsearchs( 'part_svc', { 'svcpart' => $svcpart } ); die "No part_svc entry for svcpart $svcpart!" unless $part_svc; @groups = $cgi->param('radius_usergroup'); + } else { + my($query) = $cgi->keywords; if ( $query =~ /^(\d+)$/ ) { #editing $svcnum=$1; @@ -46,35 +48,43 @@ if ( $cgi->param('error') ) { $svcnum=''; - #set gecos - my($cust_pkg)=qsearchs('cust_pkg',{'pkgnum'=>$pkgnum}); - if ($cust_pkg) { - my($cust_main)=qsearchs('cust_main',{'custnum'=> $cust_pkg->custnum } ); - unless ( $part_svc->part_svc_column('uid')->columnflag eq 'F' ) { - $svc_acct->setfield('finger', - $cust_main->getfield('first') . " " . $cust_main->getfield('last') - ); - } - } + } +} + +my( $cust_pkg, $cust_main ) = ( '', '' ); +if ( $pkgnum ) { + $cust_pkg = qsearchs('cust_pkg', { 'pkgnum' => $pkgnum } ); + $cust_main = $cust_pkg->cust_main; +} + +unless ( $svcnum || $cgi->param('error') ) { #adding - #set fixed and default fields from part_svc - foreach my $part_svc_column ( - grep { $_->columnflag } $part_svc->all_part_svc_column - ) { - if ( $part_svc_column->columnname eq 'usergroup' ) { - @groups = split(',', $part_svc_column->columnvalue); - } else { - $svc_acct->setfield( $part_svc_column->columnname, - $part_svc_column->columnvalue, - ); - } + #set gecos + if ($cust_main) { + unless ( $part_svc->part_svc_column('uid')->columnflag eq 'F' ) { + $svc_acct->setfield('finger', + $cust_main->getfield('first') . " " . $cust_main->getfield('last') + ); } + } + #set fixed and default fields from part_svc + foreach my $part_svc_column ( + grep { $_->columnflag } $part_svc->all_part_svc_column + ) { + if ( $part_svc_column->columnname eq 'usergroup' ) { + @groups = split(',', $part_svc_column->columnvalue); + } else { + $svc_acct->setfield( $part_svc_column->columnname, + $part_svc_column->columnvalue, + ); + } } + } #fixed radius groups always override & display -if ( $part_svc->part_svc_column('usergroup')->columnflag eq "F" ) { +if ( $part_svc->part_svc_column('usergroup')->columnflag eq 'F' ) { @groups = split(',', $part_svc->part_svc_column('usergroup')->columnvalue); } @@ -106,47 +116,81 @@ my $pmax = $conf->config('passwordmax') || 8; my $pmax2 = $pmax+2; my $p1 = popurl(1); -print header("$action $svc account"); - -print qq!Error: !, $cgi->param('error'), - "

" - if $cgi->param('error'); - -print 'Service # '. ( $svcnum ? "$svcnum" : " (NEW)" ). '
'. - 'Service: '. $part_svc->svc. '

'. - < - - - -END - -print &ntable("#cccccc",2), <Username - -Password - -(blank to generate) + +%> + +<%= header("$action $svc account") %> + +<% if ( $cgi->param('error') ) { %> + Error: <%= $cgi->param('error') %> +

+<% } %> + +<% if ( $cust_main ) { %> + <%= include( '/elements/small_custview.html', $cust_main, '', 1 ) %> +
+<% } %> + +
+ + + + +Service # <%= $svcnum ? "$svcnum" : " (NEW)" %>
+ +<%= ntable("#cccccc",2) %> + + + Service + <%= $part_svc->svc %> + + + + Username + + MAXLENGTH=<%= $ulen %>> + + + + + Password + + MAXLENGTH=<%= $pmax %>> + (blank to generate) + -END + +<% my $sec_phrase = $svc_acct->sec_phrase; if ( $conf->exists('security_phrase') ) { - print <Security phrase - - (for forgotten passwords) +%> + + + Security phrase + + + (for forgotten passwords) + -END -} else { - print qq!!; -} +<% } else { %> + + + +<% } %> + + +<% #domain my $domsvc = $svc_acct->domsvc || 0; if ( $part_svc->part_svc_column('domsvc')->columnflag eq 'F' ) { - print qq!!; -} else { +%> + + + +<% } else { + my %svc_domain = (); if ( $domsvc ) { @@ -170,7 +214,6 @@ if ( $part_svc->part_svc_column('domsvc')->columnflag eq 'F' ) { } } - my $cust_pkg = qsearchs('cust_pkg', { 'pkgnum' => $pkgnum } ); if ($cust_pkg && !$conf->exists('svc_acct-alldomains') ) { my @cust_svc = map { qsearch('cust_svc', { 'pkgnum' => $_->pkgnum } ) } @@ -183,121 +226,223 @@ if ( $part_svc->part_svc_column('domsvc')->columnflag eq 'F' ) { } else { %svc_domain = map { $_->svcnum => $_ } qsearch('svc_domain', {} ); } - print qq!Domain!. - qq!"; -} +%> + + + Domain + + + + + +<% } %> + + +<% #pop my $popnum = $svc_acct->popnum || 0; -if ( $part_svc->part_svc_column('popnum')->columnflag eq "F" ) { - print qq!!; -} else { - print qq!Access number!. - qq!!. FS::svc_acct_pop::popselector($popnum). ''; -} +if ( $part_svc->part_svc_column('popnum')->columnflag eq 'F' ) { +%> -my($uid,$gid,$finger,$dir)=( - $svc_acct->uid, - $svc_acct->gid, - $svc_acct->finger, - $svc_acct->dir, -); + -print < - -END -if ( !$finger && $part_svc->part_svc_column('uid')->columnflag eq 'F' ) { - print ''; -} else { - print 'GECOS'. - qq!!; -} -print qq!!; +<% } else { %> + + + Access number + <%= FS::svc_acct_pop::popselector($popnum) %> + + +<% } %> + +<% #uid/gid %> +<% foreach my $xid (qw( uid gid )) { %> + + <% + if ( $part_svc->part_svc_column($xid)->columnflag eq 'F' + || ! $conf->exists("svc_acct-edit_$xid") + ) { + %> + + <% if ( length($svc_acct->$xid()) ) { %> + + + <%= uc($xid) %> + <%= $svc_acct->$xid() %> + + + + + <% } else { %> + + + + <% } %> + + <% } else { %> + + + <%= uc($xid) %> + + + + + + <% } %> + +<% } %> + + +<% +#finger +if ( $part_svc->part_svc_column('uid')->columnflag eq 'F' + && ! $svc_acct->finger ) { +%> + + + +<% } else { %> + + + GECOS + + + + + +<% } %> + + + + + +<% +#shell my $shell = $svc_acct->shell; -if ( $part_svc->part_svc_column('shell')->columnflag eq "F" +if ( $part_svc->part_svc_column('shell')->columnflag eq 'F' || ( !$shell && $part_svc->part_svc_column('uid')->columnflag eq 'F' ) ) { - print qq!!; -} else { - print qq!Shell"; -} +%> -my($quota,$slipip)=( - $svc_acct->quota, - $svc_acct->slipip, -); + -if ( $part_svc->part_svc_column('quota')->columnflag eq "F" ) -{ - print qq!!; -} else { - print <Quota: - - -END -} +<% } else { %> + + + Shell + + + + + +<% } %> + + +<% if ( $part_svc->part_svc_column('quota')->columnflag eq 'F' ) { %> + + + +<% } else { %> + + + Quota: + + + +<% } %> -if ( $part_svc->part_svc_column('slipip')->columnflag eq "F" ) { - print qq!!; -} else { - print qq!IP!; -} +<% if ( $part_svc->part_svc_column('slipip')->columnflag eq 'F' ) { %> + + + +<% } else { %> + + + IP + + + +<% } %> + + +<% foreach my $r ( grep { /^r(adius|[cr])_/ } fields('svc_acct') ) { $r =~ /^^r(adius|[cr])_(.+)$/ or next; #? my $a = $2; - if ( $part_svc->part_svc_column($r)->columnflag eq 'F' ) { - print qq!'; - } else { - print qq!$FS::raddb::attrib{$a}'; - } -} +%> -print 'RADIUS groups'; -if ( $part_svc->part_svc_column('usergroup')->columnflag eq "F" ) { - print ''. join('
', @groups); -} else { - print ''. &FS::svc_acct::radius_usergroup_selector( \@groups ); -} -print ''; + <% if ( $part_svc->part_svc_column($r)->columnflag eq 'F' ) { %> -foreach my $field ($svc_acct->virtual_fields) { - if ( $part_svc->part_svc_column($field)->columnflag ne 'F' ) { - # If the flag is X, it won't even show up in $svc_acct->virtual_fields. - print $svc_acct->pvf($field)->widget('HTML', 'edit', - $svc_acct->getfield($field)); - } -} + + + <% } else { %> + + + <%= $FS::raddb::attrib{$a} %> + + + + <% } %> + +<% } %> + + + + RADIUS groups + + <% if ( $part_svc->part_svc_column('usergroup')->columnflag eq 'F' ) { %> + + <%= join('
', @groups) %> + + <% } else { %> + + <%= FS::svc_acct::radius_usergroup_selector( \@groups ) %> + + <% } %> + + + +<% foreach my $field ($svc_acct->virtual_fields) { %> + + <% # If the flag is X, it won't even show up in $svc_acct->virtual_fields. %> + <% if ( $part_svc->part_svc_column($field)->columnflag ne 'F' ) { %> + + <%= $svc_acct->pvf($field)->widget('HTML', 'edit', $svc_acct->getfield($field)) %> + + <% } %> + +<% } %> -#submit -print qq!
!; + +
-print < - - -END + -%> + diff --git a/httemplate/elements/small_custview.html b/httemplate/elements/small_custview.html index 1e8ae739a..e0c22e0c4 100644 --- a/httemplate/elements/small_custview.html +++ b/httemplate/elements/small_custview.html @@ -1,2 +1,2 @@ <% my $conf = new FS::Conf; %> -<%= small_custview( shift, shift || $conf->config('countrydefault') ) %> +<%= small_custview( shift, shift || scalar($conf->config('countrydefault')), @_ ) %> diff --git a/httemplate/view/svc_acct.cgi b/httemplate/view/svc_acct.cgi index 1486d7b11..7257fc3e4 100755 --- a/httemplate/view/svc_acct.cgi +++ b/httemplate/view/svc_acct.cgi @@ -1,4 +1,3 @@ - <% my $conf = new FS::Conf; @@ -24,41 +23,46 @@ if ($pkgnum) { my $part_svc = qsearchs('part_svc',{'svcpart'=> $cust_svc->svcpart } ); die "Unknown svcpart" unless $part_svc; +my $svc = $part_svc->svc; -my $domain; -if ( $svc_acct->domsvc ) { - my $svc_domain = qsearchs('svc_domain', { 'svcnum' => $svc_acct->domsvc } ); - die "Unknown domain" unless $svc_domain; - $domain = $svc_domain->domain; -} else { - die "No svc_domain.svcnum record for svc_acct.domsvc: ". $cust_svc->domsvc; -} +die 'Empty domsvc for svc_acct.svcnum '. $svc_acct->svcnum + unless $svc_acct->domsvc; +my $svc_domain = qsearchs('svc_domain', { 'svcnum' => $svc_acct->domsvc } ); +die 'Unknown domain (domsvc '. $svc_acct->domsvc. + ' for svc_acct.svcnum '. $svc_acct->svcnum. ')' + unless $svc_domain; +my $domain = $svc_domain->domain; %> - +<% if ( $custnum ) { %> -<%= header('Account View', menubar( - ( ( $pkgnum || $custnum ) - ? ( "View this customer (#$custnum)" => "${p}view/cust_main.cgi?$custnum", - ) - : ( "Cancel this (unaudited) account" => - "javascript:areyousure(\'${p}misc/cancel-unaudited.cgi?$svcnum\')" ) - ), - "Main menu" => $p, -)) %> + <%= header("View $svc account", menubar( + "View this customer (#$custnum)" => "${p}view/cust_main.cgi?$custnum", + "Main menu" => $p, + )) %> -<% + <%= include( '/elements/small_custview.html', $custnum, '', 1 ) %> +
+ +<% } else { %> -#if ( $cust_pkg && $cust_pkg->part_pkg->plan eq 'sqlradacct_hour' ) { -if ( $part_svc->part_export('sqlradius') - || $part_svc->part_export('sqlradius_withdomain') -) { + + + <%= header('Account View', menubar( + "Cancel this (unaudited) account" => + "javascript:areyousure(\'${p}misc/cancel-unaudited.cgi?$svcnum\')", + "Main menu" => $p, + )) %> + +<% } %> + +<% if ( $part_svc->part_export_usage ) { my $last_bill; my %plandata; @@ -151,60 +155,73 @@ function enable_change () { } %> -Service Information -| Edit this information +Service #<%= $svcnum %> +| Edit this service <% if ( @part_svc ) { %> | <% } %> <%= &ntable("#cccccc") %><%= &ntable("#cccccc",2) %> -Service number - <%= $svcnum %> -Service - <%= $part_svc->svc %> -Username - <%= $svc_acct->username %> -Domain - <%= $domain %> - -Password - <% - -my $password = $svc_acct->_password; -if ( $password =~ /^\*\w+\* (.*)$/ ) { - $password = $1; - print "(login disabled) "; -} -if ( $conf->exists('showpasswords') ) { - print '
'. encode_entities($password). '
'; -} else { - print "(hidden)"; -} -print ""; -$password = ''; -if ( $conf->exists('security_phrase') ) { - my $sec_phrase = $svc_acct->sec_phrase; - print 'Security phrase'. - $svc_acct->sec_phrase. ''; -} + + Service + <%= $part_svc->svc %> + + + Username + <%= $svc_acct->username %> + + + Domain + <%= $domain %> + + + + Password + + + <% my $password = $svc_acct->_password; %> + <% if ( $password =~ /^\*\w+\* (.*)$/ ) { + $password = $1; + %> + (login disabled) + <% } %> + + <% if ( $conf->exists('showpasswords') ) { %> +
<%= encode_entities($password) %>
+ <% } else { %> + (hidden) + <% } %> + + + +<% $password = ''; %> -my $svc_acct_pop = $svc_acct->popnum - ? qsearchs('svc_acct_pop',{'popnum'=>$svc_acct->popnum}) - : ''; -print "Access number". - "". $svc_acct_pop->text. '' - if $svc_acct_pop; +<% if ( $conf->exists('security_phrase') ) { + my $sec_phrase = $svc_acct->sec_phrase; +%> + + Security phrase + <%= $svc_acct->sec_phrase %> + +<% } %> +<% if ( $svc_acct->popnum ) { + my $svc_acct_pop = qsearchs('svc_acct_pop',{'popnum'=>$svc_acct->popnum}); %> + + Access number + <%= $svc_acct_pop->text %> + +<% } %> <% if ($svc_acct->uid ne '') { %> @@ -260,49 +277,56 @@ print "Access number". <% } %> -<% - -my($attribute); -foreach $attribute ( grep /^radius_/, $svc_acct->fields ) { - #warn $attribute; +<% foreach my $attribute ( grep /^radius_/, $svc_acct->fields ) { $attribute =~ /^radius_(.*)$/; my $pattribute = $FS::raddb::attrib{$1}; - print "Radius (reply) $pattribute". - "". $svc_acct->getfield($attribute). - ""; -} -foreach $attribute ( grep /^rc_/, $svc_acct->fields ) { - #warn $attribute; +%> + + Radius (reply) <%= $pattribute %> + <%= $svc_acct->getfield($attribute) %> + +<% } %> + +<% foreach my $attribute ( grep /^rc_/, $svc_acct->fields ) { $attribute =~ /^rc_(.*)$/; my $pattribute = $FS::raddb::attrib{$1}; - print "Radius (check) $pattribute: ". - "". $svc_acct->getfield($attribute). - ""; -} +%> + + Radius (check) <%= $pattribute %> + <%= $svc_acct->getfield($attribute) %> + +<% } %> -print 'RADIUS groups'. - join('
', $svc_acct->radius_groups). ''; + + RADIUS groups + <%= join('
', $svc_acct->radius_groups) %> + -if ( $svc_acct->seconds =~ /^\d+$/ ) { - print 'Prepaid time'. - duration_exact($svc_acct->seconds). ''; -} +<% if ( $svc_acct->seconds =~ /^\d+$/ ) { %> + + Prepaid time + <%= duration_exact($svc_acct->seconds) %> + +<% } %> +<% # Can this be abstracted further? Maybe a library function like # widget('HTML', 'view', $svc_acct) ? It would definitely make UI # style management easier. - -foreach (sort { $a cmp $b } $svc_acct->virtual_fields) { - print $svc_acct->pvf($_)->widget('HTML', 'view', $svc_acct->getfield($_)), - "\n"; -} %> - -<% -print '

'; +<% foreach (sort { $a cmp $b } $svc_acct->virtual_fields) { %> + <%= $svc_acct->pvf($_)->widget('HTML', 'view', $svc_acct->getfield($_)) %> +<% } %> + + + +

-print join("\n", $conf->config('svc_acct-notes') ). '

'. - joblisting({'svcnum'=>$svcnum}, 1). ''; +<%= join("
", $conf->config('svc_acct-notes') ) %> +

-%> +<%= joblisting({'svcnum'=>$svcnum}, 1) %> + + + -- 2.11.0