From 24742325b7f75b6cf30ef4a169aadf36785f1cd2 Mon Sep 17 00:00:00 2001
From: Daniel Valdivia <18384552+dvaldivia@users.noreply.github.com>
Date: Wed, 17 Jan 2024 15:37:28 -0800
Subject: [PATCH] Remove useAPI from DeleteUser and DeleteIDPConfigurationModal
(#3191)
---
api/embedded_spec.go | 22 ++++++---
.../check_user_service_accounts_parameters.go | 22 +++++++--
models/selected_users.go | 44 +++++++++++++++++
swagger.yml | 44 +++++++++--------
web-app/src/api/consoleApi.ts | 13 +++--
.../IDP/DeleteIDPConfigurationModal.tsx | 24 +++++----
.../src/screens/Console/Users/DeleteUser.tsx | 49 +++++++++----------
7 files changed, 145 insertions(+), 73 deletions(-)
create mode 100644 models/selected_users.go
diff --git a/api/embedded_spec.go b/api/embedded_spec.go
index 7df225638..b663b4653 100644
--- a/api/embedded_spec.go
+++ b/api/embedded_spec.go
@@ -5268,10 +5268,7 @@ func init() {
"in": "body",
"required": true,
"schema": {
- "type": "array",
- "items": {
- "type": "string"
- }
+ "$ref": "#/definitions/selectedUsers"
}
}
],
@@ -7988,6 +7985,12 @@ func init() {
}
}
},
+ "selectedUsers": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
"serverDrives": {
"type": "object",
"properties": {
@@ -14458,10 +14461,7 @@ func init() {
"in": "body",
"required": true,
"schema": {
- "type": "array",
- "items": {
- "type": "string"
- }
+ "$ref": "#/definitions/selectedUsers"
}
}
],
@@ -17327,6 +17327,12 @@ func init() {
}
}
},
+ "selectedUsers": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
"serverDrives": {
"type": "object",
"properties": {
diff --git a/api/operations/user/check_user_service_accounts_parameters.go b/api/operations/user/check_user_service_accounts_parameters.go
index b7868d400..0a6877424 100644
--- a/api/operations/user/check_user_service_accounts_parameters.go
+++ b/api/operations/user/check_user_service_accounts_parameters.go
@@ -29,6 +29,9 @@ import (
"github.com/go-openapi/errors"
"github.com/go-openapi/runtime"
"github.com/go-openapi/runtime/middleware"
+ "github.com/go-openapi/validate"
+
+ "github.com/minio/console/models"
)
// NewCheckUserServiceAccountsParams creates a new CheckUserServiceAccountsParams object
@@ -52,7 +55,7 @@ type CheckUserServiceAccountsParams struct {
Required: true
In: body
*/
- SelectedUsers []string
+ SelectedUsers models.SelectedUsers
}
// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface
@@ -66,7 +69,7 @@ func (o *CheckUserServiceAccountsParams) BindRequest(r *http.Request, route *mid
if runtime.HasBody(r) {
defer r.Body.Close()
- var body []string
+ var body models.SelectedUsers
if err := route.Consumer.Consume(r.Body, &body); err != nil {
if err == io.EOF {
res = append(res, errors.Required("selectedUsers", "body", ""))
@@ -74,8 +77,19 @@ func (o *CheckUserServiceAccountsParams) BindRequest(r *http.Request, route *mid
res = append(res, errors.NewParseError("selectedUsers", "body", "", err))
}
} else {
- // no validation required on inline body
- o.SelectedUsers = body
+ // validate body object
+ if err := body.Validate(route.Formats); err != nil {
+ res = append(res, err)
+ }
+
+ ctx := validate.WithOperationRequest(r.Context())
+ if err := body.ContextValidate(ctx, route.Formats); err != nil {
+ res = append(res, err)
+ }
+
+ if len(res) == 0 {
+ o.SelectedUsers = body
+ }
}
} else {
res = append(res, errors.Required("selectedUsers", "body", ""))
diff --git a/models/selected_users.go b/models/selected_users.go
new file mode 100644
index 000000000..3fb95ac7a
--- /dev/null
+++ b/models/selected_users.go
@@ -0,0 +1,44 @@
+// Code generated by go-swagger; DO NOT EDIT.
+
+// This file is part of MinIO Console Server
+// Copyright (c) 2023 MinIO, Inc.
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+//
+
+package models
+
+// This file was generated by the swagger tool.
+// Editing this file might prove futile when you re-run the swagger generate command
+
+import (
+ "context"
+
+ "github.com/go-openapi/strfmt"
+)
+
+// SelectedUsers selected users
+//
+// swagger:model selectedUsers
+type SelectedUsers []string
+
+// Validate validates this selected users
+func (m SelectedUsers) Validate(formats strfmt.Registry) error {
+ return nil
+}
+
+// ContextValidate validates this selected users based on context it is used
+func (m SelectedUsers) ContextValidate(ctx context.Context, formats strfmt.Registry) error {
+ return nil
+}
diff --git a/swagger.yml b/swagger.yml
index ad2bfa183..8b62b2965 100644
--- a/swagger.yml
+++ b/swagger.yml
@@ -25,7 +25,7 @@ securityDefinitions:
type: apiKey
# Apply the key security definition to all APIs
security:
- - key: []
+ - key: [ ]
parameters:
limit:
name: limit
@@ -54,7 +54,7 @@ paths:
schema:
$ref: "#/definitions/ApiError"
# Exclude this API from the authentication requirement
- security: []
+ security: [ ]
tags:
- Auth
post:
@@ -74,7 +74,7 @@ paths:
schema:
$ref: "#/definitions/ApiError"
# Exclude this API from the authentication requirement
- security: []
+ security: [ ]
tags:
- Auth
/login/oauth2/auth:
@@ -94,7 +94,7 @@ paths:
description: Generic error response.
schema:
$ref: "#/definitions/ApiError"
- security: []
+ security: [ ]
tags:
- Auth
@@ -295,8 +295,8 @@ paths:
get:
summary: List Objects
security:
- - key: []
- - anonymous: []
+ - key: [ ]
+ - anonymous: [ ]
operationId: ListObjects
parameters:
- name: bucket_name
@@ -411,8 +411,8 @@ paths:
post:
summary: Uploads an Object.
security:
- - key: []
- - anonymous: []
+ - key: [ ]
+ - anonymous: [ ]
consumes:
- multipart/form-data
parameters:
@@ -438,8 +438,8 @@ paths:
summary: Download Multiple Objects
operationId: DownloadMultipleObjects
security:
- - key: []
- - anonymous: []
+ - key: [ ]
+ - anonymous: [ ]
produces:
- application/octet-stream
parameters:
@@ -471,8 +471,8 @@ paths:
summary: Download Object
operationId: Download Object
security:
- - key: []
- - anonymous: []
+ - key: [ ]
+ - anonymous: [ ]
produces:
- application/octet-stream
parameters:
@@ -1546,9 +1546,7 @@ paths:
in: body
required: true
schema:
- type: array
- items:
- type: string
+ $ref: "#/definitions/selectedUsers"
responses:
200:
description: A successful response.
@@ -2889,7 +2887,7 @@ paths:
- name: order
in: query
type: string
- enum: [timeDesc, timeAsc]
+ enum: [ timeDesc, timeAsc ]
default: timeDesc
- name: timeStart
in: query
@@ -3766,6 +3764,10 @@ definitions:
items:
$ref: "#/definitions/user"
title: list of resulting users
+ selectedUsers:
+ type: array
+ items:
+ type: string
addUserRequest:
type: object
required:
@@ -4325,7 +4327,7 @@ definitions:
properties:
loginStrategy:
type: string
- enum: [form, redirect, service-account, redirect-service-account]
+ enum: [ form, redirect, service-account, redirect-service-account ]
redirectRules:
type: array
items:
@@ -4424,7 +4426,7 @@ definitions:
type: string
status:
type: string
- enum: [ok]
+ enum: [ ok ]
operator:
type: boolean
distributedMode:
@@ -4455,7 +4457,7 @@ definitions:
type: string
values:
type: array
- items: {}
+ items: { }
resultTarget:
type: object
properties:
@@ -4911,7 +4913,7 @@ definitions:
type: string
service:
type: string
- enum: [replication]
+ enum: [ replication ]
syncMode:
type: string
bandwidth:
@@ -5110,7 +5112,7 @@ definitions:
format: int64
newer_noncurrent_expiration_versions:
type: integer
- format: int64
+ format: int64
transitionResponse:
type: object
diff --git a/web-app/src/api/consoleApi.ts b/web-app/src/api/consoleApi.ts
index cfad43275..0bd52bacc 100644
--- a/web-app/src/api/consoleApi.ts
+++ b/web-app/src/api/consoleApi.ts
@@ -149,6 +149,8 @@ export interface ListUsersResponse {
users?: User[];
}
+export type SelectedUsers = string[];
+
export interface AddUserRequest {
accessKey: string;
secretKey: string;
@@ -3242,7 +3244,7 @@ export class Api<
* @secure
*/
checkUserServiceAccounts: (
- selectedUsers: string[],
+ selectedUsers: SelectedUsers,
params: RequestParams = {},
) =>
this.request({
@@ -3250,6 +3252,7 @@ export class Api<
method: "POST",
body: selectedUsers,
secure: true,
+ type: ContentType.Json,
format: "json",
...params,
}),
@@ -3635,7 +3638,7 @@ export class Api<
* @secure
*/
listUsersForPolicy: (policy: string, params: RequestParams = {}) =>
- this.request({
+ this.request({
path: `/policies/${policy}/users`,
method: "GET",
secure: true,
@@ -3653,7 +3656,7 @@ export class Api<
* @secure
*/
listGroupsForPolicy: (policy: string, params: RequestParams = {}) =>
- this.request({
+ this.request({
path: `/policies/${policy}/groups`,
method: "GET",
secure: true,
@@ -3805,7 +3808,7 @@ export class Api<
},
params: RequestParams = {},
) =>
- this.request({
+ this.request({
path: `/bucket-users/${bucket}`,
method: "GET",
query: query,
@@ -4566,7 +4569,7 @@ export class Api<
* @secure
*/
listNodes: (params: RequestParams = {}) =>
- this.request({
+ this.request({
path: `/nodes`,
method: "GET",
secure: true,
diff --git a/web-app/src/screens/Console/IDP/DeleteIDPConfigurationModal.tsx b/web-app/src/screens/Console/IDP/DeleteIDPConfigurationModal.tsx
index 380cfdfe6..ae06f31fd 100644
--- a/web-app/src/screens/Console/IDP/DeleteIDPConfigurationModal.tsx
+++ b/web-app/src/screens/Console/IDP/DeleteIDPConfigurationModal.tsx
@@ -14,16 +14,17 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
-import React, { Fragment } from "react";
+import React, { Fragment, useState } from "react";
import { ConfirmDeleteIcon } from "mds";
import {
setErrorSnackMessage,
setServerNeedsRestart,
} from "../../../systemSlice";
import { useAppDispatch } from "../../../store";
-import { ErrorResponseHandler } from "../../../common/types";
-import useApi from "../Common/Hooks/useApi";
import ConfirmDialog from "../Common/ModalWrapper/ConfirmDialog";
+import { api } from "api";
+import { SetIDPResponse } from "../../../api/consoleApi";
+import { errorToHandler } from "../../../api/errors";
interface IDeleteIDPConfigurationModalProps {
closeDeleteModalAndRefresh: (refresh: boolean) => void;
@@ -39,22 +40,27 @@ const DeleteIDPConfigurationModal = ({
idpType,
}: IDeleteIDPConfigurationModalProps) => {
const dispatch = useAppDispatch();
- const onDelSuccess = (res: any) => {
+ const onDelSuccess = (res: SetIDPResponse) => {
closeDeleteModalAndRefresh(true);
dispatch(setServerNeedsRestart(res.restart === true));
};
- const onDelError = (err: ErrorResponseHandler) =>
- dispatch(setErrorSnackMessage(err));
- const onClose = () => closeDeleteModalAndRefresh(false);
- const [deleteLoading, invokeDeleteApi] = useApi(onDelSuccess, onDelError);
+ const onClose = () => closeDeleteModalAndRefresh(false);
+ const [deleteLoading, setDeleteLoading] = useState(false);
if (!idp) {
return null;
}
const onConfirmDelete = () => {
- invokeDeleteApi("DELETE", `/api/v1/idp/${idpType}/${idp}`);
+ setDeleteLoading(true);
+ api.idp
+ .deleteConfiguration(idp, idpType)
+ .then((res) => {
+ onDelSuccess(res.data);
+ })
+ .catch((err) => dispatch(setErrorSnackMessage(errorToHandler(err.error))))
+ .finally(() => setDeleteLoading(false));
};
const displayName = idp === "_" ? "Default" : idp;
diff --git a/web-app/src/screens/Console/Users/DeleteUser.tsx b/web-app/src/screens/Console/Users/DeleteUser.tsx
index 1ea74e0cd..4ffc92628 100644
--- a/web-app/src/screens/Console/Users/DeleteUser.tsx
+++ b/web-app/src/screens/Console/Users/DeleteUser.tsx
@@ -17,14 +17,14 @@
import React, { Fragment, useEffect, useState } from "react";
import { useNavigate } from "react-router-dom";
import { setErrorSnackMessage } from "../../../systemSlice";
-import { ErrorResponseHandler } from "../../../common/types";
import { ConfirmDeleteIcon, DataTable, InformativeMessage, Loader } from "mds";
import { encodeURLString } from "../../../common/utils";
import { IAM_PAGES } from "../../../common/SecureComponent/permissions";
-import useApi from "../Common/Hooks/useApi";
import ConfirmDialog from "../Common/ModalWrapper/ConfirmDialog";
-import api from "../../../common/api";
import { useAppDispatch } from "../../../store";
+import { api } from "api";
+import { UserServiceAccountItem } from "../../../api/consoleApi";
+import { errorToHandler } from "../../../api/errors";
interface IDeleteUserProps {
closeDeleteModalAndRefresh: (refresh: boolean) => void;
@@ -40,33 +40,31 @@ const DeleteUser = ({
const navigate = useNavigate();
const dispatch = useAppDispatch();
- const onDelSuccess = () => closeDeleteModalAndRefresh(true);
- const onDelError = (err: ErrorResponseHandler) =>
- dispatch(setErrorSnackMessage(err));
const onClose = () => closeDeleteModalAndRefresh(false);
- const [deleteLoading, invokeDeleteApi] = useApi(onDelSuccess, onDelError);
const [loadingSA, setLoadingSA] = useState(true);
const [hasSA, setHasSA] = useState(false);
- const [userSAList, setUserSAList] = useState([]);
+ const [userSAList, setUserSAList] = useState([]);
+ const [deleteLoading, setDeleteLoading] = useState(false);
const userLoggedIn = localStorage.getItem("userLoggedIn") || "";
useEffect(() => {
if (selectedUsers) {
- api
- .invoke("POST", `/api/v1/users/service-accounts`, selectedUsers)
+ api.users
+ .checkUserServiceAccounts(selectedUsers)
.then((res) => {
- setUserSAList(res.userServiceAccountList);
- if (res.hasSA) {
- setHasSA(true);
+ if (res.data) {
+ setUserSAList(res.data.userServiceAccountList ?? []);
+ if (res.data.hasSA) {
+ setHasSA(true);
+ }
}
- setLoadingSA(false);
})
- .catch((err: ErrorResponseHandler) => {
- dispatch(setErrorSnackMessage(err));
- setLoadingSA(false);
- });
+ .catch((err) =>
+ dispatch(setErrorSnackMessage(errorToHandler(err.error))),
+ )
+ .finally(() => setLoadingSA(false));
}
}, [selectedUsers, dispatch]);
@@ -102,18 +100,17 @@ const DeleteUser = ({
);
closeDeleteModalAndRefresh(true);
} else {
- invokeDeleteApi("DELETE", `/api/v1/user/${encodeURLString(user)}`);
- closeDeleteModalAndRefresh(true);
- navigate(`${IAM_PAGES.USERS}`);
+ api.user
+ .removeUser(encodeURLString(user))
+ .then((res) => {
+ closeDeleteModalAndRefresh(true);
+ navigate(`${IAM_PAGES.USERS}`);
+ })
+ .finally(() => setDeleteLoading(false));
}
}
};
- interface userSACount {
- userName: string;
- numSAs: number;
- }
-
const noSAtext =
"Are you sure you want to delete the following " +
selectedUsers.length +