diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index a14a3e3c..79e7a0a8 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -69,6 +69,7 @@ jobs:
docker exec -t libki-test-server prove /app/t/stdout.t
docker exec -t -e TEST_POD=1 libki-test-server prove /app/t/02pod.t
docker exec -t -e TEST_POD=1 libki-test-server prove /app/t/03podcoverage.t
+ docker exec -t prove t/controller_API-Client-v1_0.t
publish-docker-io-debian:
name: Push Debian image (docker.io)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 42bc0811..9987884a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
+## [4.9.0]
+### Added
+- Add passwordless mode support to Print Manager authentication api
+
## [4.7.9]
### Added
- Add passwordless mode support to Print Manager authentication api
diff --git a/lib/Libki.pm b/lib/Libki.pm
index 81445167..79838e89 100644
--- a/lib/Libki.pm
+++ b/lib/Libki.pm
@@ -13,7 +13,7 @@ use DateTime::Format::MySQL;
use DateTime;
use File::Slurp;
-our $VERSION = '4.7.9';
+our $VERSION = '4.9.0';
# Set flags and add plugins for the application.
#
diff --git a/lib/Libki/Controller/API/Client/v1_0.pm b/lib/Libki/Controller/API/Client/v1_0.pm
index da8f7912..0d990086 100644
--- a/lib/Libki/Controller/API/Client/v1_0.pm
+++ b/lib/Libki/Controller/API/Client/v1_0.pm
@@ -9,6 +9,7 @@ use Libki::SIP qw( authenticate_via_sip );
use Libki::LDAP qw( authenticate_via_ldap );
use Libki::Hours qw( minutes_until_closing );
use Libki::Utils::Printing qw( create_print_job_and_file );
+use Libki::Utils::User qw( create_guest );
use DateTime::Format::MySQL;
use DateTime;
@@ -84,18 +85,19 @@ sub index : Path : Args(0) {
}
$client->get_from_storage;
+ my $client_status = $client->status // q{};
- if ($client->status eq "unlock") {
+ if ($client_status eq "unlock") {
$c->stash(
unlock => 1,
minutes => $client->session->minutes,
username => $client->session->user->username,
);
- } elsif ($client->status eq "shutdown" || $client->status eq "suspend" || $client->status eq "restart") {
+ } elsif ($client_status eq "shutdown" || $client_status eq "suspend" || $client_status eq "restart") {
$c->stash(
- $client->status => 1,
+ $client_status => 1,
);
- } elsif ($client->status eq "wakeup") {
+ } elsif ($client_status eq "wakeup") {
my $host = $c->setting('WOLHost') || '255.255.255.255';
my $port = $c->setting('WOLPort') || 9;
my @mac_addresses = split(/[\r\n]+/, $c->setting('ClientMACAddresses'));
@@ -139,6 +141,8 @@ sub index : Path : Args(0) {
ClientBehavior => $c->stash->{Settings}->{ClientBehavior},
ReservationShowUsername => $c->stash->{Settings}->{ReservationShowUsername},
+ EnableGuestSelfRegistration => $c->stash->{Settings}->{EnableGuestSelfRegistration},
+
EnableClientSessionLocking => $c->stash->{Settings}->{EnableClientSessionLocking},
EnableClientPasswordlessMode => $c->stash->{Settings}->{EnableClientPasswordlessMode},
@@ -199,10 +203,32 @@ sub index : Path : Args(0) {
my $client_type = $c->request->params->{'type'};
my $units;
- my $user = $c->model('DB::User')
- ->single( { instance => $instance, username => $username } );
+ my $user
+ = $username
+ ? $c->model('DB::User')->single( { instance => $instance, username => $username } )
+ : undef;
if ( $action eq 'login' ) {
+ my $create_guest = $c->request->params->{'createGuest'};
+ if ($create_guest) {
+ if ( $c->setting('EnableGuestSelfRegistration') ) {
+ ( $user, $password ) = Libki::Utils::User::create_guest($c);
+ $username = $user->username;
+
+ $c->stash(
+ username => $username,
+ password => $password,
+ );
+ }
+ else {
+ delete( $c->stash->{Settings} );
+ $c->stash( authenticated => 0, error => "GUEST_SELF_REG_NOT_ENABLED" );
+ $c->res->status(501);
+ $c->forward( $c->view('JSON') );
+ return;
+ }
+ }
+
$log->debug( __PACKAGE__
. " - username: $username, client_name: $client_name" );
@@ -488,31 +514,35 @@ sub index : Path : Args(0) {
}
elsif ( $action eq 'logout' ) {
my $session = $user->session;
- my $session_id = $session->session_id;
- my $location = $session->client->location;
- my $type = $session->client->type;
- my $success = $user->session->delete();
- $success &&= 1;
- $c->stash( logged_out => $success );
+ if ($session) {
+ my $session_id = $session->session_id;
+ my $location = $session->client->location;
+ my $type = $session->client->type;
- $c->model('DB::Statistic')->create(
- {
- instance => $instance,
- username => $username,
- client_name => $client_name,
- client_location => $client_location,
- client_type => $client_type,
- action => 'LOGOUT',
- created_on => $now,
- session_id => $session_id,
- info => to_json(
- {
- client_version => $version
- }
- ),
- }
- );
+ my $success = $session->delete() ? 1 : 0;
+ $c->stash( logged_out => $success );
+
+ $c->model('DB::Statistic')->create(
+ {
+ instance => $instance,
+ username => $username,
+ client_name => $client_name,
+ client_location => $client_location,
+ client_type => $client_type,
+ action => 'LOGOUT',
+ created_on => $now,
+ session_id => $session_id,
+ info => to_json(
+ {
+ client_version => $version
+ }
+ ),
+ }
+ );
+ } else {
+ $c->stash( logged_out => 0 );
+ }
}
}
diff --git a/lib/Libki/Controller/Administration/API/User.pm b/lib/Libki/Controller/Administration/API/User.pm
index 4e79b7cd..b0086a6f 100644
--- a/lib/Libki/Controller/Administration/API/User.pm
+++ b/lib/Libki/Controller/Administration/API/User.pm
@@ -1,12 +1,12 @@
package Libki::Controller::Administration::API::User;
use Moose;
-use String::Random qw(random_string);
use namespace::autoclean;
use POSIX;
use Libki::Utils::Printing;
+use Libki::Utils::User;
use JSON qw(to_json);
@@ -32,7 +32,7 @@ sub get : Local : Args(1) {
my ( $self, $c, $id ) = @_;
my $instance = $c->instance;
- my $user = $c->model('DB::User')->find({ instance => $instance, id => $id });
+ my $user = $c->model('DB::User')->find( { instance => $instance, id => $id } );
my $roles = $user->roles;
my @roles;
@@ -42,18 +42,20 @@ sub get : Local : Args(1) {
$c->stash(
{
- id => $user->id,
- username => $user->username,
- firstname => $user->firstname,
- lastname => $user->lastname,
- category => $user->category,
- minutes => $user->minutes($c),
- status => $user->status,
- notes => $user->notes,
- funds => $user->funds,
- is_troublemaker => $user->is_troublemaker,
- troublemaker_until => defined($user->troublemaker_until) ? $user->troublemaker_until->strftime('%Y-%m-%d 23:59') : undef,
- roles => \@roles,
+ id => $user->id,
+ username => $user->username,
+ firstname => $user->firstname,
+ lastname => $user->lastname,
+ category => $user->category,
+ minutes => $user->minutes($c),
+ status => $user->status,
+ notes => $user->notes,
+ funds => $user->funds,
+ is_troublemaker => $user->is_troublemaker,
+ troublemaker_until => defined( $user->troublemaker_until )
+ ? $user->troublemaker_until->strftime('%Y-%m-%d 23:59')
+ : undef,
+ roles => \@roles,
}
);
@@ -79,33 +81,24 @@ sub create : Local : Args(0) {
my $success = 0;
- my $now = $c->now();
- my $user = $c->model('DB::User')->create(
+ my $now = $c->now();
+ my $user = Libki::Utils::User::create_or_update_user(
+ $c,
{
- instance => $instance,
- username => $username,
- firstname => $firstname,
- lastname => $lastname,
- category => $category,
- password => $password,
- status => 'enabled',
- created_on => $now,
- updated_on => $now,
- creation_source => 'local',
+ instance => $instance,
+ username => $username,
+ firstname => $firstname,
+ lastname => $lastname,
+ category => $category,
+ password => $password,
+ status => 'enabled',
+ created_on => $now,
+ updated_on => $now,
+ creation_source => 'local',
+ minutes => $minutes,
}
);
- if (defined $minutes) {
- $c->model('DB::Allotment')->update_or_create(
- {
- instance => $instance,
- user_id => $user->id,
- location => '',
- minutes => $minutes,
- }
- );
- }
-
$success = 1 if ($user);
$c->stash( 'success' => $success );
@@ -123,43 +116,11 @@ sub create_guest : Local : Args(0) {
my $category = $params->{category};
- my $current_guest_number_setting = $c->model('DB::Setting')->find_or_new({ instance => $instance, name => 'CurrentGuestNumber' });
- my $current_guest_number = $current_guest_number_setting->value ? $current_guest_number_setting->value + 1 : 1;
- $current_guest_number_setting->set_column( 'value', $current_guest_number );
- $current_guest_number_setting->update_or_insert();
-
- my $prefix_setting = $c->setting('GuestPassPrefix');
- my $prefix = $prefix_setting || 'guest';
-
- my $username = $prefix . $current_guest_number;
- my $password =
- random_string("nnnn"); #TODO: Make the pattern a system setting
-
- my $minutes_allotment = $c->setting('DefaultGuestTimeAllowance');
- $minutes_allotment = 0 unless $minutes_allotment > 0;
-
- my $success = 0;
-
- my $now = $c->now();
- my $user = $c->model('DB::User')->create(
- {
- instance => $instance,
- username => $username,
- password => $password,
- status => 'enabled',
- is_guest => 'Yes',
- created_on => $now,
- updated_on => $now,
- category => $category,
- creation_source => 'local',
- }
- );
-
- $success = 1 if ($user);
+ my ( $user, $password, $minutes_allotment ) = Libki::Utils::User::create_guest( $c, $category );
$c->stash(
- 'success' => $success,
- 'username' => $username,
+ 'success' => $user ? 1 : 0,
+ 'username' => $user ? $user->username : q{},
'password' => $password,
'category' => $category,
'minutes' => $minutes_allotment,
@@ -175,58 +136,47 @@ sub batch_create_guest : Local : Args(0) {
my ( $self, $c ) = @_;
my $instance = $c->instance;
- my $params = $c->request->params;
- my $category = $params->{category};
+ my $params = $c->request->params;
+ my $category = $params->{category};
my $prefix_setting = $c->setting('GuestPassPrefix');
- my $prefix = $prefix_setting || 'guest';
+ my $prefix = $prefix_setting || 'guest';
my $success = 0;
my $batch_guest_pass_custom_css = $c->setting('BatchGuestPassCustomCSS');
- my $batch_guest_pass_template = $c->setting('BatchGuestPassTemplate');
+ my $batch_guest_pass_template = $c->setting('BatchGuestPassTemplate');
- my $guest_count = $c->setting('GuestBatchCount') || 10;
+ my $guest_count = $c->setting('GuestBatchCount') || 10;
my $batch_guest_pass_username_label = $c->setting('BatchGuestPassUsernameLabel');
my $batch_guest_pass_password_label = $c->setting('BatchGuestPassPasswordLabel');
my $minutes_allotment = $c->setting('DefaultGuestTimeAllowance');
$minutes_allotment = 0 unless ( $minutes_allotment > 0 );
- my $current_guest_number_setting = $c->model('DB::Setting')->find_or_new({ instance => $instance, name => 'CurrentGuestNumber' });
- my $current_guest_number = $current_guest_number_setting->value ? $current_guest_number_setting->value + 1 : 1;
+ my $current_guest_number_setting = $c->model('DB::Setting')
+ ->find_or_new( { instance => $instance, name => 'CurrentGuestNumber' } );
+ my $current_guest_number
+ = $current_guest_number_setting->value ? $current_guest_number_setting->value + 1 : 1;
my $now = $c->now();
my $file_contents .= "
";
my @guests;
- for ( my $i = 0 ; $i < $guest_count ; $i++ ) {
+ for ( my $i = 0; $i < $guest_count; $i++ ) {
- $current_guest_number = $current_guest_number + 1;
- my $username = $prefix . $current_guest_number;
- my $password =
- random_string("nnnn"); #TODO: Make the pattern a system setting
-
- my $user = $c->model('DB::User')->create(
- {
- instance => $instance,
- username => $username,
- password => $password,
- status => 'enabled',
- is_guest => 'Yes',
- created_on => $now,
- updated_on => $now,
- category => $category,
- creation_source => 'local',
- }
- );
+ my ( $user, $password, $minutes_allotment )
+ = Libki::Utils::User::create_guest( $c, $category );
+ my $username = $user->username;
$file_contents .= "\n";
$file_contents .= "\n";
- $file_contents .= "$batch_guest_pass_username_label$username";
+ $file_contents
+ .= "$batch_guest_pass_username_label$username";
$file_contents .= "";
$file_contents .= "\n\n";
- $file_contents .= "$batch_guest_pass_password_label$password\n\n";
+ $file_contents
+ .= "$batch_guest_pass_password_label$password\n\n";
$file_contents .= "";
$file_contents .= "
";
$file_contents .= "";
@@ -236,12 +186,9 @@ sub batch_create_guest : Local : Args(0) {
$success = $success + 1 if ($user);
}
- $current_guest_number_setting->set_column( 'value', $current_guest_number );
- $current_guest_number_setting->update_or_insert();
-
- if ( $batch_guest_pass_template ) {
+ if ($batch_guest_pass_template) {
$file_contents = q{};
- my $tt = Template->new() || die $Template::ERROR;
+ my $tt = Template->new() || die $Template::ERROR;
my $vars = {
batch_guest_pass_custom_css => $batch_guest_pass_custom_css,
batch_guest_pass_username_label => $batch_guest_pass_username_label,
@@ -285,12 +232,12 @@ sub update : Local : Args(0) {
# For some reason the list of checkboxes are created
# as a list within a list if multiple are checked
- @roles = @{$roles[0]} if ref( $roles[0] ) eq 'ARRAY';
+ @roles = @{ $roles[0] } if ref( $roles[0] ) eq 'ARRAY';
$minutes = undef if $minutes eq q{};
- $minutes = 0 if defined($minutes) && $minutes < 0;
+ $minutes = 0 if defined($minutes) && $minutes < 0;
- my $user = $c->model('DB::User')->find({ instance => $instance, id => $id });
+ my $user = $c->model('DB::User')->find( { instance => $instance, id => $id } );
my $now = $c->now();
@@ -309,7 +256,7 @@ sub update : Local : Args(0) {
}
);
- if (defined $minutes) {
+ if ( defined $minutes ) {
$c->model('DB::Allotment')->update_or_create(
{
instance => $instance,
@@ -318,25 +265,26 @@ sub update : Local : Args(0) {
minutes => $minutes,
}
);
- } else {
- $c->model('DB::Allotment')->search( { instance => $instance, user_id => $user->id } )->delete;
+ }
+ else {
+ $c->model('DB::Allotment')->search( { instance => $instance, user_id => $user->id } )
+ ->delete;
}
if ( $c->check_user_roles(qw/superadmin/) ) {
# Update the user's roles
my @libki_roles = $c->model('DB::Role')->search();
- foreach my $lr ( @libki_roles ) {
+ foreach my $lr (@libki_roles) {
my $role = $lr->role;
- if ( grep { /$role/ } @roles ) {
+ if ( grep {/$role/} @roles ) {
## Add the role if it doesn't exists
- $c->model('DB::UserRole')
- ->find_or_create( { user_id => $id, role_id => $lr->id } );
+ $c->model('DB::UserRole')->find_or_create( { user_id => $id, role_id => $lr->id } );
}
else {
## Delete the role if it does already exist
- $c->model('DB::UserRole')
- ->search( { user_id => $id, role_id => $lr->id } )->delete();
+ $c->model('DB::UserRole')->search( { user_id => $id, role_id => $lr->id } )
+ ->delete();
}
}
}
@@ -370,7 +318,7 @@ sub delete : Local : Args(1) {
$msg = q{ADMIN_CANNOT_DELETE_SUPERADMIN};
}
elsif ( $i_am_superadmin || ( $i_am_admin && !$user_is_superadmin ) ) {
- $c->schema->txn_do(
+ $c->model('DB')->txn_do(
sub {
if ( $user->delete() ) {
$success = 1;
@@ -414,8 +362,8 @@ sub is_username_unique : Local : Args(1) {
my ( $self, $c, $username ) = @_;
my $instance = $c->instance;
- my $count =
- $c->model('DB::User')->search( { instance => $instance, username => $username } )->count();
+ my $count = $c->model('DB::User')->search( { instance => $instance, username => $username } )
+ ->count();
my $is_unique = ($count) ? 0 : 1;
@@ -436,21 +384,21 @@ sub toggle_troublemaker : Local : Args(3) {
my $success = 0;
- my $user = $c->model('DB::User')->find({ instance => $instance, id => $id });
+ my $user = $c->model('DB::User')->find( { instance => $instance, id => $id } );
my $is_troublemaker = ( $user->is_troublemaker eq 'Yes' ) ? 'No' : 'Yes';
my $now = $c->now();
- $user->set_column( 'is_troublemaker', $is_troublemaker );
- $user->set_column( 'updated_on', $now );
+ $user->set_column( 'is_troublemaker', $is_troublemaker );
+ $user->set_column( 'updated_on', $now );
$user->set_column( 'troublemaker_until', undef );
- if ( $until != 0 && $is_troublemaker eq 'Yes'){
+ if ( $until != 0 && $is_troublemaker eq 'Yes' ) {
my $troublemaker_until = $now->clone;
$troublemaker_until->add( days => $until );
$user->set_column( 'troublemaker_until', $troublemaker_until );
- $user->set_column( 'notes', $notes eq '' ? undef : $notes );
+ $user->set_column( 'notes', $notes eq '' ? undef : $notes );
}
if ( $user->update() ) {
@@ -474,7 +422,7 @@ sub change_password : Local : Args(0) {
my $id = $c->request->params->{'id'};
my $password = $c->request->params->{'password'};
- my $user = $c->model('DB::User')->find({ instance => $instance, id => $id });
+ my $user = $c->model('DB::User')->find( { instance => $instance, id => $id } );
my $now = $c->now();
@@ -487,7 +435,7 @@ sub change_password : Local : Args(0) {
if ( $i_am_admin || $i_am_superadmin ) {
if ( $i_am_superadmin || ( $i_am_admin && !$user_is_superadmin ) ) {
- $user->set_column( 'password', $password );
+ $user->set_column( 'password', $password );
$user->set_column( 'updated_on', $now );
if ( $user->update() ) {
diff --git a/lib/Libki/SIP.pm b/lib/Libki/SIP.pm
index cc673375..7717d2e6 100644
--- a/lib/Libki/SIP.pm
+++ b/lib/Libki/SIP.pm
@@ -191,7 +191,7 @@ sub authenticate_via_sip {
);
unless ($is_admin) {
- $c->txn_do(
+ $c->model('DB')->txn_do(
sub {
$user->delete;
diff --git a/lib/Libki/Schema/DB/Result/User.pm b/lib/Libki/Schema/DB/Result/User.pm
index 5cf4a34b..d7a22369 100644
--- a/lib/Libki/Schema/DB/Result/User.pm
+++ b/lib/Libki/Schema/DB/Result/User.pm
@@ -392,9 +392,9 @@ __PACKAGE__->add_columns(
);
=head2 has_role
-
+
Check if a user has the specified role
-
+
=cut
use Perl6::Junction qw/any/;
diff --git a/lib/Libki/Utils/User.pm b/lib/Libki/Utils/User.pm
new file mode 100644
index 00000000..426d6150
--- /dev/null
+++ b/lib/Libki/Utils/User.pm
@@ -0,0 +1,176 @@
+package Libki::Utils::User;
+
+use Modern::Perl;
+
+use Carp;
+
+use String::Random qw(random_string);
+
+=head2 create_or_update_user
+
+Create a user with the given criterea.
+If the username exists, that user will be updated instead.
+
+=cut
+
+sub create_or_update_user {
+ my ( $c, $params ) = @_;
+
+ my $instance = $params->{instance} || $c->instance;
+ my $username = $params->{username};
+ my $password = $params->{password};
+ my $firstname = $params->{firstname};
+ my $lastname = $params->{lastname};
+ my $category = $params->{category};
+ my $creation_source = $params->{creation_source} || 'local';
+ my $status = $params->{status} || 'enabled';
+ my $minutes = $params->{minutes} || undef;
+ my $is_admin = $params->{admin};
+ my $is_superadmin = $params->{superadmin};
+
+ confess "No username passed" unless $username;
+ confess "No password passed" unless $password;
+
+ my $schema = $c->schema;
+ my $user_rs = $schema->resultset('User');
+
+ my $now = $c->now();
+
+ my $default_time_allowance_setting = $schema->resultset('Setting')
+ ->find( { instance => $instance, name => 'DefaultTimeAllowance' } );
+ my $default_time_allowance
+ = $default_time_allowance_setting ? $default_time_allowance_setting->value : 0;
+
+ my $user;
+ $schema->txn_do(
+ sub {
+ $user
+ = $user_rs->search( { instance => $instance, username => $username } )->next();
+
+ if ($user) {
+ $user->set_column( 'password', $password );
+ $user->update(
+ {
+ password => $password,
+ updated_on => $now,
+ }
+ );
+ }
+ else {
+ $user = $user_rs->create(
+ {
+ instance => $instance,
+ username => $username,
+ password => $password,
+ category => $category,
+ firstname => $firstname,
+ lastname => $lastname,
+ status => 'enabled',
+ creation_source => 'local',
+ is_troublemaker => 'No',
+ created_on => $now,
+ updated_on => $now,
+ }
+ );
+
+ }
+
+ if ( defined $minutes ) {
+ $c->model('DB::Allotment')->update_or_create(
+ {
+ instance => $user->instance,
+ user_id => $user->id,
+ location => '',
+ minutes => $minutes,
+ }
+ );
+ }
+
+ if ($is_superadmin) {
+ my $role = $schema->resultset('Role')->search( { role => 'superadmin' } )->single();
+
+ $schema->resultset('UserRole')->update_or_create(
+ {
+ role_id => $role->id,
+ user_id => $user->id,
+ }
+ );
+ }
+
+ if ( $is_admin || $is_superadmin ) {
+ my $role = $schema->resultset('Role')->search( { role => 'admin' } )->single();
+
+ $schema->resultset('UserRole')->update_or_create(
+ {
+ role_id => $role->id,
+ user_id => $user->id,
+ }
+ );
+ }
+ }
+ );
+
+ return $user;
+}
+
+=head2 create_guest
+
+Create a guest account with the given category.
+If $client is passed, minutes will be set for that client type.
+
+=cut
+
+sub create_guest {
+ my ( $c, $category, $client ) = @_;
+
+ my $instance = $c->instance;
+
+ my $now = $c->now();
+
+ my ( $user, $password, $minutes_allotment );
+ $c->model('DB')->txn_do(
+ sub {
+
+ my $current_guest_number_setting = $c->model('DB::Setting')
+ ->find_or_new( { instance => $instance, name => 'CurrentGuestNumber' } );
+
+ my $current_guest_number
+ = $current_guest_number_setting->value
+ ? $current_guest_number_setting->value + 1
+ : 1;
+ $current_guest_number_setting->set_column( 'value', $current_guest_number );
+ $current_guest_number_setting->update_or_insert();
+
+ my $prefix_setting = $c->setting('GuestPassPrefix');
+ my $prefix = $prefix_setting || 'guest';
+
+ my $username = $prefix . $current_guest_number;
+ $password = random_string("nnnn"); #TODO: Make the pattern a system setting
+
+ $user = $c->model('DB::User')->create(
+ {
+ instance => $instance,
+ username => $username,
+ password => $password,
+ status => 'enabled',
+ is_guest => 'Yes',
+ created_on => $now,
+ updated_on => $now,
+ category => $category,
+ creation_source => 'local',
+ }
+ );
+
+ $minutes_allotment = $c->setting('DefaultGuestTimeAllowance');
+ $minutes_allotment = 0 unless $minutes_allotment > 0;
+
+ # If created from the client login as guest button, we can give a more accurate number
+ $minutes_allotment = $user->minutes( $c, $client ) if $client;
+
+ }
+ );
+
+ return ( $user, $password, $minutes_allotment );
+}
+
+1;
diff --git a/root/dynamic/templates/administration/settings/index.tt b/root/dynamic/templates/administration/settings/index.tt
index 411a64c8..af91f21d 100644
--- a/root/dynamic/templates/administration/settings/index.tt
+++ b/root/dynamic/templates/administration/settings/index.tt
@@ -799,6 +799,17 @@