Skip to content

Commit

Permalink
Merge branch 'main' into issue-23930
Browse files Browse the repository at this point in the history
  • Loading branch information
edewit authored Oct 17, 2023
2 parents ecf1f7e + 0d008df commit b020eb3
Show file tree
Hide file tree
Showing 159 changed files with 1,736 additions and 941 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -509,7 +509,7 @@ jobs:
timeout-minutes: 75
strategy:
matrix:
browser: [chrome, firefox]
browser: [chrome]
fail-fast: false
steps:
- uses: actions/checkout@v4
Expand All @@ -519,7 +519,7 @@ jobs:
uses: ./.github/actions/integration-test-setup

- name: Run Account Console IT
run: ./mvnw test ${{ env.SUREFIRE_RETRY }} -Pauth-server-quarkus -Dtest=**.account2.**,!SigningInTest#passwordlessWebAuthnTest,!SigningInTest#twoFactorWebAuthnTest -Dbrowser=${{ matrix.browser }} "-Dwebdriver.chrome.driver=$CHROMEWEBDRIVER/chromedriver" "-Dwebdriver.gecko.driver=$GECKOWEBDRIVER/geckodriver" -f testsuite/integration-arquillian/tests/other/base-ui/pom.xml | misc/log/trimmer.sh
run: ./mvnw test ${{ env.SUREFIRE_RETRY }} -Pauth-server-quarkus -Dtest=**.account2.**,!SigningInTest#passwordlessWebAuthnTest,!SigningInTest#twoFactorWebAuthnTest -Dbrowser=${{ matrix.browser }} "-Dwebdriver.chrome.driver=$CHROMEWEBDRIVER/chromedriver" -f testsuite/integration-arquillian/tests/other/base-ui/pom.xml | misc/log/trimmer.sh

