summaryrefslogtreecommitdiff
path: root/httemplate
diff options
context:
space:
mode:
Diffstat (limited to 'httemplate')
-rw-r--r--httemplate/edit/process/access_user.html3
-rw-r--r--httemplate/edit/process/svc_dsl.html15
-rwxr-xr-xhttemplate/edit/svc_acct.cgi7
-rw-r--r--httemplate/elements/change_password.html6
-rw-r--r--httemplate/elements/random_pass.html18
-rw-r--r--httemplate/elements/validate_password.html58
-rw-r--r--httemplate/misc/xmlhttp-validate_password.html50
-rw-r--r--httemplate/pref/pref-process.html20
8 files changed, 161 insertions, 16 deletions
diff --git a/httemplate/edit/process/access_user.html b/httemplate/edit/process/access_user.html
index 0554bb940..bbe4268be 100644
--- a/httemplate/edit/process/access_user.html
+++ b/httemplate/edit/process/access_user.html
@@ -43,7 +43,8 @@ sub post_new_object_callback {
if ( length($cgi->param('_password')) ) {
my $password = scalar($cgi->param('_password'));
- $access_user->change_password_fields($password);
+ my $error = $access_user->is_password_allowed($password)
+ || $access_user->change_password($password);
}
}
diff --git a/httemplate/edit/process/svc_dsl.html b/httemplate/edit/process/svc_dsl.html
index 627329a00..889366e07 100644
--- a/httemplate/edit/process/svc_dsl.html
+++ b/httemplate/edit/process/svc_dsl.html
@@ -1,5 +1,6 @@
<% include( 'elements/svc_Common.html',
'table' => 'svc_dsl',
+ 'precheck_callback' => $precheck_callback,
)
%>
<%init>
@@ -7,4 +8,18 @@
die "access denied"
unless $FS::CurrentUser::CurrentUser->access_right('Provision customer service'); #something else more specific?
+my $precheck_callback = sub {
+ my $cgi = shift;
+ my $svcnum = $cgi->param('svcnum');
+ my $error = '';
+ if ( $svcnum ) {
+ my $old = FS::svc_dsl->by_key($svcnum);
+ my $newpass = $cgi->param('password');
+ if ( $old and $newpass ne $old->password ) {
+ $error ||= $old->is_password_allowed($newpass);
+ }
+ }
+ $error;
+};
+
</%init>
diff --git a/httemplate/edit/svc_acct.cgi b/httemplate/edit/svc_acct.cgi
index 31678a991..0cf0c20e1 100755
--- a/httemplate/edit/svc_acct.cgi
+++ b/httemplate/edit/svc_acct.cgi
@@ -50,7 +50,12 @@
'required' => $part_svc->part_svc_column('_password')->required ) %>
<TD>
<INPUT TYPE="text" ID="clear_password" NAME="clear_password" VALUE="<% $password %>" SIZE=<% $pmax2 %> MAXLENGTH=<% $pmax %>>
- <& /elements/random_pass.html, 'clear_password' &>
+ <& /elements/random_pass.html, 'clear_password' &><BR>
+ <DIV ID="clear_password_result" STYLE="font-size: smaller"></DIV>
+ <& '/elements/validate_password.html',
+ 'fieldid' => 'clear_password',
+ 'svcnum' => $svcnum
+ &>
</TD>
</TR>
%}else{
diff --git a/httemplate/elements/change_password.html b/httemplate/elements/change_password.html
index 625ba1fb5..7d8daaeaf 100644
--- a/httemplate/elements/change_password.html
+++ b/httemplate/elements/change_password.html
@@ -16,6 +16,12 @@
<& /elements/random_pass.html, $pre.'password', 'randomize' &>
<INPUT TYPE="submit" VALUE="change">
<INPUT TYPE="button" VALUE="cancel" onclick="<%$pre%>toggle(false)">
+ <DIV ID="<%$pre%>password_result" STYLE="font-size: smaller"></DIV>
+ <& '/elements/validate_password.html',
+ 'fieldid' => $pre.'password',
+ 'svcnum' => $svc_acct->svcnum,
+
+ &>
% if ( $error ) {
<BR><SPAN STYLE="color: #ff0000"><% $error |h %></SPAN>
% }
diff --git a/httemplate/elements/random_pass.html b/httemplate/elements/random_pass.html
index b215b77d9..14bbb581d 100644
--- a/httemplate/elements/random_pass.html
+++ b/httemplate/elements/random_pass.html
@@ -1,13 +1,23 @@
<INPUT TYPE="button" VALUE="<% emt($label) %>" onclick="randomPass()">
<SCRIPT TYPE="text/javascript">
function randomPass() {
+ var lower='<% join('', 'a'..'z') %>';
+ var upper='<% join('', 'A'..'Z') %>';
+ var number='<% join('', '0'..'9') %>';
+ var symbol='`~!@#$%^&*-_=+:;<>,.?';
+ var pw_set=lower+upper+number+symbol;
+ var pass=[];
+ pass.push(lower.charAt(Math.floor(Math.random() * lower.length)));
+ pass.push(upper.charAt(Math.floor(Math.random() * lower.length)));
+ pass.push(number.charAt(Math.floor(Math.random() * number.length)));
+ pass.push(symbol.charAt(Math.floor(Math.random() * symbol.length)));
var i=0;
- var pw_set='<% join('', 'a'..'z', 'A'..'Z', '0'..'9' ) %>';
- var pass='';
- while(i < 8) {
+ while(i < 4) {
i++;
- pass += pw_set.charAt(Math.floor(Math.random() * pw_set.length));
+ pass.push(pw_set.charAt(Math.floor(Math.random() * pw_set.length)));
}
+ for(var j, x, i = pass.length; i; j = Math.floor(Math.random() * i), x = pass[--i], pass[i] = pass[j], pass[j] = x);
+ pass = pass.join('');
document.getElementById('<% $id %>').value = pass;
}
</SCRIPT>
diff --git a/httemplate/elements/validate_password.html b/httemplate/elements/validate_password.html
new file mode 100644
index 000000000..fd2cb6ca0
--- /dev/null
+++ b/httemplate/elements/validate_password.html
@@ -0,0 +1,58 @@
+<%doc>
+
+To validate passwords via javascript/xmlhttp:
+
+ <INPUT ID="password_field" TYPE="text">
+ <DIV ID="password_field_result">
+ <& '/elements/validate_password.html',
+ fieldid => 'password_field',
+ svcnum => $svcnum
+ &>
+
+The ID of the input field can be anything; the ID of the DIV in which to display results
+should be the input id plus '_result'.
+
+</%doc>
+
+<& '/elements/xmlhttp.html',
+ 'url' => $p.'misc/xmlhttp-validate_password.html',
+ 'subs' => [ 'validate_password' ],
+ 'method' => 'POST', # important not to put passwords in url
+&>
+<SCRIPT>
+function add_password_validation (fieldid) {
+ var inputfield = document.getElementById(fieldid);
+ inputfield.onchange = function () {
+ var fieldid = this.id+'_result';
+ var resultfield = document.getElementById(fieldid);
+ if (this.value) {
+ resultfield.innerHTML = '<SPAN STYLE="color: blue;">Validating password...</SPAN>';
+ validate_password('fieldid',fieldid,'svcnum','<% $opt{'svcnum'} %>','password',this.value,
+ function (result) {
+ result = JSON.parse(result);
+ var resultfield = document.getElementById(result.fieldid);
+ if (resultfield) {
+ if (result.valid) {
+ resultfield.innerHTML = '<SPAN STYLE="color: green;">Password valid!</SPAN>';
+ } else if (result.error) {
+ resultfield.innerHTML = '<SPAN STYLE="color: red;">'+result.error+'</SPAN>';
+ } else {
+ result.syserror = result.syserror || 'Server error';
+ resultfield.innerHTML = '<SPAN STYLE="color: red;">'+result.syserror+'</SPAN>';
+ }
+ }
+ }
+ );
+ } else {
+ resultfield.innerHTML = '';
+ }
+ };
+}
+add_password_validation('<% $opt{'fieldid'} %>');
+</SCRIPT>
+
+<%init>
+my %opt = @_;
+</%init>
+
+
diff --git a/httemplate/misc/xmlhttp-validate_password.html b/httemplate/misc/xmlhttp-validate_password.html
new file mode 100644
index 000000000..28dbf6460
--- /dev/null
+++ b/httemplate/misc/xmlhttp-validate_password.html
@@ -0,0 +1,50 @@
+<%doc>
+Requires cgi params 'password' (plaintext) and 'sub' ('validate_password' is only
+acceptable value.) Also accepts 'svcnum' (for svc_acct, will otherwise create an
+empty dummy svc_acct) and 'fieldid' (for html post-processing, passed along in
+results for convenience.)
+
+Returns a json-encoded hashref with keys of 'valid' (set to 1 if object is valid),
+'error' (error text if password is invalid) or 'syserror' (error text if password
+could not be validated.) Only one of these keys will be set. Will also set
+'fieldid' if it was passed.
+</%doc>
+
+<% encode_json($result) %>
+
+<%init>
+
+my $validate_password = sub {
+ my %arg = $cgi->param('arg');
+ my %result;
+
+ $result{'fieldid'} = $arg{'fieldid'}
+ if $arg{'fieldid'} =~ /^\w+$/;
+
+ $result{'syserror'} = 'Request is not POST' unless $cgi->request_method eq 'POST';
+ return \%result if $result{'syserror'};
+
+ my $password = $arg{'password'};
+ $result{'syserror'} = 'Invoked without password' unless $password;
+ return \%result if $result{'syserror'};
+
+ my $svcnum = $arg{'svcnum'};
+ $result{'syserror'} = 'Invalid svcnum' unless $svcnum =~ /^\d*$/;
+ return \%result if $result{'syserror'};
+
+ my $svc_acct = $svcnum
+ ? qsearchs('svc_acct',{'svcnum' => $svcnum})
+ : (new FS::svc_acct {});
+ $result{'syserror'} = 'Could not find service' unless $svc_acct;
+ return \%result if $result{'syserror'};
+
+ $result{'error'} = $svc_acct->is_password_allowed($password);
+ $result{'valid'} = 1 unless $result{'error'};
+ return \%result;
+};
+
+my $result = ($cgi->param('sub') eq 'validate_password')
+ ? &$validate_password()
+ : { 'syserror' => 'Invalid sub' };
+
+</%init>
diff --git a/httemplate/pref/pref-process.html b/httemplate/pref/pref-process.html
index 68f0f6e2f..665bb81c2 100644
--- a/httemplate/pref/pref-process.html
+++ b/httemplate/pref/pref-process.html
@@ -7,6 +7,8 @@
% }
<%init>
+my $access_user = $FS::CurrentUser::CurrentUser;
+
if ( FS::Conf->new->exists('disable_acl_changes') ) {
errorpage("Preference changes disabled in public demo");
die "shouldn't be reached";
@@ -19,29 +21,27 @@ if ( FS::Auth->auth_class->can('change_password')
qw(_password new_password new_password2)
) {
- if ( $cgi->param('new_password') ne $cgi->param('new_password2') ) {
+ my $oldpass = $cgi->param('_password');
+ my $newpass = $cgi->param('new_password');
+
+ if ( $newpass ne $cgi->param('new_password2') ) {
$error = "New passwords don't match";
- } elsif ( ! length($cgi->param('new_password')) ) {
+ } elsif ( ! length($newpass) ) {
$error = 'No new password entered';
- } elsif ( ! FS::Auth->authenticate( $FS::CurrentUser::CurrentUser,
- scalar($cgi->param('_password')) )
- ) {
+ } elsif ( ! FS::Auth->authenticate( $access_user, $oldpass ) ) {
$error = 'Current password incorrect; password not changed';
} else {
- $error = $FS::CurrentUser::CurrentUser->change_password(
- scalar($cgi->param('new_password'))
- );
+ $error = $access_user->is_password_allowed($newpass)
+ || $access_user->change_password($newpass);
}
}
-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) {