mirror of https://github.com/sipwise/www_admin.git
commit
41e9261d94
@ -0,0 +1,81 @@
|
||||
package admin;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Catalyst::Runtime '5.70';
|
||||
use XML::Simple;
|
||||
|
||||
# Set flags and add plugins for the application
|
||||
#
|
||||
# -Debug: activates the debug mode for very useful log messages
|
||||
# ConfigLoader: will load the configuration from a YAML file in the
|
||||
# application's home directory
|
||||
# Static::Simple: will serve static files from the application's root
|
||||
# directory
|
||||
|
||||
use Catalyst::Log::Log4perl;
|
||||
|
||||
use Catalyst qw/-Debug ConfigLoader Static::Simple
|
||||
Authentication Authentication::Store::Minimal Authentication::Credential::Password
|
||||
Session Session::Store::FastMmap Session::State::Cookie
|
||||
/;
|
||||
|
||||
our $VERSION = '0.01';
|
||||
|
||||
# Configure the application.
|
||||
#
|
||||
# Note that settings in admin.yml (or other external
|
||||
# configuration file that you set up manually) take precedence
|
||||
# over this when using ConfigLoader. Thus configuration
|
||||
# details given here can function as a default configuration,
|
||||
# with a external configuration file acting as an override for
|
||||
# local deployment.
|
||||
|
||||
# load configuration from admin.conf XML
|
||||
my $xs = new XML::Simple;
|
||||
my $xc = $xs->XMLin( '/usr/local/etc/admin.conf', ForceArray => 0);
|
||||
|
||||
__PACKAGE__->config( authentication => {}, %$xc );
|
||||
|
||||
if(__PACKAGE__->config->{log4perlconf}) {
|
||||
__PACKAGE__->log( Catalyst::Log::Log4perl->new(
|
||||
__PACKAGE__->config->{log4perlconf}
|
||||
));
|
||||
}
|
||||
|
||||
# Start the application
|
||||
__PACKAGE__->setup;
|
||||
|
||||
=head1 NAME
|
||||
|
||||
admin - Catalyst based application
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
The core module of the administration framework.
|
||||
|
||||
=head1 BUGS AND LIMITATIONS
|
||||
|
||||
=over
|
||||
|
||||
=item none so far
|
||||
|
||||
=back
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
L<admin::Controller::Root>, L<Catalyst>
|
||||
|
||||
=head1 AUTHORS
|
||||
|
||||
Daniel Tiefnig <dtiefnig@sipwise.com>
|
||||
|
||||
=head1 COPYRIGHT
|
||||
|
||||
The admin module is Copyright (c) 2007 Sipwise GmbH, Austria. All rights
|
||||
reserved.
|
||||
|
||||
=cut
|
||||
|
||||
1;
|
@ -0,0 +1,121 @@
|
||||
package admin::Controller::Root;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use base 'Catalyst::Controller';
|
||||
|
||||
#
|
||||
# Sets the actions in this controller to be registered with no prefix
|
||||
# so they function identically to actions created in MyApp.pm
|
||||
#
|
||||
__PACKAGE__->config->{namespace} = '';
|
||||
|
||||
=head1 NAME
|
||||
|
||||
admin::Controller::Root - Root Controller for admin
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This provides basic functionality for the admin web interface.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
=head2 auto
|
||||
|
||||
Verify user is logged in.
|
||||
|
||||
=cut
|
||||
|
||||
# Note that 'auto' runs after 'begin' but before your actions and that
|
||||
# 'auto' "chain" (all from application path to most specific class are run)
|
||||
sub auto : Private {
|
||||
my ($self, $c) = @_;
|
||||
|
||||
if ($c->controller =~ /^admin::Controller::Root\b/
|
||||
or $c->controller =~ /^admin::Controller::login\b/)
|
||||
{
|
||||
$c->log->debug('***Root::auto front page or login access granted.');
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!$c->user_exists) {
|
||||
$c->log->debug('***Root::auto User not found, forwarding to /');
|
||||
$c->response->redirect($c->uri_for('/'));
|
||||
return;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
=head2 default
|
||||
|
||||
Display default page.
|
||||
|
||||
=cut
|
||||
|
||||
sub default : Private {
|
||||
my ( $self, $c ) = @_;
|
||||
|
||||
if ($c->user_exists) {
|
||||
$c->stash->{template} = 'tt/default.tt';
|
||||
} else {
|
||||
$c->stash->{template} = 'tt/login.tt';
|
||||
}
|
||||
}
|
||||
|
||||
=head2 end
|
||||
|
||||
Attempt to render a view, if needed.
|
||||
|
||||
=cut
|
||||
|
||||
sub end : ActionClass('RenderView') {
|
||||
my ( $self, $c ) = @_;
|
||||
|
||||
$c->stash->{current_view} = $c->config->{view};
|
||||
|
||||
unless($c->response->{status} =~ /^3/) { # only if not a redirect
|
||||
if(exists $c->session->{prov_error}) {
|
||||
$c->stash->{prov_error} =
|
||||
$c->model('Provisioning')->localize($c->view($c->config->{view})->
|
||||
config->{VARIABLES}{site_config}{language},
|
||||
$c->session->{prov_error});
|
||||
delete $c->session->{prov_error};
|
||||
}
|
||||
|
||||
if(exists $c->session->{messages}) {
|
||||
$c->stash->{messages} = $c->model('Provisioning')->localize($c->view($c->config->{view})->
|
||||
config->{VARIABLES}{site_config}{language},
|
||||
$c->session->{messages});
|
||||
delete $c->session->{messages};
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
=head1 BUGS AND LIMITATIONS
|
||||
|
||||
=over
|
||||
|
||||
=item currently none
|
||||
|
||||
=back
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
Provisioning model, Catalyst
|
||||
|
||||
=head1 AUTHORS
|
||||
|
||||
Daniel Tiefnig <dtiefnig@sipwise.com>
|
||||
|
||||
=head1 COPYRIGHT
|
||||
|
||||
The Root controller is Copyright (c) 2007 Sipwise GmbH, Austria. All
|
||||
rights reserved.
|
||||
|
||||
=cut
|
||||
|
||||
# ende gelaende
|
||||
1;
|
@ -0,0 +1,331 @@
|
||||
package admin::Controller::account;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use base 'Catalyst::Controller';
|
||||
|
||||
=head1 NAME
|
||||
|
||||
admin::Controller::account - Catalyst Controller
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This provides functionality for VoIP account administration.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
=head2 index
|
||||
|
||||
Display search form.
|
||||
|
||||
=cut
|
||||
|
||||
sub index : Private {
|
||||
my ( $self, $c ) = @_;
|
||||
$c->stash->{template} = 'tt/account.tt';
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
=head2 getbyid
|
||||
|
||||
Check entered account ID and redirect.
|
||||
|
||||
=cut
|
||||
|
||||
sub getbyid : Local {
|
||||
my ( $self, $c ) = @_;
|
||||
|
||||
my $account_id = $c->request->params->{account_id};
|
||||
|
||||
if(defined $account_id and $account_id =~ /^\d+$/) {
|
||||
|
||||
if($c->model('Provisioning')->call_prov( $c, 'billing', 'get_voip_account_by_id',
|
||||
{ id => $account_id },
|
||||
\$c->session->{voip_account}
|
||||
))
|
||||
{
|
||||
$c->response->redirect("/account/detail?account_id=$account_id");
|
||||
return;
|
||||
}
|
||||
|
||||
delete $c->session->{prov_error} if $c->session->{prov_error} eq 'Client.Voip.NoSuchAccount';
|
||||
$c->session->{messages} = { accsearcherr => 'Client.Voip.NoSuchAccount' };
|
||||
} else {
|
||||
$c->session->{messages} = { accsearcherr => 'Client.Syntax.AccountID' };
|
||||
}
|
||||
|
||||
$c->response->redirect("/account");
|
||||
return;
|
||||
}
|
||||
|
||||
=head2 detail
|
||||
|
||||
Show account details.
|
||||
|
||||
=cut
|
||||
|
||||
sub detail : Local {
|
||||
my ( $self, $c ) = @_;
|
||||
$c->stash->{template} = 'tt/account_detail.tt';
|
||||
|
||||
my $account_id = $c->request->params->{account_id};
|
||||
return unless $c->model('Provisioning')->call_prov( $c, 'billing', 'get_voip_account_by_id',
|
||||
{ id => $account_id },
|
||||
\$c->session->{voip_account}
|
||||
);
|
||||
if($c->config->{billing_features}) {
|
||||
return unless $c->model('Provisioning')->call_prov( $c, 'billing', 'get_voip_account_balance',
|
||||
{ id => $account_id },
|
||||
\$c->session->{voip_account}{balance}
|
||||
);
|
||||
|
||||
$c->session->{voip_account}{balance}{cash_balance} =
|
||||
sprintf "%.2f", $c->session->{voip_account}{balance}{cash_balance} / 100;
|
||||
$c->session->{voip_account}{balance}{cash_balance_interval} =
|
||||
sprintf "%.2f", $c->session->{voip_account}{balance}{cash_balance_interval} / 100;
|
||||
|
||||
if(ref $c->session->{restore_account_input} eq 'HASH') {
|
||||
$c->stash->{account}{product} = $c->session->{restore_account_input}{product};
|
||||
$c->stash->{account}{billing_profile} = $c->session->{restore_account_input}{billing_profile};
|
||||
delete $c->session->{restore_account_input};
|
||||
}
|
||||
|
||||
if(ref $c->session->{restore_balance_input} eq 'HASH') {
|
||||
$c->stash->{balanceadd} = $c->session->{restore_balance_input};
|
||||
delete $c->session->{restore_balance_input};
|
||||
}
|
||||
|
||||
$c->stash->{edit_account} = $c->request->params->{edit_account};
|
||||
$c->stash->{edit_balance} = $c->request->params->{edit_balance};
|
||||
|
||||
# we only use this to fill the drop-down lists
|
||||
if($c->request->params->{edit_account}) {
|
||||
my $products;
|
||||
return unless $c->model('Provisioning')->call_prov( $c, 'billing', 'get_products',
|
||||
undef,
|
||||
\$products
|
||||
);
|
||||
$c->stash->{products} = [ grep { $$_{class} eq 'voip' } @{$$products{result}} ];
|
||||
my $billing_profiles;
|
||||
return unless $c->model('Provisioning')->call_prov( $c, 'billing', 'get_billing_profiles',
|
||||
undef,
|
||||
\$billing_profiles
|
||||
);
|
||||
|
||||
$c->stash->{billing_profiles} = $$billing_profiles{result};
|
||||
}
|
||||
|
||||
$c->stash->{billing_features} = 1;
|
||||
}
|
||||
|
||||
delete $c->session->{voip_account}{subscribers}
|
||||
if exists $c->session->{voip_account}{subscribers}
|
||||
and !defined $c->session->{voip_account}{subscribers}
|
||||
or ref $c->session->{voip_account}{subscribers} ne 'ARRAY'
|
||||
or $#{$c->session->{voip_account}{subscribers}} == -1;
|
||||
|
||||
$c->stash->{account} = $c->session->{voip_account};
|
||||
# $c->stash->{account}{is_locked} = 1 if $c->session->{voip_account}{status} eq 'locked';
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
=head2 create_account
|
||||
|
||||
Creates a new VoIP account.
|
||||
|
||||
=cut
|
||||
|
||||
sub create_account : Local {
|
||||
my ( $self, $c ) = @_;
|
||||
|
||||
my %messages;
|
||||
|
||||
my $acid;
|
||||
if($c->model('Provisioning')->call_prov( $c, 'billing', 'create_voip_account',
|
||||
{ product => $c->config->{def_product},
|
||||
billing_group => $c->config->{def_billprof},
|
||||
},
|
||||
\$acid))
|
||||
{
|
||||
$messages{accmsg} = 'Web.Account.Created';
|
||||
$c->session->{messages} = \%messages;
|
||||
$c->response->redirect("/account/detail?account_id=$acid");
|
||||
return;
|
||||
}
|
||||
|
||||
$c->response->redirect("/account");
|
||||
return;
|
||||
}
|
||||
|
||||
=head2 update_account
|
||||
|
||||
Update details of a VoIP account.
|
||||
|
||||
=cut
|
||||
|
||||
sub update_account : Local {
|
||||
my ( $self, $c ) = @_;
|
||||
|
||||
my %messages;
|
||||
my %settings;
|
||||
|
||||
my $account_id = $c->request->params->{account_id};
|
||||
|
||||
my $product = $c->request->params->{product};
|
||||
$settings{product} = $product if defined $product;
|
||||
|
||||
my $billing_profile = $c->request->params->{billing_profile};
|
||||
$settings{billing_profile} = $billing_profile if defined $billing_profile;
|
||||
|
||||
if(keys %settings) {
|
||||
if($c->model('Provisioning')->call_prov( $c, 'billing', 'update_voip_account',
|
||||
{ id => $account_id,
|
||||
data => \%settings,
|
||||
},
|
||||
undef))
|
||||
{
|
||||
$messages{accmsg} = 'Server.Voip.SavedSettings';
|
||||
$c->session->{messages} = \%messages;
|
||||
$c->response->redirect("/account/detail?account_id=$account_id");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
$c->session->{messages} = \%messages;
|
||||
$c->session->{restore_account_input} = \%settings;
|
||||
$c->response->redirect("/account/detail?account_id=$account_id&edit_account=1");
|
||||
return;
|
||||
}
|
||||
|
||||
=head2 lock
|
||||
|
||||
Locks and unlocks an account.
|
||||
|
||||
=cut
|
||||
|
||||
sub lock : Local {
|
||||
my ( $self, $c ) = @_;
|
||||
|
||||
my $account_id = $c->request->params->{account_id};
|
||||
my $lock = $c->request->params->{lock};
|
||||
|
||||
$c->model('Provisioning')->call_prov( $c, 'billing', 'lock_voip_account',
|
||||
{ id => $account_id,
|
||||
lock => $lock,
|
||||
},
|
||||
undef
|
||||
);
|
||||
|
||||
$c->response->redirect("/account/detail?account_id=$account_id");
|
||||
}
|
||||
|
||||
=head2 terminate
|
||||
|
||||
Terminates an account.
|
||||
|
||||
=cut
|
||||
|
||||
sub terminate : Local {
|
||||
my ( $self, $c ) = @_;
|
||||
|
||||
my %messages;
|
||||
|
||||
my $account_id = $c->request->params->{account_id};
|
||||
|
||||
if($c->model('Provisioning')->call_prov( $c, 'billing', 'terminate_voip_account',
|
||||
{ id => $account_id },
|
||||
undef))
|
||||
{
|
||||
$messages{topmsg} = 'Server.Voip.SubscriberDeleted';
|
||||
$c->session->{messages} = \%messages;
|
||||
$c->response->redirect("/account");
|
||||
return;
|
||||
}
|
||||
|
||||
$c->session->{messages} = \%messages;
|
||||
$c->response->redirect("/account/detail?account_id=$account_id");
|
||||
return;
|
||||
}
|
||||
|
||||
=head2 update_account
|
||||
|
||||
Update a VoIP account cash and free time balance.
|
||||
|
||||
=cut
|
||||
|
||||
sub update_balance : Local {
|
||||
my ( $self, $c ) = @_;
|
||||
|
||||
my %messages;
|
||||
my %settings;
|
||||
|
||||
my $account_id = $c->request->params->{account_id};
|
||||
|
||||
my $add_cash = $c->request->params->{add_cash};
|
||||
if(defined $add_cash and length $add_cash) {
|
||||
$settings{cash} = $add_cash;
|
||||
if($settings{cash} =~ /^[+-]?\d+(?:[.,]\d+)?$/) {
|
||||
$settings{cash} =~ s/,/./;
|
||||
$settings{cash} *= 100;
|
||||
} else {
|
||||
$messages{addcash} = 'Client.Syntax.CashValue';
|
||||
}
|
||||
}
|
||||
my $add_time = $c->request->params->{add_time};
|
||||
if(defined $add_time and length $add_time) {
|
||||
$messages{addtime} = 'Client.Syntax.TimeValue'
|
||||
unless $add_time =~ /^[+-]?\d+$/;
|
||||
$settings{free_time} = $add_time;
|
||||
}
|
||||
|
||||
unless(keys %messages) {
|
||||
if($c->model('Provisioning')->call_prov( $c, 'billing', 'update_voip_account_balance',
|
||||
{ id => $account_id,
|
||||
data => \%settings,
|
||||
},
|
||||
undef))
|
||||
{
|
||||
$messages{balmsg} = 'Server.Voip.SavedSettings';
|
||||
$c->session->{messages} = \%messages;
|
||||
$c->response->redirect("/account/detail?account_id=$account_id");
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
$messages{balerr} = 'Client.Voip.InputErrorFound';
|
||||
}
|
||||
|
||||
$c->session->{messages} = \%messages;
|
||||
$c->session->{restore_balance_input} = \%settings;
|
||||
$c->session->{restore_balance_input}{cash} = $add_cash
|
||||
if defined $add_cash and length $add_cash;
|
||||
$c->response->redirect("/account/detail?account_id=$account_id&edit_balance=1");
|
||||
return;
|
||||
}
|
||||
|
||||
=head1 BUGS AND LIMITATIONS
|
||||
|
||||
=over
|
||||
|
||||
=item currently none
|
||||
|
||||
=back
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
Provisioning model, Sipwise::Provisioning::Billing, Catalyst
|
||||
|
||||
=head1 AUTHORS
|
||||
|
||||
Daniel Tiefnig <dtiefnig@sipwise.com>
|
||||
|
||||
=head1 COPYRIGHT
|
||||
|
||||
The account controller is Copyright (c) 2007 Sipwise GmbH, Austria. All
|
||||
rights reserved.
|
||||
|
||||
=cut
|
||||
|
||||
# ende gelaende
|
||||
1;
|
@ -0,0 +1,200 @@
|
||||
package admin::Controller::admin;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use base 'Catalyst::Controller';
|
||||
|
||||
=head1 NAME
|
||||
|
||||
admin::Controller::admin - Catalyst Controller
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
Catalyst Controller.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
=head2 index
|
||||
|
||||
Display admin list.
|
||||
|
||||
=cut
|
||||
|
||||
sub index : Private {
|
||||
my ( $self, $c ) = @_;
|
||||
$c->stash->{template} = 'tt/admin.tt';
|
||||
|
||||
if($c->session->{admin}{is_master} or $c->session->{admin}{is_superuser}) {
|
||||
my $admins;
|
||||
return unless $c->model('Provisioning')->call_prov( $c, 'billing', 'get_admins',
|
||||
undef,
|
||||
\$admins
|
||||
);
|
||||
$c->stash->{admins} = $$admins{result};
|
||||
} else { # only own settings
|
||||
my $admin;
|
||||
return unless $c->model('Provisioning')->call_prov( $c, 'billing', 'get_admin',
|
||||
{ login => $c->session->{admin}{login} },
|
||||
\$admin
|
||||
);
|
||||
$c->stash->{admins} = [ $admin ];
|
||||
}
|
||||
|
||||
$c->stash->{edit_admin} = $c->request->params->{edit_admin};
|
||||
|
||||
if(ref $c->session->{restore_admedit_input} eq 'HASH') {
|
||||
$c->stash->{erefill} = $c->session->{restore_admedit_input};
|
||||
delete $c->session->{restore_admedit_input};
|
||||
}
|
||||
if(ref $c->session->{restore_admadd_input} eq 'HASH') {
|
||||
$c->stash->{arefill} = $c->session->{restore_admadd_input};
|
||||
delete $c->session->{restore_admadd_input};
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
=head2 do_edit_admin
|
||||
|
||||
Change settings for an admin.
|
||||
|
||||
=cut
|
||||
|
||||
sub do_edit_admin : Local {
|
||||
my ( $self, $c ) = @_;
|
||||
|
||||
my %messages;
|
||||
my %settings;
|
||||
|
||||
my $admin = $c->request->params->{admin};
|
||||
|
||||
$settings{password} = $c->request->params->{password};
|
||||
if(defined $settings{password} and length $settings{password}) {
|
||||
$messages{epass} = 'Client.Voip.PassLength'
|
||||
unless length $settings{password} >= 6;
|
||||
} else {
|
||||
delete $settings{password};
|
||||
}
|
||||
|
||||
$settings{is_master} = $c->request->params->{is_master} ? 1 : 0;
|
||||
$settings{is_active} = $c->request->params->{is_active} ? 1 : 0;
|
||||
|
||||
unless(keys %messages) {
|
||||
if($c->model('Provisioning')->call_prov( $c, 'billing', 'update_admin',
|
||||
{ login => $admin,
|
||||
data => \%settings,
|
||||
},
|
||||
undef
|
||||
))
|
||||
{
|
||||
$messages{eadmmsg} = 'Server.Voip.SavedSettings';
|
||||
$c->session->{messages} = \%messages;
|
||||
$c->response->redirect("/admin");
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
$messages{eadmerr} = 'Client.Voip.InputErrorFound';
|
||||
}
|
||||
|
||||
$c->session->{messages} = \%messages;
|
||||
$c->session->{restore_admedit_input} = \%settings;
|
||||
$c->response->redirect("/admin?edit_admin=$admin");
|
||||
return;
|
||||
}
|
||||
|
||||
=head2 do_create_admin
|
||||
|
||||
Create a new admin.
|
||||
|
||||
=cut
|
||||
|
||||
sub do_create_admin : Local {
|
||||
my ( $self, $c ) = @_;
|
||||
|
||||
my %messages;
|
||||
my %settings;
|
||||
|
||||
my $admin = $c->request->params->{admin};
|
||||
$messages{alogin} = 'Client.Syntax.MalformedLogin'
|
||||
unless $admin =~ /^\w+$/;
|
||||
|
||||
$settings{password} = $c->request->params->{password};
|
||||
$messages{apass} = 'Client.Voip.PassLength'
|
||||
unless length $settings{password} >= 6;
|
||||
|
||||
$settings{is_master} = $c->request->params->{is_master} ? 1 : 0;
|
||||
$settings{is_active} = $c->request->params->{is_active} ? 1 : 0;
|
||||
|
||||
unless(keys %messages) {
|
||||
if($c->model('Provisioning')->call_prov( $c, 'billing', 'create_admin',
|
||||
{ login => $admin,
|
||||
data => \%settings,
|
||||
},
|
||||
undef
|
||||
))
|
||||
{
|
||||
$messages{cadmmsg} = 'Web.Admin.Created';
|
||||
$c->session->{messages} = \%messages;
|
||||
$c->response->redirect("/admin");
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
$messages{cadmerr} = 'Client.Voip.InputErrorFound';
|
||||
}
|
||||
|
||||
$c->session->{messages} = \%messages;
|
||||
$c->session->{restore_admadd_input} = \%settings;
|
||||
$c->session->{restore_admadd_input}{admin} = $admin;
|
||||
$c->response->redirect("/admin");
|
||||
return;
|
||||
}
|
||||
|
||||
=head2 do_delete_admin
|
||||
|
||||
Delete a admin.
|
||||
|
||||
=cut
|
||||
|
||||
sub do_delete_admin : Local {
|
||||
my ( $self, $c ) = @_;
|
||||
|
||||
my $admin = $c->request->params->{admin};
|
||||
if($c->model('Provisioning')->call_prov( $c, 'billing', 'delete_admin',
|
||||
{ login => $admin },
|
||||
undef
|
||||
))
|
||||
{
|
||||
$c->session->{messages}{eadmmsg} = 'Web.Admin.Deleted';
|
||||
$c->response->redirect("/admin");
|
||||
return;
|
||||
}
|
||||
|
||||
$c->response->redirect("/admin");
|
||||
return;
|
||||
}
|
||||
|
||||
=head1 BUGS AND LIMITATIONS
|
||||
|
||||
=over
|
||||
|
||||
=item currently none
|
||||
|
||||
=back
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
Provisioning model, Sipwise::Provisioning::Billing, Catalyst
|
||||
|
||||
=head1 AUTHORS
|
||||
|
||||
Daniel Tiefnig <dtiefnig@sipwise.com>
|
||||
|
||||
=head1 COPYRIGHT
|
||||
|
||||
The admin controller is Copyright (c) 2007 Sipwise GmbH, Austria. All
|
||||
rights reserved.
|
||||
|
||||
=cut
|
||||
|
||||
# ende gelaende
|
||||
1;
|
@ -0,0 +1,328 @@
|
||||
package admin::Controller::customer;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use base 'Catalyst::Controller';
|
||||
|
||||
=head1 NAME
|
||||
|
||||
admin::Controller::customer - Catalyst Controller
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This provides functionality for customer administration.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
=head2 index
|
||||
|
||||
Display search form.
|
||||
|
||||
=cut
|
||||
|
||||
sub index : Private {
|
||||
my ( $self, $c ) = @_;
|
||||
$c->stash->{template} = 'tt/customer.tt';
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
=head2 search
|
||||
|
||||
Search for customers and display results.
|
||||
|
||||
=cut
|
||||
|
||||
sub search : Local {
|
||||
my ( $self, $c ) = @_;
|
||||
$c->stash->{template} = 'tt/customer.tt';
|
||||
|
||||
my $search_string = $c->request->params->{search_string};
|
||||
|
||||
my $customer_list;
|
||||
return unless $c->model('Provisioning')->call_prov( $c, 'billing', 'search_customers',
|
||||
{ filter => { anything => '%'.$search_string.'%' } },
|
||||
\$customer_list
|
||||
);
|
||||
|
||||
$c->stash->{customer_list} = $$customer_list{customers}
|
||||
if ref $$customer_list{customers} eq 'ARRAY';
|
||||
}
|
||||
|
||||
=head2 getbyid
|
||||
|
||||
Check entered customer ID and redirect.
|
||||
|
||||
=cut
|
||||
|
||||
sub getbyid : Local {
|
||||
my ( $self, $c ) = @_;
|
||||
|
||||
my $customer_id = $c->request->params->{customer_id};
|
||||
|
||||
if(defined $customer_id and $customer_id =~ /^\d+$/) {
|
||||
|
||||
if($c->model('Provisioning')->call_prov( $c, 'billing', 'get_customer',
|
||||
{ id => $customer_id },
|
||||
\$c->session->{customer}
|
||||
))
|
||||
{
|
||||
$c->response->redirect("/customer/detail?customer_id=$customer_id");
|
||||
return;
|
||||
}
|
||||
|
||||
if($c->session->{prov_error} eq 'Client.Billing.NoSuchCustomer') {
|
||||
delete $c->session->{prov_error};
|
||||
$c->session->{messages} = { custgeterr => 'Client.Billing.NoSuchCustomer' };
|
||||
}
|
||||
} else {
|
||||
$c->session->{messages} = { custgeterr => 'Web.Syntax.Numeric' };
|
||||
}
|
||||
|
||||
$c->response->redirect("/customer");
|
||||
return;
|
||||
}
|
||||
|
||||
=head2 detail
|
||||
|
||||
Show customer details.
|
||||
|
||||
=cut
|
||||
|
||||
sub detail : Local {
|
||||
my ( $self, $c ) = @_;
|
||||
$c->stash->{template} = 'tt/customer_detail.tt';
|
||||
|
||||
my $customer_id = $c->request->params->{customer_id};
|
||||
return unless $c->model('Provisioning')->call_prov( $c, 'billing', 'get_customer',
|
||||
{ id => $customer_id },
|
||||
\$c->session->{customer}
|
||||
);
|
||||
my $contracts;
|
||||
return unless $c->model('Provisioning')->call_prov( $c, 'billing', 'get_customer_contracts',
|
||||
{ id => $customer_id },
|
||||
\$contracts
|
||||
);
|
||||
$c->session->{customer}{contracts} = $$contracts{result};
|
||||
my $orders;
|
||||
return unless $c->model('Provisioning')->call_prov( $c, 'billing', 'get_customer_orders',
|
||||
{ id => $customer_id },
|
||||
\$orders
|
||||
);
|
||||
$c->session->{customer}{orders} = $$orders{result};
|
||||
|
||||
$c->stash->{customer} = $c->session->{customer};
|
||||
|
||||
if(ref $c->session->{restore_customer_input} eq 'HASH') {
|
||||
$c->stash->{customer} = $c->session->{restore_customer_input};
|
||||
delete $c->session->{restore_customer_input};
|
||||
}
|
||||
if(ref $c->session->{restore_contact_input} eq 'HASH') {
|
||||
$c->stash->{customer}{contact} = $c->session->{restore_contact_input};
|
||||
delete $c->session->{restore_contact_input};
|
||||
}
|
||||
if(ref $c->session->{restore_comm_contact_input} eq 'HASH') {
|
||||
$c->stash->{customer}{comm_contact} = $c->session->{restore_comm_contact_input};
|
||||
delete $c->session->{restore_comm_contact_input};
|
||||
}
|
||||
if(ref $c->session->{restore_tech_contact_input} eq 'HASH') {
|
||||
$c->stash->{customer}{tech_contact} = $c->session->{restore_tech_contact_input};
|
||||
delete $c->session->{restore_tech_contact_input};
|
||||
}
|
||||
|
||||
$c->stash->{show_pass} = $c->request->params->{show_pass};
|
||||
$c->stash->{edit_customer} = $c->request->params->{edit_customer};
|
||||
$c->stash->{edit_contact} = $c->request->params->{edit_contact};
|
||||
$c->stash->{edit_commercial} = $c->request->params->{edit_commercial};
|
||||
$c->stash->{edit_technical} = $c->request->params->{edit_technical};
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
=head2 create_customer
|
||||
|
||||
Creates a new customer. Not yet implemented.
|
||||
|
||||
=cut
|
||||
|
||||
sub create_customer : Local {
|
||||
my ( $self, $c ) = @_;
|
||||
|
||||
my $customer_id;
|
||||
if($c->model('Provisioning')->call_prov( $c, 'billing', 'create_customer',
|
||||
{
|
||||
},
|
||||
\$customer_id))
|
||||
{
|
||||
$c->response->redirect("/customer/detail?customer_id=$customer_id");
|
||||
return;
|
||||
}
|
||||
|
||||
$c->response->redirect("/customer");
|
||||
return;
|
||||
}
|
||||
|
||||
=head2 update_customer
|
||||
|
||||
Update details of a customer.
|
||||
|
||||
=cut
|
||||
|
||||
sub update_customer : Local {
|
||||
my ( $self, $c ) = @_;
|
||||
|
||||
my %messages;
|
||||
my %settings;
|
||||
|
||||
my $customer_id = $c->request->params->{customer_id};
|
||||
|
||||
if(defined $c->request->params->{shopuser} and length $c->request->params->{shopuser}) {
|
||||
$settings{shopuser} = $c->request->params->{shopuser};
|
||||
my $checkresult;
|
||||
return unless $c->model('Provisioning')->call_prov( $c, 'voip', 'check_username',
|
||||
$settings{shopuser}, \$checkresult
|
||||
);
|
||||
$messages{username} = 'Client.Syntax.MalformedUsername' unless $checkresult;
|
||||
}
|
||||
if(defined $c->request->params->{shoppass} and length $c->request->params->{shoppass}) {
|
||||
$settings{shoppass} = $c->request->params->{shoppass};
|
||||
$messages{password} = 'Client.Voip.PassLength' unless length $settings{shoppass} >= 6;
|
||||
}
|
||||
|
||||
if(keys %settings and ! keys %messages) {
|
||||
if($c->model('Provisioning')->call_prov( $c, 'billing', 'update_customer',
|
||||
{ id => $customer_id,
|
||||
data => \%settings,
|
||||
},
|
||||
undef))
|
||||
{
|
||||
$messages{accmsg} = 'Server.Voip.SavedSettings';
|
||||
$c->session->{messages} = \%messages;
|
||||
$c->response->redirect("/customer/detail?customer_id=$customer_id");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
$c->session->{messages} = \%messages;
|
||||
$c->session->{restore_customer_input} = \%settings;
|
||||
$c->response->redirect("/customer/detail?customer_id=$customer_id&edit_customer=1");
|
||||
return;
|
||||
}
|
||||
|
||||
=head2 update_contact
|
||||
|
||||
Update details of a customer's contact.
|
||||
|
||||
=cut
|
||||
|
||||
sub update_contact : Local {
|
||||
my ( $self, $c ) = @_;
|
||||
|
||||
my %messages;
|
||||
my %settings;
|
||||
|
||||
my $customer_id = $c->request->params->{customer_id};
|
||||
|
||||
my $ctype = $c->request->params->{ctype};
|
||||
|
||||
if(defined $c->request->params->{gender} and length $c->request->params->{gender}) {
|
||||
$settings{gender} = $c->request->params->{gender};
|
||||
} else {
|
||||
$settings{gender} = undef;
|
||||
}
|
||||
if(defined $c->request->params->{firstname} and length $c->request->params->{firstname}) {
|
||||
$settings{firstname} = $c->request->params->{firstname};
|
||||
} else {
|
||||
$settings{firstname} = undef;
|
||||
}
|
||||
if(defined $c->request->params->{lastname} and length $c->request->params->{lastname}) {
|
||||
$settings{lastname} = $c->request->params->{lastname};
|
||||
} else {
|
||||
$settings{lastname} = undef;
|
||||
}
|
||||
if(defined $c->request->params->{comregnum} and length $c->request->params->{comregnum}) {
|
||||
$settings{comregnum} = $c->request->params->{comregnum};
|
||||
} else {
|
||||
$settings{comregnum} = undef;
|
||||
}
|
||||
if(defined $c->request->params->{company} and length $c->request->params->{company}) {
|
||||
$settings{company} = $c->request->params->{company};
|
||||
} else {
|
||||
$settings{company} = undef;
|
||||
}
|
||||
if(defined $c->request->params->{street} and length $c->request->params->{street}) {
|
||||
$settings{street} = $c->request->params->{street};
|
||||
} else {
|
||||
$settings{street} = undef;
|
||||
}
|
||||
if(defined $c->request->params->{postcode} and length $c->request->params->{postcode}) {
|
||||
$settings{postcode} = $c->request->params->{postcode};
|
||||
} else {
|
||||
$settings{postcode} = undef;
|
||||
}
|
||||
if(defined $c->request->params->{phonenumber} and length $c->request->params->{phonenumber}) {
|
||||
$settings{phonenumber} = $c->request->params->{phonenumber};
|
||||
} else {
|
||||
$settings{phonenumber} = undef;
|
||||
}
|
||||
if(defined $c->request->params->{mobilenumber} and length $c->request->params->{mobilenumber}) {
|
||||
$settings{mobilenumber} = $c->request->params->{mobilenumber};
|
||||
} else {
|
||||
$settings{mobilenumber} = undef;
|
||||
}
|
||||
if(defined $c->request->params->{email} and length $c->request->params->{email}) {
|
||||
$settings{email} = $c->request->params->{email};
|
||||
} else {
|
||||
$settings{email} = undef;
|
||||
}
|
||||
if(defined $c->request->params->{newsletter} and $c->request->params->{newsletter}) {
|
||||
$settings{newsletter} = 1;
|
||||
} else {
|
||||
$settings{newsletter} = 0;
|
||||
}
|
||||
|
||||
unless(keys %messages) {
|
||||
if($c->model('Provisioning')->call_prov( $c, 'billing', 'update_customer',
|
||||
{ id => $customer_id,
|
||||
data => { $ctype => \%settings },
|
||||
},
|
||||
undef))
|
||||
{
|
||||
$messages{accmsg} = 'Server.Voip.SavedSettings';
|
||||
$c->session->{messages} = \%messages;
|
||||
$c->response->redirect("/customer/detail?customer_id=$customer_id");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
$c->session->{messages} = \%messages;
|
||||
$c->session->{'restore_'.$ctype.'_input'} = \%settings;
|
||||
$c->response->redirect("/customer/detail?customer_id=$customer_id&edit_customer=1");
|
||||
return;
|
||||
}
|
||||
|
||||
=head1 BUGS AND LIMITATIONS
|
||||
|
||||
=over
|
||||
|
||||
=item currently none
|
||||
|
||||
=back
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
Provisioning model, Sipwise::Provisioning::Billing, Catalyst
|
||||
|
||||
=head1 AUTHORS
|
||||
|
||||
Daniel Tiefnig <dtiefnig@sipwise.com>
|
||||
|
||||
=head1 COPYRIGHT
|
||||
|
||||
The account controller is Copyright (c) 2007 Sipwise GmbH, Austria. All
|
||||
rights reserved.
|
||||
|
||||
=cut
|
||||
|
||||
# ende gelaende
|
||||
1;
|
@ -0,0 +1,191 @@
|
||||
package admin::Controller::domain;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use base 'Catalyst::Controller';
|
||||
|
||||
=head1 NAME
|
||||
|
||||
admin::Controller::domain - Catalyst Controller
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
Catalyst Controller.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
=head2 index
|
||||
|
||||
Display domain list.
|
||||
|
||||
=cut
|
||||
|
||||
sub index : Private {
|
||||
my ( $self, $c ) = @_;
|
||||
$c->stash->{template} = 'tt/domain.tt';
|
||||
|
||||
my $domains;
|
||||
return unless $c->model('Provisioning')->call_prov( $c, 'billing', 'get_domains',
|
||||
undef,
|
||||
\$domains
|
||||
);
|
||||
$c->stash->{domains} = $$domains{result};
|
||||
|
||||
$c->stash->{edit_domain} = $c->request->params->{edit_domain};
|
||||
|
||||
if(ref $c->session->{restore_domedit_input} eq 'HASH') {
|
||||
foreach my $domain (@{$c->stash->{domains}}) {
|
||||
next unless $$domain{domain} eq $c->stash->{edit_domain};
|
||||
$domain = { %$domain, %{$c->session->{restore_domedit_input}} };
|
||||
last;
|
||||
}
|
||||
delete $c->session->{restore_domedit_input};
|
||||
}
|
||||
if(ref $c->session->{restore_domadd_input} eq 'HASH') {
|
||||
$c->stash->{arefill} = $c->session->{restore_domadd_input};
|
||||
delete $c->session->{restore_domadd_input};
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
=head2 do_edit_domain
|
||||
|
||||
Change settings for a domain.
|
||||
|
||||
=cut
|
||||
|
||||
sub do_edit_domain : Local {
|
||||
my ( $self, $c ) = @_;
|
||||
|
||||
my %messages;
|
||||
my %settings;
|
||||
|
||||
my $domain = $c->request->params->{domain};
|
||||
|
||||
$settings{cc} = $c->request->params->{cc};
|
||||
$messages{ecc} = 'Client.Voip.MalformedCc'
|
||||
unless $settings{cc} =~ /^\d+$/;
|
||||
|
||||
$settings{timezone} = $c->request->params->{timezone};
|
||||
$messages{etimezone} = 'Client.Syntax.MalformedTimezone'
|
||||
unless $settings{timezone} =~ m#^\w+/\w.+$#;
|
||||
|
||||
unless(keys %messages) {
|
||||
if($c->model('Provisioning')->call_prov( $c, 'billing', 'update_domain',
|
||||
{ domain => $domain,
|
||||
data => \%settings,
|
||||
},
|
||||
undef
|
||||
))
|
||||
{
|
||||
$messages{edommsg} = 'Server.Voip.SavedSettings';
|
||||
$c->session->{messages} = \%messages;
|
||||
$c->response->redirect("/domain");
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
$messages{edomerr} = 'Client.Voip.InputErrorFound';
|
||||
}
|
||||
|
||||
$c->session->{messages} = \%messages;
|
||||
$c->session->{restore_domedit_input} = \%settings;
|
||||
$c->response->redirect("/domain?edit_domain=$domain");
|
||||
return;
|
||||
}
|
||||
|
||||
=head2 do_create_domain
|
||||
|
||||
Create a new domain.
|
||||
|
||||
=cut
|
||||
|
||||
sub do_create_domain : Local {
|
||||
my ( $self, $c ) = @_;
|
||||
|
||||
my %messages;
|
||||
my %settings;
|
||||
|
||||
my $domain = $c->request->params->{domain};
|
||||
|
||||
$settings{cc} = $c->request->params->{cc};
|
||||
$messages{acc} = 'Client.Voip.MalformedCc'
|
||||
unless $settings{cc} =~ /^\d+$/;
|
||||
|
||||
$settings{timezone} = $c->request->params->{timezone};
|
||||
$messages{atimezone} = 'Client.Syntax.MalformedTimezone'
|
||||
unless $settings{timezone} =~ m#^\w+/\w.+$#;
|
||||
|
||||
unless(keys %messages) {
|
||||
if($c->model('Provisioning')->call_prov( $c, 'billing', 'create_domain',
|
||||
{ domain => $domain,
|
||||
data => \%settings,
|
||||
},
|
||||
undef
|
||||
))
|
||||
{
|
||||
$messages{cdommsg} = 'Server.Voip.SavedSettings';
|
||||
$c->session->{messages} = \%messages;
|
||||
$c->response->redirect("/domain");
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
$messages{cdomerr} = 'Client.Voip.InputErrorFound';
|
||||
}
|
||||
|
||||
$c->session->{messages} = \%messages;
|
||||
$c->session->{restore_domadd_input} = \%settings;
|
||||
$c->session->{restore_domadd_input}{domain} = $domain;
|
||||
$c->response->redirect("/domain");
|
||||
return;
|
||||
}
|
||||
|
||||
=head2 do_delete_domain
|
||||
|
||||
Delete a domain.
|
||||
|
||||
=cut
|
||||
|
||||
sub do_delete_domain : Local {
|
||||
my ( $self, $c ) = @_;
|
||||
|
||||
my $domain = $c->request->params->{domain};
|
||||
if($c->model('Provisioning')->call_prov( $c, 'billing', 'delete_domain',
|
||||
{ domain => $domain },
|
||||
undef
|
||||
))
|
||||
{
|
||||
$c->session->{messages}{edommsg} = 'Web.Domain.Deleted';
|
||||
$c->response->redirect("/domain");
|
||||
return;
|
||||
}
|
||||
|
||||
$c->response->redirect("/domain");
|
||||
return;
|
||||
}
|
||||
|
||||
=head1 BUGS AND LIMITATIONS
|
||||
|
||||
=over
|
||||
|
||||
=item currently none
|
||||
|
||||
=back
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
Provisioning model, Sipwise::Provisioning::Billing, Catalyst
|
||||
|
||||
=head1 AUTHORS
|
||||
|
||||
Daniel Tiefnig <dtiefnig@sipwise.com>
|
||||
|
||||
=head1 COPYRIGHT
|
||||
|
||||
The domain controller is Copyright (c) 2007 Sipwise GmbH, Austria. All
|
||||
rights reserved.
|
||||
|
||||
=cut
|
||||
|
||||
# ende gelaende
|
||||
1;
|
@ -0,0 +1,67 @@
|
||||
package admin::Controller::login;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use base 'Catalyst::Controller';
|
||||
|
||||
=head1 NAME
|
||||
|
||||
admin::Controller::login - Catalyst Controller
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This allows a user to log in.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
=head2 index
|
||||
|
||||
The authentication function.
|
||||
|
||||
=cut
|
||||
|
||||
sub index : Private {
|
||||
my ( $self, $c ) = @_;
|
||||
|
||||
$c->log->debug('***login::index called');
|
||||
|
||||
my $username = $c->request->params->{username} || "";
|
||||
my $password = $c->request->params->{password} || "";
|
||||
|
||||
if ($username && $password) {
|
||||
if($c->model('Provisioning')->login($c, $username, $password)) {
|
||||
$c->log->debug('***Login::index login successfull');
|
||||
}
|
||||
} else {
|
||||
$c->session->{prov_error} = 'Client.Syntax.LoginMissingPass' unless length $password;
|
||||
$c->session->{prov_error} = 'Client.Syntax.LoginMissingUsername' unless length $username;
|
||||
}
|
||||
|
||||
$c->response->redirect($c->uri_for('/'));
|
||||
}
|
||||
|
||||
=head1 BUGS AND LIMITATIONS
|
||||
|
||||
=over
|
||||
|
||||
=item currently none
|
||||
|
||||
=back
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
Provisioning model, Catalyst
|
||||
|
||||
=head1 AUTHORS
|
||||
|
||||
Daniel Tiefnig <dtiefnig@sipwise.com>
|
||||
|
||||
=head1 COPYRIGHT
|
||||
|
||||
The login controller is Copyright (c) 2007 Sipwise GmbH, Austria. All
|
||||
rights reserved.
|
||||
|
||||
=cut
|
||||
|
||||
# ende gelaende
|
||||
1;
|
@ -0,0 +1,59 @@
|
||||
package admin::Controller::logout;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use base 'Catalyst::Controller';
|
||||
|
||||
=head1 NAME
|
||||
|
||||
admin::Controller::logout - Catalyst Controller
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This will log a user out.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
=head2 index
|
||||
|
||||
The logout function.
|
||||
|
||||
=cut
|
||||
|
||||
sub index : Private {
|
||||
my ( $self, $c ) = @_;
|
||||
|
||||
$c->log->debug('***logout::index called');
|
||||
|
||||
$c->logout();
|
||||
|
||||
delete $c->session->{admin};
|
||||
|
||||
$c->response->redirect($c->uri_for('/'));
|
||||
}
|
||||
|
||||
=head1 BUGS AND LIMITATIONS
|
||||
|
||||
=over
|
||||
|
||||
=item currently none
|
||||
|
||||
=back
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
Provisioning model, Catalyst
|
||||
|
||||
=head1 AUTHORS
|
||||
|
||||
Daniel Tiefnig <dtiefnig@sipwise.com>
|
||||
|
||||
=head1 COPYRIGHT
|
||||
|
||||
The logout controller is Copyright (c) 2007 Sipwise GmbH, Austria. All
|
||||
rights reserved.
|
||||
|
||||
=cut
|
||||
|
||||
# ende gelaende
|
||||
1;
|
@ -0,0 +1,850 @@
|
||||
package admin::Controller::subscriber;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use base 'Catalyst::Controller';
|
||||
|
||||
=head1 NAME
|
||||
|
||||
admin::Controller::subscriber - Catalyst Controller
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This provides functionality for VoIP subscriber administration.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
=head2 index
|
||||
|
||||
Display search form.
|
||||
|
||||
=cut
|
||||
|
||||
sub index : Private {
|
||||
my ( $self, $c ) = @_;
|
||||
$c->stash->{template} = 'tt/subscriber.tt';
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
=head2 search
|
||||
|
||||
Search for subscribers and display results.
|
||||
|
||||
=cut
|
||||
|
||||
sub search : Local {
|
||||
my ( $self, $c ) = @_;
|
||||
$c->stash->{template} = 'tt/subscriber.tt';
|
||||
|
||||
my $limit = 10;
|
||||
|
||||
my $searchstring = $c->request->params->{search_string};
|
||||
my $offset = $c->request->params->{offset} || 0;
|
||||
$offset = 0 if $offset !~ /^\d+$/;
|
||||
|
||||
my $subscriber_list;
|
||||
return unless $c->model('Provisioning')->call_prov( $c, 'billing', 'search_subscribers',
|
||||
{ filter => { username => '%'.$searchstring.'%',
|
||||
limit => $limit,
|
||||
offset => $limit * $offset,
|
||||
},
|
||||
},
|
||||
\$subscriber_list
|
||||
);
|
||||
|
||||
$c->stash->{search_string} = $searchstring;
|
||||
$c->stash->{searched} = 1;
|
||||
if(ref $$subscriber_list{subscribers} eq 'ARRAY' and @{$$subscriber_list{subscribers}}) {
|
||||
$c->stash->{subscriber_list} = $$subscriber_list{subscribers};
|
||||
$c->stash->{total_count} = $$subscriber_list{total_count};
|
||||
$c->stash->{offset} = $offset;
|
||||
if($$subscriber_list{total_count} > @{$$subscriber_list{subscribers}}) {
|
||||
# paginate!
|
||||
my @pagination;
|
||||
foreach my $page (0 .. int(($$subscriber_list{total_count} - 1) / $limit)) {
|
||||
push @pagination, { offset => $page };
|
||||
}
|
||||
$c->stash->{max_offset} = $#pagination;
|
||||
if($#pagination > 10) {
|
||||
if($offset <= 5) {
|
||||
splice @pagination, 9, @pagination - (10), ({offset => -1});
|
||||
} else {
|
||||
if($offset < @pagination - 6) {
|
||||
splice @pagination, $offset + 4, @pagination - ($offset + 5), ({offset => -1});
|
||||
splice @pagination, 1, $offset - 4, ({offset => -1});
|
||||
} else {
|
||||
splice @pagination, 1, @pagination - 10, ({offset => -1});
|
||||
}
|
||||
}
|
||||
}
|
||||
$c->stash->{pagination} = \@pagination;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
=head2 detail
|
||||
|
||||
Display subscriber details.
|
||||
|
||||
=cut
|
||||
|
||||
sub detail : Local {
|
||||
my ( $self, $c ) = @_;
|
||||
$c->stash->{template} = 'tt/subscriber_detail.tt';
|
||||
|
||||
my $is_new = $c->request->params->{new};
|
||||
my $preferences;
|
||||
|
||||
unless($is_new) {
|
||||
my $subscriber_id = $c->request->params->{subscriber_id};
|
||||
return unless $c->model('Provisioning')->call_prov( $c, 'voip', 'get_subscriber_byid',
|
||||
{ subscriber_id => $subscriber_id },
|
||||
\$c->session->{subscriber}
|
||||
);
|
||||
return unless $c->model('Provisioning')->call_prov( $c, 'voip', 'get_subscriber_preferences',
|
||||
{ username => $c->session->{subscriber}{username},
|
||||
domain => $c->session->{subscriber}{domain},
|
||||
},
|
||||
\$preferences
|
||||
);
|
||||
return unless $c->model('Provisioning')->call_prov( $c, 'voip', 'get_subscriber_voicebox_preferences',
|
||||
{ username => $c->session->{subscriber}{username},
|
||||
domain => $c->session->{subscriber}{domain},
|
||||
},
|
||||
\$c->session->{subscriber}{voicebox_preferences}
|
||||
);
|
||||
|
||||
$c->stash->{subscriber} = $c->session->{subscriber};
|
||||
$c->stash->{subscriber}{subscriber_id} = $subscriber_id;
|
||||
$c->stash->{subscriber}{is_locked} = $c->model('Provisioning')->localize($c->view($c->config->{view})->
|
||||
config->{VARIABLES}{site_config}{language},
|
||||
'Web.Subscriber.Lock'.$$preferences{lock})
|
||||
if $$preferences{lock};
|
||||
} else {
|
||||
$c->stash->{account_id} = $c->request->params->{account_id};
|
||||
$c->stash->{edit_subscriber} = 1;
|
||||
my $domains;
|
||||
return unless $c->model('Provisioning')->call_prov( $c, 'billing', 'get_domains',
|
||||
undef, \$domains
|
||||
);
|
||||
$c->stash->{domains} = $$domains{result};
|
||||
}
|
||||
|
||||
my $db_prefs;
|
||||
return unless $c->model('Provisioning')->call_prov( $c, 'voip', 'get_preferences',
|
||||
undef, \$db_prefs
|
||||
);
|
||||
$c->session->{voip_preferences} = $$db_prefs{result};
|
||||
|
||||
### restore data entered by the user ###
|
||||
|
||||
if(ref $c->session->{restore_subscriber_input} eq 'HASH') {
|
||||
if(ref $c->stash->{subscriber} eq 'HASH') {
|
||||
$c->stash->{subscriber} = { %{$c->stash->{subscriber}}, %{$c->session->{restore_subscriber_input}} };
|
||||
} else {
|
||||
$c->stash->{subscriber} = $c->session->{restore_subscriber_input};
|
||||
}
|
||||
$c->stash->{subscriber}{edit_pass} = $c->session->{restore_subscriber_input}{password}
|
||||
if defined $c->session->{restore_subscriber_input}{password};
|
||||
$c->stash->{subscriber}{edit_webpass} = $c->session->{restore_subscriber_input}{webpassword}
|
||||
if defined $c->session->{restore_subscriber_input}{webpassword};
|
||||
delete $c->session->{restore_subscriber_input};
|
||||
}
|
||||
if(ref $c->session->{restore_preferences_input} eq 'HASH') {
|
||||
if(ref $preferences eq 'HASH') {
|
||||
$preferences = { %$preferences, %{$c->session->{restore_preferences_input}} };
|
||||
} else {
|
||||
$preferences = $c->session->{restore_preferences_input};
|
||||
}
|
||||
delete $c->session->{restore_preferences_input};
|
||||
}
|
||||
if(ref $c->session->{restore_vboxprefs_input} eq 'HASH') {
|
||||
if(ref $c->stash->{subscriber}{voicebox_preferences} eq 'HASH') {
|
||||
$c->stash->{subscriber}{voicebox_preferences} = { %{$c->stash->{subscriber}{voicebox_preferences}},
|
||||
%{$c->session->{restore_vboxprefs_input}} };
|
||||
} else {
|
||||
$c->stash->{subscriber}{voicebox_preferences} = $c->session->{restore_vboxprefs_input};
|
||||
}
|
||||
delete $c->session->{restore_vboxprefs_input};
|
||||
}
|
||||
|
||||
### build preference array for TT ###
|
||||
|
||||
if(ref $c->session->{voip_preferences} eq 'ARRAY') {
|
||||
|
||||
my $cftarget;
|
||||
my @stashprefs;
|
||||
|
||||
foreach my $pref (@{$c->session->{voip_preferences}}) {
|
||||
|
||||
# not a subscriber preference
|
||||
next if $$pref{attribute} eq 'cc';
|
||||
# managed separately
|
||||
next if $$pref{attribute} eq 'lock';
|
||||
|
||||
# only for extensions enabled systems
|
||||
next if ( $$pref{attribute} eq 'base_cli'
|
||||
or $$pref{attribute} eq 'base_user'
|
||||
or $$pref{attribute} eq 'extension'
|
||||
or $$pref{attribute} eq 'has_extension' )
|
||||
and !$c->config->{extension_features};
|
||||
|
||||
|
||||
if($$pref{attribute} eq 'cfu'
|
||||
or $$pref{attribute} eq 'cfb'
|
||||
or $$pref{attribute} eq 'cft'
|
||||
or $$pref{attribute} eq 'cfna')
|
||||
{
|
||||
if(defined $$preferences{$$pref{attribute}} and length $$preferences{$$pref{attribute}}) {
|
||||
if($$preferences{$$pref{attribute}} =~ /voicebox\.local$/) {
|
||||
$$cftarget{voicebox} = 1;
|
||||
} else {
|
||||
$$cftarget{sipuri} = $$preferences{$$pref{attribute}};
|
||||
$$cftarget{sipuri} =~ s/^sip://i;
|
||||
if($$cftarget{sipuri} =~ /^\+?\d+\@/) {
|
||||
$$cftarget{sipuri} =~ s/\@.*$//;
|
||||
}
|
||||
}
|
||||
}
|
||||
} elsif($$pref{attribute} eq 'cli') {
|
||||
if(defined $$preferences{$$pref{attribute}} and length $$preferences{$$pref{attribute}}) {
|
||||
$$preferences{$$pref{attribute}} =~ s/^sip://i;
|
||||
$$preferences{$$pref{attribute}} =~ s/\@.*$//
|
||||
if $$preferences{$$pref{attribute}} =~ /^\+?\d+\@/;
|
||||
}
|
||||
}
|
||||
|
||||
push @stashprefs,
|
||||
{ key => $$pref{attribute},
|
||||
value => $$preferences{$$pref{attribute}},
|
||||
max_occur => $$pref{max_occur},
|
||||
error => $c->session->{messages}{$$pref{attribute}}
|
||||
? $c->model('Provisioning')->localize($c->view($c->config->{view})->
|
||||
config->{VARIABLES}{site_config}{language},
|
||||
$c->session->{messages}{$$pref{attribute}})
|
||||
: undef,
|
||||
};
|
||||
}
|
||||
|
||||
# OMG
|
||||
# reorder preferences so "cftarget" appears just above "cfu" and friends
|
||||
foreach my $stashpref (@stashprefs) {
|
||||
if($$stashpref{key} eq 'cfu') {
|
||||
push @{$c->stash->{subscriber}{preferences_array}},
|
||||
{ key => 'cftarget',
|
||||
value => $cftarget,
|
||||
max_occur => 1,
|
||||
error => $c->session->{messages}{cftarget}
|
||||
? $c->model('Provisioning')->localize($c->view($c->config->{view})->
|
||||
config->{VARIABLES}{site_config}{language},
|
||||
$c->session->{messages}{cftarget})
|
||||
: undef,
|
||||
};
|
||||
}
|
||||
push @{$c->stash->{subscriber}{preferences_array}}, $stashpref;
|
||||
}
|
||||
}
|
||||
|
||||
$c->stash->{show_pass} = $c->request->params->{show_pass};
|
||||
$c->stash->{show_webpass} = $c->request->params->{show_webpass};
|
||||
$c->stash->{edit_subscriber} = $c->request->params->{edit_subscriber}
|
||||
unless $is_new;
|
||||
$c->stash->{edit_preferences} = $c->request->params->{edit_preferences};
|
||||
$c->stash->{edit_voicebox} = $c->request->params->{edit_voicebox};
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
=head2 update_subscriber
|
||||
|
||||
Update subscriber data or create a new subscriber.
|
||||
|
||||
=cut
|
||||
|
||||
sub update_subscriber : Local {
|
||||
my ( $self, $c ) = @_;
|
||||
|
||||
my (%settings, %messages);
|
||||
|
||||
my $subscriber_id = $c->request->params->{subscriber_id};
|
||||
if($subscriber_id) {
|
||||
return unless $c->model('Provisioning')->call_prov( $c, 'voip', 'get_subscriber_byid',
|
||||
{ subscriber_id => $subscriber_id },
|
||||
\$c->session->{subscriber}
|
||||
);
|
||||
} else {
|
||||
my $checkresult;
|
||||
$c->session->{subscriber}{account_id} = $c->request->params->{account_id};
|
||||
|
||||
$c->session->{subscriber}{username} = $settings{webusername} = $c->request->params->{username};
|
||||
return unless $c->model('Provisioning')->call_prov( $c, 'voip', 'check_username',
|
||||
$c->session->{subscriber}{username}, \$checkresult
|
||||
);
|
||||
$messages{username} = 'Client.Syntax.MalformedUsername' unless($checkresult);
|
||||
|
||||
$c->session->{subscriber}{domain} = $c->request->params->{domain};
|
||||
return unless $c->model('Provisioning')->call_prov( $c, 'voip', 'check_domain',
|
||||
$c->session->{subscriber}{domain}, \$checkresult
|
||||
);
|
||||
$messages{domain} = 'Client.Syntax.MalformedDomain' unless($checkresult);
|
||||
}
|
||||
|
||||
$settings{admin} = 1 if $c->request->params->{admin};
|
||||
|
||||
my $password = $c->request->params->{password};
|
||||
if(length $password) {
|
||||
$settings{password} = $password;
|
||||
if(length $password < 6) {
|
||||
$messages{password} = 'Client.Voip.PassLength';
|
||||
}
|
||||
}
|
||||
my $webpassword = $c->request->params->{webpassword};
|
||||
if(length $webpassword) {
|
||||
$settings{webpassword} = $webpassword;
|
||||
if(length $webpassword < 6) {
|
||||
$messages{webpassword} = 'Client.Voip.PassLength';
|
||||
}
|
||||
}
|
||||
|
||||
my $cc = $c->request->params->{cc};
|
||||
my $ac = $c->request->params->{ac};
|
||||
my $sn = $c->request->params->{sn};
|
||||
if(length $cc or length $ac or length $sn) {
|
||||
$settings{cc} = $cc;
|
||||
$settings{ac} = $ac;
|
||||
$settings{sn} = $sn;
|
||||
unless(length $cc and length $ac and length $sn) {
|
||||
$messages{number} = 'Client.Voip.MissingNumberPart';
|
||||
} else {
|
||||
$messages{number_cc} = 'Client.Voip.MalformedCc'
|
||||
unless $cc =~ /^[1-9][0-9]{0,2}$/;
|
||||
$messages{number_ac} = 'Client.Voip.MalformedAc'
|
||||
unless $ac =~ /^[1-9][0-9]{0,4}$/;
|
||||
$messages{number_sn} = 'Client.Voip.MalformedSn'
|
||||
unless $sn =~ /^[1-9][0-9]+$/;
|
||||
}
|
||||
}
|
||||
my $timezone = $c->request->params->{timezone};
|
||||
if(length $timezone) {
|
||||
$settings{timezone} = $timezone;
|
||||
$messages{timezone} = 'Client.Syntax.MalformedTimezone'
|
||||
unless $timezone =~ m#^\w+/\w.+$#;
|
||||
}
|
||||
|
||||
unless(keys %messages) {
|
||||
if($c->model('Provisioning')->call_prov( $c, 'billing', ($subscriber_id
|
||||
? 'update_voip_account_subscriber'
|
||||
: 'add_voip_account_subscriber'),
|
||||
{ id => $c->session->{subscriber}{account_id},
|
||||
subscriber => { username => $c->session->{subscriber}{username},
|
||||
domain => $c->session->{subscriber}{domain},
|
||||
%settings
|
||||
},
|
||||
},
|
||||
undef))
|
||||
{
|
||||
$messages{submsg} = 'Server.Voip.SavedSettings';
|
||||
$c->session->{messages} = \%messages;
|
||||
if($subscriber_id) {
|
||||
$c->response->redirect("/subscriber/detail?subscriber_id=$subscriber_id");
|
||||
} else {
|
||||
return unless $c->model('Provisioning')->call_prov( $c, 'voip', 'get_subscriber',
|
||||
{ username => $c->session->{subscriber}{username},
|
||||
domain => $c->session->{subscriber}{domain},
|
||||
},
|
||||
\$c->session->{subscriber}
|
||||
);
|
||||
$c->response->redirect("/subscriber/detail?subscriber_id=". $c->session->{subscriber}{subscriber_id});
|
||||
}
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
$messages{suberr} = 'Client.Voip.InputErrorFound';
|
||||
}
|
||||
|
||||
$c->session->{messages} = \%messages;
|
||||
$c->session->{restore_subscriber_input} = \%settings;
|
||||
if($subscriber_id) {
|
||||
$c->response->redirect("/subscriber/detail?subscriber_id=$subscriber_id&edit_subscriber=1");
|
||||
} else {
|
||||
$c->session->{restore_subscriber_input}{username} = $c->session->{subscriber}{username};
|
||||
$c->response->redirect("/subscriber/detail?account_id=". $c->session->{subscriber}{account_id} ."&new=1");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
=head2 lock
|
||||
|
||||
Locks a subscriber.
|
||||
|
||||
=cut
|
||||
|
||||
sub lock : Local {
|
||||
my ( $self, $c ) = @_;
|
||||
|
||||
my $subscriber_id = $c->request->params->{subscriber_id};
|
||||
return unless $c->model('Provisioning')->call_prov( $c, 'voip', 'get_subscriber_byid',
|
||||
{ subscriber_id => $subscriber_id },
|
||||
\$c->session->{subscriber}
|
||||
);
|
||||
|
||||
my $lock = $c->request->params->{lock};
|
||||
$c->model('Provisioning')->call_prov( $c, 'billing', 'lock_voip_account_subscriber',
|
||||
{ id => $c->session->{subscriber}{account_id},
|
||||
username => $c->session->{subscriber}{username},
|
||||
domain => $c->session->{subscriber}{domain},
|
||||
lock => $lock,
|
||||
},
|
||||
undef
|
||||
);
|
||||
|
||||
$c->response->redirect("/subscriber/detail?subscriber_id=". $c->request->params->{subscriber_id});
|
||||
}
|
||||
|
||||
=head2 terminate
|
||||
|
||||
Terminates a subscriber.
|
||||
|
||||
=cut
|
||||
|
||||
sub terminate : Local {
|
||||
my ( $self, $c ) = @_;
|
||||
|
||||
my %messages;
|
||||
|
||||
my $subscriber_id = $c->request->params->{subscriber_id};
|
||||
return unless $c->model('Provisioning')->call_prov( $c, 'voip', 'get_subscriber_byid',
|
||||
{ subscriber_id => $subscriber_id },
|
||||
\$c->session->{subscriber}
|
||||
);
|
||||
|
||||
if($c->model('Provisioning')->call_prov( $c, 'billing', 'terminate_voip_account_subscriber',
|
||||
{ id => $c->session->{subscriber}{account_id},
|
||||
username => $c->session->{subscriber}{username},
|
||||
domain => $c->session->{subscriber}{domain},
|
||||
},
|
||||
undef))
|
||||
{
|
||||
$messages{topmsg} = 'Server.Voip.SubscriberDeleted';
|
||||
$c->session->{messages} = \%messages;
|
||||
$c->response->redirect("/subscriber");
|
||||
return;
|
||||
}
|
||||
|
||||
$c->session->{messages} = \%messages;
|
||||
$c->response->redirect("/subscriber/detail?subscriber_id=$subscriber_id");
|
||||
return;
|
||||
}
|
||||
|
||||
sub update_preferences : Local {
|
||||
my ( $self, $c ) = @_;
|
||||
|
||||
my %messages;
|
||||
|
||||
my $subscriber_id = $c->request->params->{subscriber_id};
|
||||
return unless $c->model('Provisioning')->call_prov( $c, 'voip', 'get_subscriber_byid',
|
||||
{ subscriber_id => $subscriber_id },
|
||||
\$c->session->{subscriber}
|
||||
);
|
||||
my $preferences;
|
||||
return unless $c->model('Provisioning')->call_prov( $c, 'voip', 'get_subscriber_preferences',
|
||||
{ username => $c->session->{subscriber}{username},
|
||||
domain => $c->session->{subscriber}{domain},
|
||||
},
|
||||
\$preferences
|
||||
);
|
||||
## remove preferences that can't be changed
|
||||
delete $$preferences{prepaid};
|
||||
delete $$preferences{base_cli};
|
||||
delete $$preferences{extension};
|
||||
delete $$preferences{base_user};
|
||||
delete $$preferences{has_extension};
|
||||
|
||||
### blocklists ###
|
||||
|
||||
my $block_in_mode = $c->request->params->{block_in_mode};
|
||||
if(defined $block_in_mode) {
|
||||
$$preferences{block_in_mode} = $block_in_mode eq 'whitelist' ? 1 : 0;
|
||||
}
|
||||
my $block_out_mode = $c->request->params->{block_out_mode};
|
||||
if(defined $block_out_mode) {
|
||||
$$preferences{block_out_mode} = $block_out_mode eq 'whitelist' ? 1 : 0;
|
||||
}
|
||||
|
||||
$$preferences{block_in_clir} = $c->request->params->{block_in_clir} ? 1 : undef;
|
||||
|
||||
my $block_in_list = $c->request->params->{block_in_list};
|
||||
|
||||
### call forwarding ###
|
||||
|
||||
my $fw_target_select = $c->request->params->{fw_target};
|
||||
unless($fw_target_select) {
|
||||
$messages{target} = 'Client.Voip.MalformedTargetClass';
|
||||
}
|
||||
my $fw_target;
|
||||
if($fw_target_select eq 'sipuri') {
|
||||
$fw_target = $c->request->params->{fw_sipuri};
|
||||
|
||||
# normalize, so we can do some checks.
|
||||
$fw_target =~ s/^sip://i;
|
||||
if($fw_target =~ /^\+?\d+\@[a-z0-9.-]+$/i) {
|
||||
$fw_target =~ s/\@.+$//;
|
||||
}
|
||||
|
||||
if($fw_target =~ /^\+?\d+$/) {
|
||||
if($fw_target =~ /^\+[1-9][0-9]+$/) {
|
||||
$fw_target = 'sip:'. $fw_target .'@'. $c->session->{subscriber}{domain};
|
||||
} elsif($fw_target =~ /^00[1-9][0-9]+$/) {
|
||||
$fw_target =~ s/^00/+/;
|
||||
$fw_target = 'sip:'. $fw_target .'@'. $c->session->{subscriber}{domain};
|
||||
} elsif($fw_target =~ /^0[1-9][0-9]+$/) {
|
||||
$fw_target =~ s/^0/'+'.$c->session->{subscriber}{cc}/e;
|
||||
$fw_target = 'sip:'. $fw_target .'@'. $c->session->{subscriber}{domain};
|
||||
} else {
|
||||
$messages{target} = 'Client.Voip.MalformedNumber';
|
||||
$fw_target = $c->request->params->{fw_sipuri};
|
||||
}
|
||||
} elsif($fw_target =~ /^[a-z0-9&=+\$,;?\/_.!~*'()-]+\@[a-z0-9.-]+$/i) {
|
||||
$fw_target = 'sip:'. lc $fw_target;
|
||||
} elsif($fw_target =~ /^[a-z0-9&=+\$,;?\/_.!~*'()-]+$/) {
|
||||
$fw_target = 'sip:'. lc($fw_target) .'@'. $c->session->{subscriber}{domain};
|
||||
} else {
|
||||
$messages{target} = 'Client.Voip.MalformedTarget';
|
||||
$fw_target = $c->request->params->{fw_sipuri};
|
||||
}
|
||||
} elsif($fw_target_select eq 'voicebox') {
|
||||
$fw_target = 'sip:vmu'.$c->session->{subscriber}{cc}.$c->session->{subscriber}{ac}.$c->session->{subscriber}{sn}.'@voicebox.local';
|
||||
} else {
|
||||
# wtf?
|
||||
}
|
||||
|
||||
my $cfu = $c->request->params->{cfu};
|
||||
my $cfb = $c->request->params->{cfb};
|
||||
my $cft = $c->request->params->{cft};
|
||||
my $cfna = $c->request->params->{cfna};
|
||||
|
||||
# clear all forwards
|
||||
$$preferences{cfu} = undef;
|
||||
$$preferences{cft} = undef;
|
||||
$$preferences{cfb} = undef;
|
||||
$$preferences{cfna} = undef;
|
||||
$$preferences{ringtimeout} = undef;
|
||||
|
||||
unless(defined $cfu or defined $cfb or defined $cft or defined $cfna) {
|
||||
delete $messages{target} if exists $messages{target};
|
||||
} else {
|
||||
if(defined $cfu) {
|
||||
# forward unconditionally
|
||||
$$preferences{cfu} = $fw_target;
|
||||
} else {
|
||||
if(defined $cfb) {
|
||||
$$preferences{cfb} = $fw_target;
|
||||
}
|
||||
if(defined $cft) {
|
||||
$$preferences{cft} = $fw_target;
|
||||
}
|
||||
if(defined $cfna) {
|
||||
$$preferences{cfna} = $fw_target;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(defined $$preferences{cft}) {
|
||||
$$preferences{ringtimeout} = $c->request->params->{ringtimeout};
|
||||
unless(defined $$preferences{ringtimeout} and $$preferences{ringtimeout} =~ /^\d+$/
|
||||
and $$preferences{ringtimeout} < 301 and $$preferences{ringtimeout} > 4)
|
||||
{
|
||||
$messages{ringtimeout} = 'Client.Voip.MissingRingtimeout';
|
||||
}
|
||||
}
|
||||
|
||||
### outgoing calls ###
|
||||
|
||||
$$preferences{cli} = $c->request->params->{cli} or undef;
|
||||
if(defined $$preferences{cli} and $$preferences{cli} =~ /^\d+$/) {
|
||||
$$preferences{cli} = 'sip:'.$$preferences{cli}.'@'.$c->session->{subscriber}{domain};
|
||||
}
|
||||
|
||||
$$preferences{clir} = $c->request->params->{clir} ? 1 : undef;
|
||||
|
||||
$$preferences{cc} = $c->request->params->{cc} || undef;
|
||||
if(defined $$preferences{cc} and $$preferences{cc} !~ /^[1-9]\d*$/) {
|
||||
$messages{cc} = 'Client.Voip.MalformedCc';
|
||||
}
|
||||
$$preferences{ac} = $c->request->params->{ac} || undef;
|
||||
if(defined $$preferences{ac} and $$preferences{ac} !~ /^[1-9]\d*$/) {
|
||||
$messages{ac} = 'Client.Voip.MalformedAc';
|
||||
}
|
||||
$$preferences{svc_ac} = $c->request->params->{svc_ac} || undef;
|
||||
if(defined $$preferences{svc_ac} and $$preferences{svc_ac} !~ /^[1-9]\d*$/) {
|
||||
$messages{svc_ac} = 'Client.Voip.MalformedAc';
|
||||
}
|
||||
$$preferences{emerg_ac} = $c->request->params->{emerg_ac} || undef;
|
||||
if(defined $$preferences{emerg_ac} and $$preferences{emerg_ac} !~ /^[1-9]\d*$/) {
|
||||
$messages{emerg_ac} = 'Client.Voip.MalformedAc';
|
||||
}
|
||||
|
||||
### save settings ###
|
||||
|
||||
unless(keys %messages) {
|
||||
if($c->model('Provisioning')->call_prov( $c, 'voip', 'set_subscriber_preferences',
|
||||
{ username => $c->session->{subscriber}{username},
|
||||
domain => $c->session->{subscriber}{domain},
|
||||
preferences => $preferences,
|
||||
},
|
||||
undef
|
||||
))
|
||||
{
|
||||
$messages{prefmsg} = 'Server.Voip.SavedSettings';
|
||||
$c->session->{messages} = \%messages;
|
||||
$c->response->redirect("/subscriber/detail?subscriber_id=$subscriber_id#userprefs");
|
||||
return;
|
||||
|
||||
}
|
||||
} else {
|
||||
$messages{preferr} = 'Client.Voip.InputErrorFound';
|
||||
}
|
||||
|
||||
$c->session->{messages} = \%messages;
|
||||
$c->session->{restore_preferences_input} = $preferences;
|
||||
$c->response->redirect("/subscriber/detail?subscriber_id=$subscriber_id&edit_preferences=1#userprefs");
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
sub update_voicebox : Local {
|
||||
my ( $self, $c ) = @_;
|
||||
|
||||
my %messages;
|
||||
|
||||
my $subscriber_id = $c->request->params->{subscriber_id};
|
||||
return unless $c->model('Provisioning')->call_prov( $c, 'voip', 'get_subscriber_byid',
|
||||
{ subscriber_id => $subscriber_id },
|
||||
\$c->session->{subscriber}
|
||||
);
|
||||
my $vboxprefs;
|
||||
return unless $c->model('Provisioning')->call_prov( $c, 'voip', 'get_subscriber_voicebox_preferences',
|
||||
{ username => $c->session->{subscriber}{username},
|
||||
domain => $c->session->{subscriber}{domain},
|
||||
},
|
||||
\$vboxprefs
|
||||
);
|
||||
$$vboxprefs{password} = $c->request->params->{password} || undef;
|
||||
if(defined $$vboxprefs{password} and $$vboxprefs{password} !~ /^\d{4}$/) {
|
||||
$messages{vpin} = 'Client.Syntax.VoiceBoxPin';
|
||||
}
|
||||
|
||||
$$vboxprefs{email} = $c->request->params->{email};
|
||||
if(defined $$vboxprefs{email} and length $$vboxprefs{email}) {
|
||||
my $checkresult;
|
||||
return unless $c->model('Provisioning')->call_prov( $c, 'voip', 'check_email',
|
||||
$$vboxprefs{email}, \$checkresult
|
||||
);
|
||||
$messages{vemail} = 'Client.Syntax.Email' unless($checkresult);
|
||||
} else {
|
||||
$$vboxprefs{email} = undef;
|
||||
}
|
||||
|
||||
$$vboxprefs{attach} = $c->request->params->{attach} ? 1 : 0;
|
||||
|
||||
### save settings ###
|
||||
|
||||
unless(keys %messages) {
|
||||
if($c->model('Provisioning')->call_prov( $c, 'voip', 'set_subscriber_voicebox_preferences',
|
||||
{ username => $c->session->{subscriber}{username},
|
||||
domain => $c->session->{subscriber}{domain},
|
||||
preferences => $vboxprefs,
|
||||
},
|
||||
undef
|
||||
))
|
||||
{
|
||||
$messages{vboxmsg} = 'Server.Voip.SavedSettings';
|
||||
$c->session->{messages} = \%messages;
|
||||
$c->response->redirect("/subscriber/detail?subscriber_id=$subscriber_id#vboxprefs");
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
$messages{vboxerr} = 'Client.Voip.InputErrorFound';
|
||||
}
|
||||
|
||||
$c->session->{messages} = \%messages;
|
||||
$c->session->{restore_vboxprefs_input} = $vboxprefs;
|
||||
$c->response->redirect("/subscriber/detail?subscriber_id=$subscriber_id&edit_voicebox=1#vboxprefs");
|
||||
return;
|
||||
}
|
||||
|
||||
sub edit_list : Local {
|
||||
my ( $self, $c ) = @_;
|
||||
$c->stash->{template} = 'tt/subscriber_edit_list.tt';
|
||||
|
||||
my %messages;
|
||||
|
||||
my $subscriber_id = $c->request->params->{subscriber_id};
|
||||
return unless $c->model('Provisioning')->call_prov( $c, 'voip', 'get_subscriber_byid',
|
||||
{ subscriber_id => $subscriber_id },
|
||||
\$c->session->{subscriber}
|
||||
);
|
||||
my $preferences;
|
||||
return unless $c->model('Provisioning')->call_prov( $c, 'voip', 'get_subscriber_preferences',
|
||||
{ username => $c->session->{subscriber}{username},
|
||||
domain => $c->session->{subscriber}{domain},
|
||||
},
|
||||
\$preferences
|
||||
);
|
||||
my $list = $c->request->params->{list_name};
|
||||
|
||||
if(defined $$preferences{$list}) {
|
||||
my $block_list = ref $$preferences{$list} ? $$preferences{$list} : [ $$preferences{$list} ];
|
||||
|
||||
my @block_list_to_sort;
|
||||
foreach my $blockentry (@$block_list) {
|
||||
my $active = $blockentry =~ s/^#// ? 0 : 1;
|
||||
$blockentry =~ s/^([1-9])/+$1/;
|
||||
push @block_list_to_sort, { entry => $blockentry, active => $active };
|
||||
}
|
||||
my $bg = '';
|
||||
my $i = 1;
|
||||
foreach my $blockentry (sort {$a->{entry} cmp $b->{entry}} @block_list_to_sort) {
|
||||
push @{$c->stash->{list_data}}, { number => $$blockentry{entry},
|
||||
background => $bg ? '' : 'alt',
|
||||
id => $i++,
|
||||
active => $$blockentry{active},
|
||||
};
|
||||
$bg = !$bg;
|
||||
}
|
||||
}
|
||||
|
||||
$c->stash->{subscriber} = $c->session->{subscriber};
|
||||
$c->stash->{subscriber_id} = $subscriber_id;
|
||||
$c->stash->{list_name} = $list;
|
||||
if(defined $c->session->{blockaddtxt}) {
|
||||
$c->stash->{blockaddtxt} = $c->session->{blockaddtxt};
|
||||
delete $c->session->{blockaddtxt};
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
sub do_edit_list : Local {
|
||||
my ( $self, $c ) = @_;
|
||||
|
||||
my %messages;
|
||||
|
||||
my $subscriber_id = $c->request->params->{subscriber_id};
|
||||
return unless $c->model('Provisioning')->call_prov( $c, 'voip', 'get_subscriber_byid',
|
||||
{ subscriber_id => $subscriber_id },
|
||||
\$c->session->{subscriber}
|
||||
);
|
||||
my $preferences;
|
||||
return unless $c->model('Provisioning')->call_prov( $c, 'voip', 'get_subscriber_preferences',
|
||||
{ username => $c->session->{subscriber}{username},
|
||||
domain => $c->session->{subscriber}{domain},
|
||||
},
|
||||
\$preferences
|
||||
);
|
||||
my $list = $c->request->params->{list_name};
|
||||
|
||||
# input text field to add new entry to block list
|
||||
my $add = $c->request->params->{block_add};
|
||||
if(defined $add) {
|
||||
if($add =~ /^\+?[?*0-9\[\]]+$/) {
|
||||
if($add =~ /^[1-9\[]/) {
|
||||
$add =~ s/^/$c->session->{subscriber}{cc}.$c->session->{subscriber}{ac}/e;
|
||||
} elsif($add =~ /^0[^0]/) {
|
||||
$add =~ s/^0/$c->session->{subscriber}{cc}/e;
|
||||
}
|
||||
$add =~ s/^\+/00/;
|
||||
$add =~ s/^00+//;
|
||||
my $blocklist = $$preferences{$list};
|
||||
$blocklist = [] unless defined $blocklist;
|
||||
$blocklist = [ $blocklist ] unless ref $blocklist;
|
||||
$$preferences{$list} = [ @$blocklist, $add ];
|
||||
} else {
|
||||
$messages{msgadd} = 'Client.Voip.MalformedNumberPattern';
|
||||
$c->session->{blockaddtxt} = $add;
|
||||
}
|
||||
}
|
||||
|
||||
# delete link next to entries in block list
|
||||
my $del = $c->request->params->{block_del};
|
||||
if(defined $del) {
|
||||
my $blocklist = $$preferences{$list};
|
||||
if(defined $blocklist) {
|
||||
$del =~ s/^\+//;
|
||||
$del =~ s/^0/$c->session->{subscriber}{cc}/e;
|
||||
$blocklist = [ $blocklist ] unless ref $blocklist;
|
||||
if($c->request->params->{block_stat}) {
|
||||
$$preferences{$list} = [ grep { $_ ne $del } @$blocklist ];
|
||||
} else {
|
||||
$$preferences{$list} = [ grep { $_ ne '#'.$del } @$blocklist ];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# activate/deactivate link next to entries in block list
|
||||
my $act = $c->request->params->{block_act};
|
||||
if(defined $act) {
|
||||
print STDERR "Got request to de/activate $act...\n";
|
||||
my $blocklist = $$preferences{$list};
|
||||
if(defined $blocklist) {
|
||||
$act =~ s/^\+//;
|
||||
$act =~ s/^0/$c->session->{subscriber}{cc}/e;
|
||||
$blocklist = [ $blocklist ] unless ref $blocklist;
|
||||
if($c->request->params->{block_stat}) {
|
||||
$$preferences{$list} = [ grep { $_ ne $act } @$blocklist ];
|
||||
push @{$$preferences{$list}}, '#'.$act;
|
||||
} else {
|
||||
$$preferences{$list} = [ grep { $_ ne '#'.$act } @$blocklist ];
|
||||
push @{$$preferences{$list}}, $act;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unless(keys %messages) {
|
||||
$c->model('Provisioning')->call_prov( $c, 'voip', 'set_subscriber_preferences',
|
||||
{ username => $c->session->{subscriber}{username},
|
||||
domain => $c->session->{subscriber}{domain},
|
||||
preferences => {
|
||||
$list => $$preferences{$list},
|
||||
},
|
||||
},
|
||||
undef
|
||||
);
|
||||
} else {
|
||||
$messages{numerr} = 'Client.Voip.InputErrorFound';
|
||||
}
|
||||
|
||||
$c->session->{messages} = \%messages;
|
||||
$c->response->redirect("/subscriber/edit_list?subscriber_id=$subscriber_id&list_name=$list");
|
||||
|
||||
}
|
||||
|
||||
|
||||
=head1 BUGS AND LIMITATIONS
|
||||
|
||||
=over
|
||||
|
||||
=item currently none
|
||||
|
||||
=back
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
Provisioning model, Catalyst
|
||||
|
||||
=head1 AUTHORS
|
||||
|
||||
Daniel Tiefnig <dtiefnig@sipwise.com>
|
||||
|
||||
=head1 COPYRIGHT
|
||||
|
||||
The subscriber controller is Copyright (c) 2007 Sipwise GmbH, Austria. All
|
||||
rights reserved.
|
||||
|
||||
=cut
|
||||
|
||||
# ende gelaende
|
||||
1;
|
@ -0,0 +1,212 @@
|
||||
package admin::Model::Provisioning;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use base 'Catalyst::Model';
|
||||
use Scalar::Util;
|
||||
use Catalyst::Plugin::Authentication;
|
||||
|
||||
use Sipwise::Provisioning::Voip;
|
||||
use Sipwise::Provisioning::Billing;
|
||||
|
||||
=head1 NAME
|
||||
|
||||
admin::Model::Provisioning - Sipwise provisioning catalyst model
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
Catalyst Model that uses Sipwise::Provisioning::Voip to get and set VoIP
|
||||
admin and user data.
|
||||
|
||||
=cut
|
||||
|
||||
sub new {
|
||||
my $class = shift;
|
||||
|
||||
my $self = {};
|
||||
$$self{voip} = Sipwise::Provisioning::Voip->new();
|
||||
$$self{billing} = Sipwise::Provisioning::Billing->new();
|
||||
|
||||
return bless $self, $class;
|
||||
}
|
||||
|
||||
sub call_prov {
|
||||
# model, catalyst, scalar, scalar, hash-ref, scalar-ref
|
||||
my ($self, $c, $backend, $function, $parameter, $result) = @_;
|
||||
|
||||
$c->log->debug("***Provisioning::call_prov calling '$backend\::$function'");
|
||||
|
||||
eval {
|
||||
$$result = $$self{$backend}->handle_request( $function,
|
||||
{
|
||||
authentication => {
|
||||
type => 'admin',
|
||||
username => $c->session->{admin}{login},
|
||||
password => $c->session->{admin}{password},
|
||||
},
|
||||
parameters => $parameter,
|
||||
});
|
||||
};
|
||||
|
||||
if($@) {
|
||||
if(ref $@ eq 'SOAP::Fault') {
|
||||
$c->log->error("***Provisioning::call_prov: $backend\::$function failed: ". $@->faultstring);
|
||||
$c->session->{prov_error} = $@->faultcode;
|
||||
} else {
|
||||
$c->log->error("***Provisioning::call_prov: $backend\::$function failed: $@");
|
||||
$c->session->{prov_error} = 'Server.Internal';
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
##########################
|
||||
# non-standard functions #
|
||||
##########################
|
||||
|
||||
sub login {
|
||||
my ($self, $c, $admin, $password) = @_;
|
||||
|
||||
$c->log->debug('***Provisioning::login called, authenticating...');
|
||||
|
||||
unless(defined $admin and length $admin) {
|
||||
$c->session->{prov_error} = 'Client.Voip.MissingUsername';
|
||||
return;
|
||||
}
|
||||
unless(defined $password and length $password) {
|
||||
$c->session->{prov_error} = 'Client.Voip.MissingPass';
|
||||
return;
|
||||
}
|
||||
|
||||
unless(Scalar::Util::blessed($admin)
|
||||
and ($Catalyst::Plugin::Authentication::VERSION < 0.10003
|
||||
? $admin->isa("Catalyst::Plugin::Authentication::User")
|
||||
: $admin->isa("Catalyst::Authentication::User")))
|
||||
{
|
||||
if(my $user_obj = $self->_get_admin($c, $admin)) {
|
||||
$admin = $user_obj;
|
||||
} else {
|
||||
if($c->session->{prov_error} and $c->session->{prov_error} eq 'Server.Voip.NoSuchAdmin') {
|
||||
$c->log->info("***Provisioning::login authentication failed for '$admin', unknown login.");
|
||||
$c->session->{prov_error} = 'Client.Voip.AuthFailed';
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
if($self->_auth_admin($c, $admin, $password)) {
|
||||
$c->set_authenticated($admin);
|
||||
$c->log->debug('***Provisioning::login authentication succeeded.');
|
||||
$$admin{password} = $password;
|
||||
$c->session->{admin} = $admin;
|
||||
return 1;
|
||||
}
|
||||
|
||||
$c->log->info("***Provisioning::login authentication failed for '$$admin{login}', wrong password.");
|
||||
$c->session->{prov_error} = 'Client.Voip.AuthFailed';
|
||||
return;
|
||||
}
|
||||
|
||||
sub localize {
|
||||
my ($self, $lang, $messages) = @_;
|
||||
|
||||
return unless defined $messages;
|
||||
|
||||
if(ref $messages eq 'HASH') {
|
||||
my %translations;
|
||||
foreach my $msgname (keys %$messages) {
|
||||
$translations{$msgname} = eval { $$self{voip}->get_localized_string({language => $lang, code => $$messages{$msgname}}) };
|
||||
unless(defined $translations{$msgname}) {
|
||||
$translations{$msgname} = eval { $$self{voip}->get_localized_string({language => $lang, code => 'Server.Internal'}) };
|
||||
}
|
||||
}
|
||||
return \%translations;
|
||||
} elsif(!ref $messages) {
|
||||
my $translation = eval { $$self{voip}->get_localized_string({language => $lang, code => $messages}) };
|
||||
unless(defined $translation) {
|
||||
$translation = eval { $$self{voip}->get_localized_string({language => $lang, code => 'Server.Internal'}) };
|
||||
}
|
||||
return $translation;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
####################
|
||||
# helper functions #
|
||||
####################
|
||||
|
||||
sub _get_admin {
|
||||
my ($self, $c, $login) = @_;
|
||||
|
||||
my $admin_obj = eval {
|
||||
$$self{billing}->get_admin({login => $login});
|
||||
};
|
||||
if($@) {
|
||||
if(ref $@ eq 'SOAP::Fault') {
|
||||
$c->log->error("***Provisioning::_get_admin failed to get admin '$login' from DB: ". $@->faultstring)
|
||||
unless $@->faultcode eq 'Server.Voip.NoSuchAdmin';
|
||||
$c->session->{prov_error} = $@->faultcode;
|
||||
} else {
|
||||
$c->log->error("***Provisioning::_get_admin failed to get admin '$login' from DB: $@.");
|
||||
$c->session->{prov_error} = 'Server.Internal';
|
||||
}
|
||||
return;
|
||||
}
|
||||
my $return = { %$admin_obj, id => $login, store => $self };
|
||||
if($Catalyst::Plugin::Authentication::VERSION < 0.10003) {
|
||||
return bless $return, "Catalyst::Plugin::Authentication::User::Hash";
|
||||
} else {
|
||||
return bless $return, "Catalyst::Authentication::User::Hash";
|
||||
}
|
||||
}
|
||||
|
||||
sub _auth_admin {
|
||||
my ($self, $c, $admin, $pass) = @_;
|
||||
|
||||
eval { $$self{billing}->authenticate_admin({ login => $$admin{login},
|
||||
password => $pass,
|
||||
});
|
||||
};
|
||||
if($@) {
|
||||
if(ref $@ eq 'SOAP::Fault') {
|
||||
$c->log->error("***Provisioning::_auth_admin failed to auth admin '$$admin{login}': ". $@->faultstring);
|
||||
$c->session->{prov_error} = $@->faultcode;
|
||||
} else {
|
||||
$c->log->error("***Provisioning::_auth_admin failed to auth admin '$$admin{login}': $@.");
|
||||
$c->session->{prov_error} = 'Server.Internal';
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
=head1 BUGS AND LIMITATIONS
|
||||
|
||||
=over
|
||||
|
||||
=item currently none
|
||||
|
||||
=back
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
Sipwise::Provisioning::Voip, Sipwise::Provisioning::Billing, Catalyst
|
||||
|
||||
=head1 AUTHORS
|
||||
|
||||
Daniel Tiefnig <dtiefnig@sipwise.com>
|
||||
|
||||
=head1 COPYRIGHT
|
||||
|
||||
The Provisioning model is Copyright (c) 2007 Sipwise GmbH, Austria. All
|
||||
rights reserved.
|
||||
|
||||
=cut
|
||||
|
||||
# ende gelaende
|
||||
1;
|
@ -0,0 +1,64 @@
|
||||
package admin::View::Sipwise;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use base 'Catalyst::View::TT';
|
||||
|
||||
=head1 NAME
|
||||
|
||||
admin::View::Sipwise - Sipwise Catalyst View for NGCP admin interface
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
Sipwise Catalyst View for NGCP admin interface.
|
||||
|
||||
=cut
|
||||
|
||||
__PACKAGE__->config(
|
||||
## PRE_PROCESS => 'config/main',
|
||||
## TEMPLATE_EXTENSION => '.tt',
|
||||
MACRO => 'debug(message) CALL Catalyst.log.debug(message)',
|
||||
INCLUDE_PATH => [
|
||||
admin->path_to( 'root' ),
|
||||
],
|
||||
WRAPPER => 'layout/wrapper',
|
||||
ERROR => 'tt/error.tt',
|
||||
CATALYST_VAR => 'Catalyst',
|
||||
VARIABLES => {
|
||||
site_config => {
|
||||
language => 'en',
|
||||
language_string => 'English',
|
||||
css => [ '/css/sipwise.css', '/css/admin.css' ],
|
||||
title => 'Sipwise NGCP admin interface',
|
||||
company => {
|
||||
name => 'Sipwise GmbH'
|
||||
},
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
=head1 BUGS AND LIMITATIONS
|
||||
|
||||
=over
|
||||
|
||||
=item none.
|
||||
|
||||
=back
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
Catalyst
|
||||
|
||||
=head1 AUTHORS
|
||||
|
||||
Daniel Tiefnig <dtiefnig@sipwise.com>
|
||||
|
||||
=head1 COPYRIGHT
|
||||
|
||||
The Sipwise view is Copyright (c) 2007 Sipwise GmbH, Austria. All rights
|
||||
reserved.
|
||||
|
||||
=cut
|
||||
|
||||
# over and out
|
||||
1;
|
@ -0,0 +1,260 @@
|
||||
/*
|
||||
* Relative size definitions like "large" ,"0.8em", etc.
|
||||
* don't work very well 'cross different browsers.
|
||||
* Allthought it is recommended to use them, they don't
|
||||
* give useable results.
|
||||
*/
|
||||
body {
|
||||
font: 14px Trebuchet MS, Lucida Sans Unicode, Arial, sans-serif !important;
|
||||
/* hover effects for IE6 */
|
||||
behavior:url("/css/csshover.htc");
|
||||
}
|
||||
h3 {
|
||||
font-size: 18px !important;
|
||||
}
|
||||
|
||||
#header #sipwise_logo {
|
||||
margin: 3px;
|
||||
width: 200px;
|
||||
}
|
||||
|
||||
#header #heading {
|
||||
position: absolute;
|
||||
top: 20px;
|
||||
left: 250px;
|
||||
text-align: center;
|
||||
width: 400px;
|
||||
font-weight: bold;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
#header #client_logo {
|
||||
position: absolute;
|
||||
top: 2px;
|
||||
right: 2px;
|
||||
margin: 3px;
|
||||
width: 200px;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
|
||||
/* hmm, menu doesn't extend container height ... */
|
||||
#container #content {
|
||||
min-height: 570px;
|
||||
}
|
||||
|
||||
/* contentmenu's width and contentplace' margin-left should match */
|
||||
#container #contentmenu {
|
||||
width: 230px;
|
||||
}
|
||||
#container #contentplace {
|
||||
margin-left: 230px;
|
||||
}
|
||||
|
||||
/* red error messages */
|
||||
.errormsg {
|
||||
width: auto;
|
||||
margin: 0;
|
||||
padding: 5px;
|
||||
font-weight: bold;
|
||||
color: #FF1010;
|
||||
}
|
||||
/* green success messages */
|
||||
.goodmsg {
|
||||
width: auto;
|
||||
margin: 0;
|
||||
padding: 5px;
|
||||
font-weight: bold;
|
||||
color: #10BB40;
|
||||
}
|
||||
/* highlight text */
|
||||
.alert {
|
||||
width: auto;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-weight: bold;
|
||||
color: #FF1010;
|
||||
}
|
||||
|
||||
/* increase vertical spacing in tables */
|
||||
#contentplace td {
|
||||
padding: 3px 5px 3px 5px;
|
||||
}
|
||||
|
||||
/* some table alignment aliases */
|
||||
#contentplace .tdcenter {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#contentplace .tdmiddle {
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
#contentplace .tdkey {
|
||||
font-weight: bold;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
#contentplace .table_header {
|
||||
font-weight: bold;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
#contentplace .nowrap {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/* format links and images in post div's */
|
||||
#contentplace .postlink label {
|
||||
font-weight: bold;
|
||||
cursor: pointer;
|
||||
color: #006600;
|
||||
text-decoration: none;
|
||||
}
|
||||
#contentplace .postlink label:hover {
|
||||
color: #D60808;
|
||||
text-decoration: underline;
|
||||
}
|
||||
#contentplace .postlink label:after {
|
||||
content: "\bb";
|
||||
font-weight: bold;
|
||||
}
|
||||
#contentplace .postlink .hidden {
|
||||
position: absolute;
|
||||
top: -90000px;
|
||||
left: -90000px;
|
||||
}
|
||||
|
||||
/*
|
||||
* use smaller font for input elements (textfields)
|
||||
* and select boxes
|
||||
*/
|
||||
#container #contentplace input {
|
||||
font-size: 11px;
|
||||
padding: 2px 2px 2px 3px;
|
||||
border: 1px solid #606060;
|
||||
}
|
||||
|
||||
/* sigh, no border for checkboxes */
|
||||
#contentplace .checkbox {
|
||||
border: none !important;
|
||||
}
|
||||
|
||||
#contentplace .table input {
|
||||
margin: -2px 0 -2px 0;
|
||||
}
|
||||
|
||||
#contentplace select {
|
||||
font-size: 11px;
|
||||
border: 1px solid #606060;
|
||||
}
|
||||
|
||||
/* use smaller font for buttons */
|
||||
#contentplace .but {
|
||||
font-size: 11px;
|
||||
text-align: center;
|
||||
border: 1px solid #606060;
|
||||
background-color: #e0e0e0;
|
||||
padding: 2px !important;
|
||||
margin: 3px 0 5px 0;
|
||||
}
|
||||
|
||||
/* print ">>" after hyper refs */
|
||||
#contentplace a:after {
|
||||
content: "\bb";
|
||||
font-weight: bold;
|
||||
}
|
||||
/* no ">>" in heading */
|
||||
#contentplace h3 a:after {
|
||||
content: "";
|
||||
}
|
||||
|
||||
/* specify position of edit/lock/delete action links */
|
||||
#contentplace .actions {
|
||||
margin: 0 0 -17px 23px;
|
||||
position: relative;
|
||||
}
|
||||
#contentplace .aaction {
|
||||
margin: 0 8px 0 0;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* colors for disabled input fields */
|
||||
#contentplace .disabled {
|
||||
color: #808080;
|
||||
background-color: #f4f4f4;
|
||||
}
|
||||
|
||||
#contentplace .txtpreference {
|
||||
width: 160px;
|
||||
}
|
||||
|
||||
/* customize login form */
|
||||
#login {
|
||||
border: none;
|
||||
margin: 0 0 0 10px;
|
||||
}
|
||||
#login label {
|
||||
font-weight: bold;
|
||||
}
|
||||
#login_user, #login_pass {
|
||||
font-size: 11px;
|
||||
margin: 3px 0 5px 0;
|
||||
padding: 3px;
|
||||
width: 120px;
|
||||
}
|
||||
|
||||
/* decrease input text field for password */
|
||||
#edit_pass, #edit_webpass {
|
||||
width: 95px;
|
||||
}
|
||||
|
||||
/* decrease input text fields for cc/ac */
|
||||
.ishort {
|
||||
width: 40px;
|
||||
}
|
||||
|
||||
/* increase spacing between password and show/hide href */
|
||||
#contentplace .apass {
|
||||
vertical-align: middle;
|
||||
margin: 0 0 0 5px;
|
||||
}
|
||||
|
||||
/* increase spacing between amount and add textfield in
|
||||
* account balance edit
|
||||
*/
|
||||
#contentplace .account_add {
|
||||
margin: 0 0 0 15px;
|
||||
}
|
||||
/* decrease input text field for amounts */
|
||||
#contentplace .account_add input {
|
||||
width: 50px;
|
||||
}
|
||||
|
||||
/* floating menu for subscriber lock */
|
||||
#contentplace .floating {
|
||||
z-index: 100;
|
||||
display: none;
|
||||
position: absolute;
|
||||
top: 20px;
|
||||
left: 50px;
|
||||
border: 1px solid #006600;
|
||||
background-color: #DDFFDD;
|
||||
padding: 3px 10px 3px 5px;
|
||||
}
|
||||
#contentplace .menu_foo {
|
||||
z-index: 200;
|
||||
overflow: auto;
|
||||
margin: 0;
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
}
|
||||
|
||||
/* correct margin for active paginations */
|
||||
.pagination li.currentpage, .pagination li.disablepage {
|
||||
margin: 0 5px 0 0;
|
||||
}
|
||||
/* no ">>" in pagination next / previous */
|
||||
#contentplace .pagination li.nextpage a:after {
|
||||
content: "";
|
||||
}
|
@ -0,0 +1,120 @@
|
||||
<attach event="ondocumentready" handler="parseStylesheets" />
|
||||
<script>
|
||||
/**
|
||||
* Whatever:hover - V1.42.060206 - hover & active
|
||||
* ------------------------------------------------------------
|
||||
* (c) 2005 - Peter Nederlof
|
||||
* Peterned - http://www.xs4all.nl/~peterned/
|
||||
* License - http://creativecommons.org/licenses/LGPL/2.1/
|
||||
*
|
||||
* Whatever:hover is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* Whatever:hover is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* Credits and thanks to:
|
||||
* Arnoud Berendsen, Martin Reurings, Robert Hanson
|
||||
*
|
||||
* howto: body { behavior:url("csshover.htc"); }
|
||||
* ------------------------------------------------------------
|
||||
*/
|
||||
|
||||
var csshoverReg = /(^|\s)(([^a]([^ ]+)?)|(a([^#.][^ ]+)+)):(hover|active)/i,
|
||||
currentSheet, doc = window.document, hoverEvents = [], activators = {
|
||||
onhover:{on:'onmouseover', off:'onmouseout'},
|
||||
onactive:{on:'onmousedown', off:'onmouseup'}
|
||||
}
|
||||
|
||||
function parseStylesheets() {
|
||||
if(!/MSIE (5|6)/.test(navigator.userAgent)) return;
|
||||
window.attachEvent('onunload', unhookHoverEvents);
|
||||
var sheets = doc.styleSheets, l = sheets.length;
|
||||
for(var i=0; i<l; i++)
|
||||
parseStylesheet(sheets[i]);
|
||||
}
|
||||
function parseStylesheet(sheet) {
|
||||
if(sheet.imports) {
|
||||
try {
|
||||
var imports = sheet.imports, l = imports.length;
|
||||
for(var i=0; i<l; i++) parseStylesheet(sheet.imports[i]);
|
||||
} catch(securityException){}
|
||||
}
|
||||
|
||||
try {
|
||||
var rules = (currentSheet = sheet).rules, l = rules.length;
|
||||
for(var j=0; j<l; j++) parseCSSRule(rules[j]);
|
||||
} catch(securityException){}
|
||||
}
|
||||
|
||||
function parseCSSRule(rule) {
|
||||
var select = rule.selectorText, style = rule.style.cssText;
|
||||
if(!csshoverReg.test(select) || !style) return;
|
||||
|
||||
var pseudo = select.replace(/[^:]+:([a-z-]+).*/i, 'on$1');
|
||||
var newSelect = select.replace(/(\.([a-z0-9_-]+):[a-z]+)|(:[a-z]+)/gi, '.$2' + pseudo);
|
||||
var className = (/\.([a-z0-9_-]*on(hover|active))/i).exec(newSelect)[1];
|
||||
var affected = select.replace(/:(hover|active).*$/, '');
|
||||
var elements = getElementsBySelect(affected);
|
||||
if(elements.length == 0) return;
|
||||
|
||||
currentSheet.addRule(newSelect, style);
|
||||
for(var i=0; i<elements.length; i++)
|
||||
new HoverElement(elements[i], className, activators[pseudo]);
|
||||
}
|
||||
|
||||
function HoverElement(node, className, events) {
|
||||
if(!node.hovers) node.hovers = {};
|
||||
if(node.hovers[className]) return;
|
||||
node.hovers[className] = true;
|
||||
hookHoverEvent(node, events.on, function() { node.className += ' ' + className; });
|
||||
hookHoverEvent(node, events.off, function() { node.className = node.className.replace(new RegExp('\\s+'+className, 'g'),''); });
|
||||
}
|
||||
function hookHoverEvent(node, type, handler) {
|
||||
node.attachEvent(type, handler);
|
||||
hoverEvents[hoverEvents.length] = {
|
||||
node:node, type:type, handler:handler
|
||||
};
|
||||
}
|
||||
|
||||
function unhookHoverEvents() {
|
||||
for(var e,i=0; i<hoverEvents.length; i++) {
|
||||
e = hoverEvents[i];
|
||||
e.node.detachEvent(e.type, e.handler);
|
||||
}
|
||||
}
|
||||
|
||||
function getElementsBySelect(rule) {
|
||||
var parts, nodes = [doc];
|
||||
parts = rule.split(' ');
|
||||
for(var i=0; i<parts.length; i++) {
|
||||
nodes = getSelectedNodes(parts[i], nodes);
|
||||
} return nodes;
|
||||
}
|
||||
function getSelectedNodes(select, elements) {
|
||||
var result, node, nodes = [];
|
||||
var identify = (/\#([a-z0-9_-]+)/i).exec(select);
|
||||
if(identify) {
|
||||
var element = doc.getElementById(identify[1]);
|
||||
return element? [element]:nodes;
|
||||
}
|
||||
|
||||
var classname = (/\.([a-z0-9_-]+)/i).exec(select);
|
||||
var tagName = select.replace(/(\.|\#|\:)[a-z0-9_-]+/i, '');
|
||||
var classReg = classname? new RegExp('\\b' + classname[1] + '\\b'):false;
|
||||
for(var i=0; i<elements.length; i++) {
|
||||
result = tagName? elements[i].all.tags(tagName):elements[i].all;
|
||||
for(var j=0; j<result.length; j++) {
|
||||
node = result[j];
|
||||
if(classReg && !classReg.test(node.className)) continue;
|
||||
nodes[nodes.length] = node;
|
||||
}
|
||||
}
|
||||
|
||||
return nodes;
|
||||
}
|
||||
</script>
|
@ -0,0 +1,552 @@
|
||||
body
|
||||
{
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
color: #333;
|
||||
font: 0.8em Trebuchet MS, Lucida Sans Unicode, Arial, sans-serif;
|
||||
background: #e0e0e0;
|
||||
}
|
||||
|
||||
a
|
||||
{
|
||||
color: #006600;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:hover
|
||||
{
|
||||
color: #D60808;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
img
|
||||
{
|
||||
border: none;
|
||||
}
|
||||
|
||||
|
||||
#container
|
||||
{
|
||||
margin: 20px auto;
|
||||
width: 900px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
|
||||
* html #container
|
||||
{
|
||||
width: 900px;
|
||||
w\idth: 900px;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
#header
|
||||
{
|
||||
background: #fff;
|
||||
border: 2px solid #000;
|
||||
}
|
||||
|
||||
#headerlogin
|
||||
{
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
right: 20px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#headermenu
|
||||
{
|
||||
}
|
||||
|
||||
#headermenu ul
|
||||
{
|
||||
text-align: center;
|
||||
margin-left: 0;
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
#headermenu li
|
||||
{
|
||||
list-style-type: none;
|
||||
font-size: normal;
|
||||
font-weight: bold;
|
||||
padding: 0.25em 1em;
|
||||
display: inline;
|
||||
border-left: 1px solid #e0e0e0;
|
||||
}
|
||||
|
||||
#headermenu li:first-child
|
||||
{
|
||||
border-left: none;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#headerlogo img
|
||||
{
|
||||
display: block;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
#content
|
||||
{
|
||||
background: #fff;
|
||||
min-height: 400px;
|
||||
height: auto !important;
|
||||
height: 400px; /* IE hack */
|
||||
border: 2px solid #000;
|
||||
margin-top: 10px;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
#contentmenu h3
|
||||
{
|
||||
font-weight: bold;
|
||||
font-size: normal;
|
||||
margin: 20px 20px 5px 10px;
|
||||
}
|
||||
|
||||
#contentmenu h3#first
|
||||
{
|
||||
font-weight: bold;
|
||||
font-size: normal;
|
||||
margin: 0px 20px 5px 10px;
|
||||
}
|
||||
|
||||
#contentmenu
|
||||
{
|
||||
float: left;
|
||||
padding-right: 20px;
|
||||
padding-top: 20px;
|
||||
}
|
||||
|
||||
#contentmenu ul
|
||||
{
|
||||
width: 150px;
|
||||
list-style-type: none;
|
||||
margin: 0;
|
||||
padding: 0 0 0 20px;
|
||||
}
|
||||
|
||||
#contentmenu ul li
|
||||
{
|
||||
font-size: normal;
|
||||
font-weight: normal;
|
||||
border-bottom: 1px solid #e0e0e0;
|
||||
display: block;
|
||||
padding: 5px 0;
|
||||
}
|
||||
#contentmenu ul li a
|
||||
{
|
||||
font-size: normal;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#contentplace
|
||||
{
|
||||
margin-left: 220px;
|
||||
}
|
||||
|
||||
#contentplace .expert
|
||||
{
|
||||
position: relative;
|
||||
float: right;
|
||||
margin-top: 10px;
|
||||
margin-right: 30px;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#contentplace h3
|
||||
{
|
||||
font-weight: bold;
|
||||
font-size: large;
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
#contentplace h3 img
|
||||
{
|
||||
margin: 10px;
|
||||
margin-bottom: 0px;
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
#contentplace p
|
||||
{
|
||||
border: 0;
|
||||
margin: 10px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
#contentplace .p1
|
||||
{
|
||||
border: 1px solid #e0e0e0;
|
||||
margin: 20px 20px 20px 20px;
|
||||
padding: 10px 10px 10px 10px;
|
||||
}
|
||||
|
||||
#contentplace .p1full
|
||||
{
|
||||
border: 1px solid #e0e0e0;
|
||||
margin: 20px 20px 20px 20px;
|
||||
padding: 10px 10px 20px 10px;
|
||||
}
|
||||
|
||||
#contentplace .p1center
|
||||
{
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
padding: 10px 10px 10px 10px;
|
||||
}
|
||||
|
||||
#contentplace .p2center
|
||||
{
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
padding: 10px 10px 10px 10px;
|
||||
}
|
||||
|
||||
#contentplace .p2right
|
||||
{
|
||||
float: right;
|
||||
padding: 10px 10px 10px 10px;
|
||||
}
|
||||
|
||||
#contentplace .p3
|
||||
{
|
||||
border: 0;
|
||||
margin: 30px;
|
||||
padding: 10px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#contentplace .p3image
|
||||
{
|
||||
position: relative;
|
||||
margin-bottom: 20px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#contentplace .p3 .p3text
|
||||
{
|
||||
margin: 0;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
|
||||
#contentplace form input
|
||||
{
|
||||
border: 1px solid #606060;
|
||||
background-color: #fff;
|
||||
vertical-align: middle;
|
||||
padding: 3px;
|
||||
}
|
||||
|
||||
#contentplace form .nb
|
||||
{
|
||||
border: none;
|
||||
padding: 3px;
|
||||
}
|
||||
|
||||
#contentplace form .but
|
||||
{
|
||||
border: 1px solid #606060;
|
||||
background-color: #e0e0e0;
|
||||
padding: 4px;
|
||||
margin-top: 8px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
#contentplace table
|
||||
{
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#contentplace .p1center table
|
||||
{
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
border: 1px solid #e0e0e0;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
#contentplace .p1center .tdcenter
|
||||
{
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#contentplace .p2center table
|
||||
{
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
#contentplace .p2center td
|
||||
{
|
||||
text-align: center;
|
||||
border: 1px solid #e0e0e0;
|
||||
padding: 20px;
|
||||
width: 200px;
|
||||
}
|
||||
|
||||
#contentplace .p2center .tdcenter
|
||||
{
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#contentplace tr
|
||||
{
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
#contentplace td
|
||||
{
|
||||
padding: 3px;
|
||||
margin: 0;
|
||||
border: 0;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
#contentplace tr .desc
|
||||
{
|
||||
background-color: #e0e0e0;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#contentplace td .desc
|
||||
{
|
||||
background-color: #e0e0e0;
|
||||
}
|
||||
|
||||
#contentplace .template table
|
||||
{
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#contentplace .template tr
|
||||
{
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
#contentplace .template td
|
||||
{
|
||||
padding-left: 15px;
|
||||
padding-right: 15px;
|
||||
padding-bottom: 20px;
|
||||
width: 50%;
|
||||
border: 1px solid #e0e0e0;
|
||||
}
|
||||
|
||||
#contentplace .template ul
|
||||
{
|
||||
list-style-type: circle;
|
||||
}
|
||||
|
||||
#footer
|
||||
{
|
||||
margin: 0;
|
||||
padding: 20px;
|
||||
text-align: center;
|
||||
font-size: small;
|
||||
font-weight: normal;
|
||||
color: #606060;
|
||||
}
|
||||
|
||||
#contentplace .p1 .listing td
|
||||
{
|
||||
padding: 0px 5px 0px 5px;
|
||||
}
|
||||
|
||||
#contentplace .p1 .listing td.center
|
||||
{
|
||||
padding: 0px 5px 0px 5px;
|
||||
text-align: center
|
||||
}
|
||||
|
||||
#contentplace .p1 .listing th
|
||||
{
|
||||
padding: 5px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
|
||||
.p2
|
||||
{
|
||||
}
|
||||
|
||||
.p2int
|
||||
{
|
||||
padding-left: 20px;
|
||||
}
|
||||
|
||||
.error
|
||||
{
|
||||
color: #f00;
|
||||
padding-left: 20px;
|
||||
}
|
||||
|
||||
.errorExplanation
|
||||
{
|
||||
color: #f00;
|
||||
border: 1px solid #f00;
|
||||
/*margin: 10px;*/
|
||||
margin: 20px 20px 20px 20px;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.errorExplanation h2
|
||||
{
|
||||
font-weight: bold;
|
||||
font-size: large;
|
||||
}
|
||||
|
||||
.errorExplanation h2.center
|
||||
{
|
||||
font-weight: bold;
|
||||
font-size: large;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#notice
|
||||
{
|
||||
color: #060;
|
||||
border: 1px solid #060;
|
||||
margin: 20px 20px 20px 20px;
|
||||
padding: 10px;
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
font-size: normal;
|
||||
}
|
||||
|
||||
#warning
|
||||
{
|
||||
color: #f90;
|
||||
border: 1px solid #f90;
|
||||
margin: 20px 20px 20px 20px;
|
||||
padding: 10px;
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
font-size: normal;
|
||||
}
|
||||
|
||||
#warning a
|
||||
{
|
||||
color: #D60808;
|
||||
}
|
||||
|
||||
#confcode
|
||||
{
|
||||
font: 10px Courier;
|
||||
color: #000
|
||||
}
|
||||
|
||||
#username
|
||||
{
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.fcattable
|
||||
{
|
||||
/*border: 1px solid #060;*/
|
||||
width: 100%;
|
||||
|
||||
}
|
||||
|
||||
.fcatheader
|
||||
{
|
||||
background-color: #060;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
|
||||
.price
|
||||
{
|
||||
color: #f00;
|
||||
}
|
||||
|
||||
.price_free
|
||||
{
|
||||
color: #0c0;
|
||||
}
|
||||
|
||||
.logo-1
|
||||
{
|
||||
color: #000000;
|
||||
}
|
||||
|
||||
.logo-2
|
||||
{
|
||||
color: #006600;
|
||||
}
|
||||
|
||||
.pagination
|
||||
{
|
||||
padding: 2px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.pagination ul
|
||||
{
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.pagination li
|
||||
{
|
||||
list-style-type: none;
|
||||
display: inline;
|
||||
padding-bottom: 1px;
|
||||
}
|
||||
|
||||
.pagination a, .pagination a:visited
|
||||
{
|
||||
padding: 0 5px;
|
||||
border: 1px solid #060;
|
||||
text-decoration: none;
|
||||
color: #060;
|
||||
}
|
||||
|
||||
.pagination a:hover, .pagination a:active
|
||||
{
|
||||
border: 1px solid #060;
|
||||
color: #000;
|
||||
background-color: lightyellow;
|
||||
}
|
||||
|
||||
.pagination li.currentpage
|
||||
{
|
||||
font-weight: bold;
|
||||
padding: 0 5px;
|
||||
border: 1px solid #060;
|
||||
background-color: #060;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.pagination li.disablepage
|
||||
{
|
||||
padding: 0 5px;
|
||||
border: 1px solid #929292;
|
||||
color: #929292;
|
||||
}
|
||||
|
||||
.pagination li.nextpage
|
||||
{
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
* html .pagination li.currentpage, * html .pagination li.disablepage
|
||||
{
|
||||
margin-right: 5px;
|
||||
padding-right: 0;
|
||||
}
|
After Width: | Height: | Size: 1.4 KiB |
@ -0,0 +1,10 @@
|
||||
oc = "open";
|
||||
function openclose() {
|
||||
if (oc == "open") {
|
||||
document.getElementById('lock_menu').style.display = 'inline';
|
||||
oc = "close";
|
||||
} else {
|
||||
document.getElementById('lock_menu').style.display = 'none';
|
||||
oc = "open";
|
||||
}
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
<div id="container">
|
||||
|
||||
[% PROCESS layout/header %]
|
||||
|
||||
<div id="content">
|
||||
|
||||
[% PROCESS layout/menu %]
|
||||
|
||||
<div id="contentplace">
|
||||
[% IF prov_error %]<div class="errormsg">[% prov_error %]</div>[% END %]
|
||||
[% IF messages.topmsg %]<div class="goodmsg">[% messages.topmsg %]</div>[% END %]
|
||||
[% IF messages.toperr %]<div class="errormsg">[% messages.toperr %]</div>[% END %]
|
||||
|
||||
[% content %]
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
[% PROCESS layout/footer %]
|
||||
|
||||
</div>
|
@ -0,0 +1,6 @@
|
||||
<!-- BEGIN layout/footer -->
|
||||
<div id="footer">
|
||||
Copyright 2007 Sipwise, Austria.<br />
|
||||
<a href="http://sipwise.com/">http://sipwise.com</a>
|
||||
</div>
|
||||
<!-- END layout/footer -->
|
@ -0,0 +1,12 @@
|
||||
<!-- BEGIN layout/header -->
|
||||
<div id="header">
|
||||
<div id="sipwise_logo">
|
||||
<a href="http://sipwise.com/"><img src="/static/images/sipwise_logo_96.png" alt="Sipwise GmbH, Austria" /></a>
|
||||
</div>
|
||||
<div id="heading">Sipwise NGCP Administration Interface</div>
|
||||
<div id="client_logo">
|
||||
<a href="[% site_config.company.homepage %]"><img src="/static/images/client_logo.png" alt="" /></a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- END layout/header -->
|
@ -0,0 +1,28 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" lang="[% site_config.language %]">
|
||||
|
||||
<head>
|
||||
|
||||
<title>[% template.title or site_config.title %]</title>
|
||||
|
||||
[% FOREACH css_file = site_config.css %]
|
||||
<link rel="stylesheet" type="text/css" href="[% css_file %]" />
|
||||
[% END %]
|
||||
|
||||
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
|
||||
<meta http-equiv="content-language" content="[% site_config.language %]" />
|
||||
|
||||
<meta name="description" content="[% template.title or site_config.title %]" />
|
||||
<meta name="title" content="[% template.title or site_config.title %]" />
|
||||
<meta name="Company" content="[% site_config.company.name %]" />
|
||||
<meta name="keywords" content="" />
|
||||
<meta name="Language" content="[% site_config.language_string %]" />
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
[% content %]
|
||||
</body>
|
||||
|
||||
</html>
|
@ -0,0 +1,35 @@
|
||||
<div id="contentmenu">
|
||||
|
||||
<h3 id="first">Authentication</h3>
|
||||
<ul>
|
||||
[% IF Catalyst.user_exists %]
|
||||
<li>Logged in as <b>[% Catalyst.user.login %]</b></li>
|
||||
<li><a href="/logout">» Logout</a></li>
|
||||
[% ELSE %]
|
||||
<li> </li>
|
||||
<li>Not logged in</li>
|
||||
[% END %]
|
||||
</ul>
|
||||
|
||||
[% IF Catalyst.session.admin %]
|
||||
<h3>User Administration</h3>
|
||||
<ul>
|
||||
[% IF Catalyst.config.billing_features %]
|
||||
<li><a href="/customer">Customers</a></li>
|
||||
[% END %]
|
||||
<li><a href="/account">Accounts</a></li>
|
||||
<li><a href="/subscriber">Subscribers</a></li>
|
||||
[%# <li><a href="/registration">Devices</a></li> %]
|
||||
[%# <li><a href="/registration">Registrations</a></li> %]
|
||||
</ul>
|
||||
|
||||
<h3>System Administration</h3>
|
||||
<ul>
|
||||
<li><a href="/domain">Domains</a></li>
|
||||
<li><a href="/admin">Administrators</a></li>
|
||||
[%# <li><a href="/gwgroup">Gateway Settings</a></li> %]
|
||||
[%# <li><a href="/sipserver">SIP Server Settings</a></li> %]
|
||||
</ul>
|
||||
[% END %]
|
||||
|
||||
</div>
|
@ -0,0 +1,8 @@
|
||||
[% IF template.name.match('(\.html$|\.css$|\.js$|\.txt$)');
|
||||
debug("Passing page through as text: $template.name");
|
||||
content;
|
||||
ELSE;
|
||||
debug("Applying HTML page layout wrappers to $template.name\n");
|
||||
content WRAPPER layout/html + layout/body;
|
||||
END;
|
||||
-%]
|
After Width: | Height: | Size: 3.8 KiB |
After Width: | Height: | Size: 832 B |
After Width: | Height: | Size: 2.9 KiB |
@ -0,0 +1,52 @@
|
||||
<h3>Get by ID</h3>
|
||||
<div class="p1">
|
||||
<form action="/account/getbyid" method="GET">
|
||||
<input type="text" id="account_id" name="account_id" value="[% account_id %]" />
|
||||
<input type="submit" value="Get »" class="but" />
|
||||
</form>
|
||||
[% IF messages.accsearcherr %]<div class="errormsg">[% messages.accsearcherr %]</div>[% END %]
|
||||
</div>
|
||||
|
||||
<h3>Search by subscriber</h3>
|
||||
<div class="p1">
|
||||
<form action="/subscriber/search" method="post">
|
||||
<input type="text" id="search_subscriber" name="search_string" value="[% search_string %]" />
|
||||
<input type="submit" value="Search »" class="but" />
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<h3>Create new account</h3>
|
||||
<div class="p1">
|
||||
<form action="/account/create_account" method="post">
|
||||
<input type="submit" value="Create »" class="but" />
|
||||
</form>
|
||||
</div>
|
||||
|
||||
[% IF subscriber_list %]
|
||||
|
||||
<h3>Subscribers</h3>
|
||||
|
||||
<div class="p1">
|
||||
<table>
|
||||
<tr><td>SIP URI</td><td class="tdcenter">Subscriber ID</td><td class="tdcenter">Account ID</td></tr>
|
||||
|
||||
[% FOREACH subscriber = subscriber_list %]
|
||||
|
||||
<tr>
|
||||
<td><a href="/subscriber/detail?subscriber_id=[% subscriber.id %]">
|
||||
[% subscriber.username %]@[% subscriber.domain %]
|
||||
</a></td>
|
||||
<td class="tdcenter"><a href="/subscriber/detail?subscriber_id=[% subscriber.id %]">
|
||||
[% subscriber.id %]
|
||||
</a></td>
|
||||
<td class="tdcenter"><a href="/account/detail?account_id=[% subscriber.account_id %]">
|
||||
[% subscriber.account_id %]
|
||||
</a></td>
|
||||
</tr>
|
||||
|
||||
[% END %]
|
||||
|
||||
</table>
|
||||
</div>
|
||||
|
||||
[% END %]
|
@ -0,0 +1,167 @@
|
||||
<h3> VoIP Account
|
||||
<a class="noarrow" href="detail?account_id=[% account.id %]">
|
||||
#[% account.id %]</a>
|
||||
</h3>
|
||||
|
||||
[% IF ! account.terminate_timestamp %]
|
||||
<div class="actions">
|
||||
[% IF billing_features %]
|
||||
<a href="detail?account_id=[% account.id %]&edit_account=1" class="aaction">edit</a>
|
||||
[% END %]
|
||||
[% IF edit_account %]
|
||||
<a href="detail?account_id=[% account.id %]" class="aaction">cancel</a>
|
||||
[% ELSE %]
|
||||
[% IF account.is_locked %]
|
||||
<a href="lock?account_id=[% account.id %]&lock=none" class="aaction">unlock</a>
|
||||
[% ELSE %]
|
||||
<a href="lock?account_id=[% account.id %]&lock=global" class="aaction">lock</a>
|
||||
[% END %]
|
||||
<a href="terminate?account_id=[% account.id %]" class="aaction">terminate</a>
|
||||
[% END %]
|
||||
</div>
|
||||
[% END %]
|
||||
<div class="p1">
|
||||
[% IF account.is_locked %]
|
||||
<div class="alert">Account is LOCKED!</div>
|
||||
[% END %]
|
||||
[% IF messages.accmsg %]<div class="goodmsg">[% messages.accmsg %]</div>[% END %]
|
||||
[% IF messages.accerr %]<div class="errormsg">[% messages.accerr %]</div>[% END %]
|
||||
<form action="update_account" method="post">
|
||||
<input type="hidden" name="account_id" value="[% account.id %]" />
|
||||
<table>
|
||||
<tr><td class="tdkey">ID:</td><td>[% account.id %]</td></tr>
|
||||
|
||||
[% IF billing_features %]
|
||||
<tr>
|
||||
<td class="tdkey">customer:</td>
|
||||
<td>
|
||||
[% IF account.customer_id %]
|
||||
<a href="/customer/detail?customer_id=[% account.customer_id %]">[% account.customer_id %]</a>
|
||||
[% END %]
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="tdkey">product:</td>
|
||||
<td>
|
||||
[% IF edit_account %]
|
||||
<select size="1" name="product">
|
||||
[% FOREACH product = products %]
|
||||
<option[% IF product.name == account.product %] selected="selected"[% END %]>[% product.name %]</option>
|
||||
[% END %]
|
||||
</select>
|
||||
[% ELSE %]
|
||||
[% account.product %]
|
||||
[% END %]
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="tdkey">billing profile:</td>
|
||||
<td>
|
||||
[% IF edit_account %]
|
||||
<select size="1" name="billing_profile">
|
||||
[% FOREACH profile = billing_profiles %]
|
||||
<option[% IF profile.name == account.billing_profile %] selected="selected"[% END %]>[% profile.name %]</option>
|
||||
[% END %]
|
||||
</select>
|
||||
[% ELSE %]
|
||||
[% account.billing_profile %]
|
||||
[% END %]
|
||||
</td>
|
||||
</tr>
|
||||
[% END %]
|
||||
|
||||
<tr><td class="tdkey">created:</td><td>[% account.create_timestamp %]</td></tr>
|
||||
<tr><td class="tdkey">modified:</td><td>[% account.modify_timestamp %]</td></tr>
|
||||
[% IF account.terminate_timestamp %]
|
||||
<tr><td class="tdkey">terminated:</td><td><div class="alert">[% account.terminate_timestamp %]</div></td></tr>
|
||||
[% END %]
|
||||
</table>
|
||||
[% IF edit_account %]
|
||||
<input type="submit" class="but" value="Save »" />
|
||||
[% END %]
|
||||
</form>
|
||||
</div>
|
||||
|
||||
[% IF billing_features %]
|
||||
<h3>Account Balance</h3>
|
||||
|
||||
[% IF ! account.terminate_timestamp %]
|
||||
<div class="actions">
|
||||
<a href="detail?account_id=[% account.id %]&edit_balance=1" class="aaction">edit</a>
|
||||
[% IF edit_balance %]
|
||||
<a href="detail?account_id=[% account.id %]" class="aaction">cancel</a>
|
||||
[% END %]
|
||||
</div>
|
||||
[% END %]
|
||||
<div class="p1">
|
||||
[% IF messages.balmsg %]<div class="goodmsg">[% messages.balmsg %]</div>[% END %]
|
||||
[% IF messages.balerr %]<div class="errormsg">[% messages.balerr %]</div>[% END %]
|
||||
Current totals
|
||||
<form action="update_balance" method="post">
|
||||
<input type="hidden" name="account_id" value="[% account.id %]" />
|
||||
<table>
|
||||
<tr>
|
||||
<td class="tdkey">cash:</td>
|
||||
<td class="nowrap">€ [% account.balance.cash_balance %]</td>
|
||||
<td>
|
||||
[% IF edit_balance %]
|
||||
<div class="account_add">add <input type="text" name="add_cash" value="[% balanceadd.cash %]" /> Euro</div>
|
||||
[% END %]
|
||||
</td>
|
||||
</tr>
|
||||
[% IF messages.addcash %]<tr><td /><td /><td><div class="errormsg">[% messages.addcash %]</div></td></tr>[% END %]
|
||||
<tr>
|
||||
<td class="tdkey">free time:</td>
|
||||
<td class="nowrap">[% account.balance.free_time_balance %] s</td>
|
||||
<td>
|
||||
[% IF edit_balance %]
|
||||
<div class="account_add">add <input type="text" name="add_time" value="[% balanceadd.free_time %]" /> seconds</div>
|
||||
[% END %]
|
||||
</td>
|
||||
</tr>
|
||||
[% IF messages.addtime %]<tr><td /><td /><td><div class="errormsg">[% messages.addtime %]</div></td></tr>[% END %]
|
||||
</table>
|
||||
[% IF edit_balance %]
|
||||
<input type="submit" class="but" value="Save »" />
|
||||
[% END %]
|
||||
</form>
|
||||
</div>
|
||||
<div class="p1">
|
||||
Spent this billing interval
|
||||
<table>
|
||||
<tr><td class="tdkey">cash:</td><td>€ [% account.balance.cash_balance_interval %]</td></tr>
|
||||
<tr><td class="tdkey">free time:</td><td>[% account.balance.free_time_balance_interval %] s</td></tr>
|
||||
</table>
|
||||
</div>
|
||||
[% END %]
|
||||
|
||||
<h3>Subscribers</h3>
|
||||
|
||||
<div class="actions">
|
||||
<a href="/subscriber/detail?account_id=[% account.id %]&new=1" class="aaction">create new</a>
|
||||
</div>
|
||||
<div class="p1">
|
||||
[% IF account.subscribers %]
|
||||
<table>
|
||||
[% FOREACH subscriber = account.subscribers %]
|
||||
<tr>
|
||||
<td>
|
||||
[% IF subscriber.subscriber_id %]
|
||||
<a href="/subscriber/detail?subscriber_id=[% subscriber.subscriber_id %]">
|
||||
[% subscriber.username %]@[% subscriber.domain %]</a>
|
||||
[% ELSE %]
|
||||
[% subscriber.username %]@[% subscriber.domain %]
|
||||
[% END %]
|
||||
</td>
|
||||
<td>[% IF subscriber.sn %]+[% subscriber.cc %] [% subscriber.ac %] [% subscriber.sn %][% END %]</td>
|
||||
<td>[% subscriber.uuid %]</td>
|
||||
</tr>
|
||||
[% END %]
|
||||
</table>
|
||||
[% ELSE %]
|
||||
<div>
|
||||
This account does not have any subscribers yet.
|
||||
</div>
|
||||
[% END %]
|
||||
</div>
|
||||
|
@ -0,0 +1,119 @@
|
||||
<h3>Manage Administrator Accounts</h3>
|
||||
|
||||
<div class="p1">
|
||||
[% IF messages.eadmmsg %]<div class="goodmsg">[% messages.eadmmsg %]</div>[% END %]
|
||||
[% IF messages.eadmerr %]<div class="errormsg">[% messages.eadmerr %]</div>[% END %]
|
||||
|
||||
<table>
|
||||
<tr class="table_header">
|
||||
<td>login</td>
|
||||
<td>password</td>
|
||||
<td>master</td>
|
||||
<td>active</td>
|
||||
<td />
|
||||
<td />
|
||||
</tr>
|
||||
[% id = 0 %]
|
||||
[% FOREACH admin = admins %]
|
||||
<tr>
|
||||
<td>[% admin.login %]</td>
|
||||
[% IF admin.login == edit_admin %]
|
||||
<form action="/admin/do_edit_admin" method="post">
|
||||
<input type="hidden" name="admin" value="[% admin.login %]" />
|
||||
<td><input type="password" name="password" value="" /></td>
|
||||
<td class="tdcenter">
|
||||
<input type="checkbox" class="checkbox" name="is_master"
|
||||
[% IF admin.login == Catalyst.session.admin.login %]disabled="disabled"[% END %]
|
||||
[% IF erefill.is_master or !erefill && admin.is_master %]checked="checked" [% END %] />
|
||||
</td>
|
||||
<td class="tdcenter">
|
||||
<input type="checkbox" class="checkbox" name="is_active"
|
||||
[% IF admin.login == Catalyst.session.admin.login %]disabled="disabled"[% END %]
|
||||
[% IF erefill.is_active or !erefill && admin.is_active %]checked="checked" [% END %] />
|
||||
</td>
|
||||
<td>
|
||||
<div class="postlink">
|
||||
<label for="admsave[% id %]">save</label>
|
||||
<input type="image" class="hidden" src="/static/images/dot_trans.gif" alt="" id="admsave[% id %]" />
|
||||
</div>
|
||||
</td>
|
||||
</form>
|
||||
<td><a href="/admin" class="aaction">cancel</a></td>
|
||||
[% ELSE %]
|
||||
<td>********</td>
|
||||
<td class="tdcenter"><input type="checkbox" class="checkbox" disabled="disabled"[% IF admin.is_master %] checked="checked"[% END %] /></td>
|
||||
<td class="tdcenter"><input type="checkbox" class="checkbox" disabled="disabled"[% IF admin.is_active %] checked="checked"[% END %] /></td>
|
||||
<td><a href="/admin?edit_admin=[% admin.login %]" class="aaction">edit</a></td>
|
||||
[% IF admin.login != Catalyst.session.admin.login %]
|
||||
<form action="/admin/do_delete_admin" method="post">
|
||||
<td>
|
||||
<input type="hidden" name="admin" value="[% admin.login %]" />
|
||||
<div class="postlink">
|
||||
<label for="admdel[% id %]">delete</label>
|
||||
<input type="image" class="hidden" src="/static/images/dot_trans.gif" alt="" id="admdel[% id %]" />
|
||||
</div>
|
||||
</td>
|
||||
</form>
|
||||
[% ELSE %]
|
||||
<td />
|
||||
[% END %]
|
||||
[% END %]
|
||||
</tr>
|
||||
[% IF admin.login == edit_admin %]
|
||||
[% IF messages.epass %]
|
||||
<tr><td colspan="5">
|
||||
<div class="errormsg">
|
||||
[% messages.epass %]
|
||||
</div>
|
||||
</td></tr>
|
||||
[% END %]
|
||||
[% END %]
|
||||
[% id = id + 1 %]
|
||||
[% END %]
|
||||
</table>
|
||||
</div>
|
||||
|
||||
[% IF Catalyst.session.admin.is_master || Catalyst.session.admin.is_superuser %]
|
||||
<h3>Create Administrator Account</h3>
|
||||
|
||||
<div class="p1">
|
||||
[% IF messages.cadmmsg %]<div class="goodmsg">[% messages.cadmmsg %]</div>[% END %]
|
||||
[% IF messages.cadmerr %]<div class="errormsg">[% messages.cadmerr %]</div>[% END %]
|
||||
|
||||
<table>
|
||||
<tr class="table_header">
|
||||
<td>login</td>
|
||||
<td>password</td>
|
||||
<td>master</td>
|
||||
<td>active</td>
|
||||
<td />
|
||||
<td />
|
||||
</tr>
|
||||
<form action="/admin/do_create_admin" method="post">
|
||||
<tr>
|
||||
<td><input type="text" size="20" name="admin" id="adminaddtxt" value="[% arefill.admin %]" /></td>
|
||||
<td><input type="password" name="password" value="" /></td>
|
||||
<td class="tdcenter"><input type="checkbox" class="checkbox" name="is_master"[% IF arefill.is_master %] checked="checked"[% END %] /></td>
|
||||
<td class="tdcenter"><input type="checkbox" class="checkbox" name="is_active"[% IF arefill.is_active %] checked="checked"[% END %] /></td>
|
||||
<td>
|
||||
<div class="postlink">
|
||||
<label for="adminadd">Add</label>
|
||||
<input type="image" class="hidden" src="/static/images/dot_trans.gif" alt="" id="adminadd" />
|
||||
</div>
|
||||
</td>
|
||||
<td />
|
||||
</tr>
|
||||
[% IF messages.alogin || messages.apass %]
|
||||
<tr><td colspan="5">
|
||||
<div class="errormsg">
|
||||
[% messages.alogin %]
|
||||
[% IF messages.alogin && messages.apass %]<br />[% END %]
|
||||
[% messages.apass %]
|
||||
</div>
|
||||
</td></tr>
|
||||
[% END %]
|
||||
</form>
|
||||
</table>
|
||||
</div>
|
||||
[% END %]
|
||||
|
@ -0,0 +1,58 @@
|
||||
<h3>Get by ID</h3>
|
||||
<div class="p1">
|
||||
<form action="/customer/getbyid" method="GET">
|
||||
<input type="text" id="customer_id" name="customer_id" value="[% customer_id %]" />
|
||||
<input type="submit" value="Get »" class="but" />
|
||||
</form>
|
||||
[% IF messages.accgeterr %]<div class="errormsg">[% messages.accgeterr %]</div>[% END %]
|
||||
</div>
|
||||
|
||||
<h3>Search by contacts</h3>
|
||||
<div class="p1">
|
||||
<form action="/customer/search" method="post">
|
||||
<input type="text" id="search_string" name="search_string" value="[% search_string %]" />
|
||||
<input type="submit" value="Search »" class="but" />
|
||||
</form>
|
||||
[% IF messages.accsearcherr %]<div class="errormsg">[% messages.accsearcherr %]</div>[% END %]
|
||||
</div>
|
||||
<!--
|
||||
<h3>Create new customer</h3>
|
||||
<div class="p1">
|
||||
<form action="/customer/create_customer" method="post">
|
||||
<input type="submit" value="Create »" class="but" />
|
||||
</form>
|
||||
</div>
|
||||
-->
|
||||
[% IF customer_list %]
|
||||
|
||||
<h3>Customers</h3>
|
||||
|
||||
<div class="p1">
|
||||
<table>
|
||||
<tr class="table_header"><td>CustomerID</td><td>Name</td><td>Firma</td></tr>
|
||||
|
||||
[% FOREACH customer = customer_list %]
|
||||
|
||||
<tr>
|
||||
<td><a href="/customer/detail?customer_id=[% customer.id %]">
|
||||
[% customer.id %]
|
||||
</a></td>
|
||||
<td><a href="/customer/detail?customer_id=[% customer.id %]">
|
||||
[% customer.contact.firstname %] [% customer.contact.lastname %]
|
||||
</a></td>
|
||||
[% IF customer.contact.company %]
|
||||
<td><a href="/customer/detail?customer_id=[% customer.id %]">
|
||||
[% customer.contact.company %]
|
||||
</a></td>
|
||||
[% ELSE %]
|
||||
<td />
|
||||
[% END %]
|
||||
</tr>
|
||||
|
||||
[% END %]
|
||||
|
||||
</table>
|
||||
</div>
|
||||
|
||||
[% END %]
|
||||
|
@ -0,0 +1,378 @@
|
||||
<h3> Customer
|
||||
<a class="noarrow" href="detail?customer_id=[% customer.id %]">
|
||||
#[% customer.id %]</a>
|
||||
</h3>
|
||||
|
||||
<div class="actions">
|
||||
<a href="detail?customer_id=[% customer.id %]&edit_customer=1" class="aaction">edit</a>
|
||||
[% IF edit_customer %]
|
||||
<a href="detail?customer_id=[% customer.id %]" class="aaction">cancel</a>
|
||||
[% END %]
|
||||
</div>
|
||||
|
||||
<div class="p1">
|
||||
[% IF messages.custmsg %]<div class="goodmsg">[% messages.custmsg %]</div>[% END %]
|
||||
[% IF messages.custerr %]<div class="errormsg">[% messages.custerr %]</div>[% END %]
|
||||
<form action="update_customer" method="post">
|
||||
<input type="hidden" name="customer_id" value="[% customer.id %]" />
|
||||
<table>
|
||||
<tr><td class="tdkey">ID:</td><td>[% customer.id %]</td></tr>
|
||||
<tr>
|
||||
<td class="tdkey">shopuser:</td>
|
||||
<td>
|
||||
<input type="text" id="shopuser" [% IF ! edit_customer %]class="disabled" disabled="disabled"[% END %]
|
||||
name="shopuser" value="[% customer.shopuser %]" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="tdkey">shoppass:</td>
|
||||
<td>
|
||||
[% IF edit_customer %]
|
||||
<input type="text" id="shoppass" name="shoppass" value="[% customer.edit_shoppass %]" />
|
||||
[% ELSE %]
|
||||
<input type="text" id="shoppass" name="shoppass" class="disabled" disabled="disabled"
|
||||
[% IF show_pass %]
|
||||
value="[% customer.shoppass %]" /> <a href="?customer_id=[% customer.id %]" class="apass">Hide</a>
|
||||
[% ELSE %]
|
||||
[% IF customer.shoppass %]
|
||||
value="********" /> <a href="?customer_id=[% customer.id %]&show_pass=1" class="apass">Show</a>
|
||||
[% ELSE %]
|
||||
value="" />
|
||||
[% END %]
|
||||
[% END %]
|
||||
[% END %]
|
||||
</td>
|
||||
</tr>
|
||||
<tr><td class="tdkey">created:</td><td>[% customer.create_timestamp %]</td></tr>
|
||||
<tr><td class="tdkey">modified:</td><td>[% customer.modify_timestamp %]</td></tr>
|
||||
</table>
|
||||
[% IF edit_customer %]
|
||||
<input type="submit" class="but" value="Save »" />
|
||||
[% END %]
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<h3 id="contact">Contact</h3>
|
||||
|
||||
<div class="actions">
|
||||
<a href="detail?customer_id=[% customer.id %]&edit_contact=1#contact" class="aaction">edit</a>
|
||||
[% IF edit_contact %]
|
||||
<a href="detail?customer_id=[% customer.id %]#contact" class="aaction">cancel</a>
|
||||
[% END %]
|
||||
</div>
|
||||
|
||||
<div class="p1">
|
||||
[% IF messages.contmsg %]<div class="goodmsg">[% messages.contmsg %]</div>[% END %]
|
||||
[% IF messages.conterr %]<div class="errormsg">[% messages.conterr %]</div>[% END %]
|
||||
<form action="update_contact#contact" method="post">
|
||||
<input type="hidden" name="ctype" value="contact" />
|
||||
<input type="hidden" name="customer_id" value="[% customer.id %]" />
|
||||
<table>
|
||||
<tr>
|
||||
<td class="tdkey">name:</td>
|
||||
<td>
|
||||
<select [% IF ! edit_contact %]class="disabled" disabled="disabled" [% END %] name="gender">
|
||||
<option value="male"[% IF customer.contact.gender == "male" %] selected="selected"[% END %]>Mr.</option>
|
||||
<option value="female"[% IF customer.contact.gender == "female" %] selected="selected"[% END %]>Ms./Mrs.</option>
|
||||
</select>
|
||||
<input type="text" id="cont_firstname" [% IF ! edit_contact %]class="disabled" disabled="disabled"[% END %]
|
||||
name="firstname" value="[% customer.contact.firstname %]" />
|
||||
<input type="text" id="cont_lastname" [% IF ! edit_contact %]class="disabled" disabled="disabled"[% END %]
|
||||
name="lastname" value="[% customer.contact.lastname %]" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="tdkey">comm. register num.:</td>
|
||||
<td>
|
||||
<input type="text" id="cont_comregnum" [% IF ! edit_contact %]class="disabled" disabled="disabled"[% END %]
|
||||
name="comregnum" value="[% customer.contact.comregnum %]" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="tdkey">company:</td>
|
||||
<td>
|
||||
<input type="text" id="cont_company" [% IF ! edit_contact %]class="disabled" disabled="disabled"[% END %]
|
||||
name="company" value="[% customer.contact.company %]" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="tdkey">street:</td>
|
||||
<td>
|
||||
<input type="text" id="cont_street" [% IF ! edit_contact %]class="disabled" disabled="disabled"[% END %]
|
||||
name="street" value="[% customer.contact.street %]" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="tdkey">postcode / city:</td>
|
||||
<td>
|
||||
<input type="text" id="cont_postcode" [% IF ! edit_contact %]class="disabled" disabled="disabled"[% END %]
|
||||
name="postcode" value="[% customer.contact.postcode %]" />
|
||||
<input type="text" id="cont_city" [% IF ! edit_contact %]class="disabled" disabled="disabled"[% END %]
|
||||
name="city" value="[% customer.contact.city %]" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="tdkey">phonenumber:</td>
|
||||
<td>
|
||||
<input type="text" id="cont_phonenumber" [% IF ! edit_contact %]class="disabled" disabled="disabled"[% END %]
|
||||
name="phonenumber" value="[% customer.contact.phonenumber %]" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="tdkey">mobilenumber:</td>
|
||||
<td>
|
||||
<input type="text" id="cont_mobilenumber" [% IF ! edit_contact %]class="disabled" disabled="disabled"[% END %]
|
||||
name="mobilenumber" value="[% customer.contact.mobilenumber %]" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="tdkey">email:</td>
|
||||
<td>
|
||||
<input type="text" id="cont_email" [% IF ! edit_contact %]class="disabled" disabled="disabled"[% END %]
|
||||
name="email" value="[% customer.contact.email %]" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="tdkey">newsletter:</td>
|
||||
<td>
|
||||
<input type="checkbox" id="cont_newsletter" [% IF ! edit_contact %]class="disabled" disabled="disabled"[% END %]
|
||||
name="newsletter" [% IF customer.contact.newsletter %]checked="checked"[% END %] />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="tdkey">created:</td>
|
||||
<td> [% customer.contact.create_timestamp %]</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="tdkey">modified:</td>
|
||||
<td> [% customer.contact.modify_timestamp %]</td>
|
||||
</tr>
|
||||
</table>
|
||||
[% IF edit_contact %]
|
||||
<input type="submit" class="but" value="Save »" />
|
||||
[% END %]
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<h3 id="commercial">Commercial Contact</h3>
|
||||
|
||||
<div class="actions">
|
||||
<a href="detail?customer_id=[% customer.id %]&edit_commercial=1#commercial" class="aaction">edit</a>
|
||||
[% IF edit_commercial %]
|
||||
<a href="detail?customer_id=[% customer.id %]#commercial" class="aaction">cancel</a>
|
||||
[% END %]
|
||||
</div>
|
||||
|
||||
<div class="p1">
|
||||
[% IF messages.commmsg %]<div class="goodmsg">[% messages.commmsg %]</div>[% END %]
|
||||
[% IF messages.commerr %]<div class="errormsg">[% messages.commerr %]</div>[% END %]
|
||||
<form action="update_contact#commercial" method="post">
|
||||
<input type="hidden" name="ctype" value="comm_contact" />
|
||||
<input type="hidden" name="customer_id" value="[% customer.id %]" />
|
||||
<table>
|
||||
<tr>
|
||||
<td class="tdkey">name:</td>
|
||||
<td>
|
||||
<select [% IF ! edit_commercial %]class="disabled" disabled="disabled" [% END %] name="gender">
|
||||
<option value="male"[% IF customer.comm_contact.gender == "male" %] selected="selected"[% END %]>Mr.</option>
|
||||
<option value="female"[% IF customer.comm_contact.gender == "female" %] selected="selected"[% END %]>Ms./Mrs.</option>
|
||||
</select>
|
||||
<input type="text" id="comm_firstname" [% IF ! edit_commercial %]class="disabled" disabled="disabled"[% END %]
|
||||
name="firstname" value="[% customer.comm_contact.firstname %]" />
|
||||
<input type="text" id="comm_lastname" [% IF ! edit_commercial %]class="disabled" disabled="disabled"[% END %]
|
||||
name="lastname" value="[% customer.comm_contact.lastname %]" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="tdkey">phonenumber:</td>
|
||||
<td>
|
||||
<input type="text" id="comm_phonenumber" [% IF ! edit_commercial %]class="disabled" disabled="disabled"[% END %]
|
||||
name="phonenumber" value="[% customer.comm_contact.phonenumber %]" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="tdkey">mobilenumber:</td>
|
||||
<td>
|
||||
<input type="text" id="comm_mobilenumber" [% IF ! edit_commercial %]class="disabled" disabled="disabled"[% END %]
|
||||
name="mobilenumber" value="[% customer.comm_contact.mobilenumber %]" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="tdkey">email:</td>
|
||||
<td>
|
||||
<input type="text" id="comm_email" [% IF ! edit_commercial %]class="disabled" disabled="disabled"[% END %]
|
||||
name="email" value="[% customer.comm_contact.email %]" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="tdkey">newsletter:</td>
|
||||
<td>
|
||||
<input type="checkbox" id="comm_newsletter" [% IF ! edit_commercial %]class="disabled" disabled="disabled"[% END %]
|
||||
name="newsletter" [% IF customer.comm_contact.newsletter %]checked="checked"[% END %] />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="tdkey">created:</td>
|
||||
<td> [% customer.comm_contact.create_timestamp %]</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="tdkey">modified:</td>
|
||||
<td> [% customer.comm_contact.modify_timestamp %]</td>
|
||||
</tr>
|
||||
</table>
|
||||
[% IF edit_commercial %]
|
||||
<input type="submit" class="but" value="Save »" />
|
||||
[% END %]
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<h3 id="technical">Technical Contact</h3>
|
||||
|
||||
<div class="actions">
|
||||
<a href="detail?customer_id=[% customer.id %]&edit_technical=1#technical" class="aaction">edit</a>
|
||||
[% IF edit_technical %]
|
||||
<a href="detail?customer_id=[% customer.id %]#technical" class="aaction">cancel</a>
|
||||
[% END %]
|
||||
</div>
|
||||
|
||||
<div class="p1">
|
||||
[% IF messages.techmsg %]<div class="goodmsg">[% messages.techmsg %]</div>[% END %]
|
||||
[% IF messages.techerr %]<div class="errormsg">[% messages.techerr %]</div>[% END %]
|
||||
<form action="update_contact#technical" method="post">
|
||||
<input type="hidden" name="ctype" value="tech_contact" />
|
||||
<input type="hidden" name="customer_id" value="[% customer.id %]" />
|
||||
<table>
|
||||
<tr>
|
||||
<td class="tdkey">name:</td>
|
||||
<td>
|
||||
<select [% IF ! edit_technical %]class="disabled" disabled="disabled" [% END %] name="gender">
|
||||
<option value="male"[% IF customer.tech_contact.gender == "male" %] selected="selected"[% END %]>Mr.</option>
|
||||
<option value="female"[% IF customer.tech_contact.gender == "female" %] selected="selected"[% END %]>Ms./Mrs.</option>
|
||||
</select>
|
||||
<input type="text" id="tech_firstname" [% IF ! edit_technical %]class="disabled" disabled="disabled"[% END %]
|
||||
name="firstname" value="[% customer.tech_contact.firstname %]" />
|
||||
<input type="text" id="tech_lastname" [% IF ! edit_technical %]class="disabled" disabled="disabled"[% END %]
|
||||
name="lastname" value="[% customer.tech_contact.lastname %]" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="tdkey">phonenumber:</td>
|
||||
<td>
|
||||
<input type="text" id="tech_phonenumber" [% IF ! edit_technical %]class="disabled" disabled="disabled"[% END %]
|
||||
name="phonenumber" value="[% customer.tech_contact.phonenumber %]" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="tdkey">mobilenumber:</td>
|
||||
<td>
|
||||
<input type="text" id="tech_mobilenumber" [% IF ! edit_technical %]class="disabled" disabled="disabled"[% END %]
|
||||
name="mobilenumber" value="[% customer.tech_contact.mobilenumber %]" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="tdkey">email:</td>
|
||||
<td>
|
||||
<input type="text" id="tech_email" [% IF ! edit_technical %]class="disabled" disabled="disabled"[% END %]
|
||||
name="email" value="[% customer.tech_contact.email %]" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="tdkey">newsletter:</td>
|
||||
<td>
|
||||
<input type="checkbox" id="tech_newsletter" [% IF ! edit_technical %]class="disabled" disabled="disabled"[% END %]
|
||||
name="newsletter" [% IF customer.tech_contact.newsletter %]checked="checked"[% END %] />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="tdkey">created:</td>
|
||||
<td> [% customer.tech_contact.create_timestamp %]</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="tdkey">modified:</td>
|
||||
<td> [% customer.tech_contact.modify_timestamp %]</td>
|
||||
</tr>
|
||||
</table>
|
||||
[% IF edit_technical %]
|
||||
<input type="submit" class="but" value="Save »" />
|
||||
[% END %]
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<h3>Contracts</h3>
|
||||
|
||||
<!-- <div class="actions">
|
||||
<a href="/subscriber/detail?customer_id=[% customer.id %]&new=1" class="aaction">create new</a>
|
||||
</div>
|
||||
--> <div class="p1">
|
||||
[% IF customer.contracts %]
|
||||
<table>
|
||||
<tr>
|
||||
<td class="table_header">ContractID</td>
|
||||
<td class="table_header">Product</td>
|
||||
<td class="table_header">status</td>
|
||||
<td class="table_header">created</td>
|
||||
</tr>
|
||||
[% FOREACH contract = customer.contracts %]
|
||||
<tr>
|
||||
<td>
|
||||
[% IF contract.class == 'voip' %]
|
||||
<a href="/account/detail?account_id=[% contract.id %]">
|
||||
[% contract.id %]
|
||||
</a>
|
||||
[% ELSE %]
|
||||
[% contract.id %]
|
||||
[% END %]
|
||||
</td>
|
||||
<td>
|
||||
[% IF contract.class == 'voip' %]
|
||||
<a href="/account/detail?account_id=[% contract.id %]">
|
||||
[% contract.product %]
|
||||
</a>
|
||||
[% ELSE %]
|
||||
[% contract.product %]
|
||||
[% END %]
|
||||
</td>
|
||||
<td>[% contract.status %]</td>
|
||||
<td>[% contract.create_timestamp %]</td>
|
||||
</tr>
|
||||
[% END %]
|
||||
</table>
|
||||
[% ELSE %]
|
||||
<div>
|
||||
This customer does not have any contracts yet.
|
||||
</div>
|
||||
[% END %]
|
||||
</div>
|
||||
|
||||
<h3>Orders</h3>
|
||||
|
||||
<!-- <div class="actions">
|
||||
<a href="/subscriber/detail?customer_id=[% customer.id %]&new=1" class="aaction">create new</a>
|
||||
</div>
|
||||
--> <div class="p1">
|
||||
[% IF customer.orders %]
|
||||
<table>
|
||||
<tr>
|
||||
<td class="table_header">OrderID</td>
|
||||
<td class="table_header">status</td>
|
||||
<td class="table_header">created</td>
|
||||
<td class="table_header">modified</td>
|
||||
<td class="table_header">completed</td>
|
||||
</tr>
|
||||
[% FOREACH order = customer.orders %]
|
||||
<tr>
|
||||
<td>[% order.id %]</td>
|
||||
<td>[% order.status %]</td>
|
||||
<td>[% order.create_timestamp %]</td>
|
||||
<td>[% order.modify_timestamp %]</td>
|
||||
<td>[% order.complete_timestamp %]</td>
|
||||
</tr>
|
||||
[% END %]
|
||||
</table>
|
||||
[% ELSE %]
|
||||
<div>
|
||||
This customer does not have any orders yet.
|
||||
</div>
|
||||
[% END %]
|
||||
</div>
|
||||
|
@ -0,0 +1,104 @@
|
||||
<h3>Edit Domains</h3>
|
||||
|
||||
<div class="p1">
|
||||
[% IF messages.edommsg %]<div class="goodmsg">[% messages.edommsg %]</div>[% END %]
|
||||
[% IF messages.edomerr %]<div class="errormsg">[% messages.edomerr %]</div>[% END %]
|
||||
|
||||
<table>
|
||||
<tr class="table_header">
|
||||
<td>domain</td>
|
||||
<td>country code</td>
|
||||
<td>timezone</td>
|
||||
<td />
|
||||
<td />
|
||||
</tr>
|
||||
[% id = 0 %]
|
||||
[% FOREACH domain = domains %]
|
||||
<tr>
|
||||
<td>[% domain.domain %]</td>
|
||||
[% IF domain.domain == edit_domain %]
|
||||
<form action="/domain/do_edit_domain" method="post">
|
||||
<input type="hidden" name="domain" value="[% domain.domain %]" />
|
||||
<td class="tdcenter"><input class="ishort" name="cc" value="[% domain.cc %]" /></td>
|
||||
<td><input name="timezone" value="[% domain.timezone %]" /></td>
|
||||
<td>
|
||||
<div class="postlink">
|
||||
<label for="domsave[% id %]">save</label>
|
||||
<input type="image" class="hidden" src="/static/images/dot_trans.gif" alt="" id="domsave[% id %]" />
|
||||
</div>
|
||||
</td>
|
||||
</form>
|
||||
<td><a href="/domain" class="aaction">cancel</a></td>
|
||||
[% ELSE %]
|
||||
<td class="tdcenter">[% domain.cc %]</td>
|
||||
<td>[% domain.timezone %]</td>
|
||||
<td><a href="/domain?edit_domain=[% domain.domain %]" class="aaction">edit</a></td>
|
||||
<form action="/domain/do_delete_domain" method="post">
|
||||
<input type="hidden" name="domain" value="[% domain.domain %]" />
|
||||
<td>
|
||||
<div class="postlink">
|
||||
<label for="domdel[% id %]">delete</label>
|
||||
<input type="image" class="hidden" src="/static/images/dot_trans.gif" alt="" id="domdel[% id %]" />
|
||||
</div>
|
||||
</td>
|
||||
</form>
|
||||
[% END %]
|
||||
</tr>
|
||||
[% IF domain.domain == edit_domain %]
|
||||
[% IF messages.ecc || messages.etimezone %]
|
||||
<tr><td colspan="5">
|
||||
<div class="errormsg">
|
||||
[% messages.ecc %]
|
||||
[% IF messages.ecc && messages.etimezone %]<br />[% END %]
|
||||
[% messages.etimezone %]
|
||||
</div>
|
||||
</td></tr>
|
||||
[% END %]
|
||||
[% END %]
|
||||
[% id = id + 1 %]
|
||||
[% END %]
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<h3>Create domain</h3>
|
||||
|
||||
<div class="p1">
|
||||
[% IF messages.cdommsg %]<div class="goodmsg">[% messages.cdommsg %]</div>[% END %]
|
||||
[% IF messages.cdomerr %]<div class="errormsg">[% messages.cdomerr %]</div>[% END %]
|
||||
|
||||
<table>
|
||||
<tr class="table_header">
|
||||
<td>domain</td>
|
||||
<td>country code</td>
|
||||
<td>timezone</td>
|
||||
<td />
|
||||
<td />
|
||||
</tr>
|
||||
<form action="/domain/do_create_domain" method="post">
|
||||
<tr>
|
||||
<td><input type="text" size="20" name="domain" id="domainaddtxt" value="[% arefill.domain %]" /></td>
|
||||
<td class="tdcenter"><input class="ishort" name="cc" value="[% arefill.cc %]" /></td>
|
||||
<td><input name="timezone" value="[% arefill.timezone %]" /></td>
|
||||
<td>
|
||||
<div class="postlink">
|
||||
<label for="domainadd">Add</label>
|
||||
<input type="image" class="hidden" src="/static/images/dot_trans.gif" alt="" id="domainadd" />
|
||||
</div>
|
||||
</td>
|
||||
<td />
|
||||
</tr>
|
||||
[% IF messages.acc || messages.atimezone %]
|
||||
<tr><td colspan="5">
|
||||
<div class="errormsg">
|
||||
[% messages.acc %]
|
||||
[% IF messages.acc && messages.atimezone %]<br />[% END %]
|
||||
[% messages.atimezone %]
|
||||
</div>
|
||||
</td></tr>
|
||||
[% END %]
|
||||
</form>
|
||||
|
||||
</table>
|
||||
|
||||
</div>
|
||||
|
@ -0,0 +1,10 @@
|
||||
<h3>Login</h3>
|
||||
<div class="p1">
|
||||
<form id="login" action="/login" method="post">
|
||||
<label for="login_user">Username</label><br />
|
||||
<input type="text" id="login_user" name="username" /><br />
|
||||
<label for="login_pass">Password</label><br />
|
||||
<input type="password" id="login_pass" name="password" /><br />
|
||||
<input type="submit" value="Login »" class="but" />
|
||||
</form>
|
||||
</div>
|
@ -0,0 +1,83 @@
|
||||
<h3>Search Subscribers</h3>
|
||||
<div class="p1">
|
||||
<form action="/subscriber/search" method="post">
|
||||
<input type="text" id="search_subscriber" name="search_string" value="[% search_string %]" />
|
||||
<input type="submit" value="Search »" class="but" />
|
||||
</form>
|
||||
</div>
|
||||
|
||||
[% IF subscriber_list %]
|
||||
|
||||
<h3>Subscribers</h3>
|
||||
|
||||
<div class="p1">
|
||||
<table>
|
||||
<tr><td>SIP URI</td><td class="tdcenter">Account ID</td></tr>
|
||||
|
||||
[% FOREACH subscriber = subscriber_list %]
|
||||
|
||||
<tr>
|
||||
<td>
|
||||
[% IF subscriber.subscriber_id %]
|
||||
<a href="/subscriber/detail?subscriber_id=[% subscriber.subscriber_id %]">
|
||||
[% subscriber.username %]@[% subscriber.domain %]</a>
|
||||
[% ELSE %]
|
||||
[% subscriber.username %]@[% subscriber.domain %]
|
||||
[% END %]
|
||||
</td>
|
||||
<td class="tdcenter">
|
||||
<a href="/account/detail?account_id=[% subscriber.account_id %]">
|
||||
[% subscriber.account_id %]</a>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
[% END %]
|
||||
</table>
|
||||
|
||||
[% IF pagination %]
|
||||
<div class="pagination">
|
||||
<ul>
|
||||
[% IF offset == 0 %]
|
||||
<li class="disablepage">« prev</li>
|
||||
[% ELSE %]
|
||||
<li class="nextpage">
|
||||
<a href="/subscriber/search?search_string=[% search_string %]&offset=[% offset - 1 %]">« prev</a>
|
||||
</li>
|
||||
[% END %]
|
||||
[% FOREACH pagine = pagination %]
|
||||
[% IF pagine.offset == offset %]
|
||||
<li class="currentpage">
|
||||
[% pagine.offset + 1 %]
|
||||
</li>
|
||||
[% ELSIF pagine.offset == -1 %]
|
||||
...
|
||||
[% ELSE %]
|
||||
<li>
|
||||
<a href="/subscriber/search?search_string=[% search_string
|
||||
%]&offset=[% pagine.offset %]">[% pagine.offset + 1 %]</a>
|
||||
</li>
|
||||
[% END %]
|
||||
[% END %]
|
||||
[% IF offset >= max_offset %]
|
||||
<li class="disablepage">
|
||||
next »
|
||||
</li>
|
||||
[% ELSE %]
|
||||
<li class="nextpage">
|
||||
<a href="/subscriber/search?search_string=[% search_string %]&offset=[% offset + 1 %]">next »</a>
|
||||
</li>
|
||||
[% END %]
|
||||
</ul>
|
||||
</div>
|
||||
[% END %]
|
||||
|
||||
</div>
|
||||
|
||||
[% ELSIF searched %]
|
||||
|
||||
<div class="p1">
|
||||
No matching subscribers found.
|
||||
</div>
|
||||
|
||||
[% END %]
|
||||
|
@ -0,0 +1,333 @@
|
||||
[% IF subscriber.subscriber_id %]
|
||||
<h3> Subscriber
|
||||
<a class="noarrow" href="detail?subscriber_id=[% subscriber.subscriber_id %]">
|
||||
[% subscriber.username %]@[% subscriber.domain %]</a>
|
||||
</h3>
|
||||
|
||||
<div class="actions">
|
||||
<a href="detail?subscriber_id=[% subscriber.subscriber_id %]&edit_subscriber=1" class="aaction">edit</a>
|
||||
[% ELSE %]
|
||||
<h3>New subscriber</h3>
|
||||
|
||||
<div class="actions">
|
||||
[% END %]
|
||||
[% IF edit_subscriber %]
|
||||
[% IF subscriber.subscriber_id %]
|
||||
<a href="detail?subscriber_id=[% subscriber.subscriber_id %]" class="aaction">cancel</a>
|
||||
[% ELSE %]
|
||||
<a href="/account/detail?account_id=[% account_id %]" class="aaction">cancel</a>
|
||||
[% END %]
|
||||
[% ELSE %]
|
||||
<script language="JavaScript" src="/js/openclose.js" type="text/javascript"></script>
|
||||
<a href="javascript:;" class="aaction" onclick="javascript:openclose();" onkeypress="javascript:openclose();">lock</a>
|
||||
<span id="lock_menu" class="floating" onmouseout="javascript:openclose();">
|
||||
<a href="lock?subscriber_id=[% subscriber.subscriber_id %]&lock=none" class="aaction">unlock</a><br />
|
||||
<a href="lock?subscriber_id=[% subscriber.subscriber_id %]&lock=foreign" class="aaction">foreign</a><br />
|
||||
<a href="lock?subscriber_id=[% subscriber.subscriber_id %]&lock=outgoing" class="aaction">all outgoing</a><br />
|
||||
<a href="lock?subscriber_id=[% subscriber.subscriber_id %]&lock=incoming" class="aaction">incoming and outgoing</a><br />
|
||||
<a href="lock?subscriber_id=[% subscriber.subscriber_id %]&lock=global" class="aaction">global</a><br />
|
||||
</span>
|
||||
<a href="terminate?subscriber_id=[% subscriber.subscriber_id %]" class="aaction">terminate</a>
|
||||
[% END %]
|
||||
</div>
|
||||
<div class="p1">
|
||||
[% IF subscriber.is_locked %]
|
||||
<div class="alert">[% subscriber.is_locked %]</div>
|
||||
[% END %]
|
||||
[% IF messages.submsg %]<div class="goodmsg">[% messages.submsg %]</div>[% END %]
|
||||
[% IF messages.suberr %]<div class="errormsg">[% messages.suberr %]</div>[% END %]
|
||||
<form action="update_subscriber" method="post">
|
||||
<input type="hidden" name="subscriber_id" value="[% subscriber.subscriber_id %]" />
|
||||
<input type="hidden" name="account_id" value="[% account_id %]" />
|
||||
<table class="table">
|
||||
<tr><td class="tdkey">ID:</td><td>[% subscriber.subscriber_id %]</td></tr>
|
||||
<tr>
|
||||
<td class="tdkey">account ID:</td>
|
||||
<td>
|
||||
<a href="/account/detail?account_id=[% subscriber.account_id || account_id %]">
|
||||
[% subscriber.account_id || account_id %]</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr><td class="tdkey">user:</td><td>[% subscriber.webusername %]</td></tr>
|
||||
[% IF subscriber.subscriber_id %]
|
||||
<tr><td class="tdkey">SIP URI:</td><td>[% subscriber.username %]@[% subscriber.domain %]</td></tr>
|
||||
[% ELSE %]
|
||||
<tr>
|
||||
<td class="tdkey">SIP URI:</td>
|
||||
<td>
|
||||
<input type="text" name="username" value="[% subscriber.username %]" />
|
||||
@
|
||||
<select size="1" name="domain">
|
||||
[% FOREACH sdom = domains %]
|
||||
<option>[% sdom.domain %]</option>
|
||||
[% END %]
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
[% END %]
|
||||
<tr>
|
||||
<td class="tdkey">E.164 number:</td>
|
||||
<td>
|
||||
[% IF edit_subscriber %]
|
||||
<input type="text" name="cc" class="ishort" value="[% subscriber.cc %]" />
|
||||
<input type="text" name="ac" class="ishort" value="[% subscriber.ac %]" />
|
||||
<input type="text" name="sn" value="[% subscriber.sn %]" />
|
||||
[% ELSE %]
|
||||
<input type="text" class="disabled" disabled="disabled"
|
||||
[% IF subscriber.sn %]
|
||||
value="+[% subscriber.cc %] [% subscriber.ac %] [% subscriber.sn %]" />
|
||||
[% ELSE %]
|
||||
value="" />
|
||||
[% END %]
|
||||
[% END %]
|
||||
</td>
|
||||
</tr>
|
||||
[% IF messages.number %]<tr><td /><td><div class="errormsg">[% messages.number %]</div></td></tr>[% END %]
|
||||
[% IF messages.number_cc %]<tr><td /><td><div class="errormsg">[% messages.number_cc %]</div></td></tr>[% END %]
|
||||
[% IF messages.number_ac %]<tr><td /><td><div class="errormsg">[% messages.number_ac %]</div></td></tr>[% END %]
|
||||
[% IF messages.number_sn %]<tr><td /><td><div class="errormsg">[% messages.number_sn %]</div></td></tr>[% END %]
|
||||
<tr>
|
||||
<td class="tdkey">web password:</td>
|
||||
<td>
|
||||
[% IF edit_subscriber %]
|
||||
<input type="text" name="webpassword" id="edit_webpass" value="[% subscriber.edit_webpass %]" />
|
||||
[% ELSE %]
|
||||
<input type="text" id="edit_webpass" class="disabled" disabled="disabled"
|
||||
[% IF show_webpass %]
|
||||
value="[% subscriber.webpassword %]" /> <a href="?subscriber_id=[% subscriber.subscriber_id %]" class="apass">Hide</a>
|
||||
[% ELSE %]
|
||||
[% IF subscriber.webpassword %]
|
||||
value="********" /> <a href="?subscriber_id=[% subscriber.subscriber_id %]&show_webpass=1" class="apass">Show</a>
|
||||
[% ELSE %]
|
||||
value="" />
|
||||
[% END %]
|
||||
[% END %]
|
||||
[% END %]
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="tdkey">SIP password:</td>
|
||||
<td>
|
||||
[% IF edit_subscriber %]
|
||||
<input type="text" name="password" id="edit_pass" value="[% subscriber.edit_pass %]" />
|
||||
[% ELSE %]
|
||||
<input type="text" id="edit_pass" class="disabled" disabled="disabled"
|
||||
[% IF show_pass %]
|
||||
value="[% subscriber.password %]" /> <a href="?subscriber_id=[% subscriber.subscriber_id %]" class="apass">Hide</a>
|
||||
[% ELSE %]
|
||||
[% IF subscriber.password %]
|
||||
value="********" /> <a href="?subscriber_id=[% subscriber.subscriber_id %]&show_pass=1" class="apass">Show</a>
|
||||
[% ELSE %]
|
||||
value="" />
|
||||
[% END %]
|
||||
[% END %]
|
||||
[% END %]
|
||||
</td>
|
||||
</tr>
|
||||
[% IF messages.password %]<tr><td /><td><div class="errormsg">[% messages.password %]</div></td></tr>[% END %]
|
||||
<tr>
|
||||
<td class="tdkey">administrative:</td>
|
||||
<td>
|
||||
<input type="checkbox" name="admin" class="checkbox" [% IF ! edit_subscriber %]disabled="disabled"[% END %]
|
||||
[% IF subscriber.admin %]checked="checked"[% END %] />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="tdkey">timezone:</td>
|
||||
<td>
|
||||
<input type="text" name="timezone" [% IF ! edit_subscriber %]class="disabled" disabled="disabled"[% END %]
|
||||
value="[% subscriber.timezone %]" />
|
||||
</td>
|
||||
</tr>
|
||||
[% IF messages.timezone %]<tr><td /><td><div class="errormsg">[% messages.timezone %]</div></td></tr>[% END %]
|
||||
<tr><td class="tdkey">UUID:</td><td>[% subscriber.uuid %]</td></tr>
|
||||
<tr><td class="tdkey">created:</td><td>[% subscriber.create_timestamp %]</td></tr>
|
||||
<tr><td class="tdkey">modified:</td><td>[% subscriber.modify_timestamp %]</td></tr>
|
||||
</table>
|
||||
|
||||
[% IF edit_subscriber %]
|
||||
<input type="submit" class="but" value="Save »" />
|
||||
[% END %]
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<h3 id="userprefs">User Preferences</h3>
|
||||
|
||||
<div class="actions">
|
||||
<a href="detail?subscriber_id=[% subscriber.subscriber_id %]&edit_preferences=1#userprefs" class="aaction">edit</a>
|
||||
[% IF edit_preferences %]
|
||||
<a href="detail?subscriber_id=[% subscriber.subscriber_id %]#userprefs" class="aaction">cancel</a>
|
||||
[% END %]
|
||||
</div>
|
||||
<div class="p1">
|
||||
[% IF messages.prefmsg %]<div class="goodmsg">[% messages.prefmsg %]</div>[% END %]
|
||||
[% IF messages.preferr %]<div class="errormsg">[% messages.preferr %]</div>[% END %]
|
||||
<form action="update_preferences" method="post">
|
||||
<input type="hidden" name="subscriber_id" value="[% subscriber.subscriber_id %]" />
|
||||
<table>
|
||||
[% FOREACH preference = subscriber.preferences_array %]
|
||||
[% IF preference.max_occur == 1 %]
|
||||
[% IF preference.key == "block_in_mode" || preference.key == "block_out_mode" %]
|
||||
<tr>
|
||||
<td class="tdkey">[% preference.key %]:</td>
|
||||
<td>
|
||||
<select size="1" name="[% preference.key %]"
|
||||
[% IF ! edit_preferences %]class="disabled" disabled="disabled"[% END %] >
|
||||
<option [% IF ! preference.value %]selected="selected"[% END %]>blacklist</option>
|
||||
<option [% IF preference.value %]selected="selected"[% END %]>whitelist</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
[% ELSIF preference.key == "block_in_clir"
|
||||
|| preference.key == "clir"
|
||||
|| preference.key == "cfu"
|
||||
|| preference.key == "cfb"
|
||||
|| preference.key == "cft"
|
||||
|| preference.key == "cfna" %]
|
||||
<tr>
|
||||
<td class="tdkey">[% preference.key %]:</td>
|
||||
<td>
|
||||
<input type="checkbox" name="[% preference.key %]" class="checkbox"
|
||||
[% IF ! edit_preferences %]disabled="disabled"[% END %]
|
||||
[% IF preference.value %]checked="checked"[% END %] />
|
||||
</td>
|
||||
</tr>
|
||||
[% ELSIF preference.key == "prepaid"
|
||||
|| preference.key == "has_extension" %]
|
||||
<tr>
|
||||
<td class="tdkey">[% preference.key %]:</td>
|
||||
<td>
|
||||
<input type="checkbox" name="[% preference.key %]" class="checkbox"
|
||||
disabled="disabled" [% IF preference.value %]checked="checked"[% END %] />
|
||||
</td>
|
||||
</tr>
|
||||
[% ELSIF preference.key == "cftarget" %]
|
||||
<tr>
|
||||
<td class="tdkey">[% preference.key %]:</td>
|
||||
<td>
|
||||
[% IF edit_preferences %]
|
||||
<label for="cfvoicebox">
|
||||
<input type="radio" id="cfvoicebox" value="voicebox" name="fw_target" class="radio"
|
||||
[% IF ! preference.value.sipuri %]checked="checked"[% END %] />
|
||||
Voicebox
|
||||
</label>
|
||||
<br clear="all" />
|
||||
<label for="cfsipuri">
|
||||
<input type="radio" id="cfsipuri" value="sipuri" name="fw_target" class="radio"
|
||||
[% IF preference.value.sipuri %]checked="checked"[% END %] />
|
||||
number or SIP-URI:
|
||||
</label>
|
||||
<input type="text" id="cfsipuritxt" name="fw_sipuri" size="25" value="[% preference.value.sipuri %]"
|
||||
[% IF ! edit_preferences %]class="disabled" disabled="disabled"[% END %] />
|
||||
[% ELSE %]
|
||||
[% IF preference.value.sipuri %]
|
||||
<input type="text" size="25" value="[% preference.value.sipuri %]"
|
||||
class="disabled" disabled="disabled" />
|
||||
[% ELSE %]
|
||||
Voicebox
|
||||
[% END %]
|
||||
[% END %]
|
||||
</td>
|
||||
</tr>
|
||||
[% IF messages.target %]<tr><td /><td><div class="errormsg">[% messages.target %]</div></td></tr>[% END %]
|
||||
[% ELSIF preference.key == "base_cli"
|
||||
|| preference.key == "extension"
|
||||
|| preference.key == "lock"
|
||||
|| preference.key == "base_user" %]
|
||||
<tr>
|
||||
<td class="tdkey">[% preference.key %]:</td>
|
||||
<td>
|
||||
<input type="text" name="[% preference.key %]"
|
||||
class="disabled txtpreference" disabled="disabled"
|
||||
value="[% preference.value %]" />
|
||||
</td>
|
||||
</tr>
|
||||
[% ELSE %]
|
||||
<tr>
|
||||
<td class="tdkey">[% preference.key %]:</td>
|
||||
<td>
|
||||
<input type="text" name="[% preference.key %]" [% IF ! edit_preferences %]
|
||||
class="disabled txtpreference" disabled="disabled"
|
||||
[% ELSE %]
|
||||
class="txtpreference"
|
||||
[% END %]
|
||||
value="[% preference.value %]" />
|
||||
</td>
|
||||
</tr>
|
||||
[% END %]
|
||||
[% ELSE %]
|
||||
<tr>
|
||||
<td class="tdkey">[% preference.key %]:</td>
|
||||
<td>
|
||||
[% IF preference.value %]
|
||||
<select size="1" name="[% preference.key %]">
|
||||
[% FOREACH pref_entry = preference.value %]
|
||||
<option>[% pref_entry %]</option>
|
||||
[% END %]
|
||||
</select>
|
||||
[% ELSE %]
|
||||
<select size="1" name="[% preference.key %]">
|
||||
<option />
|
||||
</select>
|
||||
[% END %]
|
||||
[% IF ! edit_preferences %]
|
||||
|
||||
<a href="edit_list?subscriber_id=[% subscriber.subscriber_id %]&list_name=[% preference.key %]"
|
||||
class="aaction">edit list</a>
|
||||
[% END %]
|
||||
</td>
|
||||
</tr>
|
||||
[% END %]
|
||||
[% IF preference.error %]<tr><td /><td><div class="errormsg">[% preference.error %]</div></td></tr>[% END %]
|
||||
[% END %]
|
||||
</table>
|
||||
[% IF edit_preferences %]
|
||||
<input type="submit" class="but" value="Save »" />
|
||||
[% END %]
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<h3 id="vboxprefs">Voicebox Preferences</h3>
|
||||
|
||||
<div class="actions">
|
||||
<a href="detail?subscriber_id=[% subscriber.subscriber_id %]&edit_voicebox=1#vboxprefs" class="aaction">edit</a>
|
||||
[% IF edit_voicebox %]
|
||||
<a href="detail?subscriber_id=[% subscriber.subscriber_id %]#vboxprefs" class="aaction">cancel</a>
|
||||
[% END %]
|
||||
</div>
|
||||
<div class="p1">
|
||||
[% IF messages.vboxmsg %]<div class="goodmsg">[% messages.vboxmsg %]</div>[% END %]
|
||||
[% IF messages.vboxerr %]<div class="errormsg">[% messages.vboxerr %]</div>[% END %]
|
||||
<form action="update_voicebox" method="post">
|
||||
<input type="hidden" name="subscriber_id" value="[% subscriber.subscriber_id %]" />
|
||||
<table>
|
||||
<tr>
|
||||
<td class="tdkey">PIN:</td>
|
||||
<td>
|
||||
<input type="text" name="password" [% IF ! edit_voicebox %]class="disabled" disabled="disabled"[% END %]
|
||||
value="[% subscriber.voicebox_preferences.password %]" />
|
||||
</td>
|
||||
</tr>
|
||||
[% IF messages.vpin %]<tr><td /><td><div class="errormsg">[% messages.vpin %]</div></td></tr>[% END %]
|
||||
<tr>
|
||||
<td class="tdkey">E-Mail:</td>
|
||||
<td>
|
||||
<input type="text" name="email" [% IF ! edit_voicebox %]class="disabled" disabled="disabled"[% END %]
|
||||
value="[% subscriber.voicebox_preferences.email %]" />
|
||||
</td>
|
||||
</tr>
|
||||
[% IF messages.vemail %]<tr><td /><td><div class="errormsg">[% messages.vemail %]</div></td></tr>[% END %]
|
||||
<tr>
|
||||
<td class="tdkey">Attach WAV:</td>
|
||||
<td>
|
||||
<input type="checkbox" name="attach" class="checkbox" [% IF ! edit_voicebox %]disabled="disabled"[% END %]
|
||||
[% IF subscriber.voicebox_preferences.attach %]checked="checked"[% END %] />
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
[% IF edit_voicebox %]
|
||||
<input type="submit" class="but" value="Save »" />
|
||||
[% END %]
|
||||
</form>
|
||||
</div>
|
||||
|
@ -0,0 +1,69 @@
|
||||
<h3>Edit [% list_name %] for
|
||||
<a class="noarrow" href="detail?subscriber_id=[% subscriber_id %]">
|
||||
[% subscriber.username %]@[% subscriber.domain %]</a>
|
||||
</h3>
|
||||
|
||||
<div class="actions">
|
||||
<a href="detail?subscriber_id=[% subscriber_id %]" class="aaction">back</a>
|
||||
</div>
|
||||
<div class="p1">
|
||||
[% IF messages.nummsg %]<div class="goodmsg">[% messages.nummsg %]</div>[% END %]
|
||||
[% IF messages.numerr %]<div class="errormsg">[% messages.numerr %]</div>[% END %]
|
||||
|
||||
<table>
|
||||
[% FOREACH blockentry = list_data %]
|
||||
<tr class="[% blockentry.background %]">
|
||||
<td > [% blockentry.number %] </td>
|
||||
<form action="do_edit_list" method="post">
|
||||
<td >
|
||||
<input type="hidden" name="subscriber_id" value="[% subscriber_id %]" />
|
||||
<input type="hidden" name="list_name" value="[% list_name %]" />
|
||||
<input type="hidden" name="block_del" value="[% blockentry.number %]" />
|
||||
<input type="hidden" name="block_stat" value="[% blockentry.active %]" />
|
||||
<div class="postlink">
|
||||
<label for="listdel[% blockentry.id %]">delete</label>
|
||||
<input type="image" class="hidden" src="/static/images/dot_trans.gif" alt="" id="listdel[% blockentry.id %]" />
|
||||
</div>
|
||||
</td>
|
||||
</form>
|
||||
<form action="do_edit_list" method="post">
|
||||
<td>
|
||||
<input type="hidden" name="subscriber_id" value="[% subscriber_id %]" />
|
||||
<input type="hidden" name="list_name" value="[% list_name %]" />
|
||||
[% IF blockentry.active == 1 %]
|
||||
<input type="hidden" name="block_act" value="[% blockentry.number %]" />
|
||||
<input type="hidden" name="block_stat" value="1" />
|
||||
<div class="postlink">
|
||||
<label for="blockact[% blockentry.id %]">deactivate</label>
|
||||
<input type="image" class="hidden" src="/static/images/dot_trans.gif" alt="" id="blockact[% blockentry.id %]" />
|
||||
</div>
|
||||
[% ELSIF blockentry.active == 0 %]
|
||||
<input type="hidden" name="block_act" value="[% blockentry.number %]" />
|
||||
<input type="hidden" name="block_stat" value="0" />
|
||||
<div class="postlink">
|
||||
<label for="blockact[% blockentry.id %]">activate</label>
|
||||
<input type="image" class="hidden" src="/static/images/dot_trans.gif" alt="" id="blockact[% blockentry.id %]" />
|
||||
</div>
|
||||
[% END %]
|
||||
</td>
|
||||
</form>
|
||||
</tr>
|
||||
[% END %]
|
||||
</table>
|
||||
|
||||
<br />
|
||||
|
||||
<form action="/subscriber/do_edit_list" method="post">
|
||||
<input type="hidden" name="subscriber_id" value="[% subscriber_id %]" />
|
||||
<input type="hidden" name="list_name" value="[% list_name %]" />
|
||||
<label for="blockaddtxt">New entry:</label><br />
|
||||
<div class="postlink">
|
||||
<input type="text" size="20" name="block_add" id="blockaddtxt" value="[% blockaddtxt %]" />
|
||||
<label for="blockadd">Add entry</label>
|
||||
<input type="image" class="hidden" src="/static/images/dot_trans.gif" alt="" id="blockadd" />
|
||||
[% IF messages.msgadd %]<div class="errormsg">[% messages.msgadd %]</div>[% END %]
|
||||
</div><br clear="all" />
|
||||
</form>
|
||||
|
||||
</div>
|
||||
|
@ -0,0 +1,37 @@
|
||||
#!/usr/bin/perl -w
|
||||
|
||||
BEGIN { $ENV{CATALYST_ENGINE} ||= 'CGI' }
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use FindBin;
|
||||
use lib "$FindBin::Bin/../lib";
|
||||
use admin;
|
||||
|
||||
admin->run;
|
||||
|
||||
1;
|
||||
|
||||
=head1 NAME
|
||||
|
||||
admin_cgi.pl - Catalyst CGI
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
See L<Catalyst::Manual>
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
Run a Catalyst application as a cgi script.
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Sebastian Riedel, C<sri@oook.de>
|
||||
|
||||
=head1 COPYRIGHT
|
||||
|
||||
|
||||
This library is free software, you can redistribute it and/or modify
|
||||
it under the same terms as Perl itself.
|
||||
|
||||
=cut
|
@ -0,0 +1,75 @@
|
||||
#!/usr/bin/perl -w
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use Getopt::Long;
|
||||
use Pod::Usage;
|
||||
use Catalyst::Helper;
|
||||
|
||||
my $force = 0;
|
||||
my $mech = 0;
|
||||
my $help = 0;
|
||||
|
||||
GetOptions(
|
||||
'nonew|force' => \$force,
|
||||
'mech|mechanize' => \$mech,
|
||||
'help|?' => \$help
|
||||
);
|
||||
|
||||
pod2usage(1) if ( $help || !$ARGV[0] );
|
||||
|
||||
my $helper = Catalyst::Helper->new( { '.newfiles' => !$force, mech => $mech } );
|
||||
|
||||
pod2usage(1) unless $helper->mk_component( 'admin', @ARGV );
|
||||
|
||||
1;
|
||||
|
||||
=head1 NAME
|
||||
|
||||
admin_create.pl - Create a new Catalyst Component
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
admin_create.pl [options] model|view|controller name [helper] [options]
|
||||
|
||||
Options:
|
||||
-force don't create a .new file where a file to be created exists
|
||||
-mechanize use Test::WWW::Mechanize::Catalyst for tests if available
|
||||
-help display this help and exits
|
||||
|
||||
Examples:
|
||||
admin_create.pl controller My::Controller
|
||||
admin_create.pl controller My::Controller BindLex
|
||||
admin_create.pl -mechanize controller My::Controller
|
||||
admin_create.pl view My::View
|
||||
admin_create.pl view MyView TT
|
||||
admin_create.pl view TT TT
|
||||
admin_create.pl model My::Model
|
||||
admin_create.pl model SomeDB DBIC::Schema MyApp::Schema create=dynamic\
|
||||
dbi:SQLite:/tmp/my.db
|
||||
admin_create.pl model AnotherDB DBIC::Schema MyApp::Schema create=static\
|
||||
dbi:Pg:dbname=foo root 4321
|
||||
|
||||
See also:
|
||||
perldoc Catalyst::Manual
|
||||
perldoc Catalyst::Manual::Intro
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
Create a new Catalyst Component.
|
||||
|
||||
Existing component files are not overwritten. If any of the component files
|
||||
to be created already exist the file will be written with a '.new' suffix.
|
||||
This behavior can be suppressed with the C<-force> option.
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Sebastian Riedel, C<sri@oook.de>
|
||||
Maintained by the Catalyst Core Team.
|
||||
|
||||
=head1 COPYRIGHT
|
||||
|
||||
This library is free software, you can redistribute it and/or modify
|
||||
it under the same terms as Perl itself.
|
||||
|
||||
=cut
|
@ -0,0 +1,80 @@
|
||||
#!/usr/bin/perl -w
|
||||
|
||||
BEGIN { $ENV{CATALYST_ENGINE} ||= 'FastCGI' }
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use Getopt::Long;
|
||||
use Pod::Usage;
|
||||
use FindBin;
|
||||
use lib "$FindBin::Bin/../lib";
|
||||
use admin;
|
||||
|
||||
my $help = 0;
|
||||
my ( $listen, $nproc, $pidfile, $manager, $detach, $keep_stderr );
|
||||
|
||||
GetOptions(
|
||||
'help|?' => \$help,
|
||||
'listen|l=s' => \$listen,
|
||||
'nproc|n=i' => \$nproc,
|
||||
'pidfile|p=s' => \$pidfile,
|
||||
'manager|M=s' => \$manager,
|
||||
'daemon|d' => \$detach,
|
||||
'keeperr|e' => \$keep_stderr,
|
||||
);
|
||||
|
||||
pod2usage(1) if $help;
|
||||
|
||||
admin->run(
|
||||
$listen,
|
||||
{ nproc => $nproc,
|
||||
pidfile => $pidfile,
|
||||
manager => $manager,
|
||||
detach => $detach,
|
||||
keep_stderr => $keep_stderr,
|
||||
}
|
||||
);
|
||||
|
||||
1;
|
||||
|
||||
=head1 NAME
|
||||
|
||||
admin_fastcgi.pl - Catalyst FastCGI
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
admin_fastcgi.pl [options]
|
||||
|
||||
Options:
|
||||
-? -help display this help and exits
|
||||
-l -listen Socket path to listen on
|
||||
(defaults to standard input)
|
||||
can be HOST:PORT, :PORT or a
|
||||
filesystem path
|
||||
-n -nproc specify number of processes to keep
|
||||
to serve requests (defaults to 1,
|
||||
requires -listen)
|
||||
-p -pidfile specify filename for pid file
|
||||
(requires -listen)
|
||||
-d -daemon daemonize (requires -listen)
|
||||
-M -manager specify alternate process manager
|
||||
(FCGI::ProcManager sub-class)
|
||||
or empty string to disable
|
||||
-e -keeperr send error messages to STDOUT, not
|
||||
to the webserver
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
Run a Catalyst application as fastcgi.
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Sebastian Riedel, C<sri@oook.de>
|
||||
Maintained by the Catalyst Core Team.
|
||||
|
||||
=head1 COPYRIGHT
|
||||
|
||||
This library is free software, you can redistribute it and/or modify
|
||||
it under the same terms as Perl itself.
|
||||
|
||||
=cut
|
@ -0,0 +1,111 @@
|
||||
#!/usr/bin/perl -w
|
||||
|
||||
BEGIN {
|
||||
$ENV{CATALYST_ENGINE} ||= 'HTTP';
|
||||
$ENV{CATALYST_SCRIPT_GEN} = 30;
|
||||
require Catalyst::Engine::HTTP;
|
||||
}
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use Getopt::Long;
|
||||
use Pod::Usage;
|
||||
use FindBin;
|
||||
use lib "$FindBin::Bin/../lib";
|
||||
|
||||
my $debug = 0;
|
||||
my $fork = 0;
|
||||
my $help = 0;
|
||||
my $host = undef;
|
||||
my $port = $ENV{ADMIN_PORT} || $ENV{CATALYST_PORT} || 3000;
|
||||
my $keepalive = 0;
|
||||
my $restart = $ENV{ADMIN_RELOAD} || $ENV{CATALYST_RELOAD} || 0;
|
||||
my $restart_delay = 1;
|
||||
my $restart_regex = '\.yml$|\.yaml$|\.pm$';
|
||||
my $restart_directory = undef;
|
||||
|
||||
my @argv = @ARGV;
|
||||
|
||||
GetOptions(
|
||||
'debug|d' => \$debug,
|
||||
'fork' => \$fork,
|
||||
'help|?' => \$help,
|
||||
'host=s' => \$host,
|
||||
'port=s' => \$port,
|
||||
'keepalive|k' => \$keepalive,
|
||||
'restart|r' => \$restart,
|
||||
'restartdelay|rd=s' => \$restart_delay,
|
||||
'restartregex|rr=s' => \$restart_regex,
|
||||
'restartdirectory=s' => \$restart_directory,
|
||||
);
|
||||
|
||||
pod2usage(1) if $help;
|
||||
|
||||
if ( $restart && $ENV{CATALYST_ENGINE} eq 'HTTP' ) {
|
||||
$ENV{CATALYST_ENGINE} = 'HTTP::Restarter';
|
||||
}
|
||||
if ( $debug ) {
|
||||
$ENV{CATALYST_DEBUG} = 1;
|
||||
}
|
||||
|
||||
# This is require instead of use so that the above environment
|
||||
# variables can be set at runtime.
|
||||
require admin;
|
||||
|
||||
admin->run( $port, $host, {
|
||||
argv => \@argv,
|
||||
'fork' => $fork,
|
||||
keepalive => $keepalive,
|
||||
restart => $restart,
|
||||
restart_delay => $restart_delay,
|
||||
restart_regex => qr/$restart_regex/,
|
||||
restart_directory => $restart_directory,
|
||||
} );
|
||||
|
||||
1;
|
||||
|
||||
=head1 NAME
|
||||
|
||||
admin_server.pl - Catalyst Testserver
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
admin_server.pl [options]
|
||||
|
||||
Options:
|
||||
-d -debug force debug mode
|
||||
-f -fork handle each request in a new process
|
||||
(defaults to false)
|
||||
-? -help display this help and exits
|
||||
-host host (defaults to all)
|
||||
-p -port port (defaults to 3000)
|
||||
-k -keepalive enable keep-alive connections
|
||||
-r -restart restart when files get modified
|
||||
(defaults to false)
|
||||
-rd -restartdelay delay between file checks
|
||||
-rr -restartregex regex match files that trigger
|
||||
a restart when modified
|
||||
(defaults to '\.yml$|\.yaml$|\.pm$')
|
||||
-restartdirectory the directory to search for
|
||||
modified files
|
||||
(defaults to '../')
|
||||
|
||||
See also:
|
||||
perldoc Catalyst::Manual
|
||||
perldoc Catalyst::Manual::Intro
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
Run a Catalyst Testserver for this application.
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Sebastian Riedel, C<sri@oook.de>
|
||||
Maintained by the Catalyst Core Team.
|
||||
|
||||
=head1 COPYRIGHT
|
||||
|
||||
This library is free software, you can redistribute it and/or modify
|
||||
it under the same terms as Perl itself.
|
||||
|
||||
=cut
|
@ -0,0 +1,54 @@
|
||||
#!/usr/bin/perl -w
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use Getopt::Long;
|
||||
use Pod::Usage;
|
||||
use FindBin;
|
||||
use lib "$FindBin::Bin/../lib";
|
||||
use Catalyst::Test 'admin';
|
||||
|
||||
my $help = 0;
|
||||
|
||||
GetOptions( 'help|?' => \$help );
|
||||
|
||||
pod2usage(1) if ( $help || !$ARGV[0] );
|
||||
|
||||
print request($ARGV[0])->content . "\n";
|
||||
|
||||
1;
|
||||
|
||||
=head1 NAME
|
||||
|
||||
admin_test.pl - Catalyst Test
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
admin_test.pl [options] uri
|
||||
|
||||
Options:
|
||||
-help display this help and exits
|
||||
|
||||
Examples:
|
||||
admin_test.pl http://localhost/some_action
|
||||
admin_test.pl /some_action
|
||||
|
||||
See also:
|
||||
perldoc Catalyst::Manual
|
||||
perldoc Catalyst::Manual::Intro
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
Run a Catalyst action from the command line.
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Sebastian Riedel, C<sri@oook.de>
|
||||
Maintained by the Catalyst Core Team.
|
||||
|
||||
=head1 COPYRIGHT
|
||||
|
||||
This library is free software, you can redistribute it and/or modify
|
||||
it under the same terms as Perl itself.
|
||||
|
||||
=cut
|
Loading…
Reference in new issue