admin permission is no more dependent on the name of the role, but can be assigned to any role. Users assigned to admin role have all permissions.
461 lines
14 KiB
Perl
Executable File
461 lines
14 KiB
Perl
Executable File
#!/usr/bin/perl
|
|
|
|
use strict;
|
|
use warnings;
|
|
no warnings 'redefine';
|
|
|
|
use Data::Dumper;
|
|
|
|
use config();
|
|
use params();
|
|
use entry();
|
|
use log();
|
|
use template();
|
|
use auth();
|
|
use uac();
|
|
use studios();
|
|
use localization();
|
|
|
|
binmode STDOUT, ":utf8";
|
|
|
|
my $r = shift;
|
|
( my $cgi, my $params, my $error ) = params::get($r);
|
|
|
|
my $config = config::get('../config/config.cgi');
|
|
|
|
my ( $user, $expires ) = auth::get_user( $config, $params, $cgi );
|
|
return if ( ( !defined $user ) || ( $user eq '' ) );
|
|
|
|
our $actions = {
|
|
read => 1,
|
|
update => 2,
|
|
assign => 3,
|
|
remove => 4,
|
|
disable => 5,
|
|
scan => 6,
|
|
create => 7,
|
|
delete => 8,
|
|
};
|
|
|
|
my $user_presets = uac::get_user_presets(
|
|
$config,
|
|
{
|
|
user => $user,
|
|
project_id => $params->{project_id},
|
|
studio_id => $params->{studio_id}
|
|
}
|
|
);
|
|
$params->{default_studio_id} = $user_presets->{studio_id};
|
|
$params = uac::setDefaultStudio( $params, $user_presets );
|
|
$params->{project_id} = $user_presets->{project_id};
|
|
|
|
my $request = {
|
|
url => $ENV{QUERY_STRING} || '',
|
|
params => {
|
|
original => $params,
|
|
checked => check_params( $config, $params ),
|
|
},
|
|
};
|
|
$request = uac::prepare_request( $request, $user_presets );
|
|
$params = $request->{params}->{checked};
|
|
|
|
#process header
|
|
my $headerParams = uac::set_template_permissions( $request->{permissions}, $params );
|
|
$headerParams->{loc} = localization::get( $config, { user => $user, file => 'menu' } );
|
|
template::process( $config, 'print', template::check( $config, 'roles.html' ), $headerParams );
|
|
return unless uac::check( $config, $params, $user_presets ) == 1;
|
|
|
|
if ( defined $params->{action} ) {
|
|
save_roles( $config, $request ) if ( $params->{action} eq 'save' );
|
|
}
|
|
|
|
#show current roles
|
|
$config->{access}->{write} = 0;
|
|
show_roles( $config, $request );
|
|
|
|
return;
|
|
|
|
# update roles in database:
|
|
# role can be changed only
|
|
# role can be changed only if permission "update_role" is assigned to the user at the current studio
|
|
# role can be changed only if role level is smaller than user's maximum role level
|
|
# new roles will have role level 0 by default
|
|
#
|
|
sub save_roles {
|
|
my $config = shift;
|
|
my $request = shift;
|
|
|
|
my $params = $request->{params}->{checked};
|
|
my $permissions = $request->{permissions};
|
|
|
|
unless ( $permissions->{update_role} == 1 ) {
|
|
uac::permissions_denied('update_role');
|
|
return;
|
|
}
|
|
|
|
my $studio_id = $params->{studio_id};
|
|
my $project_id = $params->{project_id};
|
|
my $roles = uac::get_roles( $config, { project_id => $project_id, studio_id => $studio_id } );
|
|
|
|
my $role_by_id = {};
|
|
my $role_by_name = {};
|
|
for my $role (@$roles) {
|
|
$role_by_id->{ $role->{id} } = $role;
|
|
$role_by_name->{ $role->{role} } = $role;
|
|
}
|
|
|
|
my $columns = uac::get_role_columns($config);
|
|
|
|
#initialize all value ids (given by params matching to database columns)
|
|
my $values = {};
|
|
for my $param ( sort keys %$params ) {
|
|
if ( $param =~ /(.+?)\_(\d+)?$/ ) {
|
|
my $column = $1;
|
|
my $id = $2 || '';
|
|
next unless defined $columns->{$column};
|
|
$values->{$id} = {} if ( update_allowed( $permissions, $role_by_id, $id ) );
|
|
}
|
|
}
|
|
|
|
#init checkbox values with 0
|
|
for my $id ( sort keys %$values ) {
|
|
if ( update_allowed( $permissions, $role_by_id, $id ) ) {
|
|
for my $column ( keys %$columns ) {
|
|
next
|
|
if ( $column eq 'level'
|
|
|| $column eq 'role'
|
|
|| $column eq 'id'
|
|
|| $column eq 'project_id'
|
|
|| $column eq 'studio_id'
|
|
|| $column eq 'created_at'
|
|
);
|
|
$values->{$id}->{$column} = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
#set all checkbox values to 1
|
|
for my $param ( sort keys %$params ) {
|
|
if ( $param =~ /(.+?)\_(\d+)?$/ ) {
|
|
my $column = $1;
|
|
my $id = $2 || '';
|
|
next unless defined $columns->{$column};
|
|
if ( update_allowed( $permissions, $role_by_id, $id ) ) {
|
|
my $value = $params->{$param} || '';
|
|
if ( $column eq 'level' ) {
|
|
if ( check_level( $permissions, $value ) == 1 ) {
|
|
$values->{$id}->{$column} = $value;
|
|
} else {
|
|
uac::permissions_denied("change the level of role!");
|
|
return;
|
|
}
|
|
} elsif ( $column eq 'role' ) {
|
|
$values->{$id}->{$column} = $value;
|
|
} elsif ( $column eq 'admin' ) {
|
|
if ( $permissions->{is_admin} ){
|
|
$values->{$id}->{$column} = $value;
|
|
} else {
|
|
uac::permissions_denied("set admin!");
|
|
return;
|
|
}
|
|
} elsif ( $column eq 'id' || $column eq 'project_id' || $column eq 'studio_id' ) {
|
|
#id and studio id will be set later
|
|
} else {
|
|
$values->{$id}->{$column} = 1 if ( $value =~ /^\d+$/ );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#order roles to update by level
|
|
for my $id ( sort { $values->{$a}->{level} <=> $values->{$b}->{level} } keys %$values ) {
|
|
my $role = $values->{$id};
|
|
$role->{id} = $id || '';
|
|
$role->{studio_id} = $studio_id;
|
|
$role->{project_id} = $project_id;
|
|
|
|
#if you are not admin
|
|
next if check_level( $permissions, $role->{level} ) == 0;
|
|
|
|
if ( $role->{project_id} eq '' ) {
|
|
uac::print_error('missing parameter project_id!');
|
|
next;
|
|
}
|
|
if ( $role->{studio_id} eq '' ) {
|
|
uac::print_error('missing parameter studio_id!');
|
|
next;
|
|
}
|
|
if ( ( $role->{role} eq '' ) && ( $id ne '' ) ) {
|
|
uac::print_error('missing parameter role!');
|
|
next;
|
|
}
|
|
|
|
my $role_from_db = undef;
|
|
$role_from_db = $role_by_name->{ $role->{role} } if defined $role_by_name->{ $role->{role} };
|
|
|
|
if ( $id eq '' ) {
|
|
|
|
#insert role
|
|
next if $role->{role} eq '';
|
|
if ( defined $role_from_db ) {
|
|
uac::print_error("a role with name '$role->{role}' already exists!");
|
|
next;
|
|
}
|
|
$role->{level} = 0;
|
|
print "insert $id $role->{role}<br>\n";
|
|
$config->{access}->{write} = 1;
|
|
uac::insert_role( $config, $role );
|
|
$config->{access}->{write} = 0;
|
|
} else {
|
|
|
|
#update role
|
|
if ( ( defined $role_from_db ) && ( $id ne $role_from_db->{id} ) ) {
|
|
uac::print_error( 'you cannot rename role to existing role!'
|
|
. " '$role->{role}' ($id) != '$role_from_db->{role}' ($role_from_db->{id})" );
|
|
next;
|
|
}
|
|
print "update $role->{role}<br>\n";
|
|
|
|
#print '<div style="height:3em;overflow:auto;white-space:pre">'.Dumper($role).'</div>';
|
|
$config->{access}->{write} = 1;
|
|
uac::update_role( $config, $role );
|
|
$config->{access}->{write} = 0;
|
|
}
|
|
}
|
|
print qq{<div class="ok head">changes saved</div>};
|
|
|
|
}
|
|
|
|
#check if update is allowed
|
|
sub update_allowed {
|
|
my $permissions = shift;
|
|
my $role_by_id = shift;
|
|
my $id = shift;
|
|
|
|
return 0 unless defined $permissions;
|
|
return 0 unless defined $role_by_id;
|
|
return 0 unless defined $id;
|
|
return 1 if $id eq '';
|
|
return 0 unless defined $role_by_id->{$id};
|
|
my $role = $role_by_id->{$id};
|
|
return check_level( $permissions, $role->{level} );
|
|
}
|
|
|
|
#check if update is allowed
|
|
sub check_level {
|
|
my $permissions = shift;
|
|
my $level = shift;
|
|
return 0 unless defined $permissions;
|
|
return 0 unless defined $level;
|
|
return 1 if ( $permissions->{is_admin} );
|
|
return 1 if ( $permissions->{level} > $level );
|
|
return 0;
|
|
}
|
|
|
|
# user has to be assigned to studio
|
|
# user needs to have permissions read_role
|
|
sub show_roles {
|
|
my $config = shift;
|
|
my $request = shift;
|
|
|
|
my $params = $request->{params}->{checked};
|
|
my $permissions = $request->{permissions};
|
|
unless ( $permissions->{read_role} == 1 ) {
|
|
uac::permissions_denied('read_role');
|
|
return;
|
|
}
|
|
|
|
my $studio_id = $params->{studio_id};
|
|
my $project_id = $params->{project_id};
|
|
my $columns = uac::get_role_columns($config);
|
|
|
|
#get user roles
|
|
my $conditions = {};
|
|
$conditions->{studio_id} = $params->{studio_id} if ( $params->{studio_id} ne '' );
|
|
$conditions->{project_id} = $params->{project_id} if ( $params->{project_id} ne '' );
|
|
my $roles = uac::get_roles( $config, $conditions );
|
|
@$roles = reverse sort { $a->{level} cmp $b->{level} } (@$roles);
|
|
|
|
#add new role template
|
|
unshift @$roles, { role => '', level => '0' };
|
|
|
|
#print user role form
|
|
my $out = qq{
|
|
<div id="edit_roles">
|
|
<form method="post">
|
|
<input type="hidden" name="project_id" value="$project_id">
|
|
<input type="hidden" name="studio_id" value="$studio_id">
|
|
};
|
|
|
|
if ( defined $permissions->{update_role} ) {
|
|
|
|
#add new user role button
|
|
$out .= q{
|
|
<button id="add_user_role_button" onclick="add_user_role();return false;">add user role</button>
|
|
}
|
|
}
|
|
|
|
$out .= '<div class="panel">';
|
|
$out .= '<table class="table">';
|
|
my $localization = localization::get( $config, { user => $params->{presets}->{user}, file => 'roles' } );
|
|
for my $key ( keys %$localization ) {
|
|
$localization->{$key} =~ s/\(/<span class\=\"comment\">/;
|
|
$localization->{$key} =~ s/\)/<\/span>/;
|
|
}
|
|
|
|
#add role row
|
|
$out .= qq{<tr>};
|
|
my $description = $localization->{label_role} || 'role';
|
|
$out .= qq{<td>$description</td>};
|
|
|
|
for my $role (@$roles) {
|
|
$role->{active} = '';
|
|
$role->{active} = ' disabled' if check_level( $permissions, $role->{level} ) == 0;
|
|
$role->{active} = ' disabled' unless defined $permissions->{update_role};
|
|
}
|
|
|
|
for my $role (@$roles) {
|
|
my $id = $role->{id} || '';
|
|
my $value = $role->{role} || '';
|
|
my $style = '';
|
|
$style = ' id="new_user_role" class="editor" style="display:none"' if ( $id eq '' );
|
|
my $active = $role->{active};
|
|
$out .= qq{<td$style><input name="role_$id" value="$value" class="role$active" title="$value"></td>};
|
|
}
|
|
$out .= qq{</tr>};
|
|
|
|
#add level row
|
|
$out .= qq{<tr>};
|
|
$description = $localization->{label_level} || 'level';
|
|
$out .= qq{<td>$description</td>};
|
|
for my $role (@$roles) {
|
|
my $id = $role->{id} || '';
|
|
my $value = $role->{level} || '';
|
|
my $style = '';
|
|
$style = ' id="new_user_level" class="editor" style="display:none"' if ( $id eq '' );
|
|
my $active = $role->{active};
|
|
$out .= qq{<td$style><input name="level_$id" value="$value" class="role$active" title="$value"></td>};
|
|
}
|
|
$out .= qq{</tr>};
|
|
|
|
#add permission rows
|
|
$columns = sort_columns($columns);
|
|
|
|
for my $key (@$columns) {
|
|
next
|
|
if ( $key eq 'level'
|
|
|| $key eq 'role'
|
|
|| $key eq 'id'
|
|
|| $key eq 'project_id'
|
|
|| $key eq 'studio_id'
|
|
|| $key eq 'modified_at'
|
|
|| $key eq 'created_at' );
|
|
my $title = $key;
|
|
$title =~ s/\_/ /g;
|
|
my $description = $localization->{ 'label_' . $key } || $key;
|
|
$out .= qq{<tr>};
|
|
$out .= qq{<td title="$title">$description</td>};
|
|
for my $role (@$roles) {
|
|
my $value = $role->{$key} || '0';
|
|
my $id = $role->{id} || '';
|
|
my $active = $role->{active};
|
|
my $style = '';
|
|
$style = ' class="editor' . $active . '" style="display:none"' if ( $id eq '' );
|
|
my $checked = '';
|
|
$checked = 'checked="checked"' if ( $value eq '1' );
|
|
$active =~ s/\s//g;
|
|
$out .= qq{<td$style>
|
|
<input type="checkbox" name="} . $key . '_' . $id . qq{" value="$value" $checked class="$active">
|
|
</td>
|
|
};
|
|
}
|
|
$out .= qq{</tr>};
|
|
}
|
|
$out .= '</table>';
|
|
$out .= '<input type="submit" name="action" value="save">' if defined $permissions->{update_role};
|
|
$out .= '</form>';
|
|
$out .= '</div>';
|
|
print $out. "\n";
|
|
}
|
|
|
|
# sort columns by group and action
|
|
sub sort_columns {
|
|
my $columns = shift;
|
|
|
|
my $column_level = {};
|
|
my $groups = sort_groups($columns);
|
|
for my $column ( keys %$columns ) {
|
|
my @words = split /_/, $column;
|
|
my $action = shift @words;
|
|
my $group = join( ' ', @words );
|
|
|
|
my $index = $groups->{$group} || 0;
|
|
$index += $actions->{$action} if defined $actions->{$action};
|
|
$column_level->{$column} = $index;
|
|
}
|
|
|
|
my @columns = sort { $column_level->{$a} <=> $column_level->{$b} } ( keys %$column_level );
|
|
return \@columns;
|
|
}
|
|
|
|
# sort columns by group
|
|
sub sort_groups {
|
|
my $columns = shift;
|
|
my $groups = {};
|
|
|
|
#extract groups
|
|
for my $column ( keys %$columns ) {
|
|
my @words = split /_/, $column;
|
|
my $action = shift @words;
|
|
my $group = join( ' ', @words );
|
|
$groups->{$group} = 1;
|
|
}
|
|
|
|
#weigth groups
|
|
my $i = 0;
|
|
for my $group ( sort keys %$groups ) {
|
|
$groups->{$group} = $i;
|
|
$i += 100;
|
|
}
|
|
|
|
#print "<pre>";
|
|
#for my $group (sort {$groups->{$a} <=> $groups->{$b}} (keys %$groups)){
|
|
# print "$groups->{$group}\t$group\n";
|
|
#}
|
|
#print "</pre>";
|
|
|
|
return $groups;
|
|
}
|
|
|
|
sub check_params {
|
|
my $config = shift;
|
|
my $params = shift;
|
|
|
|
my $checked = {};
|
|
|
|
#template
|
|
my $template = '';
|
|
$template = template::check( $config, $params->{template}, 'roles.html' );
|
|
$checked->{template} = $template;
|
|
|
|
$checked->{action} = entry::element_of( $params->{action}, ['save']);
|
|
|
|
entry::set_numbers( $checked, $params, [
|
|
'project_id', 'studio_id', 'default_studio_id'
|
|
]);
|
|
|
|
if ( defined $checked->{studio_id} ) {
|
|
$checked->{default_studio_id} = $checked->{studio_id};
|
|
} else {
|
|
$checked->{studio_id} = -1;
|
|
}
|
|
|
|
#permission fields
|
|
for my $key ( keys %$params ) {
|
|
$checked->{$key} = $params->{$key} if ( $key =~ /^[a-z_]+_\d*$/ );
|
|
}
|
|
|
|
return $checked;
|
|
}
|
|
|