ui: App-ify Lock Sessions (#12482)

This commit moves our in-app LockSessions code into an external 'app', which can theoretically be side-loaded but for now it just makes for good isolation/code hygiene.

Functionally, there is kind of one change here, and that is we only show the 'Lock Session' tab if you have permissions to see them. Currently as our UI authorization endpoint needs to be changed slightly to suit our usecase, you will always have permissions to see Lock Sessions as we hardcode the session:read to true (obvs this is a frontend thing, not a backend thing), so it doesn't really change anything from a user perspective.

Also added very bare docs while I was here.

Small note here, ideally we need to add the each individual tab depending on whether an 'app' is enabled or not instead of just permissions, ideally it would be done totally from The Outside rather than a can based conditional on the inside, just something else to be thinking about for the future.
This commit is contained in:
John Cowen 2022-03-14 16:54:49 +00:00 committed by GitHub
parent ab099e5fcb
commit 1e26c1fe11
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 146 additions and 26 deletions

View File

@ -22,7 +22,7 @@ references:
test-results: &TEST_RESULTS_DIR /tmp/test-results test-results: &TEST_RESULTS_DIR /tmp/test-results
cache: cache:
yarn: &YARN_CACHE_KEY consul-ui-v6-{{ checksum "ui/yarn.lock" }} yarn: &YARN_CACHE_KEY consul-ui-v7-{{ checksum "ui/yarn.lock" }}
environment: &ENVIRONMENT environment: &ENVIRONMENT
TEST_RESULTS_DIR: *TEST_RESULTS_DIR TEST_RESULTS_DIR: *TEST_RESULTS_DIR

View File

@ -11,7 +11,7 @@
"scripts": { "scripts": {
"doc:toc": "doctoc README.md", "doc:toc": "doctoc README.md",
"compliance": "npm-run-all compliance:*", "compliance": "npm-run-all compliance:*",
"compliance:licenses": "license-checker --summary --onlyAllow 'Python-2.0;Apache*;Apache License, Version 2.0;Apache-2.0;Apache 2.0;Artistic-2.0;BSD;BSD-3-Clause;CC-BY-3.0;CC-BY-4.0;CC0-1.0;ISC;MIT;MPL-2.0;Public Domain;Unicode-TOU;Unlicense;WTFPL' --excludePackages 'consul-ui@2.2.0;consul-acls@0.1.0;consul-partitions@0.1.0;consul-nspaces@0.1.0'" "compliance:licenses": "license-checker --summary --onlyAllow 'Python-2.0;Apache*;Apache License, Version 2.0;Apache-2.0;Apache 2.0;Artistic-2.0;BSD;BSD-3-Clause;CC-BY-3.0;CC-BY-4.0;CC0-1.0;ISC;MIT;MPL-2.0;Public Domain;Unicode-TOU;Unlicense;WTFPL' --excludePackages 'consul-ui@2.2.0;consul-acls@0.1.0;consul-lock-sessions@0.1.0;consul-partitions@0.1.0;consul-nspaces@0.1.0'"
}, },
"devDependencies": { "devDependencies": {

View File

@ -0,0 +1,52 @@
<!-- START component-docs:@tagName -->
# Consul::LockSession::Notifications
<!-- END component-docs:@tagName -->
<!-- START component-docs:@description-->
A Notification component specifically for LockSessions.
<!-- END component-docs:@description -->
```hbs preview-template
<figure>
<figcaption>
Provide a widget for to change the @type
</figcaption>
<select
onchange={{action (mut this.type) value="target.value"}}
>
<option>kv</option>
<option>success</option>
<option>error</option>
</select>
</figure>
<figure>
<figcaption>
Use the component
</figcaption>
<Consul::LockSession::Notifications
@type={{if (contains this.type (array 'success' 'error')) 'remove' 'kv'}}
@error={{if (eq this.type 'error') (hash
status="403"
detail=""
) undefined }}
/>
</figure>
```
## Arguments
<!-- START component-docs:@args -->
| Argument | Type | Default | Description |
| :-------- | :--------------- | :------ | :------------------------------------------------- |
| type | "remove" \| "kv" | | The type of Notification to use |
| error | error | | Consul UI shaped error only used for `remove` type |
<!-- END component-docs:@args -->

View File

@ -33,4 +33,15 @@
</notice.Body> </notice.Body>
</Notice> </Notice>
{{/if}} {{/if}}
{{else if (eq @type 'kv')}}
<Notice
@type="warning"
data-test-session-warning
as |notice|>
<notice.Body>
<p>
<strong>Warning.</strong> This KV has a lock session. You can edit KV's with lock sessions, but we recommend doing so with care, or not doing so at all. It may negatively impact the active node it's associated with. See below for more details on the Lock Session and see <a href="{{env 'CONSUL_DOCS_URL'}}/internals/sessions.html" target="_blank" rel="noopener noreferrer">our documentation</a> for more information.
</p>
</notice.Body>
</Notice>
{{/if}} {{/if}}

View File

@ -0,0 +1,5 @@
{
"name": "consul-lock-sessions",
"version": "0.1.0",
"private": true
}

View File

@ -0,0 +1,15 @@
(routes => routes({
dc: {
nodes: {
show: {
sessions: {
_options: { path: '/lock-sessions' },
},
},
},
},
}))(
(json, data = (typeof document !== 'undefined' ? document.currentScript.dataset : module.exports)) => {
data[`routes`] = JSON.stringify(json);
}
);

View File

@ -0,0 +1,7 @@
(services => services({
}))(
(json, data = (typeof document !== 'undefined' ? document.currentScript.dataset : module.exports)) => {
data[`services`] = JSON.stringify(json);
}
);

View File

@ -106,6 +106,12 @@ module.exports = {
urlSchema: 'auto', urlSchema: 'auto',
urlPrefix: 'docs/consul-acls', urlPrefix: 'docs/consul-acls',
}, },
{
root: `${path.dirname(require.resolve('consul-lock-sessions/package.json'))}/app/components`,
pattern: '**/README.mdx',
urlSchema: 'auto',
urlPrefix: 'docs/consul-lock-sessions',
},
{ {
root: `${path.dirname(require.resolve('consul-partitions/package.json'))}/app/components`, root: `${path.dirname(require.resolve('consul-partitions/package.json'))}/app/components`,
pattern: '**/README.mdx', pattern: '**/README.mdx',

View File

@ -97,16 +97,7 @@ as |parts|}}
{{! if a KV has a session `Session` will always be populated despite any specific session permissions }} {{! if a KV has a session `Session` will always be populated despite any specific session permissions }}
{{#if item.Session}} {{#if item.Session}}
<Notice <Consul::LockSession::Notifications @type="kv" />
@type="warning"
data-test-session-warning
as |notice|>
<notice.Body>
<p>
<strong>Warning.</strong> This KV has a lock session. You can edit KV's with lock sessions, but we recommend doing so with care, or not doing so at all. It may negatively impact the active node it's associated with. See below for more details on the Lock Session and see <a href="{{env 'CONSUL_DOCS_URL'}}/internals/sessions.html" target="_blank" rel="noopener noreferrer">our documentation</a> for more information.
</p>
</notice.Body>
</Notice>
{{/if}} {{/if}}
<Consul::Kv::Form <Consul::Kv::Form

View File

@ -107,11 +107,35 @@ as |item tomography|}}
<TabNav @items={{ <TabNav @items={{
compact compact
(array (array
(hash label="Health Checks" href=(href-to "dc.nodes.show.healthchecks") selected=(is-href "dc.nodes.show.healthchecks")) (hash
(hash label="Service Instances" href=(href-to "dc.nodes.show.services") selected=(is-href "dc.nodes.show.services")) label=(t 'routes.dc.nodes.show.healthchecks.title')
(if tomography.distances (hash label="Round Trip Time" href=(href-to "dc.nodes.show.rtt") selected=(is-href "dc.nodes.show.rtt")) '') href=(href-to "dc.nodes.show.healthchecks")
(hash label="Lock Sessions" href=(href-to "dc.nodes.show.sessions") selected=(is-href "dc.nodes.show.sessions")) selected=(is-href "dc.nodes.show.healthchecks")
(hash label="Metadata" href=(href-to "dc.nodes.show.metadata") selected=(is-href "dc.nodes.show.metadata")) )
(hash
label=(t 'routes.dc.nodes.show.services.title')
href=(href-to "dc.nodes.show.services")
selected=(is-href "dc.nodes.show.services")
)
(if tomography.distances
(hash
label=(t 'routes.dc.nodes.show.rtt.title')
href=(href-to "dc.nodes.show.rtt")
selected=(is-href "dc.nodes.show.rtt")
)
'')
(if (can 'read sessions')
(hash
label=(t 'routes.dc.nodes.show.sessions.title')
href=(href-to "dc.nodes.show.sessions")
selected=(is-href "dc.nodes.show.sessions")
)
'')
(hash
label=(t 'routes.dc.nodes.show.metadata.title')
href=(href-to "dc.nodes.show.metadata")
selected=(is-href "dc.nodes.show.metadata")
)
) )
}}/> }}/>
</BlockSlot> </BlockSlot>

View File

@ -29,6 +29,7 @@ module.exports = function(defaults, $ = process.env) {
const apps = [ const apps = [
'consul-ui', 'consul-ui',
'consul-acls', 'consul-acls',
'consul-lock-sessions',
'consul-partitions', 'consul-partitions',
'consul-nspaces' 'consul-nspaces'
].map(item => { ].map(item => {

View File

@ -44,6 +44,7 @@ ${environment === 'production' ? `{{jsonEncode .}}` : JSON.stringify(config.oper
</script> </script>
<script src="${rootURL}assets/consul-ui/services.js"></script> <script src="${rootURL}assets/consul-ui/services.js"></script>
<script src="${rootURL}assets/consul-ui/routes.js"></script> <script src="${rootURL}assets/consul-ui/routes.js"></script>
<script src="${rootURL}assets/consul-lock-sessions/routes.js"></script>
${ ${
environment === 'development' || environment === 'staging' environment === 'development' || environment === 'staging'
? ` ? `

View File

@ -79,6 +79,7 @@
"chalk": "^4.1.0", "chalk": "^4.1.0",
"clipboard": "^2.0.4", "clipboard": "^2.0.4",
"consul-acls": "*", "consul-acls": "*",
"consul-lock-sessions": "*",
"consul-nspaces": "*", "consul-nspaces": "*",
"consul-partitions": "*", "consul-partitions": "*",
"css.escape": "^1.5.1", "css.escape": "^1.5.1",

View File

@ -2,6 +2,7 @@ dc:
nodes: nodes:
show: show:
healthchecks: healthchecks:
title: Health Checks
empty: | empty: |
<p> <p>
This node has no health checks{items, select, This node has no health checks{items, select,
@ -15,6 +16,14 @@ dc:
<p> <p>
This node has a failing serf node check. The health statuses shown on this page are the statuses as they were known before the node became unreachable. This node has a failing serf node check. The health statuses shown on this page are the statuses as they were known before the node became unreachable.
</p> </p>
services:
title: Service Instances
rtt:
title: Round Trip Time
sessions:
title: Lock Sessions
metadata:
title: Metadata
services: services:
show: show:
topology: topology:

View File

@ -240,9 +240,6 @@
rtt: { rtt: {
_options: { path: '/round-trip-time' }, _options: { path: '/round-trip-time' },
}, },
sessions: {
_options: { path: '/lock-sessions' },
},
metadata: { metadata: {
_options: { path: '/metadata' }, _options: { path: '/metadata' },
}, },