diff --git a/models/bulk_user_groups.go b/models/bulk_user_groups.go new file mode 100644 index 000000000..17ef1d5b2 --- /dev/null +++ b/models/bulk_user_groups.go @@ -0,0 +1,98 @@ +// Code generated by go-swagger; DO NOT EDIT. + +// This file is part of MinIO Console Server +// Copyright (c) 2020 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 ( + "github.com/go-openapi/errors" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" + "github.com/go-openapi/validate" +) + +// BulkUserGroups bulk user groups +// +// swagger:model bulkUserGroups +type BulkUserGroups struct { + + // groups + // Required: true + Groups []string `json:"groups"` + + // users + // Required: true + Users []string `json:"users"` +} + +// Validate validates this bulk user groups +func (m *BulkUserGroups) Validate(formats strfmt.Registry) error { + var res []error + + if err := m.validateGroups(formats); err != nil { + res = append(res, err) + } + + if err := m.validateUsers(formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +func (m *BulkUserGroups) validateGroups(formats strfmt.Registry) error { + + if err := validate.Required("groups", "body", m.Groups); err != nil { + return err + } + + return nil +} + +func (m *BulkUserGroups) validateUsers(formats strfmt.Registry) error { + + if err := validate.Required("users", "body", m.Users); err != nil { + return err + } + + return nil +} + +// MarshalBinary interface implementation +func (m *BulkUserGroups) MarshalBinary() ([]byte, error) { + if m == nil { + return nil, nil + } + return swag.WriteJSON(m) +} + +// UnmarshalBinary interface implementation +func (m *BulkUserGroups) UnmarshalBinary(b []byte) error { + var res BulkUserGroups + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *m = res + return nil +} diff --git a/portal-ui/src/screens/Console/Users/AddToGroup.tsx b/portal-ui/src/screens/Console/Users/AddToGroup.tsx new file mode 100644 index 000000000..e9c8ee94c --- /dev/null +++ b/portal-ui/src/screens/Console/Users/AddToGroup.tsx @@ -0,0 +1,160 @@ +// This file is part of MinIO Console Server +// Copyright (c) 2019 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 . +import React, { useState, useEffect } from "react"; +import { createStyles, Theme, withStyles } from "@material-ui/core/styles"; +import { Button, LinearProgress } from "@material-ui/core"; +import Grid from "@material-ui/core/Grid"; +import Typography from "@material-ui/core/Typography"; +import api from "../../../common/api"; +import GroupsSelectors from "./GroupsSelectors"; +import Title from "../../../common/Title"; +import ModalWrapper from "../Common/ModalWrapper/ModalWrapper"; + +interface IAddToGroup { + open: boolean; + checkedUsers: any; + closeModalAndRefresh: any; + classes: any; +} + +const styles = (theme: Theme) => + createStyles({ + errorBlock: { + color: "red" + }, + strongText: { + fontWeight: 700 + }, + keyName: { + marginLeft: 5 + }, + buttonContainer: { + textAlign: "right" + } + }); + +const AddToGroup = ({ + open, + checkedUsers, + closeModalAndRefresh, + classes +}: IAddToGroup) => { + //Local States + const [saving, isSaving] = useState(false); + const [updatingError, setError] = useState(""); + const [selectedGroups, setSelectedGroups] = useState([]); + + //Effects + useEffect(() => { + if (saving) { + if (selectedGroups.length > 0) { + api + .invoke("PUT", "/api/v1/users-groups-bulk", { + groups: selectedGroups, + users: checkedUsers + }) + .then(res => { + isSaving(false); + setError(""); + closeModalAndRefresh(true); + }) + .catch(err => { + isSaving(false); + setError(err); + }); + } else { + isSaving(false); + setError("You need to select at least one group to assign"); + } + } + }, [ + saving, + isSaving, + setError, + closeModalAndRefresh, + selectedGroups, + checkedUsers + ]); + + //Fetch Actions + const setSaving = (event: React.FormEvent) => { + event.preventDefault(); + + isSaving(true); + }; + + return ( + { + closeModalAndRefresh(false); + }} + title="Add Users to Group" + > +
+ + {updatingError !== "" && ( + + + {updatingError} + + + )} + + + Users to be altered + + + {checkedUsers.join(", ")} + + +
+
+ + + + +
+
+ + + + {saving && ( + + + + )} +
+
+
+ ); +}; + +export default withStyles(styles)(AddToGroup); diff --git a/portal-ui/src/screens/Console/Users/AddUser.tsx b/portal-ui/src/screens/Console/Users/AddUser.tsx index 8ac928a57..f698cbbc7 100644 --- a/portal-ui/src/screens/Console/Users/AddUser.tsx +++ b/portal-ui/src/screens/Console/Users/AddUser.tsx @@ -55,8 +55,6 @@ interface IAddUserContentState { accessKey: string; secretKey: string; selectedGroups: string[]; - loadingGroups: boolean; - groupsList: any[]; enabled: string; } @@ -69,10 +67,8 @@ class AddUserContent extends React.Component< addError: "", accessKey: "", secretKey: "", - selectedGroups: [], - loadingGroups: false, - groupsList: [], - enabled: "enabled" + enabled: "enabled", + selectedGroups: [] }; componentDidMount(): void { @@ -188,8 +184,6 @@ class AddUserContent extends React.Component< accessKey, secretKey, selectedGroups, - loadingGroups, - groupsList, enabled } = this.state; @@ -268,8 +262,6 @@ class AddUserContent extends React.Component< selectedGroups: elements }); }} - loading={loadingGroups} - records={groupsList} /> diff --git a/portal-ui/src/screens/Console/Users/GroupsSelectors.tsx b/portal-ui/src/screens/Console/Users/GroupsSelectors.tsx index 58b0a649d..262e74434 100644 --- a/portal-ui/src/screens/Console/Users/GroupsSelectors.tsx +++ b/portal-ui/src/screens/Console/Users/GroupsSelectors.tsx @@ -39,8 +39,6 @@ interface IGroupsProps { classes: any; selectedGroups: string[]; setSelectedGroups: any; - records: any[]; - loading: boolean; } const styles = (theme: Theme) => diff --git a/portal-ui/src/screens/Console/Users/Users.tsx b/portal-ui/src/screens/Console/Users/Users.tsx index 58da89628..2b7c7dacd 100644 --- a/portal-ui/src/screens/Console/Users/Users.tsx +++ b/portal-ui/src/screens/Console/Users/Users.tsx @@ -16,35 +16,36 @@ import React from "react"; import { createStyles, Theme, withStyles } from "@material-ui/core/styles"; -import Table from "@material-ui/core/Table"; -import TableBody from "@material-ui/core/TableBody"; -import TableCell from "@material-ui/core/TableCell"; -import TableHead from "@material-ui/core/TableHead"; -import TableRow from "@material-ui/core/TableRow"; -import Paper from "@material-ui/core/Paper"; -import Grid from "@material-ui/core/Grid"; import api from "../../../common/api"; import { Button, IconButton, LinearProgress, TableFooter, - TablePagination + TablePagination, + Table, + TableBody, + TableCell, + TableHead, + TableRow, + Paper, + Grid, + Typography, + TextField, + InputAdornment } from "@material-ui/core"; -import Typography from "@material-ui/core/Typography"; -import { User, UsersList } from "./types"; -import { usersSort } from "../../../utils/sortFunctions"; -import { MinTablePaginationActions } from "../../../common/MinTablePaginationActions"; -import AddUser from "./AddUser"; -import DeleteUser from "./DeleteUser"; -import { CreateIcon } from "../../../icons"; -import TextField from "@material-ui/core/TextField"; -import InputAdornment from "@material-ui/core/InputAdornment"; import SearchIcon from "@material-ui/icons/Search"; import Checkbox from "@material-ui/core/Checkbox"; import DeleteIcon from "@material-ui/icons/Delete"; import ViewIcon from "@material-ui/icons/Visibility"; import GroupIcon from "@material-ui/icons/Group"; +import { User, UsersList } from "./types"; +import { usersSort } from "../../../utils/sortFunctions"; +import { MinTablePaginationActions } from "../../../common/MinTablePaginationActions"; +import { CreateIcon } from "../../../icons"; +import AddUser from "./AddUser"; +import DeleteUser from "./DeleteUser"; +import AddToGroup from "./AddToGroup"; const styles = (theme: Theme) => createStyles({ @@ -112,6 +113,7 @@ interface IUsersState { selectedUser: User | null; addGroupOpen: boolean; filter: string; + checkedUsers: string[]; } class Users extends React.Component { @@ -127,7 +129,8 @@ class Users extends React.Component { deleteOpen: false, selectedUser: null, addGroupOpen: false, - filter: "" + filter: "", + checkedUsers: [] }; fetchRecords() { @@ -176,6 +179,17 @@ class Users extends React.Component { }); } + closeAddGroupBulk(unCheckAll: boolean = false) { + let newStates = { addGroupOpen: false }; + let addUsers = {}; + + if (unCheckAll) { + addUsers = { checkedUsers: [] }; + } + + this.setState({ ...newStates, ...addUsers }); + } + componentDidMount(): void { this.fetchRecords(); } @@ -191,7 +205,9 @@ class Users extends React.Component { rowsPerPage, deleteOpen, selectedUser, - filter + filter, + checkedUsers, + addGroupOpen } = this.state; const handleChangePage = (event: unknown, newPage: number) => { @@ -213,6 +229,28 @@ class Users extends React.Component { elementItem.accessKey.includes(filter) ); + const selectionChanged = (e: React.ChangeEvent) => { + const targetD = e.target; + const value = targetD.value; + const checked = targetD.checked; + + let elements: string[] = [...checkedUsers]; // We clone the checkedUsers array + + if (checked) { + // If the user has checked this field we need to push this to checkedUsersList + elements.push(value); + } else { + // User has unchecked this field, we need to remove it from the list + elements = elements.filter(element => element !== value); + } + + this.setState({ + checkedUsers: elements + }); + + return elements; + }; + return ( {addScreenOpen && ( @@ -233,6 +271,16 @@ class Users extends React.Component { }} /> )} + {addGroupOpen && ( + { + this.closeAddGroupBulk(close); + }} + /> + )} + Users @@ -262,10 +310,13 @@ class Users extends React.Component { variant="contained" color="primary" startIcon={} + disabled={checkedUsers.length <= 0} onClick={() => { - this.setState({ - addGroupOpen: true - }); + if (checkedUsers.length > 0) { + this.setState({ + addGroupOpen: true + }); + } }} > Add to Group @@ -305,9 +356,11 @@ class Users extends React.Component { diff --git a/restapi/admin_users.go b/restapi/admin_users.go index 1a5f196b1..dee36eeae 100644 --- a/restapi/admin_users.go +++ b/restapi/admin_users.go @@ -20,15 +20,15 @@ import ( "github.com/go-openapi/errors" "github.com/go-openapi/runtime/middleware" "github.com/go-openapi/swag" - "github.com/minio/mcs/restapi/operations" - - "github.com/minio/mcs/restapi/operations/admin_api" - "github.com/minio/mcs/models" + "github.com/minio/mcs/restapi/operations" + "github.com/minio/mcs/restapi/operations/admin_api" "github.com/minio/minio/pkg/madmin" "context" + "fmt" "log" + "strings" ) func registerUsersHandlers(api *operations.McsAPI) { @@ -83,6 +83,15 @@ func registerUsersHandlers(api *operations.McsAPI) { return admin_api.NewUpdateUserInfoOK().WithPayload(userUpdateResponse) }) + // Update User-Groups Bulk + api.AdminAPIBulkUpdateUsersGroupsHandler = admin_api.BulkUpdateUsersGroupsHandlerFunc(func(params admin_api.BulkUpdateUsersGroupsParams, principal *models.Principal) middleware.Responder { + error := getAddUsersListToGroupsResponse(params) + if error != nil { + return admin_api.NewBulkUpdateUsersGroupsDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(error.Error())}) + } + + return admin_api.NewBulkUpdateUsersGroupsOK() + }) } func listUsers(ctx context.Context, client MinioAdmin) ([]*models.User, error) { @@ -402,3 +411,70 @@ func getUpdateUserResponse(params admin_api.UpdateUserInfoParams) (*models.User, } return userElem, nil } + +// addUsersListToGroups iterates over the user list & assigns the requested groups to each user. +func addUsersListToGroups(ctx context.Context, client MinioAdmin, usersToUpdate []string, groupsToAssign []string) error { + // We update each group with the complete usersList + parallelGroupsUpdate := func(groupToAssign string) chan error { + groupProcess := make(chan error) + + go func() { + defer close(groupProcess) + // We add the users array to the group. + err := updateGroupMembers(ctx, client, groupToAssign, usersToUpdate, false) + + groupProcess <- err + }() + return groupProcess + } + + var groupsUpdateList []chan error + + // We get each group name & add users accordingly + for _, groupName := range groupsToAssign { + // We update the group + proc := parallelGroupsUpdate(groupName) + groupsUpdateList = append(groupsUpdateList, proc) + } + + errorsList := []string{} // We get the errors list because we want to have all errors at once. + for _, err := range groupsUpdateList { + errorFromUpdate := <-err // We store the error to avoid Data Race + if errorFromUpdate != nil { + // If there is an error, we store the errors strings so we can join them after we receive all errors + errorsList = append(errorsList, errorFromUpdate.Error()) // We wait until all the channels have been closed. + } + } + + // If there are errors, we throw the final error with the errors inside + if len(errorsList) > 0 { + errGen := fmt.Errorf("error in users-groups assignation: %q", strings.Join(errorsList[:], ",")) + return errGen + } + + return nil +} + +func getAddUsersListToGroupsResponse(params admin_api.BulkUpdateUsersGroupsParams) error { + ctx := context.Background() + + mAdmin, err := newMAdminClient() + if err != nil { + log.Println("error creating Madmin Client:", err) + return err + } + + // create a minioClient interface implementation + // defining the client to be used + adminClient := adminClient{client: mAdmin} + + usersList := params.Body.Users + groupsList := params.Body.Groups + + if err := addUsersListToGroups(ctx, adminClient, usersList, groupsList); err != nil { + log.Println("error updating groups bulk users:", err.Error()) + return err + } + + return nil +} diff --git a/restapi/admin_users_test.go b/restapi/admin_users_test.go index 1f76f6719..48028e98c 100644 --- a/restapi/admin_users_test.go +++ b/restapi/admin_users_test.go @@ -258,7 +258,7 @@ func TestUserGroups(t *testing.T) { t.Errorf("Failed on %s:, error occurred: %s", function, err.Error()) } - // Test-2: updateUserGroups() make sure errors are handled correctly when error on DeleteUser() + // Test-2: updateUserGroups() make sure errors are handled correctly when error on UpdateGroupMembersMock() // mock function response from removeUser(accessKey) minioUpdateGroupMembersMock = func(remove madmin.GroupAddRemove) error { @@ -368,3 +368,34 @@ func TestSetUserStatus(t *testing.T) { assert.Equal("error", err.Error()) } } + +func TestUserGroupsBulk(t *testing.T) { + assert := asrt.New(t) + // mock minIO client + adminClient := adminClientMock{} + ctx := context.Background() + + function := "updateUserGroups()" + mockUserGroups := []string{"group1", "group2", "group3"} + mockUsers := []string{"testUser", "testUser2"} + + // Test-1: addUsersListToGroups() updates the groups for a users list + // mock function response from updateUserGroups(accessKey, groupsToAssign) + minioUpdateGroupMembersMock = func(remove madmin.GroupAddRemove) error { + return nil + } + + if err := addUsersListToGroups(ctx, adminClient, mockUsers, mockUserGroups); err != nil { + t.Errorf("Failed on %s:, error occurred: %s", function, err.Error()) + } + + // Test-2: addUsersListToGroups() make sure errors are handled correctly when error on updateGroupMembers() + // mock function response from removeUser(accessKey) + minioUpdateGroupMembersMock = func(remove madmin.GroupAddRemove) error { + return errors.New("error") + } + + if err := addUsersListToGroups(ctx, adminClient, mockUsers, mockUserGroups); assert.Error(err) { + assert.Equal("error in users-groups assignation: \"error,error,error\"", err.Error()) + } +} diff --git a/restapi/embedded_spec.go b/restapi/embedded_spec.go index ab2199218..bb95daa32 100644 --- a/restapi/embedded_spec.go +++ b/restapi/embedded_spec.go @@ -1096,6 +1096,36 @@ func init() { } } }, + "/users-groups-bulk": { + "put": { + "tags": [ + "AdminAPI" + ], + "summary": "Bulk functionality to Add Users to Groups", + "operationId": "BulkUpdateUsersGroups", + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/bulkUserGroups" + } + } + ], + "responses": { + "200": { + "description": "A successful response." + }, + "default": { + "description": "Generic error response.", + "schema": { + "$ref": "#/definitions/error" + } + } + } + } + }, "/users/{name}": { "get": { "tags": [ @@ -1356,6 +1386,27 @@ func init() { } } }, + "bulkUserGroups": { + "type": "object", + "required": [ + "users", + "groups" + ], + "properties": { + "groups": { + "type": "array", + "items": { + "type": "string" + } + }, + "users": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, "configDescription": { "type": "object", "properties": { @@ -2948,6 +2999,36 @@ func init() { } } }, + "/users-groups-bulk": { + "put": { + "tags": [ + "AdminAPI" + ], + "summary": "Bulk functionality to Add Users to Groups", + "operationId": "BulkUpdateUsersGroups", + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/bulkUserGroups" + } + } + ], + "responses": { + "200": { + "description": "A successful response." + }, + "default": { + "description": "Generic error response.", + "schema": { + "$ref": "#/definitions/error" + } + } + } + } + }, "/users/{name}": { "get": { "tags": [ @@ -3208,6 +3289,27 @@ func init() { } } }, + "bulkUserGroups": { + "type": "object", + "required": [ + "users", + "groups" + ], + "properties": { + "groups": { + "type": "array", + "items": { + "type": "string" + } + }, + "users": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, "configDescription": { "type": "object", "properties": { diff --git a/restapi/operations/admin_api/bulk_update_users_groups.go b/restapi/operations/admin_api/bulk_update_users_groups.go new file mode 100644 index 000000000..4f0d85d3e --- /dev/null +++ b/restapi/operations/admin_api/bulk_update_users_groups.go @@ -0,0 +1,90 @@ +// Code generated by go-swagger; DO NOT EDIT. + +// This file is part of MinIO Console Server +// Copyright (c) 2020 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 admin_api + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime/middleware" + + "github.com/minio/mcs/models" +) + +// BulkUpdateUsersGroupsHandlerFunc turns a function with the right signature into a bulk update users groups handler +type BulkUpdateUsersGroupsHandlerFunc func(BulkUpdateUsersGroupsParams, *models.Principal) middleware.Responder + +// Handle executing the request and returning a response +func (fn BulkUpdateUsersGroupsHandlerFunc) Handle(params BulkUpdateUsersGroupsParams, principal *models.Principal) middleware.Responder { + return fn(params, principal) +} + +// BulkUpdateUsersGroupsHandler interface for that can handle valid bulk update users groups params +type BulkUpdateUsersGroupsHandler interface { + Handle(BulkUpdateUsersGroupsParams, *models.Principal) middleware.Responder +} + +// NewBulkUpdateUsersGroups creates a new http.Handler for the bulk update users groups operation +func NewBulkUpdateUsersGroups(ctx *middleware.Context, handler BulkUpdateUsersGroupsHandler) *BulkUpdateUsersGroups { + return &BulkUpdateUsersGroups{Context: ctx, Handler: handler} +} + +/*BulkUpdateUsersGroups swagger:route PUT /users-groups-bulk AdminAPI bulkUpdateUsersGroups + +Bulk functionality to Add Users to Groups + +*/ +type BulkUpdateUsersGroups struct { + Context *middleware.Context + Handler BulkUpdateUsersGroupsHandler +} + +func (o *BulkUpdateUsersGroups) ServeHTTP(rw http.ResponseWriter, r *http.Request) { + route, rCtx, _ := o.Context.RouteInfo(r) + if rCtx != nil { + r = rCtx + } + var Params = NewBulkUpdateUsersGroupsParams() + + uprinc, aCtx, err := o.Context.Authorize(r, route) + if err != nil { + o.Context.Respond(rw, r, route.Produces, route, err) + return + } + if aCtx != nil { + r = aCtx + } + var principal *models.Principal + if uprinc != nil { + principal = uprinc.(*models.Principal) // this is really a models.Principal, I promise + } + + if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params + o.Context.Respond(rw, r, route.Produces, route, err) + return + } + + res := o.Handler.Handle(Params, principal) // actually handle the request + + o.Context.Respond(rw, r, route.Produces, route, res) + +} diff --git a/restapi/operations/admin_api/bulk_update_users_groups_parameters.go b/restapi/operations/admin_api/bulk_update_users_groups_parameters.go new file mode 100644 index 000000000..01c4652a3 --- /dev/null +++ b/restapi/operations/admin_api/bulk_update_users_groups_parameters.go @@ -0,0 +1,94 @@ +// Code generated by go-swagger; DO NOT EDIT. + +// This file is part of MinIO Console Server +// Copyright (c) 2020 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 admin_api + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "io" + "net/http" + + "github.com/go-openapi/errors" + "github.com/go-openapi/runtime" + "github.com/go-openapi/runtime/middleware" + + "github.com/minio/mcs/models" +) + +// NewBulkUpdateUsersGroupsParams creates a new BulkUpdateUsersGroupsParams object +// no default values defined in spec. +func NewBulkUpdateUsersGroupsParams() BulkUpdateUsersGroupsParams { + + return BulkUpdateUsersGroupsParams{} +} + +// BulkUpdateUsersGroupsParams contains all the bound params for the bulk update users groups operation +// typically these are obtained from a http.Request +// +// swagger:parameters BulkUpdateUsersGroups +type BulkUpdateUsersGroupsParams struct { + + // HTTP Request Object + HTTPRequest *http.Request `json:"-"` + + /* + Required: true + In: body + */ + Body *models.BulkUserGroups +} + +// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface +// for simple values it will use straight method calls. +// +// To ensure default values, the struct must have been initialized with NewBulkUpdateUsersGroupsParams() beforehand. +func (o *BulkUpdateUsersGroupsParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error { + var res []error + + o.HTTPRequest = r + + if runtime.HasBody(r) { + defer r.Body.Close() + var body models.BulkUserGroups + if err := route.Consumer.Consume(r.Body, &body); err != nil { + if err == io.EOF { + res = append(res, errors.Required("body", "body")) + } else { + res = append(res, errors.NewParseError("body", "body", "", err)) + } + } else { + // validate body object + if err := body.Validate(route.Formats); err != nil { + res = append(res, err) + } + + if len(res) == 0 { + o.Body = &body + } + } + } else { + res = append(res, errors.Required("body", "body")) + } + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} diff --git a/restapi/operations/admin_api/bulk_update_users_groups_responses.go b/restapi/operations/admin_api/bulk_update_users_groups_responses.go new file mode 100644 index 000000000..35bfc6d46 --- /dev/null +++ b/restapi/operations/admin_api/bulk_update_users_groups_responses.go @@ -0,0 +1,113 @@ +// Code generated by go-swagger; DO NOT EDIT. + +// This file is part of MinIO Console Server +// Copyright (c) 2020 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 admin_api + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime" + + "github.com/minio/mcs/models" +) + +// BulkUpdateUsersGroupsOKCode is the HTTP code returned for type BulkUpdateUsersGroupsOK +const BulkUpdateUsersGroupsOKCode int = 200 + +/*BulkUpdateUsersGroupsOK A successful response. + +swagger:response bulkUpdateUsersGroupsOK +*/ +type BulkUpdateUsersGroupsOK struct { +} + +// NewBulkUpdateUsersGroupsOK creates BulkUpdateUsersGroupsOK with default headers values +func NewBulkUpdateUsersGroupsOK() *BulkUpdateUsersGroupsOK { + + return &BulkUpdateUsersGroupsOK{} +} + +// WriteResponse to the client +func (o *BulkUpdateUsersGroupsOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.Header().Del(runtime.HeaderContentType) //Remove Content-Type on empty responses + + rw.WriteHeader(200) +} + +/*BulkUpdateUsersGroupsDefault Generic error response. + +swagger:response bulkUpdateUsersGroupsDefault +*/ +type BulkUpdateUsersGroupsDefault struct { + _statusCode int + + /* + In: Body + */ + Payload *models.Error `json:"body,omitempty"` +} + +// NewBulkUpdateUsersGroupsDefault creates BulkUpdateUsersGroupsDefault with default headers values +func NewBulkUpdateUsersGroupsDefault(code int) *BulkUpdateUsersGroupsDefault { + if code <= 0 { + code = 500 + } + + return &BulkUpdateUsersGroupsDefault{ + _statusCode: code, + } +} + +// WithStatusCode adds the status to the bulk update users groups default response +func (o *BulkUpdateUsersGroupsDefault) WithStatusCode(code int) *BulkUpdateUsersGroupsDefault { + o._statusCode = code + return o +} + +// SetStatusCode sets the status to the bulk update users groups default response +func (o *BulkUpdateUsersGroupsDefault) SetStatusCode(code int) { + o._statusCode = code +} + +// WithPayload adds the payload to the bulk update users groups default response +func (o *BulkUpdateUsersGroupsDefault) WithPayload(payload *models.Error) *BulkUpdateUsersGroupsDefault { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the bulk update users groups default response +func (o *BulkUpdateUsersGroupsDefault) SetPayload(payload *models.Error) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *BulkUpdateUsersGroupsDefault) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(o._statusCode) + if o.Payload != nil { + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } + } +} diff --git a/restapi/operations/admin_api/bulk_update_users_groups_urlbuilder.go b/restapi/operations/admin_api/bulk_update_users_groups_urlbuilder.go new file mode 100644 index 000000000..7290df968 --- /dev/null +++ b/restapi/operations/admin_api/bulk_update_users_groups_urlbuilder.go @@ -0,0 +1,104 @@ +// Code generated by go-swagger; DO NOT EDIT. + +// This file is part of MinIO Console Server +// Copyright (c) 2020 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 admin_api + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "errors" + "net/url" + golangswaggerpaths "path" +) + +// BulkUpdateUsersGroupsURL generates an URL for the bulk update users groups operation +type BulkUpdateUsersGroupsURL struct { + _basePath string +} + +// WithBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *BulkUpdateUsersGroupsURL) WithBasePath(bp string) *BulkUpdateUsersGroupsURL { + o.SetBasePath(bp) + return o +} + +// SetBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *BulkUpdateUsersGroupsURL) SetBasePath(bp string) { + o._basePath = bp +} + +// Build a url path and query string +func (o *BulkUpdateUsersGroupsURL) Build() (*url.URL, error) { + var _result url.URL + + var _path = "/users-groups-bulk" + + _basePath := o._basePath + if _basePath == "" { + _basePath = "/api/v1" + } + _result.Path = golangswaggerpaths.Join(_basePath, _path) + + return &_result, nil +} + +// Must is a helper function to panic when the url builder returns an error +func (o *BulkUpdateUsersGroupsURL) Must(u *url.URL, err error) *url.URL { + if err != nil { + panic(err) + } + if u == nil { + panic("url can't be nil") + } + return u +} + +// String returns the string representation of the path with query string +func (o *BulkUpdateUsersGroupsURL) String() string { + return o.Must(o.Build()).String() +} + +// BuildFull builds a full url with scheme, host, path and query string +func (o *BulkUpdateUsersGroupsURL) BuildFull(scheme, host string) (*url.URL, error) { + if scheme == "" { + return nil, errors.New("scheme is required for a full url on BulkUpdateUsersGroupsURL") + } + if host == "" { + return nil, errors.New("host is required for a full url on BulkUpdateUsersGroupsURL") + } + + base, err := o.Build() + if err != nil { + return nil, err + } + + base.Scheme = scheme + base.Host = host + return base, nil +} + +// StringFull returns the string representation of a complete url +func (o *BulkUpdateUsersGroupsURL) StringFull(scheme, host string) string { + return o.Must(o.BuildFull(scheme, host)).String() +} diff --git a/restapi/operations/bulk_update_users_groups.go b/restapi/operations/bulk_update_users_groups.go new file mode 100644 index 000000000..e45730f9d --- /dev/null +++ b/restapi/operations/bulk_update_users_groups.go @@ -0,0 +1,90 @@ +// Code generated by go-swagger; DO NOT EDIT. + +// This file is part of MinIO Console Server +// Copyright (c) 2020 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 operations + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime/middleware" + + "github.com/minio/mcs/models" +) + +// BulkUpdateUsersGroupsHandlerFunc turns a function with the right signature into a bulk update users groups handler +type BulkUpdateUsersGroupsHandlerFunc func(BulkUpdateUsersGroupsParams, *models.Principal) middleware.Responder + +// Handle executing the request and returning a response +func (fn BulkUpdateUsersGroupsHandlerFunc) Handle(params BulkUpdateUsersGroupsParams, principal *models.Principal) middleware.Responder { + return fn(params, principal) +} + +// BulkUpdateUsersGroupsHandler interface for that can handle valid bulk update users groups params +type BulkUpdateUsersGroupsHandler interface { + Handle(BulkUpdateUsersGroupsParams, *models.Principal) middleware.Responder +} + +// NewBulkUpdateUsersGroups creates a new http.Handler for the bulk update users groups operation +func NewBulkUpdateUsersGroups(ctx *middleware.Context, handler BulkUpdateUsersGroupsHandler) *BulkUpdateUsersGroups { + return &BulkUpdateUsersGroups{Context: ctx, Handler: handler} +} + +/*BulkUpdateUsersGroups swagger:route PUT /user/groups bulkUpdateUsersGroups + +Bulk functionality to Add Users to Groups + +*/ +type BulkUpdateUsersGroups struct { + Context *middleware.Context + Handler BulkUpdateUsersGroupsHandler +} + +func (o *BulkUpdateUsersGroups) ServeHTTP(rw http.ResponseWriter, r *http.Request) { + route, rCtx, _ := o.Context.RouteInfo(r) + if rCtx != nil { + r = rCtx + } + var Params = NewBulkUpdateUsersGroupsParams() + + uprinc, aCtx, err := o.Context.Authorize(r, route) + if err != nil { + o.Context.Respond(rw, r, route.Produces, route, err) + return + } + if aCtx != nil { + r = aCtx + } + var principal *models.Principal + if uprinc != nil { + principal = uprinc.(*models.Principal) // this is really a models.Principal, I promise + } + + if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params + o.Context.Respond(rw, r, route.Produces, route, err) + return + } + + res := o.Handler.Handle(Params, principal) // actually handle the request + + o.Context.Respond(rw, r, route.Produces, route, res) + +} diff --git a/restapi/operations/bulk_update_users_groups_parameters.go b/restapi/operations/bulk_update_users_groups_parameters.go new file mode 100644 index 000000000..28150db15 --- /dev/null +++ b/restapi/operations/bulk_update_users_groups_parameters.go @@ -0,0 +1,94 @@ +// Code generated by go-swagger; DO NOT EDIT. + +// This file is part of MinIO Console Server +// Copyright (c) 2020 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 operations + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "io" + "net/http" + + "github.com/go-openapi/errors" + "github.com/go-openapi/runtime" + "github.com/go-openapi/runtime/middleware" + + "github.com/minio/mcs/models" +) + +// NewBulkUpdateUsersGroupsParams creates a new BulkUpdateUsersGroupsParams object +// no default values defined in spec. +func NewBulkUpdateUsersGroupsParams() BulkUpdateUsersGroupsParams { + + return BulkUpdateUsersGroupsParams{} +} + +// BulkUpdateUsersGroupsParams contains all the bound params for the bulk update users groups operation +// typically these are obtained from a http.Request +// +// swagger:parameters BulkUpdateUsersGroups +type BulkUpdateUsersGroupsParams struct { + + // HTTP Request Object + HTTPRequest *http.Request `json:"-"` + + /* + Required: true + In: body + */ + Body *models.BulkUserGroups +} + +// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface +// for simple values it will use straight method calls. +// +// To ensure default values, the struct must have been initialized with NewBulkUpdateUsersGroupsParams() beforehand. +func (o *BulkUpdateUsersGroupsParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error { + var res []error + + o.HTTPRequest = r + + if runtime.HasBody(r) { + defer r.Body.Close() + var body models.BulkUserGroups + if err := route.Consumer.Consume(r.Body, &body); err != nil { + if err == io.EOF { + res = append(res, errors.Required("body", "body")) + } else { + res = append(res, errors.NewParseError("body", "body", "", err)) + } + } else { + // validate body object + if err := body.Validate(route.Formats); err != nil { + res = append(res, err) + } + + if len(res) == 0 { + o.Body = &body + } + } + } else { + res = append(res, errors.Required("body", "body")) + } + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} diff --git a/restapi/operations/bulk_update_users_groups_responses.go b/restapi/operations/bulk_update_users_groups_responses.go new file mode 100644 index 000000000..a0b0344c4 --- /dev/null +++ b/restapi/operations/bulk_update_users_groups_responses.go @@ -0,0 +1,113 @@ +// Code generated by go-swagger; DO NOT EDIT. + +// This file is part of MinIO Console Server +// Copyright (c) 2020 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 operations + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime" + + "github.com/minio/mcs/models" +) + +// BulkUpdateUsersGroupsOKCode is the HTTP code returned for type BulkUpdateUsersGroupsOK +const BulkUpdateUsersGroupsOKCode int = 200 + +/*BulkUpdateUsersGroupsOK A successful response. + +swagger:response bulkUpdateUsersGroupsOK +*/ +type BulkUpdateUsersGroupsOK struct { +} + +// NewBulkUpdateUsersGroupsOK creates BulkUpdateUsersGroupsOK with default headers values +func NewBulkUpdateUsersGroupsOK() *BulkUpdateUsersGroupsOK { + + return &BulkUpdateUsersGroupsOK{} +} + +// WriteResponse to the client +func (o *BulkUpdateUsersGroupsOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.Header().Del(runtime.HeaderContentType) //Remove Content-Type on empty responses + + rw.WriteHeader(200) +} + +/*BulkUpdateUsersGroupsDefault Generic error response. + +swagger:response bulkUpdateUsersGroupsDefault +*/ +type BulkUpdateUsersGroupsDefault struct { + _statusCode int + + /* + In: Body + */ + Payload *models.Error `json:"body,omitempty"` +} + +// NewBulkUpdateUsersGroupsDefault creates BulkUpdateUsersGroupsDefault with default headers values +func NewBulkUpdateUsersGroupsDefault(code int) *BulkUpdateUsersGroupsDefault { + if code <= 0 { + code = 500 + } + + return &BulkUpdateUsersGroupsDefault{ + _statusCode: code, + } +} + +// WithStatusCode adds the status to the bulk update users groups default response +func (o *BulkUpdateUsersGroupsDefault) WithStatusCode(code int) *BulkUpdateUsersGroupsDefault { + o._statusCode = code + return o +} + +// SetStatusCode sets the status to the bulk update users groups default response +func (o *BulkUpdateUsersGroupsDefault) SetStatusCode(code int) { + o._statusCode = code +} + +// WithPayload adds the payload to the bulk update users groups default response +func (o *BulkUpdateUsersGroupsDefault) WithPayload(payload *models.Error) *BulkUpdateUsersGroupsDefault { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the bulk update users groups default response +func (o *BulkUpdateUsersGroupsDefault) SetPayload(payload *models.Error) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *BulkUpdateUsersGroupsDefault) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(o._statusCode) + if o.Payload != nil { + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } + } +} diff --git a/restapi/operations/bulk_update_users_groups_urlbuilder.go b/restapi/operations/bulk_update_users_groups_urlbuilder.go new file mode 100644 index 000000000..cadee05aa --- /dev/null +++ b/restapi/operations/bulk_update_users_groups_urlbuilder.go @@ -0,0 +1,104 @@ +// Code generated by go-swagger; DO NOT EDIT. + +// This file is part of MinIO Console Server +// Copyright (c) 2020 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 operations + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "errors" + "net/url" + golangswaggerpaths "path" +) + +// BulkUpdateUsersGroupsURL generates an URL for the bulk update users groups operation +type BulkUpdateUsersGroupsURL struct { + _basePath string +} + +// WithBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *BulkUpdateUsersGroupsURL) WithBasePath(bp string) *BulkUpdateUsersGroupsURL { + o.SetBasePath(bp) + return o +} + +// SetBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *BulkUpdateUsersGroupsURL) SetBasePath(bp string) { + o._basePath = bp +} + +// Build a url path and query string +func (o *BulkUpdateUsersGroupsURL) Build() (*url.URL, error) { + var _result url.URL + + var _path = "/user/groups" + + _basePath := o._basePath + if _basePath == "" { + _basePath = "/api/v1" + } + _result.Path = golangswaggerpaths.Join(_basePath, _path) + + return &_result, nil +} + +// Must is a helper function to panic when the url builder returns an error +func (o *BulkUpdateUsersGroupsURL) Must(u *url.URL, err error) *url.URL { + if err != nil { + panic(err) + } + if u == nil { + panic("url can't be nil") + } + return u +} + +// String returns the string representation of the path with query string +func (o *BulkUpdateUsersGroupsURL) String() string { + return o.Must(o.Build()).String() +} + +// BuildFull builds a full url with scheme, host, path and query string +func (o *BulkUpdateUsersGroupsURL) BuildFull(scheme, host string) (*url.URL, error) { + if scheme == "" { + return nil, errors.New("scheme is required for a full url on BulkUpdateUsersGroupsURL") + } + if host == "" { + return nil, errors.New("host is required for a full url on BulkUpdateUsersGroupsURL") + } + + base, err := o.Build() + if err != nil { + return nil, err + } + + base.Scheme = scheme + base.Host = host + return base, nil +} + +// StringFull returns the string representation of a complete url +func (o *BulkUpdateUsersGroupsURL) StringFull(scheme, host string) string { + return o.Must(o.BuildFull(scheme, host)).String() +} diff --git a/restapi/operations/mcs_api.go b/restapi/operations/mcs_api.go index 359ef2f9a..59e33fb5d 100644 --- a/restapi/operations/mcs_api.go +++ b/restapi/operations/mcs_api.go @@ -87,6 +87,9 @@ func NewMcsAPI(spec *loads.Document) *McsAPI { UserAPIBucketSetPolicyHandler: user_api.BucketSetPolicyHandlerFunc(func(params user_api.BucketSetPolicyParams, principal *models.Principal) middleware.Responder { return middleware.NotImplemented("operation user_api.BucketSetPolicy has not yet been implemented") }), + AdminAPIBulkUpdateUsersGroupsHandler: admin_api.BulkUpdateUsersGroupsHandlerFunc(func(params admin_api.BulkUpdateUsersGroupsParams, principal *models.Principal) middleware.Responder { + return middleware.NotImplemented("operation admin_api.BulkUpdateUsersGroups has not yet been implemented") + }), AdminAPIConfigInfoHandler: admin_api.ConfigInfoHandlerFunc(func(params admin_api.ConfigInfoParams, principal *models.Principal) middleware.Responder { return middleware.NotImplemented("operation admin_api.ConfigInfo has not yet been implemented") }), @@ -242,6 +245,8 @@ type McsAPI struct { UserAPIBucketInfoHandler user_api.BucketInfoHandler // UserAPIBucketSetPolicyHandler sets the operation handler for the bucket set policy operation UserAPIBucketSetPolicyHandler user_api.BucketSetPolicyHandler + // AdminAPIBulkUpdateUsersGroupsHandler sets the operation handler for the bulk update users groups operation + AdminAPIBulkUpdateUsersGroupsHandler admin_api.BulkUpdateUsersGroupsHandler // AdminAPIConfigInfoHandler sets the operation handler for the config info operation AdminAPIConfigInfoHandler admin_api.ConfigInfoHandler // UserAPICreateBucketEventHandler sets the operation handler for the create bucket event operation @@ -399,6 +404,9 @@ func (o *McsAPI) Validate() error { if o.UserAPIBucketSetPolicyHandler == nil { unregistered = append(unregistered, "user_api.BucketSetPolicyHandler") } + if o.AdminAPIBulkUpdateUsersGroupsHandler == nil { + unregistered = append(unregistered, "admin_api.BulkUpdateUsersGroupsHandler") + } if o.AdminAPIConfigInfoHandler == nil { unregistered = append(unregistered, "admin_api.ConfigInfoHandler") } @@ -621,6 +629,10 @@ func (o *McsAPI) initHandlerCache() { o.handlers["PUT"] = make(map[string]http.Handler) } o.handlers["PUT"]["/buckets/{name}/set-policy"] = user_api.NewBucketSetPolicy(o.context, o.UserAPIBucketSetPolicyHandler) + if o.handlers["PUT"] == nil { + o.handlers["PUT"] = make(map[string]http.Handler) + } + o.handlers["PUT"]["/users-groups-bulk"] = admin_api.NewBulkUpdateUsersGroups(o.context, o.AdminAPIBulkUpdateUsersGroupsHandler) if o.handlers["GET"] == nil { o.handlers["GET"] = make(map[string]http.Handler) } diff --git a/swagger.yml b/swagger.yml index 1900fef9f..09ea3a69e 100644 --- a/swagger.yml +++ b/swagger.yml @@ -336,6 +336,25 @@ paths: $ref: "#/definitions/error" tags: - AdminAPI + /users-groups-bulk: + put: + summary: Bulk functionality to Add Users to Groups + operationId: BulkUpdateUsersGroups + parameters: + - name: body + in: body + required: true + schema: + $ref: "#/definitions/bulkUserGroups" + responses: + 200: + description: A successful response. + default: + description: Generic error response. + schema: + $ref: "#/definitions/error" + tags: + - AdminAPI /groups: get: summary: List Groups @@ -1230,4 +1249,17 @@ definitions: type: array items: type: string - + bulkUserGroups: + type: object + required: + - users + - groups + properties: + users: + type: array + items: + type: string + groups: + type: array + items: + type: string