2020-12-16 06:58:00 +00:00
|
|
|
import React, { useContext, useState } from "react";
|
2020-12-09 21:55:17 +00:00
|
|
|
import { useTranslation } from "react-i18next";
|
|
|
|
import {
|
|
|
|
AlertVariant,
|
|
|
|
Button,
|
|
|
|
ButtonVariant,
|
|
|
|
Label,
|
|
|
|
PageSection,
|
|
|
|
ToolbarItem,
|
|
|
|
} from "@patternfly/react-core";
|
2020-12-16 06:58:00 +00:00
|
|
|
import { InfoCircleIcon, WarningTriangleIcon } from "@patternfly/react-icons";
|
2020-12-09 21:55:17 +00:00
|
|
|
import UserRepresentation from "keycloak-admin/lib/defs/userRepresentation";
|
|
|
|
|
|
|
|
import { useAdminClient } from "../context/auth/AdminClient";
|
|
|
|
import { ViewHeader } from "../components/view-header/ViewHeader";
|
2020-12-11 10:28:38 +00:00
|
|
|
import { KeycloakDataTable } from "../components/table-toolbar/KeycloakDataTable";
|
2020-12-09 21:55:17 +00:00
|
|
|
import { useAlerts } from "../components/alert/Alerts";
|
2020-12-16 06:58:00 +00:00
|
|
|
import { RealmContext } from "../context/realm-context/RealmContext";
|
|
|
|
|
|
|
|
type BruteUser = UserRepresentation & {
|
|
|
|
brute?: Record<string, object>;
|
|
|
|
};
|
2020-09-09 09:07:17 +00:00
|
|
|
|
2020-09-10 18:04:03 +00:00
|
|
|
export const UsersSection = () => {
|
2020-12-09 21:55:17 +00:00
|
|
|
const { t } = useTranslation("users");
|
|
|
|
const adminClient = useAdminClient();
|
|
|
|
const { addAlert } = useAlerts();
|
2020-12-16 06:58:00 +00:00
|
|
|
const { realm: realmName } = useContext(RealmContext);
|
|
|
|
|
2020-12-09 21:55:17 +00:00
|
|
|
const [key, setKey] = useState("");
|
|
|
|
const refresh = () => setKey(`${new Date().getTime()}`);
|
|
|
|
|
|
|
|
const loader = async (first?: number, max?: number, search?: string) => {
|
|
|
|
const params: { [name: string]: string | number } = {
|
|
|
|
first: first!,
|
|
|
|
max: max!,
|
|
|
|
};
|
|
|
|
if (search) {
|
|
|
|
params.search = search;
|
|
|
|
}
|
2020-12-16 06:58:00 +00:00
|
|
|
|
|
|
|
const users = await adminClient.users.find({ ...params });
|
|
|
|
const realm = await adminClient.realms.findOne({ realm: realmName });
|
|
|
|
if (realm?.bruteForceProtected) {
|
|
|
|
const brutes = await Promise.all(
|
|
|
|
users.map((user: BruteUser) =>
|
|
|
|
adminClient.attackDetection.findOne({
|
|
|
|
id: user.id!,
|
|
|
|
})
|
|
|
|
)
|
|
|
|
);
|
|
|
|
for (let index = 0; index < users.length; index++) {
|
|
|
|
const user: BruteUser = users[index];
|
|
|
|
user.brute = brutes[index];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return users;
|
2020-12-09 21:55:17 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
const deleteUser = async (user: UserRepresentation) => {
|
|
|
|
try {
|
|
|
|
await adminClient.users.del({ id: user.id! });
|
|
|
|
refresh();
|
|
|
|
addAlert(t("userDeletedSuccess"), AlertVariant.success);
|
|
|
|
} catch (error) {
|
|
|
|
addAlert(t("userDeletedError", { error }), AlertVariant.danger);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2020-12-16 06:58:00 +00:00
|
|
|
const StatusRow = (user: BruteUser) => {
|
2020-12-09 21:55:17 +00:00
|
|
|
return (
|
|
|
|
<>
|
|
|
|
{!user.enabled && (
|
2020-12-16 06:58:00 +00:00
|
|
|
<Label key={user.id} color="red" icon={<InfoCircleIcon />}>
|
2020-12-09 21:55:17 +00:00
|
|
|
{t("disabled")}
|
|
|
|
</Label>
|
|
|
|
)}
|
2020-12-16 06:58:00 +00:00
|
|
|
{user.brute?.disabled && (
|
|
|
|
<Label key={user.id} color="orange" icon={<WarningTriangleIcon />}>
|
|
|
|
{t("temporaryDisabled")}
|
|
|
|
</Label>
|
|
|
|
)}
|
2020-12-09 21:55:17 +00:00
|
|
|
</>
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
2020-09-18 08:04:55 +00:00
|
|
|
return (
|
|
|
|
<>
|
2020-12-09 21:55:17 +00:00
|
|
|
<ViewHeader titleKey="users:title" subKey="users:userExplain" />
|
|
|
|
<PageSection variant="light">
|
2020-12-11 10:18:29 +00:00
|
|
|
<KeycloakDataTable
|
2020-12-09 21:55:17 +00:00
|
|
|
key={key}
|
|
|
|
loader={loader}
|
|
|
|
isPaginated
|
|
|
|
ariaLabelKey="users:title"
|
|
|
|
searchPlaceholderKey="users:searchForUser"
|
|
|
|
toolbarItem={
|
|
|
|
<>
|
|
|
|
<ToolbarItem>
|
|
|
|
<Button>{t("addUser")}</Button>
|
|
|
|
</ToolbarItem>
|
|
|
|
<ToolbarItem>
|
|
|
|
<Button variant={ButtonVariant.plain}>{t("deleteUser")}</Button>
|
|
|
|
</ToolbarItem>
|
|
|
|
</>
|
|
|
|
}
|
|
|
|
actions={[
|
|
|
|
{
|
|
|
|
title: t("common:delete"),
|
|
|
|
onRowClick: (user) => {
|
|
|
|
deleteUser(user);
|
|
|
|
},
|
|
|
|
},
|
|
|
|
]}
|
|
|
|
columns={[
|
|
|
|
{
|
|
|
|
name: "username",
|
|
|
|
displayKey: "users:username",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "email",
|
|
|
|
displayKey: "users:email",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "lastName",
|
|
|
|
displayKey: "users:lastName",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "firstName",
|
|
|
|
displayKey: "users:firstName",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "status",
|
|
|
|
displayKey: "users:status",
|
|
|
|
cellRenderer: StatusRow,
|
|
|
|
},
|
|
|
|
]}
|
|
|
|
/>
|
|
|
|
</PageSection>
|
2020-09-18 08:04:55 +00:00
|
|
|
</>
|
|
|
|
);
|
2020-09-09 09:07:17 +00:00
|
|
|
};
|