summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIvan Kohler <ivan@freeside.biz>2013-05-09 01:42:39 -0700
committerIvan Kohler <ivan@freeside.biz>2013-05-09 01:42:39 -0700
commit120718856665ca90ad852535d1155f8ea8ecb6b6 (patch)
tree2ac0472c1fd67ecc843619597f1cca7d8f774204
parentd8843f184a7f6ee87eec99724f2d6430c1df34ea (diff)
NG auth: pw changes, RT#21563
-rw-r--r--FS/FS/Auth/internal.pm57
-rw-r--r--FS/FS/access_user.pm23
-rw-r--r--httemplate/edit/access_user.html10
-rw-r--r--httemplate/edit/process/access_user.html28
-rw-r--r--httemplate/edit/process/elements/process.html7
-rw-r--r--httemplate/pref/pref-process.html36
-rw-r--r--httemplate/pref/pref.html34
7 files changed, 138 insertions, 57 deletions
diff --git a/FS/FS/Auth/internal.pm b/FS/FS/Auth/internal.pm
index 5d9170e23..bb116ce75 100644
--- a/FS/FS/Auth/internal.pm
+++ b/FS/FS/Auth/internal.pm
@@ -2,29 +2,32 @@ package FS::Auth::internal;
#use base qw( FS::Auth );
use strict;
-use Crypt::Eksblowfish::Bcrypt qw(bcrypt_hash);
+use Crypt::Eksblowfish::Bcrypt qw(bcrypt_hash en_base64 de_base64);
use FS::Record qw( qsearchs );
use FS::access_user;
sub authenticate {
my($self, $username, $check_password ) = @_;
- my $access_user = qsearchs('access_user', { 'username' => $username,
- 'disabled' => '',
- }
- )
+ my $access_user =
+ ref($username) ? $username
+ : qsearchs('access_user', { 'username' => $username,
+ 'disabled' => '',
+ }
+ )
or return 0;
if ( $access_user->_password_encoding eq 'bcrypt' ) {
my( $cost, $salt, $hash ) = split(',', $access_user->_password);
- my $check_hash = bcrypt_hash( { key_nul => 1,
- cost => $cost,
- salt => $salt,
- },
- $check_password
- );
+ my $check_hash = en_base64( bcrypt_hash( { key_nul => 1,
+ cost => $cost,
+ salt => de_base64($salt),
+ },
+ $check_password
+ )
+ );
$hash eq $check_hash;
@@ -39,7 +42,35 @@ sub authenticate {
}
-#sub change_password {
-#}
+sub change_password {
+ my($self, $access_user, $new_password) = @_;
+
+ $self->change_password_fields( $access_user, $new_password );
+
+ $access_user->replace;
+
+}
+
+sub change_password_fields {
+ my($self, $access_user, $new_password) = @_;
+
+ $access_user->_password_encoding('bcrypt');
+
+ my $cost = 8;
+
+ my $salt = pack( 'C*', map int(rand(256)), 1..16 );
+
+ my $hash = bcrypt_hash( { key_nul => 1,
+ cost => $cost,
+ salt => $salt,
+ },
+ $new_password,
+ );
+
+ $access_user->_password(
+ join(',', $cost, en_base64($salt), en_base64($hash) )
+ );
+
+}
1;
diff --git a/FS/FS/access_user.pm b/FS/FS/access_user.pm
index 509cc0950..cdee3773b 100644
--- a/FS/FS/access_user.pm
+++ b/FS/FS/access_user.pm
@@ -4,6 +4,7 @@ use strict;
use base qw( FS::m2m_Common FS::option_Common );
use vars qw( $DEBUG $me $conf $htpasswd_file );
use FS::UID;
+use FS::Auth;
use FS::Conf;
use FS::Record qw( qsearch qsearchs dbh );
use FS::access_user_pref;
@@ -563,7 +564,27 @@ sub is_system_user {
fs_signup
fs_bootstrap
fs_selfserv
-) );
+ ) );
+}
+
+=item change_password NEW_PASSWORD
+
+=cut
+
+sub change_password {
+ #my( $self, $password ) = @_;
+ #FS::Auth->auth_class->change_password( $self, $password );
+ FS::Auth->auth_class->change_password( @_ );
+}
+
+=item change_password_fields NEW_PASSWORD
+
+=cut
+
+sub change_password_fields {
+ #my( $self, $password ) = @_;
+ #FS::Auth->auth_class->change_password_fields( $self, $password );
+ FS::Auth->auth_class->change_password_fields( @_ );
}
=back
diff --git a/httemplate/edit/access_user.html b/httemplate/edit/access_user.html
index 86ce25374..b087943c2 100644
--- a/httemplate/edit/access_user.html
+++ b/httemplate/edit/access_user.html
@@ -3,8 +3,7 @@
'table' => 'access_user',
'fields' => [
'username',
- { field=>'_password', type=>'password' },
- { field=>'_password2', type=>'password' },
+ @pw_fields,
'last',
'first',
{ field=>'user_custnum', type=>'search-cust_main', },
@@ -50,6 +49,13 @@
die "access denied"
unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+my @pw_fields =
+ FS::Auth->auth_class->can('change_password')
+ ? ( { field=>'_password', type=>'password' },
+ { field=>'_password2', type=>'password' },
+ )
+ : ();
+
my $check_user_custnum_search = <<END;
<SCRIPT TYPE="text/javascript">
function check_user_custnum_search(what) {
diff --git a/httemplate/edit/process/access_user.html b/httemplate/edit/process/access_user.html
index 8e7e70a06..7fc7c25e1 100644
--- a/httemplate/edit/process/access_user.html
+++ b/httemplate/edit/process/access_user.html
@@ -3,14 +3,15 @@
% print $cgi->redirect(popurl(2) . "access_user.html?" . $cgi->query_string);
% } else {
<% include( 'elements/process.html',
- 'table' => 'access_user',
- 'viewall_dir' => 'browse',
- 'copy_on_empty' => [ '_password' ],
+ 'table' => 'access_user',
+ 'viewall_dir' => 'browse',
+ 'copy_on_empty' => [ '_password', '_password_encoding' ],
'clear_on_error' => [ '_password', '_password2' ],
- 'process_m2m' => { 'link_table' => 'access_usergroup',
- 'target_table' => 'access_group',
- },
- 'precheck_callback'=> \&precheck_callback,
+ 'process_m2m' => { 'link_table' => 'access_usergroup',
+ 'target_table' => 'access_group',
+ },
+ 'precheck_callback' => \&precheck_callback,
+ 'post_new_object_callback' => \&post_new_object_callback,
)
%>
% }
@@ -26,11 +27,24 @@ if ( FS::Conf->new->exists('disable_acl_changes') ) {
sub precheck_callback {
my $cgi = shift;
+
my $o = FS::access_user->new({username => $cgi->param('username')});
if( $o->is_system_user and !$cgi->param('usernum') ) {
$cgi->param('username','');
return "username '".$o->username."' reserved for system account."
}
+
return '';
}
+
+sub post_new_object_callback {
+ my( $cgi, $access_user ) = @_;
+
+ if ( length($cgi->param('_password')) ) {
+ my $password = scalar($cgi->param('_password'));
+ $access_user->change_password_fields($password);
+ }
+
+}
+
</%init>
diff --git a/httemplate/edit/process/elements/process.html b/httemplate/edit/process/elements/process.html
index fb1ee7a27..2afbdd082 100644
--- a/httemplate/edit/process/elements/process.html
+++ b/httemplate/edit/process/elements/process.html
@@ -70,6 +70,9 @@ Example:
#return an error string or empty for no error
'precheck_callback' => sub { my( $cgi ) = @_; },
+ #after the new object is created
+ 'post_new_object_callback' => sub { my( $cgi, $object ) = @_; },
+
#after everything's inserted
'noerror_callback' => sub { my( $cgi, $object ) = @_; },
@@ -226,6 +229,10 @@ foreach my $value ( @values ) {
}
}
+ if ( $opt{'post_new_object_callback'} ) {
+ &{ $opt{'post_new_object_callback'} }( $cgi, $new );
+ }
+
if ( $opt{'agent_virt'} ) {
if ( ! $new->agentnum
diff --git a/httemplate/pref/pref-process.html b/httemplate/pref/pref-process.html
index 242e12294..962ee51b6 100644
--- a/httemplate/pref/pref-process.html
+++ b/httemplate/pref/pref-process.html
@@ -13,35 +13,35 @@ if ( FS::Conf->new->exists('disable_acl_changes') ) {
}
my $error = '';
-my $access_user = '';
-if ( grep { $cgi->param($_) !~ /^\s*$/ }
- qw(_password new_password new_password2)
+if ( FS::Auth->auth_class->can('change_password')
+ && grep { $cgi->param($_) !~ /^\s*$/ }
+ qw(_password new_password new_password2)
) {
- $access_user = qsearchs( 'access_user', {
- 'usernum' => $FS::CurrentUser::CurrentUser->usernum,
- 'username' => $FS::CurrentUser::CurrentUser->username,
- '_password' => scalar($cgi->param('_password')),
- } );
+ if ( $cgi->param('new_password') ne $cgi->param('new_password2') ) {
+ $error = "New passwords don't match";
- $error = 'Current password incorrect; password not changed'
- unless $access_user;
+ } elsif ( ! length($cgi->param('new_password')) ) {
+ $error = 'No new password entered';
- $error ||= "New passwords don't match"
- unless $cgi->param('new_password') eq $cgi->param('new_password2');
+ } elsif ( ! FS::Auth->authenticate( $FS::CurrentUser::CurrentUser,
+ scalar($cgi->param('_password')) )
+ ) {
+ $error = 'Current password incorrect; password not changed';
- $error ||= "No new password entered"
- unless length($cgi->param('new_password'));
+ } else {
- $access_user->_password($cgi->param('new_password')) unless $error;
+ $error = $FS::CurrentUser::CurrentUser->change_password(
+ scalar($cgi->param('new_password'))
+ );
-} else {
-
- $access_user = $FS::CurrentUser::CurrentUser;
+ }
}
+my $access_user = $FS::CurrentUser::CurrentUser;
+
#well, if you got your password change wrong, you don't get anything else
#changed right now. but it should be sticky on the form
unless ( $error ) { # if ($access_user) {
diff --git a/httemplate/pref/pref.html b/httemplate/pref/pref.html
index 9861c3f85..dc44db0b0 100644
--- a/httemplate/pref/pref.html
+++ b/httemplate/pref/pref.html
@@ -4,28 +4,30 @@
<% include('/elements/error.html') %>
+% if ( FS::Auth->auth_class->can('change_password') ) {
-<% mt('Change password (leave blank for no change)') |h %>
-<% ntable("#cccccc",2) %>
+ <% mt('Change password (leave blank for no change)') |h %>
+ <% ntable("#cccccc",2) %>
- <TR>
- <TH ALIGN="right">Current password: </TH>
- <TD><INPUT TYPE="password" NAME="_password"></TD>
- </TR>
+ <TR>
+ <TH ALIGN="right">Current password: </TH>
+ <TD><INPUT TYPE="password" NAME="_password"></TD>
+ </TR>
- <TR>
- <TH ALIGN="right">New password: </TH>
- <TD><INPUT TYPE="password" NAME="new_password"></TD>
- </TR>
+ <TR>
+ <TH ALIGN="right">New password: </TH>
+ <TD><INPUT TYPE="password" NAME="new_password"></TD>
+ </TR>
- <TR>
- <TH ALIGN="right">Re-enter new password: </TH>
- <TD><INPUT TYPE="password" NAME="new_password2"></TD>
- </TR>
+ <TR>
+ <TH ALIGN="right">Re-enter new password: </TH>
+ <TD><INPUT TYPE="password" NAME="new_password2"></TD>
+ </TR>
-</TABLE>
-<BR>
+ </TABLE>
+ <BR>
+% }
Interface
<% ntable("#cccccc",2) %>