Skip to content

Commit ef7ca9e

Browse files
authored
feat(identities) show expiration in identity list (canonical#2186)
## Done - feat(identities) show expiration in identity list ## QA 1. Run the LXD-UI: - On the demo server via the link posted by @webteam-app below. This is only available for PRs created by collaborators of the repo. Ask @Kxiru or @edlerd for access. - With a local copy of this branch, [build and run as described in the docs](https://github.com/canonical/lxd-ui/blob/main/CONTRIBUTING.md#setting-up-for-development). 2. Perform the following QA steps: - open permissions > identities - issue a new token for expiry in 1 second - check expiry warning within list ## Screenshots [if relevant, include a screenshot or screen capture]
2 parents 053fd3c + 0a2c7d2 commit ef7ca9e

3 files changed

Lines changed: 42 additions & 0 deletions

File tree

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { type FC } from "react";
2+
import { isBeforeNow, isoTimeToString, UNDEFINED_DATE } from "util/helpers";
3+
import type { LxdIdentity } from "types/permissions";
4+
import { Icon, Tooltip } from "@canonical/react-components";
5+
6+
interface Props {
7+
identity: LxdIdentity;
8+
}
9+
10+
const IdentityExpiration: FC<Props> = ({ identity }) => {
11+
const expiry = identity.expires_at ?? UNDEFINED_DATE;
12+
const isValid = expiry !== UNDEFINED_DATE;
13+
const isExpired = isBeforeNow(expiry);
14+
const caption = isValid ? isoTimeToString(expiry) : "-";
15+
16+
return isExpired ? (
17+
<Tooltip message="Has expired" position="right">
18+
<span>{caption}</span>
19+
<Icon name="warning" className="u-margin-left--small" />
20+
</Tooltip>
21+
) : (
22+
caption
23+
);
24+
};
25+
26+
export default IdentityExpiration;

src/pages/permissions/PermissionIdentities.tsx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ import {
4141
import CreateIdentity from "pages/permissions/CreateIdentity";
4242
import PermissionIdentitiesActions from "pages/permissions/PermissionIdentitiesActions";
4343
import ResourceLabel from "components/ResourceLabel";
44+
import IdentityExpiration from "pages/permissions/IdentityExpiration";
4445
import EditIdentityGroupsPanel from "./panels/EditIdentityGroupsPanel";
4546

4647
const PermissionIdentities: FC = () => {
@@ -74,6 +75,7 @@ const PermissionIdentities: FC = () => {
7475
{ content: "ID", sortKey: "id", className: "identity-id" },
7576
{ content: "Auth method", sortKey: "authmethod", className: "auth-method" },
7677
{ content: "Type", sortKey: "type", className: "identity-type" },
78+
{ content: "Expires", sortKey: "expires", className: "expires" },
7779
{
7880
content: "Groups",
7981
sortKey: "groups",
@@ -183,6 +185,11 @@ const PermissionIdentities: FC = () => {
183185
"aria-label": "Type",
184186
className: "u-truncate identity-type",
185187
},
188+
{
189+
content: <IdentityExpiration identity={identity} />,
190+
role: "cell",
191+
"aria-label": "Expires",
192+
},
186193
{
187194
content: getGroupLink(),
188195
role: "cell",
@@ -224,6 +231,7 @@ const PermissionIdentities: FC = () => {
224231
name: name.toLowerCase(),
225232
authentication_method: identity.authentication_method,
226233
type: identity.type,
234+
expires: identity.expires_at ?? "",
227235
groups: identity.groups?.length || 0,
228236
},
229237
};

src/util/helpers.tsx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,14 @@ export const isoTimeToString = (isoTime: string): string => {
3434
});
3535
};
3636

37+
export const isBeforeNow = (time: string): boolean => {
38+
if (!time || time === UNDEFINED_DATE) {
39+
return false;
40+
}
41+
const parsed = Date.parse(time);
42+
return !Number.isNaN(parsed) && parsed < Date.now();
43+
};
44+
3745
export const stringToIsoTime = (dateTime: string): string => {
3846
const date = new Date(dateTime);
3947
return date.toISOString();

0 commit comments

Comments
 (0)