From 9fd5f370a4dbbf004254a028b17927ad32ddc3db Mon Sep 17 00:00:00 2001 From: Mathieu Leplatre Date: Tue, 2 Oct 2018 11:58:21 +0200 Subject: [PATCH 1/3] Fix #401: Show create bucket only if allowed --- src/components/Sidebar.js | 26 +++++++++++++--------- src/permission.js | 8 +++++++ test/components/Sidebar_test.js | 38 ++++++++++++++++++++++++++++----- test/permission_test.js | 29 ++++++++++++++++++++++++- 4 files changed, 85 insertions(+), 16 deletions(-) diff --git a/src/components/Sidebar.js b/src/components/Sidebar.js index 541215b50..98245b249 100644 --- a/src/components/Sidebar.js +++ b/src/components/Sidebar.js @@ -13,6 +13,7 @@ import * as React from "react"; import Spinner from "./Spinner"; import AdminLink from "./AdminLink"; import url from "../url"; +import { canCreateBucket } from "../permission"; type SideBarLinkProps = { currentPath: string, @@ -170,6 +171,7 @@ function filterBuckets(buckets, filters): BucketEntry[] { } type BucketsMenuState = { + canCreateBucket: boolean, hideReadOnly: boolean, search: ?string, }; @@ -195,6 +197,7 @@ class BucketsMenu extends PureComponent { render() { const { + canCreateBucket, currentPath, busy, buckets, @@ -205,17 +208,19 @@ class BucketsMenu extends PureComponent { const filteredBuckets = filterBuckets(buckets, this.state); return (
-
-
- - - Create bucket - + {canCreateBucket && ( +
+
+ + + Create bucket + +
-
+ )}
Filters @@ -326,6 +331,7 @@ export default class Sidebar extends PureComponent {
{authenticated && ( 0; } +export function canCreateBucket(session: SessionState): boolean { + return can(session, (perm: PermissionsListEntry) => { + return ( + perm.resource_name == "root" && perm.permissions.includes("bucket:create") + ); + }); +} + export function canEditBucket( session: SessionState, bucket: BucketState diff --git a/test/components/Sidebar_test.js b/test/components/Sidebar_test.js index 4c796beb4..7875693a9 100644 --- a/test/components/Sidebar_test.js +++ b/test/components/Sidebar_test.js @@ -2,6 +2,7 @@ import { expect } from "chai"; import { createSandbox, createComponent } from "../test_utils"; import Sidebar from "../../src/components/Sidebar"; +import { clone } from "../../src/utils"; describe("Sidebar component", () => { let sandbox; @@ -48,12 +49,12 @@ describe("Sidebar component", () => { ], }; - beforeEach(() => { - const params = { bid: "mybuck", cid: "mycoll" }; - const location = { pathname: "" }; - const capabilities = { history: {} }; - const settings = { sidebarMaxListedCollections: 2 }; + const params = { bid: "mybuck", cid: "mycoll" }; + const location = { pathname: "" }; + const capabilities = { history: {} }; + const settings = { sidebarMaxListedCollections: 2 }; + beforeEach(() => { node = createComponent(Sidebar, { match: { params }, location, @@ -96,5 +97,32 @@ describe("Sidebar component", () => { expect(targetEntry.classList.contains("active")).eql(true); }); + + describe("Create bucket", () => { + it("should be shown by default", () => { + node = createComponent(Sidebar, { + match: { params }, + location, + session, + settings, + capabilities, + }); + expect(node.querySelector(".bucket-create")).to.exist; + }); + + it("should be hidden if not allowed", () => { + const notAllowed = clone(session); + notAllowed.permissions = [{ resource_name: "root", permissions: [] }]; + + node = createComponent(Sidebar, { + match: { params }, + location, + session: notAllowed, + settings, + capabilities, + }); + expect(node.querySelector(".bucket-create")).to.not.exist; + }); + }); }); }); diff --git a/test/permission_test.js b/test/permission_test.js index 9f6959f1a..85a50d106 100644 --- a/test/permission_test.js +++ b/test/permission_test.js @@ -3,6 +3,7 @@ import { expect } from "chai"; import { AUTHENTICATED, EVERYONE, + canCreateBucket, canEditBucket, canCreateCollection, canEditCollection, @@ -14,8 +15,34 @@ import { permissionsToFormData, } from "../src/permission"; +describe("canCreateBucket", () => { + it("should always return true if no permissions list", () => { + const session = { permissions: null }; + expect(canCreateBucket(session)).eql(true); + }); + + it("should return false if root perm is not listed", () => { + const session = { permissions: [{ bucket_id: "xyz" }] }; + expect(canCreateBucket(session)).eql(false); + }); + + it("should return false if perm is not listed", () => { + const session = { + permissions: [{ resource_name: "root", permissions: [] }], + }; + expect(canCreateBucket(session)).eql(false); + }); + + it("should return true if perm is listed", () => { + const session = { + permissions: [{ resource_name: "root", permissions: ["bucket:create"] }], + }; + expect(canCreateBucket(session)).eql(true); + }); +}); + describe("canEditBucket", () => { - it("should always return true if no permisssions list", () => { + it("should always return true if no permissions list", () => { const session = { permissions: null }; const bucket = {}; expect(canEditBucket(session, bucket)).eql(true); From db0ab8ad774d9cf233ba0bdc92d8f333480b7df7 Mon Sep 17 00:00:00 2001 From: Mathieu Leplatre Date: Tue, 2 Oct 2018 12:51:52 +0200 Subject: [PATCH 2/3] Fix flow --- src/components/Sidebar.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/Sidebar.js b/src/components/Sidebar.js index 98245b249..537ccf1c5 100644 --- a/src/components/Sidebar.js +++ b/src/components/Sidebar.js @@ -135,6 +135,7 @@ function BucketCollectionsMenu(props) { } type BucketsMenuProps = { + canCreateBucket: boolean, currentPath: string, busy: boolean, buckets: BucketEntry[], @@ -179,7 +180,7 @@ type BucketsMenuState = { class BucketsMenu extends PureComponent { constructor(props: BucketsMenuProps) { super(props); - this.state = { hideReadOnly: false, search: null }; + this.state = { canCreateBucket: true, hideReadOnly: false, search: null }; } toggleReadOnly = () => { From 1bfab5331fbc37e6f5bcc77b970acc3a6eac3659 Mon Sep 17 00:00:00 2001 From: Mathieu Leplatre Date: Tue, 2 Oct 2018 17:06:53 +0200 Subject: [PATCH 3/3] @glasserc review --- src/components/Sidebar.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/components/Sidebar.js b/src/components/Sidebar.js index 537ccf1c5..6700c9145 100644 --- a/src/components/Sidebar.js +++ b/src/components/Sidebar.js @@ -172,7 +172,6 @@ function filterBuckets(buckets, filters): BucketEntry[] { } type BucketsMenuState = { - canCreateBucket: boolean, hideReadOnly: boolean, search: ?string, }; @@ -180,7 +179,7 @@ type BucketsMenuState = { class BucketsMenu extends PureComponent { constructor(props: BucketsMenuProps) { super(props); - this.state = { canCreateBucket: true, hideReadOnly: false, search: null }; + this.state = { hideReadOnly: false, search: null }; } toggleReadOnly = () => {