Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix permissions for items shown in admin dashboard #2145

Merged
merged 29 commits into from
May 9, 2017
Merged
Show file tree
Hide file tree
Changes from 27 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
e86b8a6
Initial test of filtering pkgs
impactmass Apr 19, 2017
6e6faf7
Filter showing packages by permissions
impactmass Apr 19, 2017
89f8084
Resolve issue with hasAccess check on registry items
impactmass Apr 21, 2017
e94e517
Comment
impactmass Apr 21, 2017
0f44637
Merge branch 'development' into seun-audit-package-access
impactmass Apr 21, 2017
b54b918
Merge branch 'development' into seun-audit-package-access
impactmass Apr 21, 2017
098133c
Comment edit
impactmass Apr 21, 2017
31c87db
Call packages coll without filter
impactmass Apr 21, 2017
8e92fc1
Merge branch 'development' into seun-audit-package-access
impactmass Apr 24, 2017
053b283
Move audience addition to ReactionApps
impactmass Apr 24, 2017
a650181
Merge branch 'development' into seun-audit-package-access
impactmass Apr 25, 2017
593dd6e
Better comment
impactmass Apr 25, 2017
f01d98a
Check not needed again.Apps come based on access level
impactmass Apr 25, 2017
c008d2e
space fix
impactmass Apr 25, 2017
227579f
Merge branch 'development' into seun-audit-package-access
impactmass Apr 26, 2017
369cdcd
Test: Permissions on toolbar component
impactmass Apr 27, 2017
4b0e0c4
hasProduct access on toolbar
impactmass Apr 27, 2017
3ed8398
Fix data
impactmass Apr 27, 2017
159f2a1
Use createProduct as filter
impactmass Apr 27, 2017
0420448
Refactor toolbar permission check
impactmass Apr 28, 2017
c2ef579
Improve Comment
impactmass Apr 28, 2017
b8539ac
Merge branch 'development' into seun-audit-package-access
impactmass May 2, 2017
26762d5
Add missing perms in pub
impactmass May 2, 2017
3e21aeb
Merge branch 'development' into seun-audit-package-access
impactmass May 4, 2017
95ce280
Merge branch 'development' into seun-audit-package-access
impactmass May 5, 2017
70c8490
remove comment
impactmass May 2, 2017
1fbf9c4
Add comment on filter line
impactmass May 4, 2017
590bebb
Merge branch 'development' into seun-audit-package-access
impactmass May 8, 2017
d880c9a
Merge branch 'development' into seun-audit-package-access
May 9, 2017
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion client/modules/accounts/templates/dropdown/dropdown.html
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
<ul class="user-accounts-dropdown-apps">
{{> userAccountsDropdown}}
<!--administrative shortcut icons -->
{{#each reactionApps reactionAppsOptions}}
{{#each reactionApps provides="shortcut" enabled=true}}
<li class="dropdown-apps-icon">
<a href={{pathFor name}} id="dropdown-apps-{{name}}" title="{{label}}">
<i class="{{icon}}"></i>
Expand Down
13 changes: 0 additions & 13 deletions client/modules/accounts/templates/dropdown/dropdown.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,16 +72,3 @@ Template.loginDropdown.events({
template.$(".dropdown-toggle").dropdown("toggle");
}
});

Template.accountsDropdownApps.helpers({
reactionAppsOptions() {
// get shortcuts with audience permissions based on user roles
const roles = Roles.getRolesForUser(Meteor.userId(), Reaction.getShopId());

return {
provides: "shortcut",
enabled: true,
audience: roles
};
}
});
7 changes: 5 additions & 2 deletions client/modules/accounts/templates/members/member.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,11 @@ Template.memberSettings.helpers({
// Get all permissions, add them to an array
if (registryItem.permissions) {
for (const permission of registryItem.permissions) {
permission.shopId = shopId;
permissions.push(permission);
// check needed because of non-object perms in the permissions array (e.g "admin", "owner")
if (typeof permission === "object") {
permission.shopId = shopId;
permissions.push(permission);
}
}
}

Expand Down
38 changes: 25 additions & 13 deletions client/modules/core/helpers/apps.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,6 @@ export function Apps(optionHash) {
const reactionApps = [];
let options = {};

// remove audience permissions for owner
if (Reaction.hasOwnerAccess() && optionHash.audience) {
delete optionHash.audience;
}

// allow for object or option.hash
if (optionHash) {
if (optionHash.hash) {
Expand All @@ -66,6 +61,14 @@ export function Apps(optionHash) {
options.shopId = Reaction.getShopId();
}

// make sure audience is used for all calls to ReactionApps
options.audience = Roles.getRolesForUser(Meteor.userId(), Reaction.getShopId());

// remove audience permissions for owner (still needed here for older/legacy calls)
if (Reaction.hasOwnerAccess() && options.audience) {
delete options.audience;
}

//
// build filter to only get matching registry elements
//
Expand All @@ -89,24 +92,33 @@ export function Apps(optionHash) {
}
}

// fetch the packages
delete filter["registry.audience"]; // Temporarily remove "audience" key (see comment below)

// TODO: Review fix for filter on Packages.find(filter)
// The current "filter" setup uses "audience" field which is not present in the registry array in most (if not all) docs
// in the Packages coll.
// For now, the audience checks (after the Package.find call) filters out the registry items based on permissions. But
// part of the filtering should have been handled by the Package.find call, if the "audience" filter works as it should.
Packages.find(filter).forEach((app) => {
const matchingRegistry = _.filter(app.registry, function (item) {
const itemFilter = registryFilter;
const itemFilter = _.cloneDeep(registryFilter);

// check audience permissions only if they exist as part of optionHash and are part of the registry item
// ideally all routes should use it, safe for backwards compatibility though
// owner bypasses permissions
if (!Reaction.hasOwnerAccess() && item.audience && registryFilter.audience) {
if (!Reaction.hasOwnerAccess() && item.permissions && registryFilter.audience) {
let hasAccess;

for (const permission of registryFilter.audience) {
if (item.audience.indexOf(permission) > -1) {
hasAccess = true;
}
// make sure user also has audience perms
if (Roles.userIsInRole(Meteor.userId(), permission, Reaction.getShopId())) {
// This checks that the registry item contains a permissions matches with the user's permission for the shop
const hasPermissionToRegistryItem = item.permissions.indexOf(permission) > -1;
// This checks that the user's permission set have the right value that is on the registry item
const hasRoleAccessForShop = Roles.userIsInRole(Meteor.userId(), permission, Reaction.getShopId());

// both checks must pass for access to be granted
if (hasPermissionToRegistryItem && hasRoleAccessForShop) {
hasAccess = true;
break;
}
}

Expand Down
47 changes: 28 additions & 19 deletions imports/plugins/core/dashboard/client/components/toolbar.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ class PublishControls extends Component {
dashboardHeaderTemplate: PropTypes.oneOfType([PropTypes.func, PropTypes.node, PropTypes.string]),
documentIds: PropTypes.arrayOf(PropTypes.string),
documents: PropTypes.arrayOf(PropTypes.object),
hasCreateProductAccess: PropTypes.bool,
isEnabled: PropTypes.bool,
isPreview: PropTypes.bool,
onAddProduct: PropTypes.func,
Expand Down Expand Up @@ -61,16 +62,20 @@ class PublishControls extends Component {
}

renderVisibilitySwitch() {
return (
<Switch
i18nKeyLabel="app.editMode"
i18nKeyOnLabel="app.editMode"
label={"Edit Mode"}
onLabel={"Edit Mode"}
checked={!this.props.isPreview}
onChange={this.onViewContextChange}
/>
);
if (this.props.hasCreateProductAccess) {
return (
<Switch
i18nKeyLabel="app.editMode"
i18nKeyOnLabel="app.editMode"
label={"Edit Mode"}
onLabel={"Edit Mode"}
checked={!this.props.isPreview}
onChange={this.onViewContextChange}
/>
);
}

return null;
}

renderAdminButton() {
Expand All @@ -90,14 +95,18 @@ class PublishControls extends Component {
}

renderAddButton() {
return (
<FlatButton
i18nKeyTooltip="app.shortcut.addProductLabel"
icon={"fa fa-plus"}
tooltip={"Add Product"}
onClick={this.props.onAddProduct}
/>
);
if (this.props.hasCreateProductAccess) {
return (
<FlatButton
i18nKeyTooltip="app.shortcut.addProductLabel"
icon={"fa fa-plus"}
tooltip={"Add Product"}
onClick={this.props.onAddProduct}
/>
);
}

return null;
}

renderPackageButons() {
Expand All @@ -113,7 +122,7 @@ class PublishControls extends Component {
}

renderCustomControls() {
if (this.props.dashboardHeaderTemplate) {
if (this.props.dashboardHeaderTemplate && this.props.hasCreateProductAccess) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not specific to this PR, but has the createProduct permission become a bit of a universal check for more than just creating products?

if (this.props.isEnabled) {
return [
<VerticalDivider key="customControlsVerticaldivider" />,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ function composer(props, onData) {
isEnabled: isRevisionControlEnabled(),
isActionViewAtRootView: Reaction.isActionViewAtRootView(),
actionViewIsOpen: Reaction.isActionViewOpen(),
hasCreateProductAccess: Reaction.hasPermission("createProduct", Meteor.userId(), Reaction.shopId),

// Callbacks
onAddProduct: handleAddProduct,
Expand Down
6 changes: 4 additions & 2 deletions server/publications/collections/packages.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,11 @@ function transform(doc, userId) {
registry.shopId = doc.shopId;
registry.packageName = registry.packageName || doc.name;
registry.settingsKey = (registry.name || doc.name).split("/").splice(-1)[0];

// check and set package enabled state
// todo could add audience permissions to registry
registry.permissions = [...permissions];
if (registry.route) {
registry.permissions.push(registry.name || doc.name + "/" + registry.template);
}
if (doc.settings && doc.settings[registry.settingsKey]) {
registry.enabled = !!doc.settings[registry.settingsKey].enabled;
} else {
Expand Down