ComponentManager permissions logic, Batch Manager content type expansion, Stylekit 2.0.14, SFJS 0.3.58

This commit is contained in:
Mo Bitar
2019-04-29 18:48:52 -05:00
parent 997451e568
commit a9cfbc53e0
6 changed files with 85 additions and 57 deletions

View File

@@ -505,16 +505,24 @@ class ComponentManager {
}.bind(this)) }.bind(this))
} }
isItemWithinComponentContextJurisdiction(item, component) { isItemIdWithinComponentContextJurisdiction(uuid, component) {
let itemIdsInJurisdiction = this.itemIdsInContextJurisdictionForComponent(component);
return itemIdsInJurisdiction.includes(uuid);
}
/* Returns items that given component has context permissions for */
itemIdsInContextJurisdictionForComponent(component) {
let itemIds = [];
for(let handler of this.handlersForArea(component.area)) { for(let handler of this.handlersForArea(component.area)) {
if(handler.contextRequestHandler) { if(handler.contextRequestHandler) {
var itemInContext = handler.contextRequestHandler(component); var itemInContext = handler.contextRequestHandler(component);
if(itemInContext && itemInContext.uuid == item.uuid) { if(itemInContext) {
return true; itemIds.push(itemInContext.uuid);
} }
} }
} }
return false;
return itemIds;
} }
handlersForArea(area) { handlersForArea(area) {
@@ -522,24 +530,32 @@ class ComponentManager {
} }
handleSaveItemsMessage(component, message) { handleSaveItemsMessage(component, message) {
var responseItems = message.data.items; let responseItems = message.data.items;
var requiredPermissions; let requiredPermissions = [];
// Check if you're just trying to save the context item, which requires only stream-context-item permissions let itemIdsInContextJurisdiction = this.itemIdsInContextJurisdictionForComponent(component);
if(responseItems.length == 1 && this.isItemWithinComponentContextJurisdiction(responseItems[0], component)) {
requiredPermissions = [ // Pending as in needed to be accounted for in permissions.
{ let pendingResponseItems = responseItems.slice();
for(let responseItem of responseItems.slice()) {
if(itemIdsInContextJurisdiction.includes(responseItem.uuid)) {
requiredPermissions.push({
name: "stream-context-item" name: "stream-context-item"
} });
]; _.pull(pendingResponseItems, responseItem);
} else { // We break because there can only be one context item
var requiredContentTypes = _.uniq(responseItems.map((i) => {return i.content_type})).sort(); break;
requiredPermissions = [ }
{ }
name: "stream-items",
content_types: requiredContentTypes // Check to see if additional privileges are required
} if(pendingResponseItems.length > 0) {
]; var requiredContentTypes = _.uniq(pendingResponseItems.map((i) => {return i.content_type})).sort();
requiredPermissions.push({
name: "stream-items",
content_types: requiredContentTypes
});
} }
this.runWithPermissions(component, requiredPermissions, () => { this.runWithPermissions(component, requiredPermissions, () => {
@@ -751,41 +767,44 @@ class ComponentManager {
} }
runWithPermissions(component, requiredPermissions, runFunction) { runWithPermissions(component, requiredPermissions, runFunction) {
if(!component.permissions) { if(!component.permissions) {
component.permissions = []; component.permissions = [];
} }
// Make copy as not to mutate input values
requiredPermissions = JSON.parse(JSON.stringify(requiredPermissions));
var acquiredPermissions = component.permissions; var acquiredPermissions = component.permissions;
var acquiredMatchesRequired = true;
for(var required of requiredPermissions) { for(let required of requiredPermissions.slice()) {
var matching = acquiredPermissions.find((candidate) => { // Remove anything we already have
var matchesContentTypes = true; let respectiveAcquired = acquiredPermissions.find((candidate) => candidate.name == required.name);
if(candidate.content_types && required.content_types) { if(!respectiveAcquired) {
matchesContentTypes = JSON.stringify(candidate.content_types.sort()) == JSON.stringify(required.content_types.sort()); continue;
} }
return candidate.name == required.name && matchesContentTypes;
});
if(!matching) { // We now match on name, lets substract from required.content_types anything we have in acquired.
/* Required permissions can be 1 content type, and requestedPermisisons may send an array of content types. let requiredContentTypes = required.content_types;
In the case of an array, we can just check to make sure that requiredPermissions content type is found in the array
*/
matching = acquiredPermissions.find((candidate) => {
return Array.isArray(candidate.content_types)
&& Array.isArray(required.content_types)
&& candidate.content_types.containsPrimitiveSubset(required.content_types);
});
if(!matching) { if(!requiredContentTypes) {
acquiredMatchesRequired = false; // If this permission does not require any content types (i.e stream-context-item)
break; // then we can remove this from required since we match by name (respectiveAcquired.name == required.name)
} _.pull(requiredPermissions, required);
continue;
}
for(let acquiredContentType of respectiveAcquired.content_types) {
// console.log("Removing content_type", acquiredContentType, "from", requiredContentTypes);
_.pull(requiredContentTypes, acquiredContentType);
}
if(requiredContentTypes.length == 0) {
// We've removed all acquired and end up with zero, means we already have all these permissions
_.pull(requiredPermissions, required);
} }
} }
if(!acquiredMatchesRequired) { if(requiredPermissions.length > 0) {
this.promptForPermissions(component, requiredPermissions, function(approved){ this.promptForPermissions(component, requiredPermissions, function(approved){
if(approved) { if(approved) {
runFunction(); runFunction();
@@ -804,9 +823,13 @@ class ComponentManager {
scope.callback = function(approved) { scope.callback = function(approved) {
if(approved) { if(approved) {
for(var permission of permissions) { for(let permission of permissions) {
if(!component.permissions.includes(permission)) { let matchingPermission = component.permissions.find((candidate) => candidate.name == permission.name);
if(!matchingPermission) {
component.permissions.push(permission); component.permissions.push(permission);
} else {
// Permission already exists, but content_types may have been expanded
matchingPermission.content_types = _.uniq(matchingPermission.content_types.concat(permission.content_types));
} }
} }
component.setDirty(true); component.setDirty(true);

View File

@@ -141,7 +141,12 @@ class NativeExtManager {
permissions: [ permissions: [
{ {
name: "stream-items", name: "stream-items",
content_types: ["Note", "Tag", "SN|Component", "SN|Theme", "SF|Extension", "Extension", "SF|MFA", "SN|Editor", "SN|UserPreferences"] content_types: [
"Note", "Tag", "SN|SmartTag",
"SN|Component", "SN|Theme", "SN|UserPreferences",
"SF|Extension", "Extension", "SF|MFA", "SN|Editor",
"SN|FileSafe|Credentials", "SN|FileSafe|FileMetadata", "SN|FileSafe|Integration"
]
} }
] ]
} }

View File

@@ -20,7 +20,7 @@
#notes-title-bar { #notes-title-bar {
padding-top: 16px; padding-top: 16px;
font-weight: normal; font-weight: normal;
font-size: 18px; font-size: var(--sn-stylekit-font-size-h1);
.section-title-bar-header .title { .section-title-bar-header .title {
color: var(--sn-stylekit-neutral-color); color: var(--sn-stylekit-neutral-color);

12
package-lock.json generated
View File

@@ -4756,9 +4756,9 @@
"dev": true "dev": true
}, },
"sn-stylekit": { "sn-stylekit": {
"version": "2.0.13", "version": "2.0.14",
"resolved": "https://registry.npmjs.org/sn-stylekit/-/sn-stylekit-2.0.13.tgz", "resolved": "https://registry.npmjs.org/sn-stylekit/-/sn-stylekit-2.0.14.tgz",
"integrity": "sha512-rGDc2cc0/r84lQn/HJOw6GvJz5VonSK2UVdLTS9TFo+wwbAtRnww8aj7VILgNneUAnqwdCKdY5O/Fk3rN0Hw7g==", "integrity": "sha512-48RqEhxLbvDrEmY+SgiQg8IbeAlf0bjtHk/RAhMNwGc9ZrUgBoxMyxJJgUZeKiyx+dm8POfaxpsgzHBG9Qix+A==",
"dev": true "dev": true
}, },
"snake-case": { "snake-case": {
@@ -4830,9 +4830,9 @@
"dev": true "dev": true
}, },
"standard-file-js": { "standard-file-js": {
"version": "0.3.57", "version": "0.3.58",
"resolved": "https://registry.npmjs.org/standard-file-js/-/standard-file-js-0.3.57.tgz", "resolved": "https://registry.npmjs.org/standard-file-js/-/standard-file-js-0.3.58.tgz",
"integrity": "sha512-DJA3KKHTTKXnMzl7xer0mu5aPhAv/XUftIJokq+G/BNx1EHG30mwC3YTDJhAOjfSDXR+M4geB0A7gj80LA1Veg==", "integrity": "sha512-xkoC+lDK12WPL2+ckD2Ki8WfTsy8TphvwqLS9OASuY06MHdVh9qGGooYvewjXSQkSQTBDrs7f+0mzEX0Rn2AZw==",
"dev": true "dev": true
}, },
"statuses": { "statuses": {

View File

@@ -37,8 +37,8 @@
"mocha": "^5.2.0", "mocha": "^5.2.0",
"serve-static": "^1.13.2", "serve-static": "^1.13.2",
"sn-models": "0.1.14", "sn-models": "0.1.14",
"sn-stylekit": "2.0.13", "sn-stylekit": "2.0.14",
"standard-file-js": "0.3.57", "standard-file-js": "0.3.58",
"grunt-shell": "^2.1.0" "grunt-shell": "^2.1.0"
} }
} }