Commit 53d7f388 authored by Francesc Guasch's avatar Francesc Guasch
Browse files

Merge branch 'develop' of github.com:UPC/ravada into develop

parents 93197936 3df267ab
......@@ -1345,6 +1345,17 @@ sub _set_url_isos($self, $new_url='http://localhost/iso/') {
}
sub _get_column_info
{
my $self = shift;
my ($table, $field) = @_;
my $dbh = $CONNECTOR->dbh;
my $sth = $dbh->column_info(undef,undef,$table,$field);
my $row = $sth->fetchrow_hashref;
$sth->finish;
return $row;
}
sub _upgrade_table {
my $self = shift;
my ($table, $field, $definition) = @_;
......@@ -1776,6 +1787,18 @@ sub _clean_iso_mini {
$sth->finish;
}
sub _upgrade_users_table {
my $self = shift;
my $data = $self->_get_column_info('users', 'change_password');
if ($data->{'COLUMN_DEF'} == 1) {
my $sth = $CONNECTOR->dbh->prepare("UPDATE users set change_password=0");
$sth->execute;
$sth = $CONNECTOR->dbh->prepare("ALTER TABLE users ALTER change_password SET DEFAULT 0");
$sth->execute;
}
}
sub _upgrade_tables {
my $self = shift;
# return if $CONNECTOR->dbh->{Driver}{Name} !~ /mysql/i;
......@@ -1889,6 +1912,8 @@ sub _upgrade_tables {
$self->_upgrade_table('messages','date_changed','timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP');
$self->_upgrade_table('grant_types', 'is_int', 'int DEFAULT 0');
$self->_upgrade_users_table();
}
sub _upgrade_timestamps($self) {
......
......@@ -501,6 +501,24 @@ sub id {
return $id;
}
=head2 password_will_be_changed
Returns true if user password will be changed
$user->password_will_be_changed();
=cut
sub password_will_be_changed {
my $self = shift;
_init_connector();
my $sth = $$CON->dbh->prepare("SELECT change_password FROM users WHERE name=?");
$sth->execute($self->name);
return $sth->fetchrow();
}
=head2 change_password
Changes the password of an User
......@@ -514,14 +532,22 @@ Arguments: password
sub change_password {
my $self = shift;
my $password = shift or die "ERROR: password required\n";
my ($force_change_password) = @_;
_init_connector();
die "Password too small" if length($password)<6;
my $sth= $$CON->dbh->prepare("UPDATE users set password=?"
." WHERE name=?");
$sth->execute(sha1_hex($password), $self->name);
my $sth;
if (defined($force_change_password)) {
$sth= $$CON->dbh->prepare("UPDATE users set password=?, change_password=?"
." WHERE name=?");
$sth->execute(sha1_hex($password), $force_change_password ? 1 : 0, $self->name);
} else {
my $sth= $$CON->dbh->prepare("UPDATE users set password=?"
." WHERE name=?");
$sth->execute(sha1_hex($password), $self->name);
}
}
=head2 compare_password
......
......@@ -999,4 +999,13 @@ sub _check_port($self,@args) {
return 0;
}
sub copy_config($self, $domain) {
my $config_new = $self->_load();
for my $field ( keys %$config_new ) {
my $value = $config_new->{$field};
$value = 0 if $field eq 'is_active';
$self->_store($field, $value);
}
}
1;
......@@ -22,6 +22,7 @@
.service("listMess", gtListMess)
.controller("SupportForm", suppFormCtrl)
.controller("AddUserForm",addUserFormCrtl)
.controller("ChangePasswordForm",changePasswordFormCrtl)
// .controller("machines", machinesCrtl)
// .controller("messages", messagesCrtl)
.controller("users", usersCrtl)
......@@ -74,6 +75,11 @@
function addUserFormCrtl($scope, $http, request){
};
function changePasswordFormCrtl($scope, $http, request){
};
function swNewMach() {
......
......@@ -156,6 +156,7 @@ hook before_routes => sub {
,url => undef
,_logged_in => undef
,_anonymous => undef
,forcing_change_password => undef
,_user => undef
,footer=> $CONFIG_FRONT->{footer}
,monitoring => 0
......@@ -187,6 +188,10 @@ hook before_routes => sub {
return if $url =~ m{^/anonymous};
if ((defined $USER) && (_logged_in($c)) && (! $USER->is_temporary) && (! $USER->is_external) && ($USER->password_will_be_changed())) {
return change_password($c, 1);
}
if (($url =~ m{^/machine/(clone|display|info|view)/}
|| $url =~ m{^/(list_bases_anonymous|request/)}i
|| $url =~ m{^/ws/subscribe}
......@@ -1116,10 +1121,18 @@ any '/admin/user/(:id).(:type)' => sub {
}
}
}
if ($c->param('set_password')) {
$user->change_password($c->param('password'), $c->param('force_change_password'));
}
$c->stash(user => $user);
return $c->render(template => 'main/manage_user');
};
any '/user/change_password' => sub {
my $c = shift;
return change_password($c);
};
get '/list_ldap_attributes/(#cn)' => sub {
my $c = shift;
......@@ -2554,6 +2567,39 @@ sub register {
$c->render(template => 'bootstrap/new_user');
}
sub change_password {
my $c = shift;
my ($forcing_change_password) = @_;
return $c->render(text => "User is anonymous")
if (! _logged_in($c));
return $c->render(text => "User is temporary")
if $USER->is_temporary;
return $c->render(text => "User is external")
if $USER->is_external;
my $old_password = $c->param('old_password');
if ($old_password) {
return $c->render(template => 'bootstrap/change_password', error => [ "Old password do not match!" ]) if (! $USER->compare_password($old_password));
my $new_password = $c->param('new_password');
return $c->render(template => 'bootstrap/change_password', error => [ "New password length is less than 6!" ]) if (length($new_password) < 6);
my $repeated_new_password = $c->param('repeated_new_password');
return $c->render(template => 'bootstrap/change_password', error => [ "New password and their repeat do not match!" ]) if ($new_password ne $repeated_new_password);
$USER->change_password($c->param('new_password'), 0);
$c->redirect_to('/');
}
$c->render(template => 'bootstrap/change_password', forcing_change_password => $forcing_change_password);
}
sub manage_machine {
my $c = shift;
my ($domain) = _search_requested_machine($c);
......
......@@ -2,7 +2,7 @@ CREATE TABLE `users` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` char(255) NOT NULL,
`password` char(255) DEFAULT NULL,
`change_password` integer DEFAULT 1,
`change_password` integer DEFAULT 0,
`is_admin` integer DEFAULT 0,
`is_temporary` integer DEFAULT 0,
`is_external` integer DEFAULT 0,
......
......@@ -2,7 +2,7 @@ CREATE TABLE `users` (
`id` integer NOT NULL PRIMARY KEY AUTOINCREMENT
, `name` char(255) NOT NULL
, `password` char(255) DEFAULT NULL
, `change_password` integer DEFAULT 1
, `change_password` integer DEFAULT 0
, `is_admin` integer DEFAULT 0
, `is_temporary` integer DEFAULT 0
, `is_external` integer DEFAULT 0
......
<!DOCTYPE html>
<html ng-app="ravada.app">
%= include 'bootstrap/header'
<body id="page-top" data-spy="scroll" data-target=".navbar-fixed-top" role="document">
<div id="wrapper">
%= include 'bootstrap/navigation'
<div id="page-wrapper">
<!--CHANGE PASSWORD-->
<div ng-controller="ChangePasswordForm">
<div class="page-title">
<div class="card">
<div class="card-header">
<h2><%=l 'Change password' %>
</h2>
</div>
%= include '/ng-templates/change_password'
</div>
</div>
</div>
</div>
</div>
%= include 'bootstrap/scripts'
</body>
</html>
......@@ -13,6 +13,7 @@ navbar-dark bg-dark fixed-top navbar-expand-lg navbar-inverse">
<div class="collapse navbar-collapse justify-content-end" id="navbarNavDropdown">
<!-- Top Menu Items -->
<ul class="navbar-nav">
% if (! $forcing_change_password) {
% if ($_logged_in) {
% if ( !$_anonymous ) {
<li class="nav-item active">
......@@ -73,6 +74,7 @@ navbar-dark bg-dark fixed-top navbar-expand-lg navbar-inverse">
</div>
</li>
% }
% }
% }
</ul>
</div>
......
<html>
%= include 'bootstrap/header'
<body id="page-top" data-spy="scroll" data-target=".fixed-top" role="document">
<body id="page-top" data-spy="scroll" data-target=".fixed-top" role="document" ng-app="ravada.app">
<div id="wrapper">
%= include 'bootstrap/navigation'
<div id="page-wrapper">
......@@ -21,6 +21,11 @@
<li class="nav-item">
<a class="nav-link" href="#grants" role="tab" data-toggle="tab" aria-controls="grants" aria-selected="true">Grants</a>
</li>
% }
% if (( $_user->is_admin ) && (! $user->is_external)) {
<li class="nav-item">
<a class="nav-link" href="#password" role="tab" data-toggle="tab" aria-controls="password" aria-selected="true">Password</a>
</li>
% }
</ul>
<div class="tab-content" id="myTabContent">
......@@ -33,6 +38,11 @@
<div class="tab-pane fade" id="grants" role="tabpanel" aria-labelledby="grants-tab">
%= include '/main/manage_user_grants'
</div>
% }
% if (( $_user->is_admin ) && (! $user->is_external)) {
<div class="tab-pane fade" id="password" role="tabpanel" aria-labelledby="password-tab">
%= include '/main/manage_user_password'
</div>
% }
</div>
</div><! --page-header -->
......
<div class="card">
<div class="card-body">
<form method="post" name="form" action="/admin/user/<%= $user->id %>.json" novalidate>
<input type="hidden" name="set_password" value="1">
<label for="password"><%=l 'New password' %></label><br/>
<input type="text" name="password" ng-model="password" ng-minlength="6">
<br>
<br>
<input type="checkbox" name="force_change_password" value="1" checked>
<label for="force_change_password"><%=l 'Force change password on first access' %></label><br/>
<div ng-show="form.$submitted || (form.password.$touched && form.password.$dirty)">
<div ng-show="form.password.$error.minlength" class="alert alert-warning">
<strong><%=l 'Oops!' %></strong>&nbsp;<%=l 'New Password must be at least 6 characters' %>.
</div>
</div>
<input type="submit" class="btn btn-primary" name="set_password" value="<%=l 'Set New Password' %>">
</form>
</div>
</div>
<div class="card-body">
<form name="form" role="form" method="post" action="/user/change_password" novalidate>
<div class="from-group">
<label for="old_password"><%=l 'Old Password' %></label>
<input class="form-control" ng-model="old_password" ng-model-onblur placeholder="<%=l 'Enter Old Password' %>" type="password" name="old_password" id="old_password" required="true" ng-pattern="/^[a-zA-Z0-9]*$/"><br/>
</div>
<div class="from-group">
<label for="new_password"><%=l 'New Password' %></label>
<input class="form-control" ng-model="new_password" ng-model-onblur placeholder="<%=l 'Enter New Password' %>" type="password" ng-minlength="6" name="new_password" id="new_password" required="true" ng-pattern="/^[a-zA-Z0-9]*$/"><br/>
</div>
<div class="from-group">
<label for="repeated_new_password"><%=l 'Repeat New Password' %></label>
<input class="form-control" ng-model="repeated_new_password" ng-model-onblur placeholder="<%=l 'Re-Enter New Password' %>" type="password" name="repeated_new_password" id="repeated_new_password" required="true" ng-pattern="/^[a-zA-Z0-9]*$/"><br/>
</div>
<div ng-show="form.$submitted || (form.old_password.$touched && form.old_password.$dirty)">
<div ng-show="form.old_password.$error.required" class="alert alert-warning">
<strong><%=l 'Oops!' %></strong>&nbsp;<%=l 'Old Password is required' %>.
</div>
<div ng-show="form.old_password.$error.pattern" class="alert alert-warning">
<strong><%=l 'Oops!' %></strong>&nbsp;<%=l 'Old Password can only contain words and numbers' %>.
</div>
<div ng-show="form.new_password.$error.required" class="alert alert-warning">
<strong><%=l 'Oops!' %></strong>&nbsp;<%=l 'New Password is required' %>.
</div>
<div ng-show="form.new_password.$error.minlength" class="alert alert-warning">
<strong><%=l 'Oops!' %></strong>&nbsp;<%=l 'New Password must be at least 6 characters' %>.
</div>
<div ng-show="form.new_password.$error.pattern" class="alert alert-warning">
<strong><%=l 'Oops!' %></strong>&nbsp;<%=l 'New Password can only contain words and numbers' %>.
</div>
<div ng-show="old_password === new_password" class="alert alert-warning">
<strong><%=l 'Oops!' %></strong>&nbsp;<%=l 'Old and New Passwords match!' %>.
</div>
<div ng-show="form.repeated_new_password.$error.required" class="alert alert-warning">
<strong><%=l 'Oops!' %></strong>&nbsp;<%=l 'Repeated New Password is required' %>.
</div>
<div ng-show="new_password != repeated_new_password" class="alert alert-warning">
<strong><%=l 'Oops!' %></strong>&nbsp;<%=l 'Password and their confirmation do not match!' %>.
</div>
</div>
<button type="submit" ng-disabled="form.$invalid || old_password === new_password || new_password != repeated_new_password" id="submitbutton" class="btn btn-primary"><%=l 'Submit' %></button>
% if (scalar @$error) {
% for my $i (@$error) {
<div class="alert alert-danger">
<%= $i %>
</div>
% }
% }
</form>
</div>
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment