Initial version client scopes (#111)

* initial version client scopes

* remove use of newer replaceAll

* review
This commit is contained in:
Erik Jan de Wit 2020-09-25 19:11:25 +02:00 committed by GitHub
parent 8210ba5ba0
commit e7b108a623
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 845 additions and 26 deletions

View file

@ -1,12 +1,14 @@
import React from "react";
import { Page, PageSection } from "@patternfly/react-core";
import { Page } from "@patternfly/react-core";
import { BrowserRouter as Router, Route, Switch } from "react-router-dom";
import { Header } from "./PageHeader";
import { PageNav } from "./PageNav";
import { Help } from "./components/help-enabler/HelpHeader";
import { BrowserRouter as Router, Route, Switch } from "react-router-dom";
import { NewRealmForm } from "./realm/add/NewRealmForm";
import { NewClientForm } from "./clients/add/NewClientForm";
import { NewClientScopeForm } from "./client-scopes/add/NewClientScopeForm";
import { ImportForm } from "./clients/import/ImportForm";
import { ClientsSection } from "./clients/ClientsSection";
import { ClientScopesSection } from "./client-scopes/ClientScopesSection";
@ -47,6 +49,11 @@ export const App = () => {
path="/client-scopes"
component={ClientScopesSection}
></Route>
<Route
exact
path="/add-client-scopes"
component={NewClientScopeForm}
></Route>
<Route
exact
path="/realm-roles"

View file

@ -0,0 +1,58 @@
import React from "react";
import { useTranslation } from "react-i18next";
import {
Table,
TableBody,
TableHeader,
TableVariant,
} from "@patternfly/react-table";
import { ClientScopeRepresentation } from "./models/client-scope";
type ClientScopeListProps = {
clientScopes: ClientScopeRepresentation[];
};
export const ClientScopeList = ({ clientScopes }: ClientScopeListProps) => {
const { t } = useTranslation("client-scopes");
const columns: (keyof ClientScopeRepresentation)[] = [
"name",
"description",
"protocol",
];
const data = clientScopes.map((c) => {
return { cells: columns.map((col) => c[col]) };
});
return (
<>
<Table
variant={TableVariant.compact}
cells={[
{ title: t("name") },
{ title: t("description") },
{
title: t("protocol"),
},
]}
rows={data}
actions={[
{
title: t("common:export"),
onClick: () => {},
},
{
title: t("common:delete"),
onClick: () => {},
},
]}
aria-label={t("clientScopeList")}
>
<TableHeader />
<TableBody />
</Table>
</>
);
};

View file

@ -1,10 +1,53 @@
import { PageSection } from "@patternfly/react-core";
import React from "react";
import React, { useContext, useState } from "react";
import { Button, PageSection } from "@patternfly/react-core";
import { useTranslation } from "react-i18next";
import { useHistory } from "react-router-dom";
import { RealmContext } from "../components/realm-context/RealmContext";
import { HttpClientContext } from "../http-service/HttpClientContext";
import { ClientRepresentation } from "../realm/models/Realm";
import { DataLoader } from "../components/data-loader/DataLoader";
import { TableToolbar } from "../components/table-toolbar/TableToolbar";
import { ClientScopeList } from "./ClientScopesList";
export const ClientScopesSection = () => {
const { t } = useTranslation("client-scopes");
const history = useHistory();
const [max, setMax] = useState(10);
const [first, setFirst] = useState(0);
const httpClient = useContext(HttpClientContext)!;
const { realm } = useContext(RealmContext);
const loader = async () => {
return await httpClient
.doGet(`/admin/realms/${realm}/client-scopes`, { params: { first, max } })
.then((r) => r.data as ClientRepresentation[]);
};
return (
<>
<PageSection variant="light">The Client Scopes Page</PageSection>
</>
<PageSection variant="light">
<DataLoader loader={loader}>
{(scopes) => (
<TableToolbar
count={scopes!.length}
first={first}
max={max}
onNextClick={setFirst}
onPreviousClick={setFirst}
onPerPageSelect={(first, max) => {
setFirst(first);
setMax(max);
}}
toolbarItem={
<Button onClick={() => history.push("/add-client-scopes")}>
{t("createClientScope")}
</Button>
}
>
<ClientScopeList clientScopes={scopes} />
</TableToolbar>
)}
</DataLoader>
</PageSection>
);
};

View file

@ -0,0 +1,485 @@
[
{
"id": "3507ed12-d8b0-455c-b91a-62a6765ecf0f",
"name": "address",
"description": "OpenID Connect built-in scope: address",
"protocol": "openid-connect",
"attributes": {
"include.in.token.scope": "true",
"display.on.consent.screen": "true",
"consent.screen.text": "${addressScopeConsentText}"
},
"protocolMappers": [
{
"id": "b0582082-abab-4c63-b3b7-a92afe6b3436",
"name": "address",
"protocol": "openid-connect",
"protocolMapper": "oidc-address-mapper",
"consentRequired": false,
"config": {
"user.attribute.formatted": "formatted",
"user.attribute.country": "country",
"user.attribute.postal_code": "postal_code",
"userinfo.token.claim": "true",
"user.attribute.street": "street",
"id.token.claim": "true",
"user.attribute.region": "region",
"access.token.claim": "true",
"user.attribute.locality": "locality"
}
}
]
},
{
"id": "eb8c7985-5459-45a9-ace5-2959ce0fd1c9",
"name": "email",
"description": "OpenID Connect built-in scope: email",
"protocol": "openid-connect",
"attributes": {
"include.in.token.scope": "true",
"display.on.consent.screen": "true",
"consent.screen.text": "${emailScopeConsentText}"
},
"protocolMappers": [
{
"id": "348dfe5c-26e6-43e8-bc80-b7db9f842f24",
"name": "email",
"protocol": "openid-connect",
"protocolMapper": "oidc-usermodel-property-mapper",
"consentRequired": false,
"config": {
"userinfo.token.claim": "true",
"user.attribute": "email",
"id.token.claim": "true",
"access.token.claim": "true",
"claim.name": "email",
"jsonType.label": "String"
}
},
{
"id": "bfe77908-4ca3-40ea-b5be-75bea87f5bb1",
"name": "email verified",
"protocol": "openid-connect",
"protocolMapper": "oidc-usermodel-property-mapper",
"consentRequired": false,
"config": {
"userinfo.token.claim": "true",
"user.attribute": "emailVerified",
"id.token.claim": "true",
"access.token.claim": "true",
"claim.name": "email_verified",
"jsonType.label": "boolean"
}
}
]
},
{
"id": "e604d76d-20ec-4d80-acee-1885af201568",
"name": "microprofile-jwt",
"description": "Microprofile - JWT built-in scope",
"protocol": "openid-connect",
"attributes": {
"include.in.token.scope": "true",
"display.on.consent.screen": "false"
},
"protocolMappers": [
{
"id": "63a71cf3-df7c-4a81-a23f-d3ba62801c72",
"name": "upn",
"protocol": "openid-connect",
"protocolMapper": "oidc-usermodel-property-mapper",
"consentRequired": false,
"config": {
"userinfo.token.claim": "true",
"user.attribute": "username",
"id.token.claim": "true",
"access.token.claim": "true",
"claim.name": "upn",
"jsonType.label": "String"
}
},
{
"id": "5eb3444b-8e96-4267-9afc-20abd56613aa",
"name": "groups",
"protocol": "openid-connect",
"protocolMapper": "oidc-usermodel-realm-role-mapper",
"consentRequired": false,
"config": {
"multivalued": "true",
"user.attribute": "foo",
"id.token.claim": "true",
"access.token.claim": "true",
"claim.name": "groups",
"jsonType.label": "String"
}
}
]
},
{
"id": "2cdac876-a8ce-4cde-8bcb-00e28804ec91",
"name": "offline_access",
"description": "OpenID Connect built-in scope: offline_access",
"protocol": "openid-connect",
"attributes": {
"consent.screen.text": "${offlineAccessScopeConsentText}",
"display.on.consent.screen": "true"
}
},
{
"id": "3db88729-214e-4c71-8fac-ee744279538b",
"name": "phone",
"description": "OpenID Connect built-in scope: phone",
"protocol": "openid-connect",
"attributes": {
"include.in.token.scope": "true",
"display.on.consent.screen": "true",
"consent.screen.text": "${phoneScopeConsentText}"
},
"protocolMappers": [
{
"id": "00ca4abc-fc26-4273-9d77-d7a793f38976",
"name": "phone number verified",
"protocol": "openid-connect",
"protocolMapper": "oidc-usermodel-attribute-mapper",
"consentRequired": false,
"config": {
"userinfo.token.claim": "true",
"user.attribute": "phoneNumberVerified",
"id.token.claim": "true",
"access.token.claim": "true",
"claim.name": "phone_number_verified",
"jsonType.label": "boolean"
}
},
{
"id": "98885779-b84e-4565-bc1b-a0c703f03be0",
"name": "phone number",
"protocol": "openid-connect",
"protocolMapper": "oidc-usermodel-attribute-mapper",
"consentRequired": false,
"config": {
"userinfo.token.claim": "true",
"user.attribute": "phoneNumber",
"id.token.claim": "true",
"access.token.claim": "true",
"claim.name": "phone_number",
"jsonType.label": "String"
}
}
]
},
{
"id": "82aca51c-22b4-4156-93a9-3ed33ec2adcc",
"name": "profile",
"description": "OpenID Connect built-in scope: profile",
"protocol": "openid-connect",
"attributes": {
"include.in.token.scope": "true",
"display.on.consent.screen": "true",
"consent.screen.text": "${profileScopeConsentText}"
},
"protocolMappers": [
{
"id": "d974a079-8416-4dea-9e49-76dab694e836",
"name": "full name",
"protocol": "openid-connect",
"protocolMapper": "oidc-full-name-mapper",
"consentRequired": false,
"config": {
"id.token.claim": "true",
"access.token.claim": "true",
"userinfo.token.claim": "true"
}
},
{
"id": "2b0e5ec3-cc38-44c4-8851-98c0e3e3f60d",
"name": "birthdate",
"protocol": "openid-connect",
"protocolMapper": "oidc-usermodel-attribute-mapper",
"consentRequired": false,
"config": {
"userinfo.token.claim": "true",
"user.attribute": "birthdate",
"id.token.claim": "true",
"access.token.claim": "true",
"claim.name": "birthdate",
"jsonType.label": "String"
}
},
{
"id": "feef3c77-5a8e-4f22-94c8-fc606eb8dad0",
"name": "website",
"protocol": "openid-connect",
"protocolMapper": "oidc-usermodel-attribute-mapper",
"consentRequired": false,
"config": {
"userinfo.token.claim": "true",
"user.attribute": "website",
"id.token.claim": "true",
"access.token.claim": "true",
"claim.name": "website",
"jsonType.label": "String"
}
},
{
"id": "e0340530-efde-4bdf-8399-c98b994e3c4f",
"name": "nickname",
"protocol": "openid-connect",
"protocolMapper": "oidc-usermodel-attribute-mapper",
"consentRequired": false,
"config": {
"userinfo.token.claim": "true",
"user.attribute": "nickname",
"id.token.claim": "true",
"access.token.claim": "true",
"claim.name": "nickname",
"jsonType.label": "String"
}
},
{
"id": "bef63a97-20a4-4595-9e31-881273af8b47",
"name": "locale",
"protocol": "openid-connect",
"protocolMapper": "oidc-usermodel-attribute-mapper",
"consentRequired": false,
"config": {
"userinfo.token.claim": "true",
"user.attribute": "locale",
"id.token.claim": "true",
"access.token.claim": "true",
"claim.name": "locale",
"jsonType.label": "String"
}
},
{
"id": "3a4e571b-9ee4-4553-8a54-dcf0ab757b39",
"name": "picture",
"protocol": "openid-connect",
"protocolMapper": "oidc-usermodel-attribute-mapper",
"consentRequired": false,
"config": {
"userinfo.token.claim": "true",
"user.attribute": "picture",
"id.token.claim": "true",
"access.token.claim": "true",
"claim.name": "picture",
"jsonType.label": "String"
}
},
{
"id": "d0c55da1-f814-4bfe-a311-b34ddd7ee2fb",
"name": "updated at",
"protocol": "openid-connect",
"protocolMapper": "oidc-usermodel-attribute-mapper",
"consentRequired": false,
"config": {
"userinfo.token.claim": "true",
"user.attribute": "updatedAt",
"id.token.claim": "true",
"access.token.claim": "true",
"claim.name": "updated_at",
"jsonType.label": "String"
}
},
{
"id": "392fa527-96e9-41a5-8fa4-6deb1f3916a5",
"name": "middle name",
"protocol": "openid-connect",
"protocolMapper": "oidc-usermodel-attribute-mapper",
"consentRequired": false,
"config": {
"userinfo.token.claim": "true",
"user.attribute": "middleName",
"id.token.claim": "true",
"access.token.claim": "true",
"claim.name": "middle_name",
"jsonType.label": "String"
}
},
{
"id": "042e6e1e-f041-432f-88bc-79421366fb99",
"name": "gender",
"protocol": "openid-connect",
"protocolMapper": "oidc-usermodel-attribute-mapper",
"consentRequired": false,
"config": {
"userinfo.token.claim": "true",
"user.attribute": "gender",
"id.token.claim": "true",
"access.token.claim": "true",
"claim.name": "gender",
"jsonType.label": "String"
}
},
{
"id": "e269f729-2eca-4ff0-9caf-3baa4f6188c5",
"name": "zoneinfo",
"protocol": "openid-connect",
"protocolMapper": "oidc-usermodel-attribute-mapper",
"consentRequired": false,
"config": {
"userinfo.token.claim": "true",
"user.attribute": "zoneinfo",
"id.token.claim": "true",
"access.token.claim": "true",
"claim.name": "zoneinfo",
"jsonType.label": "String"
}
},
{
"id": "b3929aa6-6acf-4b13-9d23-ee459926feef",
"name": "given name",
"protocol": "openid-connect",
"protocolMapper": "oidc-usermodel-property-mapper",
"consentRequired": false,
"config": {
"userinfo.token.claim": "true",
"user.attribute": "firstName",
"id.token.claim": "true",
"access.token.claim": "true",
"claim.name": "given_name",
"jsonType.label": "String"
}
},
{
"id": "877d4b97-2520-40f7-9e58-cd99560a4637",
"name": "profile",
"protocol": "openid-connect",
"protocolMapper": "oidc-usermodel-attribute-mapper",
"consentRequired": false,
"config": {
"userinfo.token.claim": "true",
"user.attribute": "profile",
"id.token.claim": "true",
"access.token.claim": "true",
"claim.name": "profile",
"jsonType.label": "String"
}
},
{
"id": "f6aab00d-4b15-4ef3-a037-50d8a6c047ff",
"name": "family name",
"protocol": "openid-connect",
"protocolMapper": "oidc-usermodel-property-mapper",
"consentRequired": false,
"config": {
"userinfo.token.claim": "true",
"user.attribute": "lastName",
"id.token.claim": "true",
"access.token.claim": "true",
"claim.name": "family_name",
"jsonType.label": "String"
}
},
{
"id": "52483504-1da0-4645-8df0-d7ec36bf835a",
"name": "username",
"protocol": "openid-connect",
"protocolMapper": "oidc-usermodel-property-mapper",
"consentRequired": false,
"config": {
"userinfo.token.claim": "true",
"user.attribute": "username",
"id.token.claim": "true",
"access.token.claim": "true",
"claim.name": "preferred_username",
"jsonType.label": "String"
}
}
]
},
{
"id": "dc401683-7876-4a01-a670-73deae0a10c2",
"name": "role_list",
"description": "SAML role list",
"protocol": "saml",
"attributes": {
"consent.screen.text": "${samlRoleListScopeConsentText}",
"display.on.consent.screen": "true"
},
"protocolMappers": [
{
"id": "4903f029-ca74-4447-b9ac-cf7799f2391c",
"name": "role list",
"protocol": "saml",
"protocolMapper": "saml-role-list-mapper",
"consentRequired": false,
"config": {
"single": "false",
"attribute.nameformat": "Basic",
"attribute.name": "Role"
}
}
]
},
{
"id": "715eec20-9d2b-45cf-b2c3-fd11aae96b63",
"name": "roles",
"description": "OpenID Connect scope for add user roles to the access token",
"protocol": "openid-connect",
"attributes": {
"include.in.token.scope": "false",
"display.on.consent.screen": "true",
"consent.screen.text": "${rolesScopeConsentText}"
},
"protocolMappers": [
{
"id": "d1464021-822d-41d8-8195-d8962fe70f61",
"name": "audience resolve",
"protocol": "openid-connect",
"protocolMapper": "oidc-audience-resolve-mapper",
"consentRequired": false,
"config": {}
},
{
"id": "b85d197d-f195-4dcd-a873-77ee4ec9fcea",
"name": "realm roles",
"protocol": "openid-connect",
"protocolMapper": "oidc-usermodel-realm-role-mapper",
"consentRequired": false,
"config": {
"user.attribute": "foo",
"access.token.claim": "true",
"claim.name": "realm_access.roles",
"jsonType.label": "String",
"multivalued": "true"
}
},
{
"id": "ef5b5c95-5236-41f1-ab9b-3e4213abbe76",
"name": "client roles",
"protocol": "openid-connect",
"protocolMapper": "oidc-usermodel-client-role-mapper",
"consentRequired": false,
"config": {
"user.attribute": "foo",
"access.token.claim": "true",
"claim.name": "resource_access.${client_id}.roles",
"jsonType.label": "String",
"multivalued": "true"
}
}
]
},
{
"id": "30b4d89f-bfd9-45d4-b71f-01dd0f64da57",
"name": "web-origins",
"description": "OpenID Connect scope for add allowed web origins to the access token",
"protocol": "openid-connect",
"attributes": {
"include.in.token.scope": "false",
"display.on.consent.screen": "false",
"consent.screen.text": ""
},
"protocolMappers": [
{
"id": "76f254c5-dc78-4048-abc9-c9de9d55f5a4",
"name": "allowed web origins",
"protocol": "openid-connect",
"protocolMapper": "oidc-allowed-origins-mapper",
"consentRequired": false,
"config": {}
}
]
}
]

View file

@ -0,0 +1,181 @@
import React, { useContext, useState } from "react";
import {
ActionGroup,
AlertVariant,
Button,
Form,
FormGroup,
PageSection,
Select,
SelectVariant,
Switch,
TextInput,
} from "@patternfly/react-core";
import { useTranslation } from "react-i18next";
import { Controller, useForm } from "react-hook-form";
import { ClientScopeRepresentation } from "../models/client-scope";
import { HelpItem } from "../../components/help-enabler/HelpItem";
import { HttpClientContext } from "../../http-service/HttpClientContext";
import { RealmContext } from "../../components/realm-context/RealmContext";
import { useAlerts } from "../../components/alert/Alerts";
export const NewClientScopeForm = () => {
const { t } = useTranslation("client-scopes");
const { register, control, handleSubmit } = useForm<
ClientScopeRepresentation
>();
const httpClient = useContext(HttpClientContext)!;
const { realm } = useContext(RealmContext);
const [open, isOpen] = useState(false);
const [add, Alerts] = useAlerts();
const save = async (clientScopes: ClientScopeRepresentation) => {
try {
const keyValues = Object.keys(clientScopes.attributes!).map((key) => {
const newKey = key.replace(/_/g, ".");
return { [newKey]: clientScopes.attributes![key] };
});
clientScopes.attributes = Object.assign({}, ...keyValues);
await httpClient.doPost(
`/admin/realms/${realm}/client-scopes`,
clientScopes
);
add(t("createClientScopeSuccess"), AlertVariant.success);
} catch (error) {
add(`${t("createClientScopeError")} '${error}'`, AlertVariant.danger);
}
};
return (
<PageSection variant="light">
<Alerts />
<Form isHorizontal onSubmit={handleSubmit(save)}>
<FormGroup
label={
<>
{t("name")} <HelpItem item="clientScope.name" />
</>
}
fieldId="kc-name"
isRequired
>
<TextInput
ref={register({ required: true })}
type="text"
id="kc-name"
name="name"
/>
</FormGroup>
<FormGroup
label={
<>
{t("description")} <HelpItem item="clientScope.description" />
</>
}
fieldId="kc-description"
>
<TextInput
ref={register}
type="text"
id="kc-description"
name="description"
/>
</FormGroup>
<FormGroup
label={
<>
{t("protocol")} <HelpItem item="clientScope.protocol" />
</>
}
fieldId="kc-protocol"
>
<Controller
name="protocol"
defaultValue=""
control={control}
render={({ onChange, value }) => (
<Select
id="kc-protocol"
required
onToggle={() => isOpen(!open)}
onSelect={(_, value, isPlaceholder) => {
onChange(isPlaceholder ? "" : (value as string));
isOpen(false);
}}
selections={value}
variant={SelectVariant.single}
aria-label="Select Encryption type"
isOpen={open}
></Select>
)}
/>
</FormGroup>
<FormGroup
label={
<>
{t("displayOnConsentScreen")}{" "}
<HelpItem item="clientScope.displayOnConsentScreen" />
</>
}
fieldId="kc-display.on.consent.screen"
>
<Controller
name="attributes.display_on_consent_screen"
control={control}
defaultValue={false}
render={({ onChange, value }) => (
<Switch
id="kc-display.on.consent.screen"
label={t("common:on")}
labelOff={t("common:off")}
isChecked={value}
onChange={onChange}
/>
)}
/>
</FormGroup>
<FormGroup
label={
<>
{t("consentScreenText")}{" "}
<HelpItem item="clientScope.consentScreenText" />
</>
}
fieldId="kc-consent-screen-text"
>
<TextInput
ref={register}
type="text"
id="kc-consent-screen-text"
name="attributes.consent_screen_text"
/>
</FormGroup>
<FormGroup
label={
<>
{t("guiOrder")} <HelpItem item="clientScope.guiOrder" />
</>
}
fieldId="kc-gui-order"
>
<TextInput
ref={register}
type="number"
id="kc-gui-order"
name="attributes.gui_order"
/>
</FormGroup>
<ActionGroup>
<Button variant="primary" type="submit">
{t("common:save")}
</Button>
<Button variant="link">{t("common:cancel")}</Button>
</ActionGroup>
</Form>
</PageSection>
);
};

View file

@ -0,0 +1,14 @@
{
"client-scopes": {
"createClientScope": "Create client scope",
"clientScopeList": "List of client scopes",
"name": "Name",
"description": "Description",
"protocol": "Protocol",
"createClientScopeSuccess": "Client scope created",
"createClientScopeError": "Could not create client scope:",
"displayOnConsentScreen": "Display on consent screen",
"consentScreenText": "Consent screen text",
"guiOrder": "GUI Order"
}
}

View file

@ -0,0 +1,24 @@
/**
* https://www.keycloak.org/docs-api/4.1/rest-api/#_protocolmapperrepresentation
*/
export interface ProtocolMapperRepresentation {
config?: Record<string, any>;
id?: string;
name?: string;
protocol?: string;
protocolMapper?: string;
}
/**
* https://www.keycloak.org/docs-api/6.0/rest-api/index.html#_clientscoperepresentation
*/
export interface ClientScopeRepresentation {
attributes?: Record<string, any>;
description?: string;
id?: string;
name?: string;
protocol?: string;
protocolMappers?: ProtocolMapperRepresentation[];
}

View file

@ -1,7 +1,8 @@
import React from "react";
import React, { useContext } from "react";
import { Tooltip } from "@patternfly/react-core";
import { HelpIcon } from "@patternfly/react-icons";
import { useTranslation } from "react-i18next";
import { HelpContext } from "./HelpHeader";
type HelpItemProps = {
item: string;
@ -9,11 +10,16 @@ type HelpItemProps = {
export const HelpItem = ({ item }: HelpItemProps) => {
const { t } = useTranslation();
const { enabled } = useContext(HelpContext);
return (
<Tooltip position="right" content={t(`help:${item}`)}>
<span id={item} data-testid={item}>
<HelpIcon />
</span>
</Tooltip>
<>
{enabled && (
<Tooltip position="right" content={t(`help:${item}`)}>
<span id={item} data-testid={item}>
<HelpIcon />
</span>
</Tooltip>
)}
</>
);
};

View file

@ -1,5 +1,13 @@
{
"help": {
"storybook": "Sometimes you need some help and it's nice when the app does that"
"storybook": "Sometimes you need some help and it's nice when the app does that",
"clientScope": {
"name": "Name of the client scope. Must be unique in the realm. Name should not contain space characters as it is used as value of scope parameter",
"description": "Description of the client scope",
"protocol": "Which SSO protocol configuration is being supplied by this client scope",
"displayOnConsentScreen": "If on, and this client scope is added to some client with consent required, the text specified by 'Consent Screen Text' will be displayed on consent screen. If off, this client scope will not be displayed on the consent screen",
"consentScreenText": "Text that will be shown on the consent screen when this client scope is added to some client with consent required. Defaults to name of client scope if it is not filled",
"guiOrder": "Specify order of the provider in GUI (such as in Consent page) as integer"
}
}
}

View file

@ -4,15 +4,15 @@ import { initReactI18next } from "react-i18next";
import common from "./common-messages.json";
import clients from "./clients/messages.json";
import clientScopes from "./client-scopes/messages.json";
import realm from "./realm/messages.json";
import roles from "./realm-roles/messages.json";
import help from "./help.json";
const initOptions = {
ns: ["common", "help", "clients", "realm", "roles"],
defaultNS: "common",
resources: {
en: { ...common, ...help, ...clients, ...realm, ...roles },
en: { ...common, ...help, ...clients, ...clientScopes, ...realm, ...roles },
},
lng: "en",
fallbackLng: "en",

View file

@ -1,3 +1,5 @@
import { ClientScopeRepresentation } from "../../client-scopes/models/client-scope";
export interface RealmRepresentation {
id: string;
realm: string;
@ -231,15 +233,6 @@ export interface ClientRepresentation {
origin: string;
}
export interface ClientScopeRepresentation {
id: string;
name: string;
description: string;
protocol: string;
attributes: { [index: string]: string };
protocolMappers: ProtocolMapperRepresentation[];
}
export interface UserFederationProviderRepresentation {
id: string;
displayName: string;