Table of users

Jens Pelzetter 2020-09-23 20:41:00 +02:00
parent f8a0079be7
commit defc184de5
12 changed files with 482 additions and 20 deletions

1
.gitignore vendored
View File

@ -11,3 +11,4 @@ target
.settings
.tscache
*.vscode
/ccm-core/nbproject/

View File

@ -20,7 +20,9 @@ package org.libreccm.ui.admin;
import org.libreccm.l10n.GlobalizationHelper;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.ResourceBundle;
import java.util.stream.Collectors;
@ -43,6 +45,11 @@ public class AdminPagesModel {
@Inject
private GlobalizationHelper globalizationHelper;
/**
* Cache for bundles
*/
private final Map<String, ResourceBundle> bundles = new HashMap<>();
public List<AdminPageModel> getAdminPages() {
return adminPages
.stream()
@ -56,13 +63,11 @@ public class AdminPagesModel {
}
private AdminPageModel buildAdminPageModel(final AdminPage fromAdminPage) {
final ResourceBundle labelBundle = ResourceBundle.getBundle(
fromAdminPage.getLabelBundle(),
globalizationHelper.getNegotiatedLocale()
final ResourceBundle labelBundle = getBundle(
fromAdminPage.getLabelBundle()
);
final ResourceBundle descriptionBundle = ResourceBundle.getBundle(
fromAdminPage.getDescriptionBundle(),
globalizationHelper.getNegotiatedLocale()
final ResourceBundle descriptionBundle = getBundle(
fromAdminPage.getDescriptionBundle()
);
final AdminPageModel model = new AdminPageModel();
@ -77,4 +82,17 @@ public class AdminPagesModel {
return model;
}
private ResourceBundle getBundle(final String bundleName) {
if (bundles.containsKey(bundleName)) {
return bundles.get(bundleName);
} else {
final ResourceBundle bundle = ResourceBundle.getBundle(
bundleName,
globalizationHelper.getNegotiatedLocale()
);
bundles.put(bundleName, bundle);
return bundle;
}
}
}

View File

@ -0,0 +1,90 @@
/*
* Copyright (C) 2020 LibreCCM Foundation.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
package org.libreccm.ui.admin.usersgroupsroles;
import org.libreccm.core.CoreConstants;
import org.libreccm.security.AuthorizationRequired;
import org.libreccm.security.GroupRepository;
import org.libreccm.security.RequiresPrivilege;
import org.libreccm.security.RoleRepository;
import org.libreccm.security.UserRepository;
import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import javax.inject.Named;
import javax.transaction.Transactional;
/**
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
@RequestScoped
@Named("UsersGroupsRolesOverviewModel")
public class OverviewModel {
@Inject
private GroupRepository groupRepository;
@Inject
private RoleRepository roleRepository;
@Inject
private UserRepository userRepository;
@AuthorizationRequired
@RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN)
@Transactional
public long getActiveUsersCount() {
return userRepository
.findAll()
.stream()
.filter(user -> !user.isBanned())
.count();
}
@AuthorizationRequired
@RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN)
@Transactional
public long getDisabledUsersCount() {
return userRepository
.findAll()
.stream()
.filter(user -> user.isBanned())
.count();
}
@AuthorizationRequired
@RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN)
@Transactional
public long getGroupsCount() {
return groupRepository
.findAll()
.size();
}
@AuthorizationRequired
@RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN)
@Transactional
public long getRolesCount() {
return roleRepository
.findAll()
.size();
}
}

View File

@ -23,9 +23,14 @@ import org.libreccm.security.AuthorizationRequired;
import org.libreccm.security.RequiresPrivilege;
import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import javax.mvc.Controller;
import javax.ws.rs.DefaultValue;
import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.QueryParam;
/**
*
@ -35,12 +40,43 @@ import javax.ws.rs.Path;
@Controller
@Path("/users-groups-roles")
public class UsersGroupsRolesController {
@Inject
private UsersTableModel usersTableModel;
@GET
@Path("/")
@AuthorizationRequired
@RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN)
public String getPlaceholder() {
return "org/libreccm/ui/admin/users-groups-roles.xhtml";
public String getOverview() {
return "org/libreccm/ui/admin/users-groups-roles/overview.xhtml";
}
@GET
@Path("/groups")
@AuthorizationRequired
@RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN)
public String getGroups() {
return "org/libreccm/ui/admin/users-groups-roles/groups.xhtml";
}
@GET
@Path("/roles")
@AuthorizationRequired
@RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN)
public String getRoles() {
return "org/libreccm/ui/admin/users-groups-roles/roles.xhtml";
}
@GET
@Path("/users")
@AuthorizationRequired
@RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN)
public String getUsers(
@QueryParam("filterterm") @DefaultValue("") final String filterTerm
) {
usersTableModel.setFilterTerm(filterTerm);
return "org/libreccm/ui/admin/users-groups-roles/users.xhtml";
}
}

View File

@ -0,0 +1,66 @@
/*
* Copyright (C) 2020 LibreCCM Foundation.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
package org.libreccm.ui.admin.usersgroupsroles;
import org.libreccm.core.CoreConstants;
import org.libreccm.security.AuthorizationRequired;
import org.libreccm.security.RequiresPrivilege;
import org.libreccm.security.User;
import org.libreccm.security.UserRepository;
import java.util.List;
import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import javax.inject.Named;
import javax.transaction.Transactional;
/**
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
@RequestScoped
@Named("UsersTableModel")
public class UsersTableModel {
@Inject
private UserRepository userRepository;
private String filterTerm;
public String getFilterTerm() {
return filterTerm;
}
protected void setFilterTerm(final String filterTerm) {
this.filterTerm = filterTerm;
}
@AuthorizationRequired
@RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN)
@Transactional
public List<User> getUsers() {
if (filterTerm == null || filterTerm.isEmpty()) {
return userRepository.findAllOrderdByUsername();
} else {
return userRepository.filtered(filterTerm);
}
}
}

View File

@ -5,19 +5,42 @@
xmlns:ui="http://xmlns.jcp.org/jsf/facelets">
<ui:composition template="/WEB-INF/views/org/libreccm/ui/admin/ccm-admin.xhtml">
<ui:param name="activePage" value="usersgroupsroles" />
<ui:param name="title" value="#{AdminMessages['usersgroupsroles.label']}" />
<ui:define name="breadcrumb">
<li class="breadcrumb-item active">
#{AdminMessages['usersgroupsroles.label']}
</li>
</ui:define>
<!-- <ui:param name="activePage" value="usersgroupsroles" />
<ui:param name="title" value="#{AdminMessages['usersgroupsroles.label']}" />
<ui:define name="breadcrumb">
<li class="breadcrumb-item active">
#{AdminMessages['usersgroupsroles.label']}
</li>
</ui:define>-->
<ui:define name="main">
<div class="container">
<h1>#{AdminMessages['usersgroupsroles.label']}</h1>
<p>Placeholder</p>
<div class="container-fluid mx-1">
<div class="row">
<nav class="col-md-2 list-group">
<a class="list-group-item list-group-item-action #{activePanel == 'overview' ? 'active' : ''}"
href="#{request.contextPath}/@admin/users-groups-roles">
#{AdminMessages['usersgroupsroles.overview.label']}
</a>
<a class="list-group-item list-group-item-action #{activePanel == 'users' ? 'active' : ''}"
href="#{request.contextPath}/@admin/users-groups-roles/users">
#{AdminMessages['usersgroupsroles.users.label']}
</a>
<a class="list-group-item list-group-item-action #{activePanel == 'groups' ? 'active' : ''}"
href="#{request.contextPath}/@admin/users-groups-roles/groups">
#{AdminMessages['usersgroupsroles.groups.label']}
</a>
<a class="list-group-item list-group-item-action #{activePanel == 'roles' ? 'active' : ''}"
href="#{request.contextPath}/@admin/users-groups-roles/roles">
#{AdminMessages['usersgroupsroles.roles.label']}
</a>
</nav>
<div class="col-md-10">
<h1>#{title}</h1>
<ui:insert name="panel"></ui:insert>
</div>
</div>
</div>
</ui:define>

View File

@ -0,0 +1,26 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:c="http://xmlns.jcp.org/jsp/jstl/core"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets">
<ui:composition template="/WEB-INF/views/org/libreccm/ui/admin/users-groups-roles.xhtml">
<ui:param name="activePage" value="usersgroupsroles" />
<ui:param name="activePanel" value="groups" />
<ui:param name="title"
value="#{AdminMessages['usersgroupsroles.groups.label']}" />
<ui:define name="breadcrumb">
<li class="breadcrumb-item">
<a href="#{request.contextPath}/@admin/users-groups-roles/">#{AdminMessages['usersgroupsroles.label']}</a>
</li>
<li class="breadcrumb-item active">
#{AdminMessages['usersgroupsroles.groups.label']}
</li>
</ui:define>
<ui:define name="panel">
<p>Groups placeholder</p>
</ui:define>
</ui:composition>
</html>

View File

@ -0,0 +1,24 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:c="http://xmlns.jcp.org/jsp/jstl/core"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets">
<ui:composition template="/WEB-INF/views/org/libreccm/ui/admin/users-groups-roles.xhtml">
<ui:param name="activePage" value="usersgroupsroles" />
<ui:param name="activePanel" value="overview" />
<ui:param name="title" value="#{AdminMessages['usersgroupsroles.label']}" />
<ui:define name="breadcrumb">
<li class="breadcrumb-item active">
#{AdminMessages['usersgroupsroles.label']}
</li>
</ui:define>
<ui:define name="panel">
<p>#{UsersGroupsRolesOverviewModel.activeUsersCount} #{AdminMessages['usersgroupsroles.active_users_count.label']}</p>
<p>#{UsersGroupsRolesOverviewModel.disabledUsersCount} #{AdminMessages['usersgroupsroles.disabled_users_count.label']}</p>
<p>#{UsersGroupsRolesOverviewModel.groupsCount} #{AdminMessages['usersgroupsroles.groups_count.label']}</p>
<p>#{UsersGroupsRolesOverviewModel.rolesCount} #{AdminMessages['usersgroupsroles.roles_count.label']}</p>
</ui:define>
</ui:composition>
</html>

View File

@ -0,0 +1,26 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:c="http://xmlns.jcp.org/jsp/jstl/core"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets">
<ui:composition template="/WEB-INF/views/org/libreccm/ui/admin/users-groups-roles.xhtml">
<ui:param name="activePage" value="usersgroupsroles" />
<ui:param name="activePanel" value="roles" />
<ui:param name="title"
value="#{AdminMessages['usersgroupsroles.roles.label']}" />
<ui:define name="breadcrumb">
<li class="breadcrumb-item">
<a href="#{request.contextPath}/@admin/users-groups-roles/">#{AdminMessages['usersgroupsroles.label']}</a>
</li>
<li class="breadcrumb-item active">
#{AdminMessages['usersgroupsroles.roles.label']}
</li>
</ui:define>
<ui:define name="panel">
<p>Roles placeholder</p>
</ui:define>
</ui:composition>
</html>

View File

@ -0,0 +1,110 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:c="http://xmlns.jcp.org/jsp/jstl/core"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
xmlns:xlink="http://www.w3.org/1999/xlink">
<ui:composition template="/WEB-INF/views/org/libreccm/ui/admin/users-groups-roles.xhtml">
<ui:param name="activePage" value="usersgroupsroles" />
<ui:param name="activePanel" value="users" />
<ui:param name="title"
value="#{AdminMessages['usersgroupsroles.users.label']}" />
<ui:define name="breadcrumb">
<li class="breadcrumb-item">
<a href="#{request.contextPath}/@admin/users-groups-roles/">#{AdminMessages['usersgroupsroles.label']}</a>
</li>
<li class="breadcrumb-item active">
#{AdminMessages['usersgroupsroles.users.label']}
</li>
</ui:define>
<ui:define name="panel">
<div class="row mb-2">
<div class="col-sm-9">
<form action="#{request.contextPath}/@admin/users-groups-roles/users"
class="form-inline"
method="get">
<div class="form-group">
<label class="mr-2" for="filter-term">
#{AdminMessages['usersgroupsroles.users.filter.label']}
</label>
<input class="form-control"
id="filter-term"
name="filterterm"
type="text"
value="#{UsersTableModel.filterTerm}"/>
</div>
<button class="btn btn-secondary ml-1" type="submit">
#{AdminMessages['usersgroupsroles.users.filter.submit']}
</button>
</form>
</div>
<div class="col-sm-3 text-right">
<a class="btn btn-secondary" href="#">
<svg class="bi"
width="1em"
height="1em"
fill="currentColor">
<use xlink:href="#{request.contextPath}/assets/bootstrap/bootstrap-icons.svg#person-plus" />
</svg>
<span>#{AdminMessages['usersgroupsroles.users.add']}</span>
</a>
</div>
</div>
<table class="table table-hover users-table">
<thead class="thead-light">
<tr>
<th>#{AdminMessages['usersgroupsroles.users.table.headers.username']}</th>
<th>#{AdminMessages['usersgroupsroles.users.table.headers.givenname']}</th>
<th>#{AdminMessages['usersgroupsroles.users.table.headers.familyname']}</th>
<th>#{AdminMessages['usersgroupsroles.users.table.headers.email']}</th>
<th class="text-center">#{AdminMessages['usersgroupsroles.users.table.headers.disabled']}</th>
<th class="text-center" colspan="2">#{AdminMessages['usersgroupsroles.users.table.headers.actions']}</th>
</tr>
</thead>
<tbody>
<c:forEach items="#{UsersTableModel.users}" var="user">
<tr>
<td>#{user.name}</td>
<td>#{user.givenName}</td>
<td>#{user.familyName}</td>
<td>
#{user.primaryEmailAddress.address}
</td>
<td class="text-center">
#{user.banned ? AdminMessages['usersgroupsroles.users.table.headers.disabled.true'] : AdminMessages['usersgroupsroles.users.table.headers.disabled.false']}
</td>
<td class="text-center action-col">
<a class="btn btn-info" href="#">
<svg class="bi"
width="1em"
height="1em"
fill="currentColor">
<use xlink:href="#{request.contextPath}/assets/bootstrap/bootstrap-icons.svg#eye" />
</svg>
<span>#{AdminMessages['usersgroupsroles.users.detailslink.label']}
</span>
</a>
</td>
<td class="text-center action-col">
<button class="btn btn-danger">
<svg class="bi"
width="1em"
height="1em"
fill="currentColor">
<use xlink:href="#{request.contextPath}/assets/bootstrap/bootstrap-icons.svg#person-x" />
</svg>
<span>
#{AdminMessages['usersgroupsroles.users.disablebutton.label']}
</span>
</button>
</td>
</tr>
</c:forEach>
</tbody>
</table>
</ui:define>
</ui:composition>
</html>

View File

@ -17,3 +17,24 @@ usersgroupsroles.description=Manage users, groups and roles
systeminformation.tabs.libreccm.label=LibreCCM System Information
systeminformation.tabs.java.label=Java System Properties
breadcrumbs.start=LibreCCM Admin
usersgroupsroles.users.label=Users
usersgroupsroles.groups.label=Groups
usersgroupsroles.roles.label=Roles
usersgroupsroles.overview.label=Overview
usersgroupsroles.active_users_count.label=active users
usersgroupsroles.disabled_users_count.label=disabled users
usersgroupsroles.groups_count.label=groups
usersgroupsroles.roles_count.label=roles
usersgroupsroles.users.table.headers.username=User Name
usersgroupsroles.users.table.headers.givenname=Given Name
usersgroupsroles.users.table.headers.familyname=Family Name
usersgroupsroles.users.table.headers.email=Email
usersgroupsroles.users.table.headers.disabled=Disabled?
usersgroupsroles.users.table.headers.actions=Actions
usersgroupsroles.users.table.headers.disabled.true=Yes
usersgroupsroles.users.table.headers.disabled.false=No
usersgroupsroles.users.detailslink.label=Details
usersgroupsroles.users.disablebutton.label=Disable
usersgroupsroles.users.add=Add user
usersgroupsroles.users.filter.label=Filter users
usersgroupsroles.users.filter.submit=Submit

View File

@ -17,3 +17,24 @@ usersgroupsroles.description=Verwaltungen von Benutzer*innen, Gruppen und Rollen
systeminformation.tabs.libreccm.label=LibreCCM System Informationen
systeminformation.tabs.java.label=Java System Properties
breadcrumbs.start=LibreCCM Admin
usersgroupsroles.users.label=Benutzer*innen
usersgroupsroles.groups.label=Gruppen
usersgroupsroles.roles.label=Rollen
usersgroupsroles.overview.label=\u00dcberblick
usersgroupsroles.active_users_count.label=aktive Benutzer*innen
usersgroupsroles.disabled_users_count.label=inaktive Benutzer*innen
usersgroupsroles.groups_count.label=Gruppen
usersgroupsroles.roles_count.label=Rollen
usersgroupsroles.users.table.headers.username=Benutzername
usersgroupsroles.users.table.headers.givenname=Vorname
usersgroupsroles.users.table.headers.familyname=Familienname
usersgroupsroles.users.table.headers.email=E-Mail
usersgroupsroles.users.table.headers.disabled=Inaktiv?
usersgroupsroles.users.table.headers.actions=Aktionen
usersgroupsroles.users.table.headers.disabled.true=Ja
usersgroupsroles.users.table.headers.disabled.false=Nein
usersgroupsroles.users.detailslink.label=Details
usersgroupsroles.users.disablebutton.label=Sperren
usersgroupsroles.users.add=Benutzer*in hinzuf\u00fcgen
usersgroupsroles.users.filter.label=Benutzer*innen filtern
usersgroupsroles.users.filter.submit=Anwenden