Created
December 23, 2014 16:59
-
-
Save boxfoot/79350b7ccb561dc731a9 to your computer and use it in GitHub Desktop.
use `gulp cleanProfiles` to remove all negative (false) permissions from Salesforce permission files.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* By Benj Kamm, [email protected] */ | |
// Look for the value of the first text node within the current node. | |
// Returns 'false' if not found, otherwise the value of the first text node in the subnode. | |
function getXMLNodeValue(el, key) { | |
var matches = el.getElementsByTagName(key); | |
if (!matches.length) { | |
return 'false'; | |
} | |
return matches[0].childNodes[0].nodeValue; | |
} | |
// Look for all permissions of type <tagName>, return as an array | |
function getXMLTags(doc, tagName) { | |
return Array.prototype.slice.call(doc.getElementsByTagName(tagName)); | |
} | |
module.exports = { | |
getXMLNodeValue: getXMLNodeValue, | |
getXMLTags: getXMLTags | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* By Benj Kamm, [email protected] */ | |
var gulp = require('gulp'), | |
profileCleaner = require('./profileCleaner.js'); | |
gulp.task('cleanProfiles', function() { | |
var SRC_URLS = [ | |
'src/profiles/*.profile', | |
'src/permissionsets/*.permissionset' | |
]; | |
return gulp.src(SRC_URLS, {base: './'}) | |
.pipe(profileCleaner()) | |
.pipe(gulp.dest('./')); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// through2 is a thin wrapper around node transform streams | |
var through = require('through2'); | |
var DOMParser = require('xmldom').DOMParser; | |
var pd = require('pretty-data').pd; | |
var gutil = require('gulp-util'); | |
var getPermissionValue = require('./common').getXMLNodeValue; | |
var getXMLTags = require('./common').getXMLTags; | |
// Removes all empty permission nodes from metadata xml files for Profile and PermissionSet | |
function removeEmptyPermissions(content) { | |
content = content.toString(); | |
var doc = new DOMParser().parseFromString(content); | |
// Remove empty <applicationVisibilities> | |
// - Profiles must have visible=false and default=false. | |
// - PermisisionSets must have visible=false (no default tag) | |
getXMLTags(doc, 'applicationVisibilities').forEach(function(el) { | |
if (getPermissionValue(el, 'visible') === 'false' && getPermissionValue(el, 'default') === 'false') { | |
el.parentNode.removeChild(el); | |
} | |
}); | |
// Remove empty <classAccesses> - enabled=false | |
getXMLTags(doc, 'classAccesses').forEach(function(el) { | |
if (getPermissionValue(el, 'enabled') === 'false') { | |
el.parentNode.removeChild(el); | |
} | |
}); | |
// Remove empty <fieldPermissions> - editable=false and readable=false. | |
getXMLTags(doc, 'fieldPermissions').forEach(function(el) { | |
if (getPermissionValue(el, 'editable') === 'false' && getPermissionValue(el, 'readable') === 'false') { | |
el.parentNode.removeChild(el); | |
} | |
}); | |
// Remove empty <objectPermissions> - only if no access at all | |
getXMLTags(doc, 'objectPermissions').forEach(function(el) { | |
if (getPermissionValue(el, 'allowCreate') === 'false' && | |
getPermissionValue(el, 'allowDelete') === 'false' && | |
getPermissionValue(el, 'allowEdit') === 'false' && | |
getPermissionValue(el, 'allowRead') === 'false' && | |
getPermissionValue(el, 'modifyAllRecords') === 'false' && | |
getPermissionValue(el, 'viewAllRecords') === 'false') { | |
el.parentNode.removeChild(el); | |
} | |
}); | |
// Remove empty <pageAccesses> - enabled=false. | |
getXMLTags(doc, 'pageAccesses').forEach(function(el) { | |
if (getPermissionValue(el, 'enabled') === 'false') { | |
el.parentNode.removeChild(el); | |
} | |
}); | |
// Remove empty <recordTypeVisibilities> - visible=false. | |
getXMLTags(doc, 'recordTypeVisibilities').forEach(function(el) { | |
if (getPermissionValue(el, 'visible') === 'false') { | |
el.parentNode.removeChild(el); | |
} | |
}); | |
// Remove empty <tabSettings> - visibility=None. | |
getXMLTags(doc, 'tabSettings').forEach(function(el) { | |
if (getPermissionValue(el, 'visibility') === 'None') { | |
el.parentNode.removeChild(el); | |
} | |
}); | |
// remove blank lines | |
return pd.xml(doc.toString()); | |
/* | |
var stream = through(); | |
stream.write(prefixText); | |
return stream; | |
*/ | |
} | |
// Plugin level function(dealing with files) | |
function profileCleaner() { | |
var filesProcessed = 0; | |
// Creating a stream through which each file will pass | |
var stream = through.obj(function(file, enc, callback) { | |
filesProcessed += 1; | |
if (file.isNull()) { | |
// Do nothing if no contents | |
} | |
if (file.isBuffer()) { | |
file.contents = new Buffer(removeEmptyPermissions(file.contents)); | |
} | |
if (file.isStream()) { | |
console.log('stream'); | |
//file.contents = through().write(removeEmptyPermissions(file.contents)); | |
} | |
this.push(file); | |
return callback(); | |
}, function(callback) { | |
gutil.log(gutil.colors.cyan('cleanProfiles')+':', 'Processed', | |
gutil.colors.magenta(filesProcessed), 'files'); | |
callback(); | |
}); | |
// returning the file stream | |
return stream; | |
}; | |
// Exporting the plugin main function | |
module.exports = profileCleaner; |
Cheers for sharing this.
I haven't worked with gulp much and that was many years ago.
I'd really appreciate if you could also include some information about environmental dependencies (e.g. what version of node and gulp we need) and how to execute this script from a command line, including how to specify where the salesforce source files live.
Also, please include whether your instructions are suitable for both ANT and SFDX users...
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I pulled this out of a larger code base and didn't run to make sure it holds together so could be missing a stray dependency. Comment if you have any problems!