Skip to content

Commit

Permalink
Merge pull request #3906 from rundeck/dev/user-list-menu
Browse files Browse the repository at this point in the history
Users summary page
  • Loading branch information
gschueler authored Aug 30, 2018
2 parents 3e91004 + 4267792 commit f120d33
Show file tree
Hide file tree
Showing 14 changed files with 405 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ import org.rundeck.util.Sizes
import org.springframework.context.ApplicationContext
import org.springframework.context.ApplicationContextAware
import org.springframework.web.multipart.MultipartHttpServletRequest
import rundeck.AuthToken
import rundeck.Execution
import rundeck.LogFileStorageRequest
import rundeck.Project
Expand Down Expand Up @@ -3075,5 +3076,33 @@ class MenuController extends ControllerBase implements ApplicationContextAware{
}
return redirect(controller:'menu',action:'jobs', params: [project: params.project])
}

def userSummary(){
AuthContext authContext = frameworkService.getAuthContextForSubject(session.subject)
if(unauthorizedResponse(frameworkService.authorizeApplicationResourceType(authContext, AuthConstants.TYPE_USER,
AuthConstants.ACTION_ADMIN),
AuthConstants.ACTION_ADMIN, 'User', 'accounts')) {
return
}
def userList = [:]
User.listOrderByLogin().each {
def obj = [:]
obj.login = it.login
obj.firstName = it.firstName
obj.lastName = it.lastName
obj.email = it.email
obj.created = it.dateCreated
obj.updated = it.lastUpdated
def lastExec = Execution.lastExecutionByUser(it.login).list()
if(lastExec?.size()>0){
obj.lastJob = lastExec.get(0).dateStarted
}
def tokenList = AuthToken.findAllByUser(it)
obj.tokens = tokenList?.size()
userList.put(it.login,obj)
}

[users:userList]
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import grails.converters.JSON
import grails.core.GrailsApplication
import org.rundeck.util.Sizes
import rundeck.AuthToken
import rundeck.Execution
import rundeck.User
import com.dtolabs.rundeck.app.api.ApiVersions
import rundeck.services.FrameworkService
Expand Down Expand Up @@ -307,8 +308,31 @@ class UserController extends ControllerBase{
}
return
}
def users = []
if(request.api_version >= ApiVersions.V27){
def userList = [:]
User.listOrderByLogin().each {
def obj = [:]
obj.login = it.login
obj.firstName = it.firstName
obj.lastName = it.lastName
obj.email = it.email
obj.created = it.dateCreated
obj.updated = it.lastUpdated
def lastExec = Execution.lastExecutionByUser(it.login).list()
if(lastExec?.size()>0){
obj.lastJob = lastExec.get(0).dateStarted
}
def tokenList = AuthToken.findAllByUser(it)
obj.tokens = tokenList?.size()
userList.put(it.login,obj)
}
userList.each{k,v -> users<<v}
}else{
users = User.findAll()
}


