Skip to content
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
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ public class OrganizationDomainRepresentation {

private String name;
private boolean verified;
private String identityProviderAlias;
private boolean autoRedirect;
Comment on lines +35 to +36

public OrganizationDomainRepresentation() {
// for reflection
Expand All @@ -57,6 +59,22 @@ public void setVerified(boolean verified) {
this.verified = verified;
}

public String getIdentityProviderAlias() {
return this.identityProviderAlias;
}

public void setIdentityProviderAlias(String identityProviderAlias) {
this.identityProviderAlias = identityProviderAlias;
}

public boolean isAutoRedirect() {
return this.autoRedirect;
}

public void setAutoRedirect(boolean autoRedirect) {
this.autoRedirect = autoRedirect;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
Expand Down
4 changes: 0 additions & 4 deletions js/apps/admin-ui/src/organizations/IdentityProviders.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -207,10 +207,6 @@ export const IdentityProviders = () => {
</Link>
),
},
{
name: "config['kc.org.domain']",
displayKey: "domain",
},
{
name: "providerId",
displayKey: "providerDetails",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
import IdentityProviderRepresentation from "@keycloak/keycloak-admin-client/lib/defs/identityProviderRepresentation";
import {
FormSubmitButton,
SelectControl,
TextControl,
} from "@keycloak/keycloak-ui-shared";
import { FormSubmitButton } from "@keycloak/keycloak-ui-shared";
import {
Button,
ButtonVariant,
Expand All @@ -12,7 +8,7 @@ import {
ModalVariant,
} from "@patternfly/react-core";
import { useEffect } from "react";
import { FormProvider, useForm, useFormContext } from "react-hook-form";
import { FormProvider, useForm } from "react-hook-form";
import { useTranslation } from "react-i18next";
import { useAdminClient } from "../admin-client";
import { DefaultSwitchControl } from "../components/SwitchControl";
Expand All @@ -23,7 +19,6 @@ import {
convertToFormValues,
} from "../util";
import { IdentityProviderSelect } from "./IdentityProviderSelect";
import { OrganizationFormType } from "./OrganizationForm";

type LinkIdentityProviderModalProps = {
orgId: string;
Expand All @@ -34,10 +29,7 @@ type LinkIdentityProviderModalProps = {
type LinkRepresentation = {
alias: string[] | string;
hideOnLogin: boolean;
config: {
"kc.org.domain": string;
"kc.org.excluded.domains": string;
};
config: Record<string, string>;
Comment on lines 29 to +32
};

export const LinkIdentityProviderModal = ({
Expand All @@ -51,7 +43,6 @@ export const LinkIdentityProviderModal = ({

const form = useForm<LinkRepresentation>({ mode: "onChange" });
const { handleSubmit, formState, setValue } = form;
const { getValues } = useFormContext<OrganizationFormType>();

useEffect(
() =>
Expand Down Expand Up @@ -139,24 +130,6 @@ export const LinkIdentityProviderModal = ({
isRequired
isDisabled={!!identityProvider}
/>
<SelectControl
name={convertAttributeNameToForm("config.kc.org.domain")}
label={t("domain")}
controller={{ defaultValue: "" }}
options={[
{ key: "", value: t("none") },
{ key: "ANY", value: t("any") },
...(getValues("domains")
? getValues("domains")!.map((d) => ({ key: d, value: d }))
: []),
]}
menuAppendTo="parent"
/>
<TextControl
label={t("excludedDomains")}
name={convertAttributeNameToForm("config.kc.org.excluded.domains")}
labelIcon={t("excludedDomainsHelp")}
/>
<DefaultSwitchControl
name="hideOnLogin"
label={t("hideOnLoginPage")}
Expand All @@ -179,14 +152,6 @@ export const LinkIdentityProviderModal = ({
labelIcon={t("showOnLoginForUnlinkedMembersHelp")}
stringify
/>
<DefaultSwitchControl
name={convertAttributeNameToForm(
"config.kc.org.broker.redirect.mode.email-matches",
)}
label={t("redirectWhenEmailMatches")}
labelIcon={t("redirectWhenEmailMatchesHelp")}
stringify
/>
</Form>
</FormProvider>
</Modal>
Expand Down
2 changes: 1 addition & 1 deletion js/apps/admin-ui/test/organization/idp.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ test.describe.serial("Identity providers", () => {
test("should add idp", async ({ page }) => {
await assertEmptyTable(page);
await clickAddIdentityProvider(page);
await fillForm(page, { name: "bitbucket", domain: "o.com" });
await fillForm(page, { name: "bitbucket" });
await confirmModal(page);
await assertNotificationMessage(
page,
Expand Down
6 changes: 0 additions & 6 deletions js/apps/admin-ui/test/organization/idp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,7 @@ export async function fillForm(
page: Page,
data: {
name: string;
domain: string;
},
) {
await selectItem(page, page.getByTestId("alias"), data.name);
await selectItem(
page,
page.locator("#config\\.kc🍺org🍺domain"),
data.domain,
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ private static String cacheKeyIdpCount(RealmModel realm) {
return realm.getId() + IDP_COUNT_KEY_SUFFIX;
}

private static String cacheKeyIdpAlias(RealmModel realm, String alias) {
public static String cacheKeyIdpAlias(RealmModel realm, String alias) {
return realm.getId() + "." + alias + IDP_ALIAS_KEY_SUFFIX;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import org.keycloak.authorization.fgap.AdminPermissionsSchema;
import org.keycloak.models.GroupModel;
import org.keycloak.models.IdentityProviderModel;
import org.keycloak.models.IdentityProviderStorageProvider.FetchMode;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.OrganizationModel;
import org.keycloak.models.RealmModel;
Expand All @@ -38,6 +39,8 @@
import org.keycloak.organization.InvitationManager;
import org.keycloak.organization.OrganizationProvider;

import static org.keycloak.models.cache.infinispan.idp.InfinispanIdentityProviderStorageProvider.cacheKeyForLogin;
import static org.keycloak.models.cache.infinispan.idp.InfinispanIdentityProviderStorageProvider.cacheKeyIdpAlias;
import static org.keycloak.models.cache.infinispan.idp.InfinispanIdentityProviderStorageProvider.cacheKeyOrgId;

public class InfinispanOrganizationProvider implements OrganizationProvider {
Expand Down Expand Up @@ -88,9 +91,15 @@ OrganizationProvider getDelegate() {

@Override
public boolean remove(OrganizationModel organization) {
// capture IdPs before deletion so we can invalidate their cache entries
java.util.List<IdentityProviderModel> idps = organization.getIdentityProviders().toList();
registerOrganizationInvalidation(organization);
registerCountInvalidation();
return getDelegate().remove(organization);
boolean removed = getDelegate().remove(organization);
if (removed) {
idps.forEach(this::registerIdentityProviderInvalidation);
}
return removed;
}

@Override
Expand Down Expand Up @@ -386,6 +395,7 @@ public boolean addIdentityProvider(OrganizationModel organization, IdentityProvi
boolean added = getDelegate().addIdentityProvider(organization, identityProvider);
if (added) {
registerOrganizationInvalidation(organization);
registerIdentityProviderInvalidation(identityProvider);
}
return added;
}
Expand All @@ -400,6 +410,7 @@ public boolean removeIdentityProvider(OrganizationModel organization, IdentityPr
boolean removed = getDelegate().removeIdentityProvider(organization, identityProvider);
if (removed) {
registerOrganizationInvalidation(organization);
registerIdentityProviderInvalidation(identityProvider);
}
return removed;
}
Expand Down Expand Up @@ -465,6 +476,16 @@ void registerOrganizationInvalidation(OrganizationModel organization) {
}
}

private void registerIdentityProviderInvalidation(IdentityProviderModel idp) {
if (realmCache != null) {
realmCache.registerInvalidation(idp.getInternalId());
realmCache.registerInvalidation(cacheKeyIdpAlias(getRealm(), idp.getAlias()));
for (FetchMode mode : FetchMode.values()) {
realmCache.registerInvalidation(cacheKeyForLogin(getRealm(), mode));
}
}
}

private void registerCountInvalidation() {
if (realmCache != null) {
realmCache.registerInvalidation(cacheKeyOrgCount(getRealm()));
Expand Down
Loading
Loading