@rancher/shell 3.0.5-rc.9 → 3.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/translations/en-us.yaml +11 -5
- package/components/FilterPanel.vue +8 -1
- package/components/PaginatedResourceTable.vue +7 -2
- package/components/PodSecurityAdmission.vue +2 -0
- package/components/PromptRemove.vue +5 -0
- package/components/ResourceTable.vue +30 -20
- package/components/form/ProjectMemberEditor.vue +2 -0
- package/components/nav/Header.vue +6 -5
- package/config/product/explorer.js +5 -5
- package/config/store.js +2 -0
- package/config/uiplugins.js +1 -1
- package/core/plugin.ts +15 -3
- package/core/types.ts +30 -7
- package/dialog/SloDialog.vue +1 -1
- package/edit/auth/oidc.vue +106 -6
- package/edit/auth/saml.vue +5 -5
- package/edit/provisioning.cattle.io.cluster/tabs/AddOnAdditionalManifest.vue +1 -0
- package/edit/provisioning.cattle.io.cluster/tabs/AddOnConfig.vue +1 -0
- package/edit/provisioning.cattle.io.cluster/tabs/Basics.vue +1 -0
- package/edit/provisioning.cattle.io.cluster/tabs/etcd/S3Config.vue +1 -0
- package/edit/provisioning.cattle.io.cluster/tabs/registries/index.vue +2 -0
- package/edit/provisioning.cattle.io.cluster/tabs/upgrade/DrainOptions.vue +6 -0
- package/initialize/install-plugins.js +1 -3
- package/list/catalog.cattle.io.clusterrepo.vue +2 -2
- package/mixins/__tests__/auth-config.test.ts +4 -6
- package/mixins/__tests__/chart.test.ts +1 -1
- package/mixins/auth-config.js +33 -10
- package/mixins/chart.js +1 -1
- package/models/management.cattle.io.cluster.js +1 -1
- package/models/workload.js +1 -1
- package/package.json +2 -2
- package/pages/auth/login.vue +8 -3
- package/pages/auth/logout.vue +6 -5
- package/pages/c/_cluster/apps/charts/AppChartCardFooter.vue +6 -0
- package/pages/c/_cluster/apps/charts/StatusLabel.vue +4 -3
- package/pages/c/_cluster/apps/charts/index.vue +12 -11
- package/pages/c/_cluster/explorer/tools/__tests__/index.test.ts +1 -1
- package/pages/c/_cluster/explorer/tools/index.vue +1 -1
- package/plugins/axios.js +3 -2
- package/plugins/dashboard-store/resource-class.js +12 -1
- package/plugins/ember-cookie.js +7 -3
- package/plugins/steve/steve-pagination-utils.ts +14 -22
- package/plugins/steve/subscribe.js +4 -2
- package/scripts/test-plugins-build.sh +4 -6
- package/scripts/typegen.sh +2 -0
- package/store/__tests__/cookies.test.ts +72 -0
- package/store/auth.js +34 -11
- package/store/cookies.ts +30 -0
- package/store/prefs.js +10 -5
- package/types/shell/index.d.ts +183 -11
- package/types/store/vuex.d.ts +2 -1
- package/types/vue-shim.d.ts +2 -5
- package/utils/auth.js +1 -1
- package/utils/pagination-utils.ts +11 -2
- package/utils/cookie-universal.js +0 -10
|
@@ -478,6 +478,12 @@ addProjectMemberDialog:
|
|
|
478
478
|
title: Add Project Member
|
|
479
479
|
|
|
480
480
|
authConfig:
|
|
481
|
+
slo:
|
|
482
|
+
sloTitle: Log Out behavior
|
|
483
|
+
sloOptions:
|
|
484
|
+
onlyRancher: Log out of Rancher and not {name}
|
|
485
|
+
logoutAll: Log out of Rancher and {name} (includes all other applications registered with {name})
|
|
486
|
+
choose: Allow the user to choose one of the above in an additional log out step
|
|
481
487
|
accessMode:
|
|
482
488
|
label: 'Configure who should be able to login and use {vendor}'
|
|
483
489
|
required: Restrict access to only the authorized users & groups
|
|
@@ -627,11 +633,6 @@ authConfig:
|
|
|
627
633
|
UID: UID Field
|
|
628
634
|
adfs: Configure an AD FS account
|
|
629
635
|
api: '{vendor} API Host'
|
|
630
|
-
sloTitle: Log Out behavior
|
|
631
|
-
sloOptions:
|
|
632
|
-
onlyRancher: Log out of Rancher and not {name}
|
|
633
|
-
logoutAll: Log out of Rancher and {name} (includes all other applications registered with {name})
|
|
634
|
-
choose: Allow the user to choose one of the above in an additional log out step
|
|
635
636
|
cert:
|
|
636
637
|
label: Certificate
|
|
637
638
|
placeholder: Paste in the certificate, starting with -----BEGIN CERTIFICATE-----
|
|
@@ -698,6 +699,9 @@ authConfig:
|
|
|
698
699
|
title: Are you sure? This update is irreversible.
|
|
699
700
|
body: '<p><b>You may need to make some additional changes</b>. Please ensure the Azure AD app has the Directory.Read.All <b>Application</b> permission added to Microsoft Graph.<br> If any endpoints were customized while configuring Azure AD authentication in Rancher, they will not be automatically updated. </p>'
|
|
700
701
|
oidc:
|
|
702
|
+
endSessionEndpoint:
|
|
703
|
+
title: End Session Endpoint
|
|
704
|
+
tooltip: Provider specific URL used for logging a user out of their session
|
|
701
705
|
genericoidc: Configure an OIDC account
|
|
702
706
|
keycloakoidc: Configure a Keycloak OIDC account
|
|
703
707
|
cognito: Configure an Amazon Cognito account
|
|
@@ -7566,6 +7570,8 @@ model:
|
|
|
7566
7570
|
saml: SAML
|
|
7567
7571
|
oauth: OAuth
|
|
7568
7572
|
oidc: OIDC
|
|
7573
|
+
keycloakoidc: Keycloak
|
|
7574
|
+
genericoidc: OIDC provider
|
|
7569
7575
|
cognito: Amazon Cognito
|
|
7570
7576
|
name:
|
|
7571
7577
|
keycloak: Keycloak (SAML)
|
|
@@ -20,6 +20,8 @@ type FilterOption = {
|
|
|
20
20
|
componentProps?: Record<string, unknown>;
|
|
21
21
|
/** Label to show next to the checkbox, or a custom component next to the checkbox */
|
|
22
22
|
label?: string | { component: ComponentType; componentProps: Record<string, unknown>; };
|
|
23
|
+
/** Tooltip to be displayed above the checkbox on hover */
|
|
24
|
+
labelTooltip?: string;
|
|
23
25
|
};
|
|
24
26
|
|
|
25
27
|
/**
|
|
@@ -97,7 +99,12 @@ const updateFilter = (key: string, value: string[]) => {
|
|
|
97
99
|
@update:value="updateFilter(filter.key, $event)"
|
|
98
100
|
>
|
|
99
101
|
<template #label>
|
|
100
|
-
<span
|
|
102
|
+
<span
|
|
103
|
+
v-if="typeof option.label === 'string'"
|
|
104
|
+
v-clean-tooltip="{content: option.labelTooltip, delay: { show: 1000 }}"
|
|
105
|
+
>
|
|
106
|
+
{{ option.label }}
|
|
107
|
+
</span>
|
|
101
108
|
<component
|
|
102
109
|
:is="option.label.component"
|
|
103
110
|
v-else
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import { defineComponent } from 'vue';
|
|
3
3
|
import ResourceFetch from '@shell/mixins/resource-fetch';
|
|
4
4
|
import ResourceTable from '@shell/components/ResourceTable.vue';
|
|
5
|
+
import { VuexStore } from '@shell/types/store/vuex';
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* This is meant to enable ResourceList like capabilities outside of List pages / components
|
|
@@ -130,13 +131,17 @@ export default defineComponent({
|
|
|
130
131
|
safeHeaders(): any[] {
|
|
131
132
|
const customHeaders: any[] = this.canPaginate ? this.paginationHeaders : this.headers;
|
|
132
133
|
|
|
133
|
-
|
|
134
|
+
const $store = this.$store as VuexStore;
|
|
135
|
+
|
|
136
|
+
return customHeaders || $store.getters['type-map/headersFor'](this.schema, this.canPaginate);
|
|
134
137
|
}
|
|
135
138
|
},
|
|
136
139
|
|
|
137
140
|
methods: {
|
|
138
141
|
clearSelection() {
|
|
139
|
-
this.$refs.table
|
|
142
|
+
const table = this.$refs.table as { clearSelection: () => void };
|
|
143
|
+
|
|
144
|
+
table.clearSelection();
|
|
140
145
|
},
|
|
141
146
|
}
|
|
142
147
|
});
|
|
@@ -222,6 +222,7 @@ export default defineComponent({
|
|
|
222
222
|
<Checkbox
|
|
223
223
|
v-if="!labelsAlwaysActive"
|
|
224
224
|
v-model:value="psaControl.active"
|
|
225
|
+
:mode="mode"
|
|
225
226
|
:data-testid="componentTestid + '--psaControl-' + i + '-active'"
|
|
226
227
|
:label="level"
|
|
227
228
|
:label-key="`podSecurityAdmission.labels.${ level }`"
|
|
@@ -281,6 +282,7 @@ export default defineComponent({
|
|
|
281
282
|
<span class="col span-2">
|
|
282
283
|
<Checkbox
|
|
283
284
|
v-model:value="psaExemptionsControl.active"
|
|
285
|
+
:mode="mode"
|
|
284
286
|
:data-testid="componentTestid + '--psaExemptionsControl-' + i + '-active'"
|
|
285
287
|
:label="dimension"
|
|
286
288
|
:label-key="`podSecurityAdmission.labels.${ dimension }`"
|
|
@@ -384,6 +384,7 @@ export default {
|
|
|
384
384
|
>
|
|
385
385
|
<span
|
|
386
386
|
v-clean-html="t('promptRemove.confirmName', { nameToMatch: escapeHtml(nameToMatch) }, true)"
|
|
387
|
+
class="confirm-text"
|
|
387
388
|
/>
|
|
388
389
|
</div>
|
|
389
390
|
</div>
|
|
@@ -472,5 +473,9 @@ export default {
|
|
|
472
473
|
flex: 1;
|
|
473
474
|
}
|
|
474
475
|
}
|
|
476
|
+
|
|
477
|
+
.confirm-text b {
|
|
478
|
+
user-select: all;
|
|
479
|
+
}
|
|
475
480
|
}
|
|
476
481
|
</style>
|
|
@@ -317,6 +317,7 @@ export default {
|
|
|
317
317
|
// add custom table columns provided by the extensions ExtensionPoint.TABLE_COL hook
|
|
318
318
|
// gate it so that we prevent errors on older versions of dashboard
|
|
319
319
|
if (this.$store.$plugin?.getUIConfig) {
|
|
320
|
+
// { column: TableColumn, paginationColumn: PaginationTableColumn }[]
|
|
320
321
|
const extensionCols = getApplicableExtensionEnhancements(this, ExtensionPoint.TABLE_COL, TableColumnLocation.RESOURCE, this.$route);
|
|
321
322
|
|
|
322
323
|
// Try and insert the columns before the Age column
|
|
@@ -339,27 +340,36 @@ export default {
|
|
|
339
340
|
}
|
|
340
341
|
|
|
341
342
|
// adding extension defined cols to the correct header config
|
|
342
|
-
extensionCols.forEach((
|
|
343
|
-
|
|
344
|
-
// validate that the required settings are supplied to enable search and sort server-side
|
|
345
|
-
// these do not check other invalid scenarios like a path is a string but to a model property, or that the field supports sort/search via api (some basic non-breaking checks are done further on)
|
|
346
|
-
if (
|
|
347
|
-
col.search !== false && // search is explicitly disabled
|
|
348
|
-
(typeof col.search !== 'string' && !Array.isArray(col.search)) && // primary property path to search on
|
|
349
|
-
typeof col.value !== 'string' // secondary property path to search on
|
|
350
|
-
) {
|
|
351
|
-
console.warn(`Unable to support server-side search for extension provided column "${ col.name || col.label || col.labelKey }" (column must provide \`search\` or \`value\` property containing a path to a property in the resource. search can be an array).`); // eslint-disable-line no-console
|
|
352
|
-
|
|
353
|
-
col.search = false;
|
|
354
|
-
}
|
|
343
|
+
extensionCols.forEach((config) => {
|
|
344
|
+
let { column: col, paginationColumn } = config;
|
|
355
345
|
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
346
|
+
if (this.externalPaginationEnabled) {
|
|
347
|
+
if (paginationColumn) {
|
|
348
|
+
// Use the pagination column, no need to
|
|
349
|
+
col = paginationColumn;
|
|
350
|
+
} else {
|
|
351
|
+
// Attempt to fall back on the single column
|
|
352
|
+
|
|
353
|
+
// validate that the required settings are supplied to enable search and sort server-side
|
|
354
|
+
// these do not check other invalid scenarios like a path is a string but to a model property, or that the field supports sort/search via api (some basic non-breaking checks are done further on)
|
|
355
|
+
if (
|
|
356
|
+
col.search !== false && // search is explicitly disabled
|
|
357
|
+
(typeof col.search !== 'string' && !Array.isArray(col.search)) && // primary property path to search on
|
|
358
|
+
typeof col.value !== 'string' // secondary property path to search on
|
|
359
|
+
) {
|
|
360
|
+
console.warn(`Unable to support server-side search for extension provided column "${ col.name || col.label || col.labelKey }" (column must provide \`search\` or \`value\` property containing a path to a property in the resource. search can be an array).`); // eslint-disable-line no-console
|
|
361
|
+
|
|
362
|
+
col.search = false;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
if (
|
|
366
|
+
col.sort !== false && // sort is explicitly disabled
|
|
367
|
+
(typeof col.sort !== 'string' && !Array.isArray(col.sort)) // primary property path to sort on
|
|
368
|
+
) {
|
|
369
|
+
console.warn(`Unable to support server-side sort for extension provided column "${ col.name || col.label || col.labelKey }" (column must provide \`sort\` property containing a path to a property, or array of paths, in the resource)`); // eslint-disable-line no-console
|
|
370
|
+
|
|
371
|
+
col.sort = false;
|
|
372
|
+
}
|
|
363
373
|
}
|
|
364
374
|
}
|
|
365
375
|
|
|
@@ -286,6 +286,7 @@ export default {
|
|
|
286
286
|
<template v-slot:body>
|
|
287
287
|
<RadioGroup
|
|
288
288
|
v-model:value="value.permissionGroup"
|
|
289
|
+
:mode="mode"
|
|
289
290
|
data-testid="permission-options"
|
|
290
291
|
:options="options"
|
|
291
292
|
name="permission-group"
|
|
@@ -301,6 +302,7 @@ export default {
|
|
|
301
302
|
>
|
|
302
303
|
<Checkbox
|
|
303
304
|
v-model:value="permission.value"
|
|
305
|
+
:mode="mode"
|
|
304
306
|
:data-testid="`custom-permission-${i}`"
|
|
305
307
|
:disabled="permission.locked"
|
|
306
308
|
class="mb-5"
|
|
@@ -29,6 +29,7 @@ import {
|
|
|
29
29
|
RcDropdownSeparator,
|
|
30
30
|
RcDropdownTrigger
|
|
31
31
|
} from '@components/RcDropdown';
|
|
32
|
+
import { SLO_AUTH_PROVIDERS } from '@shell/store/auth';
|
|
32
33
|
|
|
33
34
|
export default {
|
|
34
35
|
|
|
@@ -99,10 +100,10 @@ export default {
|
|
|
99
100
|
'showWorkspaceSwitcher'
|
|
100
101
|
]),
|
|
101
102
|
|
|
102
|
-
|
|
103
|
+
sloAuthProviderEnabled() {
|
|
103
104
|
const publicAuthProviders = this.$store.getters['rancher/all']('authProvider');
|
|
104
105
|
|
|
105
|
-
return publicAuthProviders.find((authProvider) => configType[authProvider
|
|
106
|
+
return publicAuthProviders.find((authProvider) => SLO_AUTH_PROVIDERS.includes(configType[authProvider?.id])) || {};
|
|
106
107
|
},
|
|
107
108
|
|
|
108
109
|
shouldShowSloLogoutModal() {
|
|
@@ -111,7 +112,7 @@ export default {
|
|
|
111
112
|
return false;
|
|
112
113
|
}
|
|
113
114
|
|
|
114
|
-
const { logoutAllSupported, logoutAllEnabled, logoutAllForced } = this.
|
|
115
|
+
const { logoutAllSupported, logoutAllEnabled, logoutAllForced } = this.sloAuthProviderEnabled;
|
|
115
116
|
|
|
116
117
|
return logoutAllSupported && logoutAllEnabled && !logoutAllForced;
|
|
117
118
|
},
|
|
@@ -276,8 +277,8 @@ export default {
|
|
|
276
277
|
showSloModal() {
|
|
277
278
|
this.$store.dispatch('management/promptModal', {
|
|
278
279
|
component: 'SloDialog',
|
|
279
|
-
componentProps: { authProvider: this.
|
|
280
|
-
modalWidth: '
|
|
280
|
+
componentProps: { authProvider: this.sloAuthProviderEnabled },
|
|
281
|
+
modalWidth: '600px'
|
|
281
282
|
});
|
|
282
283
|
},
|
|
283
284
|
// Sizes the product area of the header such that it shrinks to ensure the whole header bar can be shown
|
|
@@ -294,7 +294,7 @@ export function init(store) {
|
|
|
294
294
|
STEVE_NAMESPACE_COL,
|
|
295
295
|
{
|
|
296
296
|
...INGRESS_TARGET,
|
|
297
|
-
sort: 'spec.rules[0].host',
|
|
297
|
+
sort: 'spec.rules[0].host',
|
|
298
298
|
search: false, // This is broken in normal world, so disable here
|
|
299
299
|
},
|
|
300
300
|
{
|
|
@@ -359,10 +359,10 @@ export function init(store) {
|
|
|
359
359
|
STEVE_STATE_COL,
|
|
360
360
|
STEVE_NAME_COL,
|
|
361
361
|
STEVE_NAMESPACE_COL,
|
|
362
|
-
HPA_REFERENCE,
|
|
363
|
-
MIN_REPLICA,
|
|
364
|
-
MAX_REPLICA,
|
|
365
|
-
CURRENT_REPLICA,
|
|
362
|
+
HPA_REFERENCE,
|
|
363
|
+
MIN_REPLICA,
|
|
364
|
+
MAX_REPLICA,
|
|
365
|
+
CURRENT_REPLICA,
|
|
366
366
|
STEVE_AGE_COL
|
|
367
367
|
]
|
|
368
368
|
);
|
package/config/store.js
CHANGED
|
@@ -39,6 +39,7 @@ let store = {};
|
|
|
39
39
|
resolveStoreModules(require('../store/customisation.js'), 'customisation.js');
|
|
40
40
|
resolveStoreModules(require('../store/cru-resource.ts'), 'cru-resource.ts');
|
|
41
41
|
resolveStoreModules(require('../store/notifications.ts'), 'notifications.ts');
|
|
42
|
+
resolveStoreModules(require('../store/cookies.ts'), 'cookies.ts');
|
|
42
43
|
|
|
43
44
|
// If the environment supports hot reloading...
|
|
44
45
|
|
|
@@ -69,6 +70,7 @@ let store = {};
|
|
|
69
70
|
'../store/customisation.js',
|
|
70
71
|
'../store/cru-resource.ts',
|
|
71
72
|
'../store/notifications.ts',
|
|
73
|
+
'../store/cookies.ts',
|
|
72
74
|
], () => {
|
|
73
75
|
// Update `root.modules` with the latest definitions.
|
|
74
76
|
updateModules();
|
package/config/uiplugins.js
CHANGED
|
@@ -107,7 +107,7 @@ export function uiPluginAnnotation(chart, name) {
|
|
|
107
107
|
/**
|
|
108
108
|
* Parse the Rancher version string
|
|
109
109
|
*/
|
|
110
|
-
function parseRancherVersion(v) {
|
|
110
|
+
export function parseRancherVersion(v) {
|
|
111
111
|
let parsedVersion = semver.coerce(v)?.version;
|
|
112
112
|
const splitArr = parsedVersion?.split('.');
|
|
113
113
|
|
package/core/plugin.ts
CHANGED
|
@@ -16,6 +16,7 @@ import {
|
|
|
16
16
|
ModelExtensionConstructor,
|
|
17
17
|
PluginRouteRecordRaw, RegisterStore, UnregisterStore, CoreStoreSpecifics, CoreStoreConfig,
|
|
18
18
|
NavHooks, OnNavToPackage, OnNavAwayFromPackage, OnLogIn, OnLogOut,
|
|
19
|
+
PaginationTableColumn,
|
|
19
20
|
ExtensionEnvironment
|
|
20
21
|
} from './types';
|
|
21
22
|
import coreStore, { coreStoreModule, coreStoreState } from '@shell/plugins/dashboard-store';
|
|
@@ -247,10 +248,21 @@ export class Plugin implements IPlugin {
|
|
|
247
248
|
}
|
|
248
249
|
|
|
249
250
|
/**
|
|
250
|
-
* Adds a new column to a
|
|
251
|
+
* Adds a new column to a ResourceTable
|
|
252
|
+
*
|
|
253
|
+
* @param where
|
|
254
|
+
* @param when
|
|
255
|
+
* @param action
|
|
256
|
+
* @param column
|
|
257
|
+
* The information required to show a header and values for a column in a table
|
|
258
|
+
* @param paginationColumn
|
|
259
|
+
* As per `column`, but is used where server-side pagination is enabled
|
|
251
260
|
*/
|
|
252
|
-
addTableColumn(where: string, when: LocationConfig | string, column: TableColumn): void {
|
|
253
|
-
this._addUIConfig(ExtensionPoint.TABLE_COL, where, when,
|
|
261
|
+
addTableColumn(where: string, when: LocationConfig | string, column: TableColumn, paginationColumn?: PaginationTableColumn): void {
|
|
262
|
+
this._addUIConfig(ExtensionPoint.TABLE_COL, where, when, {
|
|
263
|
+
column,
|
|
264
|
+
paginationColumn
|
|
265
|
+
});
|
|
254
266
|
}
|
|
255
267
|
|
|
256
268
|
setHomePage(component: any) {
|
package/core/types.ts
CHANGED
|
@@ -130,9 +130,6 @@ export type Card = {
|
|
|
130
130
|
component: Function;
|
|
131
131
|
};
|
|
132
132
|
|
|
133
|
-
// Duplication of HeaderOptions?
|
|
134
|
-
export type TableColumn = any;
|
|
135
|
-
|
|
136
133
|
/** Definition of a tab (options that can be passed when defining an extension tab enhancement) */
|
|
137
134
|
export type Tab = {
|
|
138
135
|
name: string;
|
|
@@ -281,6 +278,9 @@ export interface ProductOptions {
|
|
|
281
278
|
// typeStoreMap: string;
|
|
282
279
|
}
|
|
283
280
|
|
|
281
|
+
/**
|
|
282
|
+
* Configuration required to show a header in a ResourceTable
|
|
283
|
+
*/
|
|
284
284
|
export interface HeaderOptions {
|
|
285
285
|
/**
|
|
286
286
|
* Name of the header. This should be unique.
|
|
@@ -305,7 +305,7 @@ export interface HeaderOptions {
|
|
|
305
305
|
/**
|
|
306
306
|
* A string which represents the path to access the value from the row object which we'll use to sort i.e. `row.meta.value`
|
|
307
307
|
*/
|
|
308
|
-
sort?: string | string[];
|
|
308
|
+
sort?: string | string[] | boolean;
|
|
309
309
|
|
|
310
310
|
/**
|
|
311
311
|
* A string which represents the path to access the value from the row object which we'll use to search i.e. `row.meta.value`.
|
|
@@ -336,6 +336,21 @@ export interface HeaderOptions {
|
|
|
336
336
|
getValue?: (row: any) => string | number | null | undefined;
|
|
337
337
|
}
|
|
338
338
|
|
|
339
|
+
/**
|
|
340
|
+
* Configuration required to show a header in a ResourceTable when server-side pagination is enable
|
|
341
|
+
*/
|
|
342
|
+
export type PaginationHeaderOptions = Omit<HeaderOptions, 'getValue'>
|
|
343
|
+
|
|
344
|
+
/**
|
|
345
|
+
* External extension configuration for @HeaderOptions
|
|
346
|
+
*/
|
|
347
|
+
export type TableColumn = HeaderOptions;
|
|
348
|
+
|
|
349
|
+
/**
|
|
350
|
+
* External extension configuration for @PaginationHeaderOptions
|
|
351
|
+
*/
|
|
352
|
+
export type PaginationTableColumn = PaginationHeaderOptions;
|
|
353
|
+
|
|
339
354
|
export interface ConfigureTypeOptions {
|
|
340
355
|
/**
|
|
341
356
|
* Override for the create button string on a list view
|
|
@@ -621,9 +636,17 @@ export interface IPlugin {
|
|
|
621
636
|
addCard(where: CardLocation | string, when: LocationConfig | string, action: Card): void;
|
|
622
637
|
|
|
623
638
|
/**
|
|
624
|
-
* Adds a new column to
|
|
625
|
-
|
|
626
|
-
|
|
639
|
+
* Adds a new column to a ResourceTable
|
|
640
|
+
*
|
|
641
|
+
* @param where
|
|
642
|
+
* @param when
|
|
643
|
+
* @param action
|
|
644
|
+
* @param column
|
|
645
|
+
* The information required to show a header and values for a column in a table
|
|
646
|
+
* @param paginationColumn
|
|
647
|
+
* As per `column`, but is used where server-side pagination is enabled
|
|
648
|
+
*/
|
|
649
|
+
addTableColumn(where: TableColumnLocation | string, when: LocationConfig | string, column: TableColumn, paginationColumn?: TableColumn): void;
|
|
627
650
|
|
|
628
651
|
/**
|
|
629
652
|
* Set the component to use for the landing home page
|
package/dialog/SloDialog.vue
CHANGED
package/edit/auth/oidc.vue
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<script>
|
|
2
2
|
import Loading from '@shell/components/Loading';
|
|
3
3
|
import CreateEditView from '@shell/mixins/create-edit-view';
|
|
4
|
-
import AuthConfig from '@shell/mixins/auth-config';
|
|
4
|
+
import AuthConfig, { SLO_OPTION_VALUES } from '@shell/mixins/auth-config';
|
|
5
5
|
import CruResource from '@shell/components/CruResource';
|
|
6
6
|
import AllowedPrincipals from '@shell/components/auth/AllowedPrincipals';
|
|
7
7
|
import FileSelector from '@shell/components/form/FileSelector';
|
|
@@ -15,6 +15,7 @@ import { RadioGroup } from '@components/Form/Radio';
|
|
|
15
15
|
import { Checkbox } from '@components/Form/Checkbox';
|
|
16
16
|
import { BASE_SCOPES } from '@shell/store/auth';
|
|
17
17
|
import CopyToClipboardText from '@shell/components/CopyToClipboardText.vue';
|
|
18
|
+
import isUrl from 'is-url';
|
|
18
19
|
|
|
19
20
|
export default {
|
|
20
21
|
components: {
|
|
@@ -33,6 +34,8 @@ export default {
|
|
|
33
34
|
CopyToClipboardText,
|
|
34
35
|
},
|
|
35
36
|
|
|
37
|
+
emits: ['validationChanged'],
|
|
38
|
+
|
|
36
39
|
mixins: [CreateEditView, AuthConfig],
|
|
37
40
|
|
|
38
41
|
data() {
|
|
@@ -56,7 +59,8 @@ export default {
|
|
|
56
59
|
userInfoEndpoint: null,
|
|
57
60
|
},
|
|
58
61
|
// TODO #13457: this is duplicated due wrong format
|
|
59
|
-
oidcScope: []
|
|
62
|
+
oidcScope: [],
|
|
63
|
+
SLO_OPTION_VALUES
|
|
60
64
|
};
|
|
61
65
|
},
|
|
62
66
|
|
|
@@ -89,6 +93,11 @@ export default {
|
|
|
89
93
|
return false;
|
|
90
94
|
}
|
|
91
95
|
|
|
96
|
+
// make sure that if SLO options are enabled on radio group, field "endSessionEndpoint" is required
|
|
97
|
+
if (this.isLogoutAllSupported && this.sloEndSessionEndpointUiEnabled && (!this.model.endSessionEndpoint || !isUrl(this.model.endSessionEndpoint))) {
|
|
98
|
+
return false;
|
|
99
|
+
}
|
|
100
|
+
|
|
92
101
|
if (this.isAmazonCognito) {
|
|
93
102
|
const { issuer } = this.model;
|
|
94
103
|
|
|
@@ -129,10 +138,36 @@ export default {
|
|
|
129
138
|
|
|
130
139
|
isAmazonCognito() {
|
|
131
140
|
return this.model?.id === 'cognito';
|
|
141
|
+
},
|
|
142
|
+
|
|
143
|
+
isLogoutAllSupported() {
|
|
144
|
+
return this.model?.logoutAllSupported;
|
|
145
|
+
},
|
|
146
|
+
|
|
147
|
+
sloOptions() {
|
|
148
|
+
return [
|
|
149
|
+
{ value: SLO_OPTION_VALUES.rancher, label: this.t('authConfig.slo.sloOptions.onlyRancher', { name: this.model?.nameDisplay }) },
|
|
150
|
+
{ value: SLO_OPTION_VALUES.all, label: this.t('authConfig.slo.sloOptions.logoutAll', { name: this.model?.nameDisplay }) },
|
|
151
|
+
{ value: SLO_OPTION_VALUES.both, label: this.t('authConfig.slo.sloOptions.choose') },
|
|
152
|
+
];
|
|
153
|
+
},
|
|
154
|
+
|
|
155
|
+
sloTypeText() {
|
|
156
|
+
const sloOptionSelected = this.sloOptions.find((item) => item.value === this.sloType);
|
|
157
|
+
|
|
158
|
+
return sloOptionSelected?.label || '';
|
|
159
|
+
},
|
|
160
|
+
|
|
161
|
+
sloEndSessionEndpointUiEnabled() {
|
|
162
|
+
return this.sloType === SLO_OPTION_VALUES.all || this.sloType === SLO_OPTION_VALUES.both;
|
|
132
163
|
}
|
|
133
164
|
},
|
|
134
165
|
|
|
135
166
|
watch: {
|
|
167
|
+
fvFormIsValid(newValue) {
|
|
168
|
+
this.$emit('validationChanged', !!newValue);
|
|
169
|
+
},
|
|
170
|
+
|
|
136
171
|
'oidcUrls.url'() {
|
|
137
172
|
this.updateEndpoints();
|
|
138
173
|
},
|
|
@@ -166,6 +201,25 @@ export default {
|
|
|
166
201
|
if (!old && neu) {
|
|
167
202
|
this.customEndpoint.value = !this.oidcUrls.url && !!this.model.issuer;
|
|
168
203
|
}
|
|
204
|
+
},
|
|
205
|
+
|
|
206
|
+
// sloType is defined on shell/mixins/auth-config.js
|
|
207
|
+
sloType(neu) {
|
|
208
|
+
switch (neu) {
|
|
209
|
+
case SLO_OPTION_VALUES.rancher:
|
|
210
|
+
this.model.logoutAllEnabled = false;
|
|
211
|
+
this.model.logoutAllForced = false;
|
|
212
|
+
this.model.endSessionEndpoint = '';
|
|
213
|
+
break;
|
|
214
|
+
case SLO_OPTION_VALUES.all:
|
|
215
|
+
this.model.logoutAllEnabled = true;
|
|
216
|
+
this.model.logoutAllForced = true;
|
|
217
|
+
break;
|
|
218
|
+
case SLO_OPTION_VALUES.both:
|
|
219
|
+
this.model.logoutAllEnabled = true;
|
|
220
|
+
this.model.logoutAllForced = false;
|
|
221
|
+
break;
|
|
222
|
+
}
|
|
169
223
|
}
|
|
170
224
|
},
|
|
171
225
|
|
|
@@ -224,11 +278,19 @@ export default {
|
|
|
224
278
|
:edit="goToEdit"
|
|
225
279
|
>
|
|
226
280
|
<template #rows>
|
|
227
|
-
<tr><td>{{ t(
|
|
228
|
-
<tr><td>{{ t(
|
|
229
|
-
<tr><td>{{ t(
|
|
281
|
+
<tr><td>{{ t('authConfig.oidc.rancherUrl') }}: </td><td>{{ model.rancherUrl }}</td></tr>
|
|
282
|
+
<tr><td>{{ t('authConfig.oidc.clientId') }}: </td><td>{{ model.clientId }}</td></tr>
|
|
283
|
+
<tr><td>{{ t('authConfig.oidc.issuer') }}: </td><td>{{ model.issuer }}</td></tr>
|
|
230
284
|
<tr v-if="model.authEndpoint">
|
|
231
|
-
<td>{{ t(
|
|
285
|
+
<td>{{ t('authConfig.oidc.authEndpoint') }}: </td><td>{{ model.authEndpoint }}</td>
|
|
286
|
+
</tr>
|
|
287
|
+
<tr v-if="isLogoutAllSupported">
|
|
288
|
+
<td>{{ t('authConfig.slo.sloTitle') }}: </td><td>{{ sloTypeText }}</td>
|
|
289
|
+
</tr>
|
|
290
|
+
<tr v-if="isLogoutAllSupported && sloEndSessionEndpointUiEnabled">
|
|
291
|
+
<td>
|
|
292
|
+
{{ t('authConfig.oidc.endSessionEndpoint.title') }}:
|
|
293
|
+
</td><td>{{ model.endSessionEndpoint }}</td>
|
|
232
294
|
</tr>
|
|
233
295
|
</template>
|
|
234
296
|
</AuthBanner>
|
|
@@ -494,6 +556,44 @@ export default {
|
|
|
494
556
|
</div>
|
|
495
557
|
</div>
|
|
496
558
|
</template>
|
|
559
|
+
|
|
560
|
+
<!-- SLO logout -->
|
|
561
|
+
<div
|
|
562
|
+
v-if="isLogoutAllSupported"
|
|
563
|
+
class="mt-40 mb-20"
|
|
564
|
+
>
|
|
565
|
+
<div class="row">
|
|
566
|
+
<div class="col span-12">
|
|
567
|
+
<h3>{{ t('authConfig.slo.sloTitle') }}</h3>
|
|
568
|
+
</div>
|
|
569
|
+
</div>
|
|
570
|
+
<div class="row">
|
|
571
|
+
<div class="col span-4">
|
|
572
|
+
<RadioGroup
|
|
573
|
+
v-model:value="sloType"
|
|
574
|
+
:mode="mode"
|
|
575
|
+
:options="sloOptions"
|
|
576
|
+
:disabled="!model.logoutAllSupported"
|
|
577
|
+
name="sloTypeRadio"
|
|
578
|
+
/>
|
|
579
|
+
</div>
|
|
580
|
+
</div>
|
|
581
|
+
<div
|
|
582
|
+
v-if="sloEndSessionEndpointUiEnabled"
|
|
583
|
+
class="row mt-20"
|
|
584
|
+
>
|
|
585
|
+
<div class="col span-6">
|
|
586
|
+
<LabeledInput
|
|
587
|
+
v-model:value="model.endSessionEndpoint"
|
|
588
|
+
:tooltip="t('authConfig.oidc.endSessionEndpoint.tooltip')"
|
|
589
|
+
:label="t('authConfig.oidc.endSessionEndpoint.title')"
|
|
590
|
+
:mode="mode"
|
|
591
|
+
required
|
|
592
|
+
data-testid="oidc-endSessionEndpoint"
|
|
593
|
+
/>
|
|
594
|
+
</div>
|
|
595
|
+
</div>
|
|
596
|
+
</div>
|
|
497
597
|
</template>
|
|
498
598
|
</CruResource>
|
|
499
599
|
</div>
|
package/edit/auth/saml.vue
CHANGED
|
@@ -73,9 +73,9 @@ export default {
|
|
|
73
73
|
|
|
74
74
|
sloOptions() {
|
|
75
75
|
return [
|
|
76
|
-
{ value: SLO_OPTION_VALUES.rancher, label: this.t('authConfig.
|
|
77
|
-
{ value: SLO_OPTION_VALUES.all, label: this.t('authConfig.
|
|
78
|
-
{ value: SLO_OPTION_VALUES.both, label: this.t('authConfig.
|
|
76
|
+
{ value: SLO_OPTION_VALUES.rancher, label: this.t('authConfig.slo.sloOptions.onlyRancher', { name: this.model?.nameDisplay }) },
|
|
77
|
+
{ value: SLO_OPTION_VALUES.all, label: this.t('authConfig.slo.sloOptions.logoutAll', { name: this.model?.nameDisplay }) },
|
|
78
|
+
{ value: SLO_OPTION_VALUES.both, label: this.t('authConfig.slo.sloOptions.choose') },
|
|
79
79
|
];
|
|
80
80
|
},
|
|
81
81
|
|
|
@@ -175,7 +175,7 @@ export default {
|
|
|
175
175
|
<tr><td>{{ t(`authConfig.saml.api`) }}: </td><td>{{ model.rancherApiHost }}</td></tr>
|
|
176
176
|
<tr><td>{{ t(`authConfig.saml.groups`) }}: </td><td>{{ model.groupsField }}</td></tr>
|
|
177
177
|
<tr v-if="isLogoutAllSupported">
|
|
178
|
-
<td>{{ t(`authConfig.
|
|
178
|
+
<td>{{ t(`authConfig.slo.sloTitle`) }}: </td><td>{{ sloTypeText }}</td>
|
|
179
179
|
</tr>
|
|
180
180
|
</template>
|
|
181
181
|
|
|
@@ -357,7 +357,7 @@ export default {
|
|
|
357
357
|
>
|
|
358
358
|
<div class="row">
|
|
359
359
|
<div class="col span-12">
|
|
360
|
-
<h3>{{ t('authConfig.
|
|
360
|
+
<h3>{{ t('authConfig.slo.sloTitle') }}</h3>
|
|
361
361
|
</div>
|
|
362
362
|
</div>
|
|
363
363
|
<div class="row">
|