Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: adds users with admin privileges to home screen #1520

Merged
merged 1 commit into from
Feb 10, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions api/launchers/stig-manager.bat
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,16 @@
::==============================================================================
:: set STIGMAN_CLIENT_DISABLED=

::==============================================================================
:: STIGMAN_CLIENT_DISPLAY_APPMANAGERS
::
:: | Default: "true" | Set to "false" to hide application manager names
:: along with their email addresses on the Stig-Manager home page.
::
:: Affects: Client
::==============================================================================
:: set STIGMAN_CLIENT_DISPLAY_APPMANAGERS=

::==============================================================================
:: STIGMAN_CLIENT_EXTRA_SCOPES
::
Expand Down
10 changes: 10 additions & 0 deletions api/launchers/stig-manager.sh
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,16 @@
#==============================================================================
# export STIGMAN_CLIENT_DISABLED=

#==============================================================================
# STIGMAN_CLIENT_DISPLAY_APPMANAGERS
#
# | Default: "true" | Set to "false" to hide application manager names
# along with their email addresses on the Stig-Manager home page.
#
# Affects: Client
#==============================================================================
# set STIGMAN_CLIENT_DISPLAY_APPMANAGERS=

#==============================================================================
# STIGMAN_CLIENT_EXTRA_SCOPES
#
Expand Down
3 changes: 2 additions & 1 deletion api/source/controllers/User.js
Original file line number Diff line number Diff line change
Expand Up @@ -120,11 +120,12 @@ module.exports.getUsers = async function getUsers (req, res, next) {
let elevate = req.query.elevate
let username = req.query.username
let usernameMatch = req.query['username-match']
let privilege = req.query['privilege']
let projection = req.query.projection
if ( !elevate && projection?.length > 0) {
throw new SmError.PrivilegeError()
}
let response = await UserService.getUsers( username, usernameMatch, projection, elevate, req.userObject)
let response = await UserService.getUsers( username, usernameMatch, privilege, projection, elevate, req.userObject)
res.json(response)
}
catch(err) {
Expand Down
1 change: 1 addition & 0 deletions api/source/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,7 @@ const STIGMAN = {
Env: {
version: "${config.version}",
apiBase: "${config.client.apiBase}",
displayAppManagers: ${config.client.displayAppManagers},
welcome: {
image: "${config.client.welcome.image}",
title: "${config.client.welcome.title.replace(/"/g, '\\"')}",
Expand Down
14 changes: 12 additions & 2 deletions api/source/service/UserService.js
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,15 @@ exports.queryUsers = async function (inProjection, inPredicates, elevate, userOb
predicates.statements.push(`ud.username ${matchStr}`)
predicates.binds.push(inPredicates.username)
}

if (inPredicates.privilege) {
predicates.statements.push(
`JSON_CONTAINS(JSON_EXTRACT(ud.lastClaims, ?), ?) `
)
predicates.binds.push(`$.${config.oauth.claims.privileges}`, JSON.stringify([inPredicates.privilege]))
}


if (needsCollectionGrantees) {
ctes.push(dbUtils.sqlGrantees({userId: inPredicates.userId, username: inPredicates.username, returnCte: true}))
}
Expand Down Expand Up @@ -293,11 +302,12 @@ exports.getUserByUsername = async function(username, projection, elevate, userOb
}
}

exports.getUsers = async function(username, usernameMatch, projection, elevate, userObject) {
exports.getUsers = async function(username, usernameMatch, privilege, projection, elevate, userObject) {
try {
let rows = await _this.queryUsers( projection, {
username: username,
usernameMatch: usernameMatch
usernameMatch: usernameMatch,
privilege: privilege
}, elevate, userObject)
return (rows)
}
Expand Down
10 changes: 10 additions & 0 deletions api/source/specification/stig-manager.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3855,6 +3855,7 @@ paths:
operationId: getUsers
parameters:
- $ref: '#/components/parameters/UsernameQuery'
- $ref: '#/components/parameters/PrivilegeQuery'
- $ref: '#/components/parameters/UsernameMatchQuery'
responses:
'200':
Expand Down Expand Up @@ -8381,6 +8382,15 @@ components:
- EMASS
- MCCAST
default: EMASS
PrivilegeQuery:
name: privilege
in: query
description: Selects Users with the specified privilege
schema:
type: string
enum:
- admin
- create_collection
RetentionDateQuery:
name: retentionDate
in: query
Expand Down
1 change: 1 addition & 0 deletions api/source/utils/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ const config = {
},
client: {
clientId: process.env.STIGMAN_CLIENT_ID || "stig-manager",
displayAppManagers: process.env.STIGMAN_CLIENT_DISPLAY_APPMANAGERS || "true",
authority: process.env.STIGMAN_CLIENT_OIDC_PROVIDER || process.env.STIGMAN_OIDC_PROVIDER || "http://localhost:8080/realms/stigman",
apiBase: process.env.STIGMAN_CLIENT_API_BASE || "api",
disabled: process.env.STIGMAN_CLIENT_DISABLED === "true",
Expand Down
3 changes: 3 additions & 0 deletions api/source/utils/log-schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,9 @@
"clientId": {
"type": "string"
},
"displayAppManagers": {
"type": "boolean"
},
"authority": {
"type": "string"
},
Expand Down
1 change: 1 addition & 0 deletions client/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ uglifyjs \
'SM/Global.js' \
'SM/StackTrace.js' \
'SM/Error.js' \
'SM/FlexboxLayout.js' \
'BufferView.js' \
'SM/EventDispatcher.js' \
'SM/Cache.js' \
Expand Down
4 changes: 4 additions & 0 deletions client/src/css/dark-mode.css
Original file line number Diff line number Diff line change
Expand Up @@ -2369,6 +2369,10 @@ td.sort-asc, td.sort-desc, td.x-grid3-hd-menu-open, td.x-grid3-hd-over {
background-color: #2b2e30
}

.sm-user-list {
background-color: #2b2e30;
}

.sm-home-widget-header {
background-color: #313537
}
Expand Down
60 changes: 59 additions & 1 deletion client/src/css/stigman.css
Original file line number Diff line number Diff line change
Expand Up @@ -1110,11 +1110,59 @@ td.x-grid3-hd-over .x-grid3-hd-inner {
border: none;
margin: 10px;
height: 400px;
width: 380px
width: 380px;
}

.sm-scroll-home-widget-body {
max-height: 340px;
overflow: auto;
scrollbar-width: thin;
margin-right: 8px;
margin-top: 5px;
}

.sm-user-list {
list-style: none;
max-height: 340px;
padding : 0;
margin-left: 0;

}

.sm-user-item {
padding: 3px;
display: flex;
align-items: left;
}

.sm-user-item::before {
content: "• ";
font-size: 16px;
color: #dedede;
margin-right: 3px;
}

.sm-user-details {
display: flex;
flex-direction: column;
font-size: 13px;
}

.sm-user-name {
font-size: 13px;
font-weight: bold;
}

.sm-user-email {
font-size: 11px;
font-style: italic;
}


.sm-home-widget-header {
background-color: #d3d3d3
}

.sm-home-widget-title {
padding: 10px 20px;
font: bold 18px Open Sans,helvetica,sans-serif;
Expand Down Expand Up @@ -2395,3 +2443,13 @@ td.x-grid3-hd-over .x-grid3-hd-inner {
.sm-checklist-read {
background-color: hsl(330 55% 24% / 1);
}
.sm-flexbox-layout-ct {
display: flex;
flex-wrap: wrap;
overflow: auto;
scrollbar-width: none;
align-content: flex-start;
}
.sm-flexbox-layout-ct:hover {
scrollbar-width: auto;
}
13 changes: 13 additions & 0 deletions client/src/js/SM/FlexboxLayout.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
SM.FlexboxLayout = Ext.extend(Ext.layout.ContainerLayout, {
onLayout : function(ct, target){
target.addClass('sm-flexbox-layout-ct');
this.renderAll(ct, target);
},
renderItem : function(c, position, target){
if(c && !c.rendered){
c.render(target);
this.configureItem(c);
}
}
})
Ext.Container.LAYOUTS['sm-flexbox'] = SM.FlexboxLayout
90 changes: 79 additions & 11 deletions client/src/js/SM/MainPanel.js
Original file line number Diff line number Diff line change
Expand Up @@ -90,18 +90,22 @@ SM.WelcomeWidget = Ext.extend(Ext.Panel, {
`<div class=sm-home-widget-header>`,
`<div class='sm-home-widget-title'>Welcome</div>`,
`</div>`,
`<div class='sm-home-widget-text'>`,
`<div class=sm-home-widget-image-text-wrap>`,
`<img src=${STIGMAN.Env.welcome.image ? `"${STIGMAN.Env.welcome.image}" onerror="this.onerror=null;this.src='img/navy.svg';"` : '"img/navy.svg"'} style="max-width:100%;max-height:100%;"/>`,
`</div>`,
`<b>STIG Manager</b> is an API and Web client for managing the assessment of Information Systems for compliance with <a href="https://public.cyber.mil/stigs/">security checklists</a> published by the United States Defense Information Systems Agency (DISA). The software is <a target="_blank" href="https://github.com/NUWCDIVNPT/stig-manager">an open source project</a> maintained by the Naval Sea Systems Command (NAVSEA) of the United States Navy.`,
`</div>`,
`<div class='sm-home-widget-text'>`,
`<div class='sm-home-widget-subtitle'>${STIGMAN.Env.welcome.title ? SM.he(STIGMAN.Env.welcome.title) : STIGMAN.Env.welcome.message || STIGMAN.Env.welcome.link ? 'Support' : ''}</div>`,
`${SM.he(STIGMAN.Env.welcome.message)}${STIGMAN.Env.welcome.message && STIGMAN.Env.welcome.link ? '<br><br>' : ''}`,
`${STIGMAN.Env.welcome.link ? '<a href="' + STIGMAN.Env.welcome.link + '">' + STIGMAN.Env.welcome.link + '</a>': ''}`,
`</div>`
`<div class="sm-scroll-home-widget-body">`,
`<div class='sm-home-widget-text'>`,
`<div class=sm-home-widget-image-text-wrap>`,
`<img src=${STIGMAN.Env.welcome.image ? `"${STIGMAN.Env.welcome.image}" onerror="this.onerror=null;this.src='img/navy.svg';"` : '"img/navy.svg"'} style="max-width:100%;max-height:100%;"/>`,
`</div>`,
`<b>STIG Manager</b> is an API and Web client for managing the assessment of Information Systems for compliance with <a href="https://public.cyber.mil/stigs/">security checklists</a> published by the United States Defense Information Systems Agency (DISA). The software is <a target="_blank" href="https://github.com/NUWCDIVNPT/stig-manager">an open source project</a> maintained by the Naval Sea Systems Command (NAVSEA) of the United States Navy.`,
`</div>`,

`<div class='sm-home-widget-text'>`,
`<div class='sm-home-widget-subtitle'>
${STIGMAN.Env.welcome.title ? SM.he(STIGMAN.Env.welcome.title) : STIGMAN.Env.welcome.message || STIGMAN.Env.welcome.link ? 'Support' : ''}
</div>`,
`${SM.he(STIGMAN.Env.welcome.message)}${STIGMAN.Env.welcome.message && STIGMAN.Env.welcome.link ? '<br><br>' : ''}`,
`${STIGMAN.Env.welcome.link ? '<a href="' + STIGMAN.Env.welcome.link + '">' + STIGMAN.Env.welcome.link + '</a>': ''}`,
`</div>`,
`</div>`,
)
const config = {
tpl: tpl,
Expand Down Expand Up @@ -200,6 +204,70 @@ SM.ResourcesWidget = Ext.extend(Ext.Panel, {
})
Ext.reg('sm-home-widget-resources', SM.ResourcesWidget)

SM.ApplicationManagers = Ext.extend(Ext.Panel, {
initComponent: function() {
const me = this
me.userListId = Ext.id()

const tpl = new Ext.XTemplate(
`<div class="sm-home-widget-header">`,
`<div class="sm-home-widget-title">
Application Managers
</div>`,
`</div>`,
`<div class="sm-scroll-home-widget-body">`,
`<div class="sm-home-widget-text">`,
`<div id="${me.userListId}" class="sm-user-list">
</div>`,
`</div>`,
`</div>`

)
const config = {
tpl: tpl,
bodyCssClass: 'sm-home-widget-body',
border: false,
data: {},
autoScroll: false
}
Ext.apply(this, Ext.apply(this.initialConfig, config))
SM.ApplicationManagers.superclass.initComponent.call(this)
this.on('afterrender', this.loadApplicationManagers, this)
},
loadApplicationManagers: async function () {
const me = this;
try {
const response = await Ext.Ajax.requestPromise({
responseType: 'json',
url: `${STIGMAN.Env.apiBase}/users?privilege=admin`,
method: 'GET',
headers: { 'Content-Type': 'application/json;charset=utf-8' },
})
const userList = Ext.get(me.userListId)
if (userList) {
const userItems = response
.map((user) => {
return `
<li class="sm-user-item">
<div class="sm-user-details">
<span class="sm-user-name">${user.displayName}</span>
${user.email
? `<span class="sm-user-email">${user.email}</span>`
: `<span class="sm-user-email">No Email Available</span>`}
</div>
</li>`
})
.join('')
userList.update(`<ul>${userItems}</ul>`)
}

} catch (e) {
SM.Error.handleError(e)
}
}
})
Ext.reg('sm-home-widget-app-managers', SM.ApplicationManagers)

SM.StigWidget = Ext.extend(Ext.Panel, {
initComponent: function() {
const me = this
Expand Down
1 change: 1 addition & 0 deletions client/src/js/resources.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ const scripts = [
'js/stigmanUtils.js',
'js/SM/Global.js',
'js/SM/Error.js',
'js/SM/FlexboxLayout.js',
'js/BufferView.js',
'js/SM/EventDispatcher.js',
'js/SM/Cache.js',
Expand Down
Loading