- name: Upload JVM Heapdumps
if: always()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@
* @version $Revision: 1 $
*/
public class JsonWebToken implements Serializable, Token {
public static final String AZP = "azp";
public static final String SUBJECT = "sub";

@JsonProperty("jti")
protected String id;

Expand All @@ -53,11 +56,11 @@ public class JsonWebToken implements Serializable, Token {
@JsonSerialize(using = StringOrArraySerializer.class)
@JsonDeserialize(using = StringOrArrayDeserializer.class)
protected String[] audience;
@JsonProperty("sub")
@JsonProperty(SUBJECT)
protected String subject;
@JsonProperty("typ")
protected String type;
@JsonProperty("azp")
@JsonProperty(AZP)
public String issuedFor;
protected Map<String, Object> otherClaims = new HashMap<>();

Expand Down Expand Up @@ -184,7 +187,7 @@ public JsonWebToken iat(Long iat) {
this.iat = iat;
return this;
}

/**
* @deprecated int will overflow with values after 2038. Use {@link #iat(Long)} ()} instead.
*/
Expand Down
26 changes: 0 additions & 26 deletions docs/documentation/.github/workflows/test-external-links.yml

This file was deleted.

25 changes: 0 additions & 25 deletions docs/documentation/.github/workflows/test-guides.yml

This file was deleted.

2 changes: 1 addition & 1 deletion docs/documentation/server_admin/topics/vault.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ All built-in providers support the configuration of key resolvers. A key resolve

[source,bash]
----
kc.[sh.bat] start --spi-vault-file-key-resolvers=REALM_UNDERSCORE_KEY,KEY_ONLY
kc.[sh|bat] start --spi-vault-file-key-resolvers=REALM_UNDERSCORE_KEY,KEY_ONLY
----

The resolvers run in the same order you declare them in the configuration. For each resolver, {project_name} uses the last entry name the resolver produces, which combines the realm with the vault key to search for the vault's secret. If {project_name} finds a secret, it returns the secret. If not, {project_name} uses the next resolver. This search continues until {project_name} finds a non-empty secret or runs out of resolvers. If {project_name} finds no secret, {project_name} returns an empty secret.
Expand Down
2 changes: 1 addition & 1 deletion docs/guides/getting-started/getting-started-openshift.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ oc process -f https://raw.githubusercontent.com/keycloak/keycloak-quickstarts/la
| oc create -f -
----
+
In this example, the user name and and password are `admin`.
In this example, the user name and password are `admin`.

. Once the command above completes, look for a message similar to this:
+
Expand Down
11 changes: 9 additions & 2 deletions docs/guides/getting-started/getting-started-zip.adoc
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<#import "/templates/guide.adoc" as tmpl>
<#import "/templates/profile.adoc" as profile>

<@tmpl.guide
title="OpenJDK"
Expand All @@ -10,14 +11,20 @@ summary="Get started with Keycloak on bare metal">

== Before you start

Make sure you have https://openjdk.java.net/[OpenJDK 17] or a higher version installed.
Make sure you have https://openjdk.java.net/[OpenJDK 17] installed.

== Download Keycloak

Download and extract https://github.com/keycloak/keycloak/releases/download/{version}/keycloak-{version}.zip[keycloak-{version}.zip]
from the Keycloak website.

After extracting this file, you should have a directory named keycloak-{version}.
<@profile.ifCommunity>
After extracting this file, you should have a directory with a name that starts with `keycloak-{version}`.
</@profile.ifCommunity>

<@profile.ifProduct>
After extracting this file, you should have a directory with a name that starts with `rhbk-{version}`.
</@profile.ifProduct>

include::templates/start-keycloak-localhost.adoc[]

Expand Down
2 changes: 1 addition & 1 deletion docs/guides/getting-started/templates/realm-config.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,6 @@ This user needs a password to log in. To set the initial password:

. Click *Credentials* at the top of the page.
. Fill in the *Set password* form with a password.
. Toggle *Temporary* to *Off* so that the user does not need update this password at the first login.
. Toggle *Temporary* to *Off* so that the user does not need to update this password at the first login.

image::set-password.png[Set password]
Original file line number Diff line number Diff line change
@@ -1,7 +1,18 @@
<#import "/templates/profile.adoc" as profile>

== Start Keycloak

. From a terminal, open the keycloak-{version} directory.
. Enter the following command:
<@profile.ifProduct>
+
[source,bash,subs="attributes+"]
----
bin/kc.sh start-dev
----
</@profile.ifProduct>

<@profile.ifCommunity>
* On Linux, run:
+
[source,bash,subs="attributes+"]
Expand All @@ -15,3 +26,7 @@ bin/kc.sh start-dev
----
bin\kc.bat start-dev
----
</@profile.ifCommunity>

Using the `start-dev` option, you are starting Keycloak development mode. In this mode, you can try out Keycloak for the first time to get it up and running quickly. This mode offers convenient defaults for developers, such as for developing a new Keycloak theme.

2 changes: 1 addition & 1 deletion docs/guides/operator/basic-deployment.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ Once the Keycloak Operator is installed and running in the cluster namespace, yo

A database should be available and accessible from the cluster namespace where Keycloak is installed.
For a list of supported databases, see <@links.server id="db"/>.
The Keycloak Operator does not manage the database and you need to provision it yourself. Consider verifying your cloud provider offering or using a database operator such as https://access.crunchydata.com/documentation/postgres-operator/latest/[Crunchy].
The Keycloak Operator does not manage the database and you need to provision it yourself. Consider verifying your cloud provider offering or using a database operator.

For development purposes, you can use an ephemeral PostgreSQL pod installation. To provision it, follow the approach below:

Expand Down
4 changes: 2 additions & 2 deletions js/apps/account-ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,13 @@
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-hook-form": "^7.47.0",
"react-i18next": "^13.2.2",
"react-i18next": "^13.3.0",
"react-router-dom": "^6.15.0",
"ui-shared": "workspace:*"
},
"devDependencies": {
"@keycloak/keycloak-admin-client": "workspace:*",
"@playwright/test": "^1.38.1",
"@playwright/test": "^1.39.0",
"@types/lodash-es": "^4.17.9",
"@types/react": "^18.2.28",
"@types/react-dom": "^18.2.13",
Expand Down
11 changes: 1 addition & 10 deletions js/apps/account-ui/playwright.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export default defineConfig({
fullyParallel: true,
forbidOnly: !!process.env.CI,
retries: process.env.CI ? 2 : 0,
workers: process.env.CI ? 1 : undefined,
workers: 1,
reporter: "html",
use: {
baseURL: process.env.CI
Expand Down Expand Up @@ -38,15 +38,6 @@ export default defineConfig({
dependencies: ["setup", "import realms"],
testIgnore: ["**/personal-info.spec.ts"],
},
{
name: "firefox",
use: {
...devices["Desktop Firefox"],
storageState: ".auth/user.json",
},
dependencies: ["setup", "import realms"],
testIgnore: ["**/personal-info.spec.ts"],
},
{
name: "personal-info",
use: {
Expand Down
19 changes: 16 additions & 3 deletions js/apps/account-ui/public/locales/fr/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"accept": "Accepter",
"accessGrantedOn": "Accès autorisé le : ",
"accountSecurity": "Sécurité du compte",
"accountUpdatedError": "Impossible de metter à jour votre compte à cause des erreurs de validation",
"accountUpdatedError": "Impossible de mettre à jour votre compte à cause des erreurs de validation",
"accountUpdatedMessage": "Votre compte a été mis à jour.",
"add": "Ajouter",
"application": "Application",
Expand Down Expand Up @@ -90,7 +90,7 @@
"permissionRequest": "Demandes d'autorisation - {{name}}",
"permissionRequests": "Demandes d'autorisation",
"permissions": "Autorisations",
"personalInfo": "Informations personelles",
"personalInfo": "Informations personnelles",
"personalInfoDescription": "Gérez vos informations de base",
"privacyPolicy": "Politique de confidentialité",
"refreshPage": "Rafraichir la page",
Expand Down Expand Up @@ -157,5 +157,18 @@
"updateSuccess": "Ressource mise à jour avec succès.",
"user": "Utilisateur",
"username": "Nom d'utilisateur",
"usernamePlaceholder": "Nom d'utiisateur ou courriel"
"usernamePlaceholder": "Nom d'utilisateur ou courriel",
"groupsListHeader": "En-tête de la liste des groupes",
"groupsListColumnsNames": "Nom des colonnes de la liste des groupes",
"aliasHelp": "Nom de la configuration",
"flowTypeHelp": "De quel genre de formulaire s'agit-il",
"createFlowHelp": "Vous pouvez créer un flow de premier niveau au sein de ce formulaire",
"rolesScope": "S'il n'y a aucun mappage de portée de rôle défini, chaque utilisateur est autorisé à utiliser cette portée du client. S'il y a des mappages de portée de rôle, l'utilisateur doit être membre d'au moins l'un des rôles.",
"scopeNameHelp": "Nom de la portée du client. Doit être unique dans le domaine. Le nom ne doit pas contenir d'espace car il est utilisé comme valeur du paramètre de la portée",
"scopeDescriptionHelp": "Description de la portée du client",
"scopeTypeHelp": "Portées du client, qui seront ajoutées comme portées par défaut à chacun des clients créés",
"clientDescriptionHelp": "Spécifie la description du client. Par exemple, « Mon client pour TimeSheet ». Prend également en charge les clés pour les valeurs localisées. Par exemple : ${my_client_description}",
"clientTypeHelp": "Le type de cette ressource. Il peut être utilisé pour grouper ensemble différentes instances de ressources avec le même type.",
"scopesHelp": "Les portées associées à cette ressource."
}

2 changes: 2 additions & 0 deletions js/apps/account-ui/src/resources/Resources.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,14 @@ const Resources = () => {
unmountOnExit
>
<Tab
data-testid="myResources"
eventKey={0}
title={<TabTitleText>{t("myResources")}</TabTitleText>}
>
<ResourcesTab />
</Tab>
<Tab
data-testid="sharedWithMe"
eventKey={1}
title={<TabTitleText>{t("sharedWithMe")}</TabTitleText>}
>
Expand Down
1 change: 1 addition & 0 deletions js/apps/account-ui/src/resources/ResourcesTab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@ export const ResourcesTab = ({ isShared = false }: ResourcesTabProps) => {
>
<Tr>
<Td
data-testid={`expand-${resource.name}`}
expand={
!isShared
? {
Expand Down
5 changes: 3 additions & 2 deletions js/apps/account-ui/src/resources/ShareTheResource.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ export const ShareTheResource = ({
<Button
key="confirm"
variant="primary"
id="done"
data-testid="done"
isDisabled={!isValid}
type="submit"
form="share-form"
Expand All @@ -147,6 +147,7 @@ export const ShareTheResource = ({
<InputGroup>
<KeycloakTextInput
id="users"
data-testid="users"
placeholder={t("usernamePlaceholder")}
validated={
errors.usernames
Expand All @@ -160,7 +161,7 @@ export const ShareTheResource = ({
<Button
key="add-user"
variant="primary"
id="add"
data-testid="add"
onClick={() => append({ value: "" })}
isDisabled={isDisabled}
>
Expand Down
10 changes: 6 additions & 4 deletions js/apps/account-ui/src/resources/SharedWith.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@ type SharedWithProps = {
permissions?: Permission[];
};

export const SharedWith = ({ permissions: p = [] }: SharedWithProps) => {
return (
export const SharedWith = ({ permissions: p = [] }: SharedWithProps) => (
<div
data-testid={`shared-with-${p.length ? p.map((e) => e.username) : "none"}`}
>
<Trans i18nKey="resourceSharedWith" count={p.length}>
<strong>
{{
Expand All @@ -20,5 +22,5 @@ export const SharedWith = ({ permissions: p = [] }: SharedWithProps) => {
}}
</strong>
</Trans>
);
};
</div>
);
46 changes: 45 additions & 1 deletion js/apps/account-ui/test/my-resources.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,51 @@ test.describe("My resources page", () => {
test("List my resources", async ({ page }) => {
await login(page, "jdoe", "jdoe", "photoz");
await page.getByTestId("resources").click();
//await expect(page.getByTestId("row[0].name")).toHaveText("one");

await expect(page.getByRole("gridcell", { name: "one" })).toBeVisible();
});

test("Nothing is shared with alice", async ({ page }) => {
await login(page, "alice", "alice", "photoz");
await page.getByTestId("resources").click();

await page.getByTestId("sharedWithMe").click();
const tableData = await page.locator("table > tr").count();
expect(tableData).toBe(0);
});

test("Share one with alice", async ({ page }) => {
await login(page, "jdoe", "jdoe", "photoz");
await page.getByTestId("resources").click();

await page.getByTestId("expand-one").click();
await expect(page.getByText("This resource is not shared.")).toBeVisible();

await page.getByTestId("share-one").click();
await page.getByTestId("users").click();
await page.getByTestId("users").fill("alice");
await page.getByTestId("add").click();

await expect(page.getByRole("group", { name: "Share with" })).toHaveText(
"Share with alice",
);

await page.getByRole("button", { name: "Options menu" }).click();
await page.getByRole("option", { name: "album:view" }).click();
await page.getByRole("button", { name: "Options menu" }).click();

await page.getByTestId("done").click();

await page.getByTestId("expand-one").click();
expect(page.getByTestId("shared-with-alice")).toBeDefined();
});

test("One is shared with alice", async ({ page }) => {
await login(page, "alice", "alice", "photoz");
await page.getByTestId("resources").click();

await page.getByTestId("sharedWithMe").click();
const rowData = await page.getByTestId("row[0].name").allTextContents();
expect(rowData).toEqual(["one"]);
});
});
Loading

0 comments on commit b020eb3

Please sign in to comment.