Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
Projets publics
Ravada-Mirror
Commits
8206cede
Commit
8206cede
authored
Aug 05, 2021
by
Francesc Guasch
Browse files
feature(frontend): manage LDAP groups
parent
b39a3e96
Changes
14
Hide whitespace changes
Inline
Side-by-side
lib/Ravada.pm
View file @
8206cede
...
...
@@ -1181,6 +1181,9 @@ sub _add_indexes_generic($self) {
,"
unique (id_domain,name):name
"
,"
unique(id_vm,public_port)
"
]
,
group_access
=>
[
"
unique (id_domain,name)
"
]
,
requests
=>
[
"
index(status,at_time)
"
,"
index(id,date_changed,status,at_time)
"
...
...
@@ -1757,6 +1760,7 @@ sub _sql_create_tables($self) {
,
id_owner
=>
'
int not null
'
,
background_color
=>
'
varchar(20)
'
,
date_created
=>
'
datetime DEFAULT CURRENT_TIMESTAMP
'
,
date_changed
=>
'
timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
'
}
]
,
...
...
@@ -1770,6 +1774,7 @@ sub _sql_create_tables($self) {
,
time_end
=>
'
time not null
'
,
date_booking
=>
'
date
'
,
visibility
=>
"
enum ('private','public') default 'public'
"
,
date_changed
=>
'
timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
'
}
]
,
...
...
@@ -1779,6 +1784,7 @@ sub _sql_create_tables($self) {
,
id_booking_entry
=>
'
int not null references `booking_entries` (`id`) ON DELETE CASCADE
'
,
ldap_group
=>
'
varchar(255) not null
'
,
date_changed
=>
'
timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
'
}
]
,
...
...
@@ -1788,6 +1794,7 @@ sub _sql_create_tables($self) {
,
id_booking_entry
=>
'
int not null references `booking_entries` (`id`) ON DELETE CASCADE
'
,
id_user
=>
'
int not null references `users` (`id`) ON DELETE CASCADE
'
,
date_changed
=>
'
timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
'
}
]
,
...
...
@@ -1797,6 +1804,7 @@ sub _sql_create_tables($self) {
,
id_booking_entry
=>
'
int not null references `booking_entries` (`id`) ON DELETE CASCADE
'
,
id_base
=>
'
int not null references `domains` (`id`) ON DELETE CASCADE
'
,
date_changed
=>
'
timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
'
}
]
,
...
...
@@ -2088,6 +2096,9 @@ sub _port_definition($driver, $definition0){
my
(
$size
)
=
sort
map
{
length
(
$_
)
}
@found
;
return
"
varchar(
$size
)
$default
";
}
elsif
(
$definition0
=~
/^timestamp /
)
{
$definition0
=
'
timestamp
';
}
}
return
$definition0
;
}
...
...
@@ -4141,6 +4152,9 @@ sub _cmd_remove_hardware {
my
$domain
=
$self
->
search_domain_by_id
(
$id_domain
);
my
$user
=
Ravada::Auth::
SQL
->
search_by_id
(
$uid
);
die
"
Error: User
"
.
$user
->
name
.
"
not allowed to remove hardware from machine
"
.
$domain
->
name
if
!
$user
->
is_admin
;
$domain
->
remove_controller
(
$hardware
,
$index
);
}
...
...
@@ -4158,7 +4172,7 @@ sub _cmd_change_hardware {
my
$user
=
Ravada::Auth::
SQL
->
search_by_id
(
$uid
);
die
"
Error: User
"
.
$user
->
name
.
"
not allowed
\n
"
if
!
$user
->
is_admin
;
if
$hardware
ne
'
memory
'
&&
!
$user
->
is_admin
;
$domain
->
change_hardware
(
$request
->
args
('
hardware
')
...
...
lib/Ravada/Auth.pm
View file @
8206cede
...
...
@@ -121,11 +121,11 @@ sub enable_LDAP {
return
$value
;
}
=head2 enable_
CAS
=head2 enable_
SSO
Sets or get
CAS
support.
Sets or get
SSO
support.
Ravada::Auth::enable_
CAS
(0);
Ravada::Auth::enable_
SSO
(0);
print "SSO is supported" if Ravada::Auth::enable_SSO();
...
...
lib/Ravada/Auth/LDAP.pm
View file @
8206cede
...
...
@@ -181,10 +181,6 @@ sub _new_uid($ldap=_init_ldap_admin(), $base=_dc_base()) {
}
}
sub
default_object_class
()
{
return
@OBJECT_CLASS
;
}
sub
_password_store
($password, $storage, $algorithm=undef) {
return
_password_rfc2307
(
$password
,
$algorithm
)
if
lc
(
$storage
)
eq
'
rfc2307
';
return
_password_pbkdf2
(
$password
,
$algorithm
)
if
lc
(
$storage
)
eq
'
pbkdf2
';
...
...
@@ -460,7 +456,11 @@ sub search_group {
return
$entries
[
0
];
}
sub
search_group_member
($cn, $retry = 0) {
=head2 search_group_members
=cut
sub
search_group_members
($cn, $retry = 0) {
my
$base
=
"
ou=groups,
"
.
_dc_base
();
my
$ldap
=
_init_ldap_admin
();
my
$mesg
=
$ldap
->
search
(
...
...
@@ -470,7 +470,7 @@ sub search_group_member($cn, $retry = 0) {
);
if
(
(
$mesg
->
code
==
1
||
$mesg
->
code
==
81
)
&&
$retry
<
3
)
{
$LDAP_ADMIN
=
undef
;
return
search_group_member
(
$cn
,
$retry
+
1
);
return
search_group_member
s
(
$cn
,
$retry
+
1
);
}
warn
$mesg
->
code
.
"
"
.
$mesg
->
error
.
"
[base:
$base
]
"
if
$mesg
->
code
;
...
...
@@ -497,7 +497,10 @@ Adds user to group
sub
add_to_group
{
my
(
$dn
,
$group_name
)
=
@_
;
if
(
$dn
!~
/=.*,/
)
{
my
$user
=
search_user
(
name
=>
$dn
)
or
confess
"
Error: user '
$dn
' not found
";
my
$user
=
search_user
(
name
=>
$dn
,
field
=>
'
uid
');
$user
=
search_user
(
name
=>
$dn
,
field
=>
'
cn
')
if
!
$user
;
confess
"
Error: user '
$dn
' not found
"
if
!
$user
;
$dn
=
$user
->
dn
;
}
...
...
@@ -590,6 +593,12 @@ sub _search_posix_group($self, $name) {
return
$posix_group
[
0
];
}
=head2 group_members
Returns a list of the group members
=cut
sub
group_members
{
return
_group_members
(
@
_
);
}
...
...
@@ -956,9 +965,16 @@ sub is_member($cn, $group) {
my
@members
=
_group_members
(
$group
);
return
1
if
grep
/^$cn$/
,
@members
;
$user
=
search_user
(
$cn
)
or
confess
"
Error: unknown user '
$cn
'
"
if
!
$user
;
$dn
=
$user
->
dn
if
!
$dn
;
if
(
!
$dn
)
{
if
(
!
$user
)
{
for
my
$field
(
'
uid
','
cn
')
{
$user
=
search_user
(
name
=>
$cn
,
field
=>
$field
);
last
if
$user
;
}
confess
"
Error: unknown user '
$cn
'
"
if
!
$user
;
}
$dn
=
$user
->
dn
if
!
$dn
;
}
return
1
if
grep
/^$dn$/
,
@members
;
...
...
lib/Ravada/Auth/SQL.pm
View file @
8206cede
...
...
@@ -1120,15 +1120,25 @@ sub ldap_entry($self) {
return
$self
->
{
_ldap_entry
}
if
$self
->
{
_ldap_entry
};
my
@entries
=
Ravada::Auth::LDAP::
search_user
(
name
=>
$self
->
name
);
$self
->
{
_ldap_entry
}
=
$entries
[
0
];
for
my
$field
(
qw(uid cn)
)
{
my
(
$entry
)
=
Ravada::Auth::LDAP::
search_user
(
name
=>
$self
->
name
,
field
=>
$field
);
next
if
!
$entry
;
$self
->
{
_ldap_entry
}
=
$entry
;
return
$entry
;
}
return
$self
->
{
_ldap_entry
}
;
return
;
}
=head2 groups
Returns a list of the groups this user belogs to
=cut
sub
groups
($self) {
return
()
if
!
$self
->
external_auth
||
$self
->
external_auth
ne
'
ldap
';
my
@groups
=
Ravada::Auth::LDAP::
search_group_member
(
$self
->
name
);
my
@groups
=
Ravada::Auth::LDAP::
search_group_member
s
(
$self
->
name
);
return
@groups
;
}
...
...
lib/Ravada/Auth/User.pm
View file @
8206cede
...
...
@@ -422,7 +422,7 @@ sub _load_allowed_groups($self) {
next
unless
$self
->
is_external
&&
$self
->
external_auth
eq
'
ldap
';
$self
->
{
_allowed
}
->
{
$id_domain
}
=
1
if
Ravada::Auth::LDAP::
is_member
(
$self
->
name
,
$name
);
if
Ravada::Auth::LDAP::
is_member
(
$self
->
ldap_entry
,
$name
);
}
}
...
...
lib/Ravada/Domain.pm
View file @
8206cede
...
...
@@ -5673,6 +5673,24 @@ sub _allow_group_access($self, %args) {
$sth
->
execute
(
$self
->
id
,
$group
);
}
=head2 list_access_groups
Returns the list of groups who can access this virtual machine
=cut
sub
list_access_groups
($self) {
my
$sth
=
$$CONNECTOR
->
dbh
->
prepare
("
SELECT name from group_access
"
.
"
WHERE id_domain=?
"
);
$sth
->
execute
(
$self
->
id
);
my
@groups
;
while
(
my
(
$name
)
=
$sth
->
fetchrow
)
{
push
@groups
,(
$name
);
}
return
@groups
;
}
sub
_fix_default_access
($self, $type) {
my
@list
=
$self
->
list_access
(
$type
);
my
$id_default
;
...
...
@@ -6353,6 +6371,12 @@ sub _set_displays_down($self) {
$sth
->
execute
(
$self
->
id
);
}
=head2 refresh_ports
Refresh the status of the exposed ports
=cut
sub
refresh_ports
($self, $request=undef) {
my
$sth_update
=
$$CONNECTOR
->
dbh
->
prepare
("
UPDATE domain_ports
"
.
"
SET is_active=?
"
...
...
lib/Ravada/WebSocket.pm
View file @
8206cede
...
...
@@ -48,6 +48,8 @@ our %TABLE_CHANNEL = (
list_alerts
=>
'
messages
'
,
list_machines
=>
'
domains
'
,
list_machines_tree
=>
'
domains
'
,
list_machines_user_including_privates
=>
['
domains
','
bookings
','
booking_entries
'
,'
booking_entry_ldap_groups
',
'
booking_entry_users
','
booking_entry_bases
']
,
list_requests
=>
'
requests
'
);
...
...
@@ -390,7 +392,7 @@ sub _date_changed_table($self, $table) {
my
$sth
=
$rvd
->
_dbh
->
prepare
("
SELECT MAX(date_changed) FROM
$table
");
$sth
->
execute
;
my
(
$date
)
=
$sth
->
fetchrow
;
return
$date
;
return
(
$date
or
'')
;
}
sub
_count_table
($self, $table) {
...
...
@@ -406,9 +408,22 @@ sub _new_info($self, $key) {
my
$channel
=
$self
->
clients
->
{
$key
}
->
{
channel
};
$channel
=~
s{/.*}{}
;
my
$table
=
$TABLE_CHANNEL
{
$channel
}
or
return
;
my
$table0
=
$TABLE_CHANNEL
{
$channel
}
or
return
;
if
(
!
ref
(
$table0
))
{
$table0
=
[
$table0
];
}
my
$count
=
'';
my
$date
=
'';
return
(
$self
->
_count_table
(
$table
),
$self
->
_date_changed_table
(
$table
));
for
my
$table
(
@$table0
)
{
$count
.=
"
:
"
if
$count
;
$count
.=
$self
->
_count_table
(
$table
);
$date
.=
"
:
"
if
$date
;
$date
.=
$self
->
_date_changed_table
(
$table
)
}
return
(
$count
,
$date
);
}
...
...
public/js/admin.js
View file @
8206cede
...
...
@@ -848,7 +848,6 @@ ravadaApp.directive("solShowMachine", swMach)
$scope
.
loading_users
=
false
;
$scope
.
error
=
response
.
data
.
error
;
$scope
.
users
=
response
.
data
.
entries
;
console
.
log
(
response
.
data
.
error
);
});
};
$scope
.
add_member
=
function
(
cn
)
{
...
...
@@ -873,6 +872,12 @@ ravadaApp.directive("solShowMachine", swMach)
$scope
.
error
=
response
.
data
.
error
;
});
};
$scope
.
remove_group
=
function
()
{
$scope
.
confirm_remove
=
false
;
$http
.
post
(
"
/ldap/group/remove/
"
+
group
).
then
(
function
(
response
)
{
$scope
.
error
=
response
.
data
.
error
;
});
};
};
...
...
public/js/ravada.js
View file @
8206cede
...
...
@@ -425,6 +425,7 @@
$scope
.
list_ldap_attributes
();
list_interfaces
();
list_users
();
list_access_groups
();
}
$scope
.
hardware_types
=
Object
.
keys
(
response
.
data
.
hardware
);
$scope
.
copy_ram
=
$scope
.
showmachine
.
max_mem
/
1024
/
1024
;
...
...
@@ -891,18 +892,24 @@
});
};
$scope
.
list_access_groups
=
function
()
{
/*
$http.get("/
domain/
access_groups/"+showmachine.id).then(function(response) {
var
list_access_groups
=
function
()
{
$http
.
get
(
"
/
machine/list_
access_groups/
"
+
$scope
.
showmachine
.
id
).
then
(
function
(
response
)
{
$scope
.
access_groups
=
response
.
data
;
});
*/
});
};
$scope
.
add_group_access
=
function
(
group
)
{
$http
.
get
(
"
/machine/add_access_group/
"
+
$scope
.
showmachine
.
id
+
"
/
"
+
group
)
.
then
(
function
(
response
)
{
$scope
.
list_access_groups
();
list_access_groups
();
});
};
$scope
.
remove_group_access
=
function
(
group
)
{
$http
.
get
(
"
/machine/remove_access_group/
"
+
$scope
.
showmachine
.
id
+
"
/
"
+
group
)
.
then
(
function
(
response
)
{
list_access_groups
();
});
};
$scope
.
message
=
[];
$scope
.
disk_remove
=
[];
$scope
.
pending_before
=
10
;
...
...
@@ -912,11 +919,9 @@
$scope
.
access_value
=
[
];
$scope
.
access_allowed
=
[
];
$scope
.
access_last
=
[
];
$scope
.
access_groups
=
[
];
$scope
.
new_base
=
undefined
;
$scope
.
list_ldap_attributes
();
$scope
.
list_access_groups
();
};
function
swListMach
()
{
...
...
script/rvd_front
View file @
8206cede
...
...
@@ -916,6 +916,15 @@ get '/machine/move_access/(#id_domain)/(#id_access)/(#position)' => sub {
return $c->render(json => { ok => 1 });
};
get '/machine/list_access_groups/(#id_domain)' => sub {
my $c = shift;
return _access_denied($c) if !$USER->is_admin;
my $domain_id = $c->stash('id_domain');
my $domain = Ravada::Front::Domain->open($domain_id);
return $c->render( json => [ $domain->list_access_groups ] );
};
get '/machine/add_access_group/(#id_domain)/(#group)' => sub($c) {
my $id_domain = $c->stash('id_domain');
...
...
@@ -923,12 +932,21 @@ get '/machine/add_access_group/(#id_domain)/(#group)' => sub($c) {
my $ok = 0;
eval {
my $domain = Ravada::Front::Domain->open($id_domain);
$domain->
add
_access
_
group
(
$group);
$domain->
grant
_access
(type => 'group' ,
group
=>
$group);
$ok =1;
};
return $c->render( json => { ok => $ok, error => $@ });
};
get '/machine/remove_access_group/(#id_domain)/(#group)' => sub($c) {
my $sth = $RAVADA->_dbh->prepare("DELETE FROM group_access WHERE id_domain=? "
." AND name=?"
);
$sth->execute($c->stash('id_domain'), $c->stash('group'));
return $c->render(json => { ok => 1 } );
};
get '/machine/compact/(#id_domain)' => sub($c) {
my $req = Ravada::Request->compact(
id_domain => $c->stash('id_domain')
...
...
@@ -973,7 +991,7 @@ get '/machine/public/#id/#value' => sub {
};
get '/machine/set/#id/#field/#value' => sub {
my %privileged = map { $_ => 1 } qw(timeout id_owner);
my %privileged = map { $_ => 1 } qw(timeout id_owner
shutdown_disconnected shutdown_timeout autostart
);
my $c = shift;
my $id = $c->stash('id');
...
...
@@ -1086,15 +1104,36 @@ any '/group/new' => sub {
return new_group($c);
};
any '/admin/user/(
:
id).(:type)' => sub {
any '/admin/user/(
#
id).(:type)' => sub {
my $c = shift;
return access_denied($c) if !$USER->can_manage_users()
&&
!$USER->can_grant();
push @{$c->stash->{js}}, '/js/admin.js';
my $user = Ravada::Auth::SQL->search_by_id($c->stash('id'));
my $id = $c->stash('id');
my $user;
if ($id =~ /cn=(.*?),/) {
$user = Ravada::Auth::SQL->new(name => $1);
} elsif ($id =~ /^\d+$/) {
$user = Ravada::Auth::SQL->search_by_id($id);
} else {
$user = Ravada::Auth::SQL->new(name => $id);
}
return $c->render(text => "Unknown user id: ".$c->stash('id'))
if !$user;
my $origin = $c->param('origin');
$c->stash(origin => $origin, warning => '');
return $c->render(text => "Unknown user ".$c->stash('id'))
if !$user || (!$user->id
&&
!$c->stash('origin'));
if ($c->param('import') ) {
return $c->render( text => "Error: missing origin") if !$origin;
if ($user->id) {
$c->stash( warning => "Warning: user already imported");
} else {
Ravada::Auth::SQL::add_user(name => $user->name, is_external => 1, is_temporary => 0
, external_auth => $origin);
$user = Ravada::Auth::SQL->new(name => $user->name);
}
}
if ($c->param('make_admin')) {
$USER->make_admin($c->stash('id')) if $c->param('is_admin');
...
...
@@ -1132,6 +1171,7 @@ get '/user/list_groups/(#id_user)' => sub($c) {
return _access_denied($c) unless $USER->is_admin || $id_user == $USER->id;
my $user = Ravada::Auth::SQL->search_by_id($id_user);
return $c->render(json => [] ) if !$user;
return $c->render(json => [$user->groups()]);
};
...
...
templates/main/admin_group.html.ep
View file @
8206cede
...
...
@@ -46,12 +46,28 @@
<button
ng-click=
"remove_member(user)"
ng-show=
"<%= $_user->can_manage_groups %>"
class=
"badge badge-light text-blue"
>
x
</button>
{{user}}
<a
ng-bind-html=
"user"
href=
"/admin/user/{{user}}.html?origin=ldap"
>
{{user}}
</a>
</td>
</tr>
</tbody>
</table>
<div
ng-show=
"group_members.length==0"
>
No members found
</div>
<div
class=
"alert alert-warning"
ng-show=
"group_members.length==0"
>
No members found
</div>
<input
type=
"button"
class=
"btn btn-outline-secondary"
ng-show=
"group_members && group_members.length==0
&& !confirm_remove"
ng-click=
"confirm_remove=true"
value=
"Remove group"
/>
<div
ng-show=
"confirm_remove"
class=
"card"
>
<div
ng-show=
"confirm_remove"
class=
"card-body"
>
<span><
%=
l
'
Are
you
sure
you
want
to
remove
this
group
?'%
></span><br/>
<input
type=
"button"
class=
"btn btn-primary"
value=
"Yes"
ng-click=
"remove_group()"
/>
<input
type=
"button"
class=
"btn btn-danger"
value=
"No"
ng-click=
"confirm_remove=false"
/>
</div>
</div>
</div>
</div>
</div>
...
...
templates/main/machine_access_group.html.ep
View file @
8206cede
<i ng-show="!ldap_groups" class="fas fa-sync-alt fa-spin"></i>
<div class="card">
<div class="card-body">
<button ng-enabled="allow_group"
ng-click="add_group_access(allow_group)">Add</button>
<select ng-model="allow_group"
ng-show="ldap_groups"
ng-options="group for group in ldap_groups | orderBy:group"
>
</select>
<button ng-show="allow_group"
ng-click="add_group_access(allow_group)">Add</button>
<div class="alert alert-warning" ng-show="access_groups.length == 0">
<div ng-show="ldap_groups && !access_groups">
<i class="fas fa-sync-alt fa-spin"></i>
</div>
<div class="card-body">
<div class="alert alert-warning" ng-show="access_groups && access_groups.length == 0">
<div ng-show="ldap_groups && ldap_groups.length == 0 ">
<%=l 'There are no LDAP groups defined.' %>
% if ( $USER->is_admin ) {
<a href="/admin/groups">Create one.</a>
% }
</div>
<%=l 'This virtual machine has no group restrictions.' %>
</div>
<div ng-show="access_groups.length > 0">
<div ng-show="access_groups && access_groups.length > 0">
<b><%=l 'Only users from these groups will be allowed to execute this machine' %></b>
</div>
<table>
</thead
>
<table ng-show="access_groups.length" class="card-table table-stripped"
>
<tbody>
<tr ng-repeat="group in access_groups">
<td>
<button ng-click="remove_group_access(group)"
class="badge badge-light text-blue">x</button>
{{group}}
<a ng-bind-html="group" href="/admin/group/{{group}}">{{group}}</a>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
templates/main/manage_user.html.ep
View file @
8206cede
...
...
@@ -9,12 +9,30 @@
<div
class=
"card"
>
<div
class=
"card-header"
>
<h2><
%=
l
'
User
'
%
>
<
%=
$
user-
>
name %>
% if ( $user->external_auth ) {
(
<
%=
$
user-
>
external_auth %>)
% if ( $user->external_auth
|| $origin
) {
(
<
%=
(
$
user-
>
external_auth
or $origin)
%>)
% }
</h2>
% if ($user->external_auth
&&
$user->ldap_entry ) {
<
%=
$
user-
>
ldap_entry->dn %>
% }
</div>
<!-- del panel heading-->
</div>
% if (!$user->id) {
<div>
<
%=
l
'
This
user
has
never
logged
in
the
Ravada
server.
'
%
>
<br/>
<a
class=
"btn btn-outline-secondary"
href=
"/admin/groups"
>
Cancel
</a>
<a
class=
"btn btn-primary"
href=
"/admin/user/<%= $user->name %>.html?origin=<%= $origin %>&import=1"
>
Import
</a>
</div>
% }
% if ($warning) {
<div
class=
"alert alert-warning"
><
%=
$
warning
%
></div>
% }
% if ($user->id) {
<ul
class=
"nav nav-tabs"
id=
"myTab"
role=
"tablist"
>
% if ( $_user->is_admin ) {
<li
class=
"nav-item"
>
...
...
@@ -38,28 +56,29 @@
% }
</ul>
% if ( $_user->is_admin
&&
$user->is_external
&&
$user->external_auth eq 'ldap'
&&
!$user->ldap_entry ) {
% }
% if ($user->id
&&
$_user->is_admin
&&
$user->is_external
&&
$user->external_auth eq 'ldap'
&&
!$user->ldap_entry ) {
<div
class=
"alert alert-danger"
>
<
%=
l
'
Error:
the
LDAP
entry
for
this
user
has
been
removed.
'
%
>
</div>
% }
<div
class=
"tab-content"
id=
"myTabContent"
>
% if ( $_user->is_admin ) {
% if (
$user->id
&&
$_user->is_admin ) {
<div
class=
"tab-pane fade show active"
id=
"admin"
role=
"tabpanel"
aria-labelledby=
"admin-tab"
>
%= include '/main/manage_user_admin'
</div>
% }
% if ( $_user->can_grant) {
% if (
$user->id
&&
$_user->can_grant) {
<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)) {
% if (
$user->id
&&
( $_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>
% }
% if ( $_user->is_admin
&&
$user->is_external
&&
$user->external_auth eq 'ldap'
&&
$user->ldap_entry ) {
% if ( $_user->is_admin
&&
$user->id
&&
$user->is_external
&&
$user->external_auth eq 'ldap'
&&
$user->ldap_entry ) {
<div
class=
"tab-pane fade"
id=
"groups"
role=
"tabpanel"
aria-labelledby=
"group-tab"
>
%= include '/main/manage_user_groups'
</div>
...
...
templates/main/manage_user_groups.html.ep
View file @
8206cede
...
...
@@ -27,7 +27,7 @@
<button ng-click="remove_group_member( <%= $user->id %>,'<%= $user->ldap_entry->dn %>',group)"
ng-show="<%= $_user->can_manage_users %>"
class="badge badge-light text-blue">x</button>
{{group}}
<a ng-bind-html="group" href="/admin/group/{{group}}">{{group}}</a>
</td>
</tr>
</tbody>
...
...
Write
Preview