Skip to content

Commit a160b92

Browse files
bexsoftBenjamin Perezdvaldivia
authored
Display temporal paths when a policy has prefixes to allow navigation (#2011)
Signed-off-by: Benjamin Perez <benjamin@bexsoft.net> Co-authored-by: Benjamin Perez <benjamin@bexsoft.net> Co-authored-by: Daniel Valdivia <18384552+dvaldivia@users.noreply.github.com>
1 parent dc3e7f5 commit a160b92

File tree

11 files changed

+1218
-7
lines changed

11 files changed

+1218
-7
lines changed

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ require (
2222
github.com/minio/cli v1.22.0
2323
github.com/minio/highwayhash v1.0.2
2424
github.com/minio/kes v0.19.2
25-
github.com/minio/madmin-go v1.3.13
25+
github.com/minio/madmin-go v1.3.14
2626
github.com/minio/mc v0.0.0-20220512134321-aa60a8db1e4d
2727
github.com/minio/minio-go/v7 v7.0.26
2828
github.com/minio/operator v0.0.0-20220414212219-ba4c097324b2

go.sum

Lines changed: 855 additions & 1 deletion
Large diffs are not rendered by default.

models/permission_resource.go

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

models/session_response.go

Lines changed: 64 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

portal-ui/src/screens/Console/Buckets/ListBuckets/Objects/ListObjects/ListObjects.tsx

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,12 @@ import {
5050
} from "../../../../Common/FormComponents/common/styleLibrary";
5151
import { Badge, Typography } from "@mui/material";
5252
import BrowserBreadcrumbs from "../../../../ObjectBrowser/BrowserBreadcrumbs";
53-
54-
import { download, extensionPreview, sortListObjects } from "../utils";
55-
53+
import {
54+
download,
55+
extensionPreview,
56+
permissionItems,
57+
sortListObjects,
58+
} from "../utils";
5659
import {
5760
BucketInfo,
5861
BucketObjectLocking,
@@ -87,6 +90,7 @@ import ActionsListSection from "./ActionsListSection";
8790
import { listModeColumns, rewindModeColumns } from "./ListObjectsHelpers";
8891
import VersionsNavigator from "../ObjectDetails/VersionsNavigator";
8992
import CheckboxWrapper from "../../../../Common/FormComponents/CheckboxWrapper/CheckboxWrapper";
93+
9094
import {
9195
setErrorSnackMessage,
9296
setSnackBarMessage,
@@ -305,6 +309,9 @@ const ListObjects = ({ match, history }: IListObjectsProps) => {
305309
const bucketInfo = useSelector(
306310
(state: AppState) => state.buckets.bucketDetails.bucketInfo
307311
);
312+
const allowResources = useSelector(
313+
(state: AppState) => state.console.session.allowResources
314+
);
308315

309316
const [records, setRecords] = useState<BucketObjectItem[]>([]);
310317
const [deleteMultipleOpen, setDeleteMultipleOpen] = useState<boolean>(false);
@@ -673,8 +680,19 @@ const ListObjects = ({ match, history }: IListObjectsProps) => {
673680
}
674681
})
675682
.catch((err: ErrorResponseHandler) => {
683+
const permitItems = permissionItems(
684+
bucketName,
685+
pathPrefix,
686+
allowResources || []
687+
);
688+
689+
if (!permitItems || permitItems.length === 0) {
690+
dispatch(setErrorSnackMessage(err));
691+
} else {
692+
setRecords(permitItems);
693+
}
694+
676695
dispatch(setLoadingObjectsList(false));
677-
dispatch(setErrorSnackMessage(err));
678696
});
679697
} else {
680698
dispatch(setLoadingObjectsList(false));
@@ -692,6 +710,7 @@ const ListObjects = ({ match, history }: IListObjectsProps) => {
692710
showDeleted,
693711
displayListObjects,
694712
bucketToRewind,
713+
allowResources,
695714
]);
696715

697716
// bucket info

portal-ui/src/screens/Console/Buckets/ListBuckets/Objects/utils.ts

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
// along with this program. If not, see <http://www.gnu.org/licenses/>.
1616

1717
import { BucketObjectItem } from "./ListObjects/types";
18+
import { IAllowResources } from "../../../types";
1819

1920
export const download = (
2021
bucketName: string,
@@ -161,3 +162,100 @@ export const sortListObjects = (fieldSort: string) => {
161162
(a.size || -1) - (b.size || -1);
162163
}
163164
};
165+
166+
export const permissionItems = (
167+
bucketName: string,
168+
currentPath: string,
169+
permissionsArray: IAllowResources[]
170+
): BucketObjectItem[] | null => {
171+
if (permissionsArray.length === 0) {
172+
return null;
173+
}
174+
175+
// We get permissions applied to the current bucket
176+
const filteredPermissionsForBucket = permissionsArray.filter(
177+
(permissionItem) =>
178+
permissionItem.resource.endsWith(`:${bucketName}`) ||
179+
permissionItem.resource.includes(`:${bucketName}/`)
180+
);
181+
182+
// No permissions for this bucket. we can throw the error message at this point
183+
if (filteredPermissionsForBucket.length === 0) {
184+
return null;
185+
}
186+
187+
const returnElements: BucketObjectItem[] = [];
188+
189+
// We split current path
190+
const splitCurrentPath = currentPath.split("/");
191+
192+
filteredPermissionsForBucket.forEach((permissionElement) => {
193+
// We review paths in resource address
194+
195+
// We split ARN & get the last item to check the URL
196+
const splitARN = permissionElement.resource.split(":");
197+
const url = splitARN.pop() || "";
198+
199+
// We split the paths of the URL & compare against current location to see if there are more items to include. In case current level is a wildcard or is the last one, we omit this validation
200+
201+
const splitURL = url.split("/");
202+
203+
// splitURL has more items than bucket name, we can continue validating
204+
if (splitURL.length > 1) {
205+
splitURL.every((currentElementInPath, index) => {
206+
// It is a wildcard element. We can stor the verification as value should be included (?)
207+
if (currentElementInPath === "*") {
208+
return false;
209+
}
210+
211+
// Element is not included in the path. The user is trying to browse something else.
212+
if (
213+
splitCurrentPath[index] &&
214+
splitCurrentPath[index] !== currentElementInPath
215+
) {
216+
return false;
217+
}
218+
219+
// This element is not included by index in the current paths list. We add it so user can browse into it
220+
if (!splitCurrentPath[index]) {
221+
returnElements.push({
222+
name: `${currentElementInPath}/`,
223+
size: 0,
224+
last_modified: new Date(),
225+
version_id: "",
226+
});
227+
}
228+
229+
return true;
230+
});
231+
}
232+
233+
// We review prefixes in allow resources for StringEquals variant only.
234+
if (permissionElement.conditionOperator === "StringEquals" || permissionElement.conditionOperator === "StringLike") {
235+
permissionElement.prefixes.forEach((prefixItem) => {
236+
// Prefix Item is not empty?
237+
if (prefixItem !== "") {
238+
const splitItems = prefixItem.split("/");
239+
240+
splitItems.every((splitElement, index) => {
241+
if (!splitElement.includes("*")) {
242+
if (splitElement !== splitURL[index]) {
243+
returnElements.push({
244+
name: `${splitElement}/`,
245+
size: 0,
246+
last_modified: new Date(),
247+
version_id: "",
248+
});
249+
return false;
250+
}
251+
return true;
252+
}
253+
return false;
254+
});
255+
}
256+
});
257+
}
258+
});
259+
260+
return returnElements;
261+
};

portal-ui/src/screens/Console/consoleSlice.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ const initialState: ConsoleState = {
2828
features: [],
2929
distributedMode: false,
3030
permissions: {},
31+
allowResources: null,
3132
},
3233
};
3334

portal-ui/src/screens/Console/types.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,17 @@ export interface ISessionPermissions {
1818
[key: string]: string[];
1919
}
2020

21+
export interface IAllowResources {
22+
conditionOperator: string;
23+
prefixes: string[];
24+
resource: string;
25+
}
26+
2127
export interface ISessionResponse {
2228
status: string;
2329
features: string[];
2430
operator: boolean;
2531
distributedMode: boolean;
2632
permissions: ISessionPermissions;
33+
allowResources: IAllowResources[] | null;
2734
}

0 commit comments

Comments
 (0)