def users = User.findAll()
withFormat {
def xmlClosure = {
users.each { u ->
Expand All @@ -317,6 +341,12 @@ class UserController extends ControllerBase{
firstName(u.firstName)
lastName(u.lastName)
email(u.email)
if(request.api_version >= ApiVersions.V27){
created(u.created)
updated(u.updated)
lastJob(u.lastJob)
tokens(u.tokens)
}
}
}
}
Expand All @@ -326,7 +356,12 @@ class UserController extends ControllerBase{
json {
return apiService.renderSuccessJson(response) {
users.each {
def u = [login: it.login, firstName: it.firstName, lastName: it.lastName, email: it.email]
def u
if(request.api_version >= ApiVersions.V27){
u = it
}else{
u = [login: it.login, firstName: it.firstName, lastName: it.lastName, email: it.email]
}
element(u)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ class ControllerBaseInterceptor {
"menu/plugins",
"menu/welcome",
"menu/storage",
"menu/summary",
"scheduledExecution/show",
"scheduledExecution/edit",
"scheduledExecution/delete",
Expand Down
5 changes: 5 additions & 0 deletions rundeckapp/grails-app/domain/rundeck/Execution.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,11 @@ class Execution extends ExecutionContext {
withProject{ project ->
eq 'project', project
}
lastExecutionByUser{ user ->
eq 'user', user
maxResults 1
order 'dateStarted', 'desc'
}
}


Expand Down
12 changes: 11 additions & 1 deletion rundeckapp/grails-app/i18n/messages.properties
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ gui.menu.Admin=Configure
gui.menu.ProjectSettings=Project Settings
gui.menu.Projects=Projects
gui.menu.PasswordUtility=Password Utility
gui.menu.Users=User Summary

# login form text
gui.login.welcome=
Expand Down Expand Up @@ -1662,4 +1663,13 @@ menu.logStorage.stats.queuedRequestCount.label.prompt=Requests:
menu.logStorage.stats.queuedRetriesCount.label.prompt=Retries:
menu.logStorage.stats.queuedIncompleteCount.label.prompt=Incomplete:
menu.logStorage.stats.retriesCount.label.prompt=Retried:
options.label=Options
options.label=Options

page.users.title=Users
page.users.summary=List of Rundeck users.
page.users.login.label=Login
page.users.created.label=Created
page.users.updated.label=Updated
page.users.lastjob.label=Last Job execution
page.users.tokens.label=N\u00BA Tokens
page.users.tokens.help=You can administrate the tokens in the User Profile page.
11 changes: 10 additions & 1 deletion rundeckapp/grails-app/i18n/messages_es_419.properties
Original file line number Diff line number Diff line change
Expand Up @@ -1644,4 +1644,13 @@ menu.logStorage.stats.queuedRequestCount.label.prompt=Requests:
menu.logStorage.stats.queuedRetriesCount.label.prompt=Retries:
menu.logStorage.stats.queuedIncompleteCount.label.prompt=Incomplete:
menu.logStorage.stats.retriesCount.label.prompt=Retried:
options.label=Options
options.label=Options

page.users.title=Usuarios
page.users.summary=Lista de usuarios de Rundeck..
page.users.login.label=Login
page.users.created.label=Creado
page.users.updated.label=Actualizado
page.users.lastjob.label=Ultima ejecucion de un trabajo
page.users.tokens.label=N\u00BA Token
page.users.tokens.help=Puedes administrar los token en la página del Perfil de Usuario.
11 changes: 10 additions & 1 deletion rundeckapp/grails-app/i18n/messages_fr_FR.properties
Original file line number Diff line number Diff line change
Expand Up @@ -1647,4 +1647,13 @@ menu.logStorage.stats.queuedRequestCount.label.prompt=Requests:
menu.logStorage.stats.queuedRetriesCount.label.prompt=Retries:
menu.logStorage.stats.queuedIncompleteCount.label.prompt=Incomplete:
menu.logStorage.stats.retriesCount.label.prompt=Retried:
options.label=Options
options.label=Options

page.users.title=Users
page.users.summary=List of Rundeck users.
page.users.login.label=Login
page.users.created.label=Created
page.users.updated.label=Updated
page.users.lastjob.label=Last Job execution
page.users.tokens.label=N\u00BA Tokens
page.users.tokens.help=You can administrate the tokens in the User Profile page.
12 changes: 11 additions & 1 deletion rundeckapp/grails-app/i18n/messages_zh_cn.properties
Original file line number Diff line number Diff line change
Expand Up @@ -1646,4 +1646,14 @@ menu.logStorage.stats.queuedRequestCount.label.prompt=Requests:
menu.logStorage.stats.queuedRetriesCount.label.prompt=Retries:
menu.logStorage.stats.queuedIncompleteCount.label.prompt=Incomplete:
menu.logStorage.stats.retriesCount.label.prompt=Retried:
options.label=Options
options.label=Options


page.users.title=Users
page.users.summary=List of Rundeck users.
page.users.login.label=Login
page.users.created.label=Created
page.users.updated.label=Updated
page.users.lastjob.label=Last Job execution
page.users.tokens.label=N\u00BA Tokens
page.users.tokens.help=You can administrate the tokens in the User Profile page.
13 changes: 13 additions & 0 deletions rundeckapp/grails-app/views/menu/_sysConfigNavMenu.gsp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@
context: 'application'
)}"/>

<g:set var="authAdmin" value="${auth.resourceAllowedTest(
kind: 'user',
action: [AuthConstants.ACTION_ADMIN],
context: 'application'
)}"/>

<ul class="dropdown-menu">
<li class="dropdown-header">System</li>
<li>
Expand Down Expand Up @@ -63,5 +69,12 @@
<g:message code="gui.menu.PasswordUtility"/>
</g:link>
</li>
<g:if test="${authAdmin}">
<li>
<g:link controller="menu" action="userSummary">
<g:message code="gui.menu.Users"/>
</g:link>
</li>
</g:if>
<g:render template="/menu/sysConfigExecutionModeNavMenu"/>
</ul>
136 changes: 136 additions & 0 deletions rundeckapp/grails-app/views/menu/userSummary.gsp
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
%{--
- Copyright 2018 Rundeck, Inc. (http://rundeck.com)
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--}%
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<meta name="layout" content="base"/>
<meta name="tabpage" content="configure"/>
<meta name="tabtitle" content="${g.message(code:'page.users.title')}"/>
<title><g:message code="page.users.title"/></title>
</head>

<body>
<div class="container-fluid">
<div class="row">
<div class="col-xs-12">
<div class="card">
<g:render template="/common/messages"/>
</div>
</div>
<div class="col-sm-12">
<div class="card">
<div class="card-content">
<div class="help-block">
<g:message code="page.users.summary"/>
</div>
<div class="pageBody" id="userProfilePage">
<div class="row">
<div class="col-sm-12">
<table class="table table-condensed table-striped">
<tr>
<th class="table-header">
<g:message code="page.users.login.label"/>
</th>
<th class="table-header">
<g:message code="domain.User.email.label"/>
</th>
<th class="table-header">
<g:message code="domain.User.firstName.label"/>
</th>
<th class="table-header">
<g:message code="domain.User.lastName.label"/>
</th>

<th class="table-header">
<g:message code="page.users.created.label"/>
</th>
<th class="table-header">
<g:message code="page.users.updated.label"/>
</th>
<th class="table-header">
<g:message code="page.users.lastjob.label"/>
</th>
<th class="table-header">
<g:message code="page.users.tokens.label"/>
<g:helpTooltip code="page.users.tokens.help" css="text-primary"/>
</th>

</tr>
<g:each in="${users}" var="user" status="index">
<tr>
<td>
${user.value.login}
</td>
<td>
${user.value.email}
<g:if test="${!user.value.email}">
<span class="text-primary small text-uppercase"><g:message code="not.set" /></span>
</g:if>
</td>
<td>
<g:enc>${user.value.firstName}</g:enc>
<g:if test="${!user.value.firstName}">
<span class="text-primary small text-uppercase"><g:message code="not.set" /></span>
</g:if>
</td>
<td>
<g:enc>${user.value.lastName}</g:enc>

<g:if test="${!user.value.lastName}">
<span class="text-primary small text-uppercase"><g:message code="not.set" /></span>
</g:if>
</td>

<td>
<g:formatDate date="${user.value.created}" format="MM/dd/yyyy hh:mm a"/>
</td>
<td>
<g:formatDate date="${user.value.updated}" format="MM/dd/yyyy hh:mm a"/>
</td>
<td>
<g:if test="${user.value.lastJob}">
<g:formatDate date="${user.value.lastJob}" format="MM/dd/yyyy hh:mm a"/>
</g:if>
<g:else>
<span class="text-primary small text-uppercase"><g:message code="none" /></span>
</g:else>
</td>
<td>

<g:if test="${user.value.tokens}">
<g:enc>${user.value.tokens}</g:enc>
</g:if>
<g:else>
<span class="text-primary small text-uppercase"><g:message code="none" /></span>
</g:else>
</td>
</tr>
</g:each>
</table>
</div>

</div>

</div>
</div>
</div>
</div>
</div>
</div>
</body>
</html>


Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,17 @@ class ApiVersions {
public static final int V24 = 24
public static final int V25 = 25
public static final int V26 = 26
public static final int V27 = 27
public static final Map VersionMap = [:]
public static final List Versions = [V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, V14, V15, V16, V17, V18, V19, V20, V21, V22, V23, V24, V25, V26]
public static final List Versions = [V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, V14, V15, V16, V17, V18,
V19, V20, V21, V22, V23, V24, V25, V26, V27]
static {
Versions.each { VersionMap[it.toString()] = it }
}
public static final Set VersionStrings = new HashSet(VersionMap.values())

public final static int API_EARLIEST_VERSION = V1
public final static int API_CURRENT_VERSION = V26
public final static int API_CURRENT_VERSION = V27
public final static int API_MIN_VERSION = API_EARLIEST_VERSION
public final static int API_MAX_VERSION = API_CURRENT_VERSION
}
Loading

0 comments on commit f120d33

Please sign in to comment.