Skip to content

Commit 85fd25d

Browse files
committed
show service account status and expiry in ui
1 parent 2d94018 commit 85fd25d

File tree

11 files changed

+303
-75
lines changed

11 files changed

+303
-75
lines changed

models/service_accounts.go

Lines changed: 97 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

portal-ui/src/api/consoleApi.ts

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -728,7 +728,13 @@ export interface BulkUserGroups {
728728
groups: string[];
729729
}
730730

731-
export type ServiceAccounts = string[];
731+
export type ServiceAccounts = {
732+
accountStatus?: string;
733+
name?: string;
734+
description?: string;
735+
expiration?: string;
736+
accessKey?: string;
737+
}[];
732738

733739
export interface ServiceAccountRequest {
734740
/** policy to be applied to the Service Account if any */
@@ -3565,7 +3571,7 @@ export class Api<
35653571
* @secure
35663572
*/
35673573
listUsersForPolicy: (policy: string, params: RequestParams = {}) =>
3568-
this.request<ServiceAccounts, Error>({
3574+
this.request<string[], Error>({
35693575
path: `/policies/${policy}/users`,
35703576
method: "GET",
35713577
secure: true,
@@ -3583,7 +3589,7 @@ export class Api<
35833589
* @secure
35843590
*/
35853591
listGroupsForPolicy: (policy: string, params: RequestParams = {}) =>
3586-
this.request<ServiceAccounts, Error>({
3592+
this.request<string[], Error>({
35873593
path: `/policies/${policy}/groups`,
35883594
method: "GET",
35893595
secure: true,
@@ -3717,7 +3723,7 @@ export class Api<
37173723
},
37183724
params: RequestParams = {},
37193725
) =>
3720-
this.request<ServiceAccounts, Error>({
3726+
this.request<string[], Error>({
37213727
path: `/bucket-users/${bucket}`,
37223728
method: "GET",
37233729
query: query,
@@ -4472,7 +4478,7 @@ export class Api<
44724478
* @secure
44734479
*/
44744480
listNodes: (params: RequestParams = {}) =>
4475-
this.request<ServiceAccounts, Error>({
4481+
this.request<string[], Error>({
44764482
path: `/nodes`,
44774483
method: "GET",
44784484
secure: true,

portal-ui/src/screens/Console/Account/Account.tsx

Lines changed: 31 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ import {
2929
} from "mds";
3030
import { useSelector } from "react-redux";
3131
import { useNavigate } from "react-router-dom";
32-
import { stringSort } from "../../../utils/sortFunctions";
3332
import { actionsTray } from "../Common/FormComponents/common/styleLibrary";
3433

3534
import ChangePasswordModal from "./ChangePasswordModal";
@@ -57,6 +56,9 @@ import PageHeaderWrapper from "../Common/PageHeaderWrapper/PageHeaderWrapper";
5756
import { api } from "api";
5857
import { errorToHandler } from "api/errors";
5958
import HelpMenu from "../HelpMenu";
59+
import { ServiceAccounts } from "../../../api/consoleApi";
60+
import { usersSort } from "../../../utils/sortFunctions";
61+
import { ACCOUNT_TABLE_COLUMNS } from "./AccountUtils";
6062

6163
const DeleteServiceAccount = withSuspense(
6264
React.lazy(() => import("./DeleteServiceAccount")),
@@ -68,7 +70,7 @@ const Account = () => {
6870

6971
const features = useSelector(selFeatures);
7072

71-
const [records, setRecords] = useState<string[]>([]);
73+
const [records, setRecords] = useState<ServiceAccounts>([]);
7274
const [loading, setLoading] = useState<boolean>(false);
7375
const [filter, setFilter] = useState<string>("");
7476
const [deleteOpen, setDeleteOpen] = useState<boolean>(false);
@@ -97,10 +99,9 @@ const Account = () => {
9799
api.serviceAccounts
98100
.listUserServiceAccounts()
99101
.then((res) => {
100-
const serviceAccounts = res.data.sort(stringSort);
101-
102102
setLoading(false);
103-
setRecords(serviceAccounts);
103+
const sortedRows = res.data.sort(usersSort);
104+
setRecords(sortedRows);
104105
})
105106
.catch((err) => {
106107
dispatch(setErrorSnackMessage(errorToHandler(err.error)));
@@ -136,14 +137,6 @@ const Account = () => {
136137
setPolicyOpen(true);
137138
};
138139

139-
const selectAllItems = () => {
140-
if (selectedSAs.length === records.length) {
141-
setSelectedSAs([]);
142-
return;
143-
}
144-
setSelectedSAs(records);
145-
};
146-
147140
const closePolicyModal = () => {
148141
setPolicyOpen(false);
149142
setLoading(true);
@@ -155,12 +148,27 @@ const Account = () => {
155148
};
156149

157150
const tableActions = [
158-
{ type: "view", onClick: policyModalOpen },
159-
{ type: "delete", onClick: confirmDeleteServiceAccount },
151+
{
152+
type: "view",
153+
onClick: (value: any) => {
154+
if (value) {
155+
policyModalOpen(value.accessKey);
156+
}
157+
},
158+
},
159+
{
160+
type: "delete",
161+
onClick: (value: any) => {
162+
if (value) {
163+
confirmDeleteServiceAccount(value.accessKey);
164+
}
165+
},
166+
},
160167
];
161168

162-
const filteredRecords = records.filter((elementItem) =>
163-
elementItem.toLowerCase().includes(filter.toLowerCase()),
169+
const filteredRecords = records.filter(
170+
(elementItem) =>
171+
elementItem?.accessKey?.toLowerCase().includes(filter.toLowerCase()),
164172
);
165173

166174
return (
@@ -259,14 +267,14 @@ const Account = () => {
259267

260268
<Grid item xs={12}>
261269
<DataTable
262-
isLoading={loading}
263-
records={filteredRecords}
264-
entityName={"Access Keys"}
265-
columns={[{ label: "Access Key" }]}
266270
itemActions={tableActions}
267-
selectedItems={selectedSAs}
271+
entityName={"Access Keys"}
272+
columns={ACCOUNT_TABLE_COLUMNS}
268273
onSelect={(e) => selectSAs(e, setSelectedSAs, selectedSAs)}
269-
onSelectAll={selectAllItems}
274+
selectedItems={selectedSAs}
275+
isLoading={loading}
276+
records={filteredRecords}
277+
idField="accessKey"
270278
/>
271279
</Grid>
272280
<Grid item xs={12} sx={{ marginTop: 15 }}>
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
// This file is part of MinIO Console Server
2+
// Copyright (c) 2023 MinIO, Inc.
3+
//
4+
// This program is free software: you can redistribute it and/or modify
5+
// it under the terms of the GNU Affero General Public License as published by
6+
// the Free Software Foundation, either version 3 of the License, or
7+
// (at your option) any later version.
8+
//
9+
// This program is distributed in the hope that it will be useful,
10+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
// GNU Affero General Public License for more details.
13+
//
14+
// You should have received a copy of the GNU Affero General Public License
15+
// along with this program. If not, see <http://www.gnu.org/licenses/>.
16+
17+
import React from "react";
18+
import { DateTime } from "luxon";
19+
20+
export const ACCOUNT_TABLE_COLUMNS = [
21+
{ label: "Access Key", elementKey: "accessKey" },
22+
{
23+
label: "Expiry",
24+
elementKey: "expiration",
25+
renderFunction: (expTime: string) => {
26+
if (expTime) {
27+
const fmtDate = DateTime.fromISO(expTime)
28+
.toUTC()
29+
.toFormat("y/M/d hh:mm:ss z");
30+
31+
return <span title={fmtDate}>{fmtDate}</span>;
32+
}
33+
return "";
34+
},
35+
},
36+
{
37+
label: "Status",
38+
elementKey: "accountStatus",
39+
renderFunction: (status: string) => {
40+
if (status === "off") {
41+
return "Disabled";
42+
} else {
43+
return "Enabled";
44+
}
45+
},
46+
},
47+
{ label: "Name", elementKey: "name" },
48+
{ label: "Description", elementKey: "description" },
49+
];

portal-ui/src/screens/Console/Account/ServiceAccountPolicy.tsx

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,14 @@ const ServiceAccountPolicy = ({
3737
closeModalAndRefresh,
3838
}: IServiceAccountPolicyProps) => {
3939
const dispatch = useAppDispatch();
40-
const [loading, setLoading] = useState<boolean>(true);
40+
const [loading, setLoading] = useState<boolean>(false);
4141
const [policyDefinition, setPolicyDefinition] = useState<string>("");
4242
useEffect(() => {
43-
if (loading) {
43+
if (!loading && selectedAccessKey !== "") {
44+
const sourceAccKey = encodeURLString(selectedAccessKey);
45+
setLoading(true);
4446
api.serviceAccounts
45-
.getServiceAccountPolicy(encodeURLString(selectedAccessKey))
47+
.getServiceAccountPolicy(sourceAccKey)
4648
.then((res) => {
4749
setLoading(false);
4850
setPolicyDefinition(res.data);
@@ -52,7 +54,8 @@ const ServiceAccountPolicy = ({
5254
dispatch(setModalErrorSnackMessage(errorToHandler(err)));
5355
});
5456
}
55-
}, [loading, setLoading, dispatch, selectedAccessKey]);
57+
// eslint-disable-next-line react-hooks/exhaustive-deps
58+
}, [selectedAccessKey]);
5659

5760
const setPolicy = (event: React.FormEvent, newPolicy: string) => {
5861
event.preventDefault();

portal-ui/src/screens/Console/Buckets/BucketDetails/AccessDetailsPanel.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ import { encodeURLString } from "../../../../common/utils";
3333
import { setErrorSnackMessage, setHelpName } from "../../../../systemSlice";
3434
import { selBucketDetailsLoading } from "./bucketDetailsSlice";
3535
import { useAppDispatch } from "../../../../store";
36-
import { Policy, ServiceAccounts } from "../../../../api/consoleApi";
36+
import { Policy } from "../../../../api/consoleApi";
3737

3838
const AccessDetails = () => {
3939
const dispatch = useAppDispatch();
@@ -46,7 +46,7 @@ const AccessDetails = () => {
4646
const [loadingPolicies, setLoadingPolicies] = useState<boolean>(true);
4747
const [bucketPolicy, setBucketPolicy] = useState<Policy[] | undefined>([]);
4848
const [loadingUsers, setLoadingUsers] = useState<boolean>(true);
49-
const [bucketUsers, setBucketUsers] = useState<ServiceAccounts>([]);
49+
const [bucketUsers, setBucketUsers] = useState<string[]>([]);
5050

5151
const bucketName = params.bucketName || "";
5252

0 commit comments

Comments
 (0)