Created
June 19, 2015 11:26
-
-
Save tarot/8c3eabd446b6befca8f3 to your computer and use it in GitHub Desktop.
ProfileのfieldPremissionとobjectPermissionを全部trueにする
This file contains hidden or 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
| { | |
| "dependencies": { | |
| "bluebird": "^2.9.9", | |
| "commander": "^2.7.1", | |
| "dotenv": "^0.5.1", | |
| "glob": "^5.0.3", | |
| "jsforce": "^1.4.0", | |
| "jszip": "^2.5.0", | |
| "lodash": "^3.5.0", | |
| "shelljs": "^0.4.0", | |
| "streamifier": "^0.1.0", | |
| "temp": "^0.8.1", | |
| "unorm": "^1.3.3", | |
| "unzip": "^0.1.11", | |
| "xml2js": "^0.4.6" | |
| } | |
| } |
This file contains hidden or 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
| jsforce = require 'jsforce' | |
| Promise = require 'bluebird' | |
| unzip = require 'unzip' | |
| _ = require 'lodash' | |
| xml2js = require 'xml2js' | |
| glob = require 'glob' | |
| path = require 'path' | |
| fs = require 'fs' | |
| unorm = require 'unorm' | |
| temp = require('temp').track() | |
| jszip = require 'jszip' | |
| streamifier = require 'streamifier' | |
| program = require 'commander' | |
| require 'shelljs/global' | |
| program | |
| .option '-d, --deploy', 'deploy actually (default: dry run)' | |
| .option '--deploy-dir <dir>', 'tmpdir for deploy packages (default: tmpdir)' | |
| .option '--retrieve-dir <dir>', 'retrieve destination (default: tmpdir)' | |
| .option '-u, --username <username>', 'username (default: process.env.SALESFORCE_USERNAME)' | |
| .option '-p, --password <password>', 'password (default: process.env.SALESFORCE_PASSWORD)' | |
| .option '--host <host>', 'host (default: process.env.SALESFORCE_HOST)' | |
| .parse process.argv | |
| require('dotenv').load() | |
| username = program.username || process.env.SALESFORCE_USERNAME | |
| password = program.password || process.env.SALESFORCE_PASSWORD | |
| host = program.host || process.env.SALESFORCE_HOST || 'login.salesforce.com' | |
| host = "https://#{host}" unless host.match /^https:\/\// | |
| api_version = process.env.SALESFORCE_API_VERSION || '33.0' | |
| dry_run = !program.deploy | |
| Promise.promisifyAll xml2js.Parser.prototype | |
| _.mixin | |
| # xml2jsのexplicitArray: false対策。jsforceのlistMetadataもこれを使っている | |
| wrap_array: (x) -> | |
| return [] unless x? | |
| if @isArray x then x else [x] | |
| # 3つずつ取得したlistMetadataを統合する | |
| _.extend require('jsforce/lib/api/metadata').prototype, | |
| list_all: (queries, version) -> | |
| queries = [] unless _.isArray queries | |
| metadata = @ | |
| Promise.reduce _.chunk(queries, 3), (all, queries) -> | |
| metadata.list(queries, version).then (res) -> all.concat _.wrap_array(res) | |
| , [] | |
| class Manifest | |
| parse_list_metadata_result: (list_metadata_result) -> | |
| types = _(list_metadata_result) | |
| .wrap_array() | |
| .groupBy (e) -> e.type | |
| .mapValues (vs) -> vs.map (e) -> e.fullName | |
| .value() | |
| _.extend @, types | |
| return @ | |
| to_unpackaged_request: (version = api_version) -> | |
| unpackaged: | |
| version: version | |
| types: _.map @, (v, k) -> name: k, members: v | |
| to_xml: (version = api_version) -> | |
| pkg = | |
| '$': xmlns: 'http://soap.sforce.com/2006/04/metadata' | |
| types: _.map @, (v, k) -> name: k, members: v | |
| version: version | |
| new xml2js.Builder().buildObject(Package: pkg) | |
| class Profile | |
| constructor: (name, xml) -> | |
| @_profile = xml.Profile | |
| @_profile.fieldPermissions = _.wrap_array @_profile.fieldPermissions | |
| @_profile.objectPermissions = _.wrap_array @_profile.objectPermissions | |
| @name = name | |
| to_meta: -> | |
| profile = _.pick @_profile, ['$', 'custom', 'fieldPermissions', 'userLicense', 'objectPermissions'] | |
| if profile.fieldPermissions? | |
| profile.fieldPermissions = profile.fieldPermissions.map (field_permission) -> | |
| editable: 'true', readable: 'true', field: field_permission.field | |
| if profile.objectPermissions? | |
| profile.objectPermissions = profile.objectPermissions.map (e) -> | |
| allowCreate: 'true' | |
| allowDelete: 'true' | |
| allowEdit: 'true' | |
| allowRead: 'true' | |
| modifyAllRecords: 'true' | |
| viewAllRecords: 'true' | |
| object: e.object | |
| Profile: profile | |
| [retrieve_dir, deploy_dir] = [program.retrieveDir, program.deployDir].map (dir) -> | |
| if dir | |
| rm '-rf', dir | |
| mkdir '-p', dir | |
| return dir | |
| else temp.mkdirSync() | |
| connection = new jsforce.Connection loginUrl: host | |
| connection.login(username, password) | |
| .then -> | |
| connection.version = api_version | |
| connection.metadata.pollInterval = 5000 | |
| connection.metadata.pollTimeout = connection.metadata.pollInterval * 50 | |
| .then -> | |
| console.log 'metadata.describe...' | |
| connection.metadata.describe() | |
| .then (describe) -> | |
| console.log 'list metadata...' | |
| queries = _(describe.metadataObjects) | |
| .filter (e) -> e.xmlName.match /^(CustomObject|Profile)$/ | |
| .map (e) -> | |
| _.toArray(e.childXmlNames).concat [e.xmlName] | |
| .flatten() | |
| .map (e) -> type: e | |
| .value() | |
| connection.metadata.list_all queries | |
| .then (meta) -> | |
| console.log 'retrieve and unzip...' | |
| manifest = new Manifest().parse_list_metadata_result meta | |
| new Promise (resolve, reject) -> | |
| connection.metadata.retrieve manifest.to_unpackaged_request() | |
| .stream() | |
| .pipe unzip.Extract(path: retrieve_dir) | |
| .on 'close', resolve | |
| .on 'error', reject | |
| .then -> | |
| console.log 'create profiles...' | |
| mkdir '-p', path.join(deploy_dir, 'profiles') | |
| Promise.all( | |
| glob.sync(path.join retrieve_dir, 'unpackaged', 'profiles', '*.profile') | |
| .map (file) -> | |
| new xml2js.Parser(explicitArray: false).parseStringAsync(fs.readFileSync file) | |
| .then (xml) -> new Profile(unorm.nfc(path.basename(file, '.profile')), xml) | |
| ) | |
| .each (profile) -> | |
| dest_file = path.join deploy_dir, 'profiles', "#{profile.name}.profile" | |
| fs.writeFileSync dest_file, new xml2js.Builder().buildObject(profile.to_meta()) | |
| .then (profiles) -> | |
| console.log 'create package.xml...' | |
| manifest = new Manifest() | |
| manifest.Profile = profiles.map (e) -> e.name | |
| dest_file = path.join deploy_dir, 'package.xml' | |
| fs.writeFileSync dest_file, manifest.to_xml() | |
| .then -> | |
| console.log 'zip...' | |
| glob.sync(path.join deploy_dir, '**', '*').reduce (zip, e) -> | |
| stat = fs.statSync(e) | |
| if stat.isDirectory() | |
| zip.folder unorm.nfc(path.join('unpackaged', path.relative(deploy_dir, e))) | |
| else if stat.isFile() | |
| zip.file unorm.nfc(path.join('unpackaged', path.relative(deploy_dir, e))), fs.readFileSync(e) | |
| return zip | |
| , new jszip() | |
| .then (zip) -> | |
| console.log 'deploy...' | |
| pkg = streamifier.createReadStream zip.generate(type: 'nodebuffer', platform: process.platform) | |
| connection.metadata.deploy pkg, checkOnly: dry_run, rollbackOnError: true | |
| .complete (error, result) -> | |
| if error? | |
| console.error error | |
| else if !result.success | |
| connection.metadata.checkDeployStatus result.id, true | |
| .then (result) -> | |
| console.error result | |
| result.details.componentFailures.forEach (e) -> console.error e | |
| else console.log result | |
| .fail -> | |
| console.error arguments |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
使い方
クレデンシャルは.env
コマンドラインオプションでもOK
-dオプション付けないとcheckOnly、--deploy-dirオプションや--retrieve-dirオプションを付ると中間ファイルを確認できる(デフォルトはtempDir)