Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
gitpod-io
GitHub Repository: gitpod-io/gitpod
Path: blob/main/components/dashboard/src/user-settings/TokenEntry.tsx
2500 views
1
/**
2
* Copyright (c) 2022 Gitpod GmbH. All rights reserved.
3
* Licensed under the GNU Affero General Public License (AGPL).
4
* See License.AGPL.txt in the project root for license information.
5
*/
6
7
import { PersonalAccessToken } from "@gitpod/public-api/lib/gitpod/experimental/v1/tokens_pb";
8
import dayjs from "dayjs";
9
import { ContextMenuEntry } from "../components/ContextMenu";
10
import { ItemFieldContextMenu } from "../components/ItemsList";
11
import Tooltip from "../components/Tooltip";
12
import { ReactComponent as ExclamationIcon } from "../images/exclamation.svg";
13
import { ReactComponent as WarningIcon } from "../images/exclamation2.svg";
14
import { AllPermissions, isNeverExpired } from "./PersonalAccessTokens";
15
import { useMemo } from "react";
16
17
interface TokenEntryProps {
18
token: PersonalAccessToken;
19
menuEntries: ContextMenuEntry[];
20
}
21
22
function TokenEntry(props: TokenEntryProps) {
23
const expiredInfo = useMemo(() => {
24
const expiration = props.token.expirationTime!.toDate();
25
if (isNeverExpired(expiration)) {
26
return {
27
expired: false,
28
content: "Never expires!",
29
tooltip: {
30
content: "The token will never expire!",
31
icon: <WarningIcon className="h-4 w-4" />,
32
},
33
};
34
}
35
const expirationTime = dayjs(expiration);
36
const expired = expirationTime.isBefore(dayjs());
37
return {
38
expired,
39
content: expirationTime.format("MMM D, YYYY"),
40
tooltip: expired
41
? {
42
content: expirationTime.format("MMM D, YYYY, hh:mm A"),
43
icon: <ExclamationIcon fill="#D97706" className="h-4 w-4" />,
44
}
45
: undefined,
46
};
47
}, [props.token.expirationTime]);
48
49
const getScopes = () => {
50
if (!props.token.scopes) {
51
return "";
52
}
53
const permissions = AllPermissions.filter((e) => e.scopes.every((v) => props.token.scopes.includes(v)));
54
if (permissions.length > 0) {
55
return permissions.map((e) => e.name).join("\n");
56
} else {
57
return "No access";
58
}
59
};
60
61
return (
62
<div className="rounded-xl whitespace-nowrap flex space-x-2 py-4 px-4 w-full justify-between hover:bg-gray-100 dark:hover:bg-gray-800 focus:bg-kumquat-light group">
63
<div className="flex items-center pr-3 w-4/12">
64
<span className="truncate">{props.token.name || ""}</span>
65
</div>
66
<div className="flex items-center w-4/12 text-gray-400 font-medium">
67
<span className="truncate whitespace-pre-line">{getScopes()}</span>
68
</div>
69
<div className="flex items-center w-3/12 text-gray-400">
70
<span className={"flex items-center gap-2 truncate" + (expiredInfo.expired ? " text-orange-600" : "")}>
71
{expiredInfo.tooltip && (
72
<Tooltip content={expiredInfo.tooltip.content}>{expiredInfo.tooltip.icon}</Tooltip>
73
)}
74
<span>{expiredInfo.content}</span>
75
</span>
76
</div>
77
<div className="flex items-center justify-end w-1/12">
78
<ItemFieldContextMenu menuEntries={props.menuEntries} />
79
</div>
80
</div>
81
);
82
}
83
84
export default TokenEntry;
85
86