From 5170280a9fe336d3fc4d90b1e014f3dbb525af70 Mon Sep 17 00:00:00 2001 From: Kyle Thornton Date: Tue, 15 Sep 2020 10:25:28 -0400 Subject: [PATCH 1/3] Adds ability to resume group membership or sharing calculations and recalculate sharing rule calculations --- README.md | 68 ++++++++++- messages/sharingcalc-recalculate.json | 4 + messages/sharingcalc-resume.json | 4 + src/commands/texei/sharingcalc/recalculate.ts | 94 +++++++++++++++ src/commands/texei/sharingcalc/resume.ts | 107 ++++++++++++++++++ src/commands/texei/sharingcalc/suspend.ts | 2 +- 6 files changed, 276 insertions(+), 3 deletions(-) create mode 100644 messages/sharingcalc-recalculate.json create mode 100644 messages/sharingcalc-resume.json create mode 100644 src/commands/texei/sharingcalc/recalculate.ts create mode 100644 src/commands/texei/sharingcalc/resume.ts diff --git a/README.md b/README.md index 395b3c3..a46d664 100644 --- a/README.md +++ b/README.md @@ -28,6 +28,8 @@ Link the plugin: sfdx plugins:link . * [`sfdx texei:package:dependencies:install [-k ] [-b ] [-p ] [-s ] [-n ] [-w ] [-r] [-a ] [-v ] [-u ] [--apiversion ] [--json] [--loglevel trace|debug|info|warn|error|fatal|TRACE|DEBUG|INFO|WARN|ERROR|FATAL]`](#sfdx-texeipackagedependenciesinstall--k-string--b-string--p-string--s-string--n-string--w-number--r--a-string--v-string--u-string---apiversion-string---json---loglevel-tracedebuginfowarnerrorfataltracedebuginfowarnerrorfatal) * [`sfdx texei:profile:clean [-k ] [-p ] [--json] [--loglevel trace|debug|info|warn|error|fatal|TRACE|DEBUG|INFO|WARN|ERROR|FATAL]`](#sfdx-texeiprofileclean--k-string--p-string---json---loglevel-tracedebuginfowarnerrorfataltracedebuginfowarnerrorfatal) * [`sfdx texei:sharedactivities:enable [-u ] [--apiversion ] [--json] [--loglevel trace|debug|info|warn|error|fatal|TRACE|DEBUG|INFO|WARN|ERROR|FATAL]`](#sfdx-texeisharedactivitiesenable--u-string---apiversion-string---json---loglevel-tracedebuginfowarnerrorfataltracedebuginfowarnerrorfatal) +* [`sfdx texei:sharingcalc:recalculate [-s ] [-u ] [--apiversion ] [--json] [--loglevel trace|debug|info|warn|error|fatal|TRACE|DEBUG|INFO|WARN|ERROR|FATAL]`](#sfdx-texeisharingcalcrecalculate--s-string--u-string---apiversion-string---json---loglevel-tracedebuginfowarnerrorfataltracedebuginfowarnerrorfatal) +* [`sfdx texei:sharingcalc:resume [-s ] [-u ] [--apiversion ] [--json] [--loglevel trace|debug|info|warn|error|fatal|TRACE|DEBUG|INFO|WARN|ERROR|FATAL]`](#sfdx-texeisharingcalcresume--s-string--u-string---apiversion-string---json---loglevel-tracedebuginfowarnerrorfataltracedebuginfowarnerrorfatal) * [`sfdx texei:sharingcalc:suspend [-s ] [-u ] [--apiversion ] [--json] [--loglevel trace|debug|info|warn|error|fatal|TRACE|DEBUG|INFO|WARN|ERROR|FATAL]`](#sfdx-texeisharingcalcsuspend--s-string--u-string---apiversion-string---json---loglevel-tracedebuginfowarnerrorfataltracedebuginfowarnerrorfatal) * [`sfdx texei:skinnyprofile:retrieve [-t ] [-v ] [-u ] [--apiversion ] [--json] [--loglevel trace|debug|info|warn|error|fatal|TRACE|DEBUG|INFO|WARN|ERROR|FATAL]`](#sfdx-texeiskinnyprofileretrieve--t-string--v-string--u-string---apiversion-string---json---loglevel-tracedebuginfowarnerrorfataltracedebuginfowarnerrorfatal) * [`sfdx texei:source:customlabel:replace -l -v [-p ] [--json] [--loglevel trace|debug|info|warn|error|fatal|TRACE|DEBUG|INFO|WARN|ERROR|FATAL]`](#sfdx-texeisourcecustomlabelreplace--l-string--v-string--p-string---json---loglevel-tracedebuginfowarnerrorfataltracedebuginfowarnerrorfatal) @@ -315,13 +317,75 @@ EXAMPLE _See code: [src/commands/texei/sharedactivities/enable.ts](https://github.com/texei/texei-sfdx-plugin/blob/v1.6.3/src/commands/texei/sharedactivities/enable.ts)_ +## `sfdx texei:sharingcalc:recalculate [-u ] [--apiversion ] [--json] [--loglevel trace|debug|info|warn|error|fatal|TRACE|DEBUG|INFO|WARN|ERROR|FATAL]` + +suspend sharing calculation + +``` +USAGE + $ sfdx texei:sharingcalc:recalculatte [-s ] [-u ] [--apiversion ] [--json] [--loglevel + trace|debug|info|warn|error|fatal|TRACE|DEBUG|INFO|WARN|ERROR|FATAL] + +OPTIONS + -s, --scope=sharingRule [default: sharingRule] scope of + recalculation + + -u, --targetusername=targetusername username or alias for the target + org; overrides default target org + + --apiversion=apiversion override the api version used for + api requests made by this command + + --json format output as json + + --loglevel=(trace|debug|info|warn|error|fatal|TRACE|DEBUG|INFO|WARN|ERROR|FATAL) [default: warn] logging level for + this command invocation + +EXAMPLE + $ sfdx texei:sharingcalc:recalculate" + Recalculated Sharing Rules +``` + +_See code: [src/commands/texei/sharingcalc/recalculate.ts](https://github.com/texei/texei-sfdx-plugin/blob/v1.6.3/src/commands/texei/sharingcalc/recalculate.ts)_ + +## `sfdx texei:sharingcalc:resume [-s ] [-u ] [--apiversion ] [--json] [--loglevel trace|debug|info|warn|error|fatal|TRACE|DEBUG|INFO|WARN|ERROR|FATAL]` + +resume sharing calculation + +``` +USAGE + $ sfdx texei:sharingcalc:resume [-s ] [-u ] [--apiversion ] [--json] [--loglevel + trace|debug|info|warn|error|fatal|TRACE|DEBUG|INFO|WARN|ERROR|FATAL] + +OPTIONS + -s, --scope=sharingRule|groupMembership [default: sharingRule] scope of + resumed calculations + + -u, --targetusername=targetusername username or alias for the target + org; overrides default target org + + --apiversion=apiversion override the api version used for + api requests made by this command + + --json format output as json + + --loglevel=(trace|debug|info|warn|error|fatal|TRACE|DEBUG|INFO|WARN|ERROR|FATAL) [default: warn] logging level for + this command invocation + +EXAMPLE + $ sfdx texei:sharingcalc:resume" + Sharing calculations resumeed +``` + +_See code: [src/commands/texei/sharingcalc/suspend.ts](https://github.com/texei/texei-sfdx-plugin/blob/v1.6.3/src/commands/texei/sharingcalc/suspend.ts)_ + ## `sfdx texei:sharingcalc:suspend [-s ] [-u ] [--apiversion ] [--json] [--loglevel trace|debug|info|warn|error|fatal|TRACE|DEBUG|INFO|WARN|ERROR|FATAL]` suspend sharing calculation ``` USAGE - $ sfdx texei:sharingcalc:suspend [-s ] [-u ] [--apiversion ] [--json] [--loglevel + $ sfdx texei:sharingcalc:suspend [-s ] [-u ] [--apiversion ] [--json] [--loglevel trace|debug|info|warn|error|fatal|TRACE|DEBUG|INFO|WARN|ERROR|FATAL] OPTIONS @@ -340,7 +404,7 @@ OPTIONS this command invocation EXAMPLE - $ sfdx texei:sharingcalc:suspend" + $ sfdx texei:sharingcalc:suspend" Sharing calculations suspended ``` diff --git a/messages/sharingcalc-recalculate.json b/messages/sharingcalc-recalculate.json new file mode 100644 index 0000000..6f4a953 --- /dev/null +++ b/messages/sharingcalc-recalculate.json @@ -0,0 +1,4 @@ +{ + "commandDescription": "recalculate sharing rules", + "scopeFlagDescription": "scope of recalculations" +} diff --git a/messages/sharingcalc-resume.json b/messages/sharingcalc-resume.json new file mode 100644 index 0000000..382e2c3 --- /dev/null +++ b/messages/sharingcalc-resume.json @@ -0,0 +1,4 @@ +{ + "commandDescription": "resumed sharing calculation", + "scopeFlagDescription": "scope of resumed calculations" +} diff --git a/src/commands/texei/sharingcalc/recalculate.ts b/src/commands/texei/sharingcalc/recalculate.ts new file mode 100644 index 0000000..f168881 --- /dev/null +++ b/src/commands/texei/sharingcalc/recalculate.ts @@ -0,0 +1,94 @@ +import { flags, core, SfdxCommand } from "@salesforce/command"; +import * as puppeteer from "puppeteer"; + +// Initialize Messages with the current plugin directory +core.Messages.importMessagesDirectory(__dirname); + +// Load the specific messages for this file. Messages from @salesforce/command, @salesforce/core, +// or any library that is using the messages framework can also be loaded this way. +const messages = core.Messages.loadMessages( + "texei-sfdx-plugin", + "sharingcalc-recalculate" +); + +const mapSharingLabel = new Map([ + ['sharingRule', 'Sharing Rule'] + ]); + +export default class Recalculate extends SfdxCommand { + public static description = messages.getMessage("commandDescription"); + + public static examples = [ + `$ sfdx texei:sharingcalc:recalculate" \nRecalculated Sharing Rules\n` + ]; + + protected static flagsConfig = { + scope: flags.string({ + char: "s", + description: messages.getMessage("scopeFlagDescription"), + required: false, + options: ["sharingRule"], + default: "sharingRule" + }) + }; + + // Comment this out if your command does not require an org username + protected static requiresUsername = true; + + // Comment this out if your command does not support a hub org username + protected static requiresDevhubUsername = false; + + // Set this to true if your command requires a project workspace; 'requiresProject' is false by default + protected static requiresProject = false; + + public async run(): Promise { + let result = {}; + + await this.reclaculateSharing(); + + return result; + } + + private async reclaculateSharing() { + const instanceUrl = this.org.getConnection().instanceUrl; + + const SHARING_CALC_PATH = "/p/own/DeferSharingSetupPage"; + + this.ux.startSpinner(`Resuming ${mapSharingLabel.get(this.flags.scope)} Calculations`, null, { stdout: true }); + this.debug(`DEBUG Login to Org`); + + const browser = await puppeteer.launch({ + args: ["--no-sandbox", "--disable-setuid-sandbox"], + headless: !(process.env.BROWSER_DEBUG === "true") + }); + const page = await browser.newPage(); + await page.goto( + `${instanceUrl}/secur/frontdoor.jsp?sid=${ + this.org.getConnection().accessToken + }`, + { waitUntil: ["domcontentloaded", "networkidle0"] } + ); + const navigationPromise = page.waitForNavigation(); + + this.debug(`DEBUG Opening Defer Sharing Calculations page`); + + await page.goto(`${instanceUrl + SHARING_CALC_PATH}`); + await navigationPromise; + + this.debug(`DEBUG Clicking 'Recalculate' button`); + + await page.click( + `#ep > .pbBody > .pbSubsection > .detailList > tbody > .detailRow > td > input[name="rule_recalc"].btn` + ); + + await navigationPromise; + + this.debug(`DEBUG Closing browser`); + + await browser.close(); + + this.ux.stopSpinner("Done."); + + return { message: `Recalculated ${mapSharingLabel.get(this.flags.scope)}s` }; + } +} diff --git a/src/commands/texei/sharingcalc/resume.ts b/src/commands/texei/sharingcalc/resume.ts new file mode 100644 index 0000000..33ed39e --- /dev/null +++ b/src/commands/texei/sharingcalc/resume.ts @@ -0,0 +1,107 @@ +import { flags, core, SfdxCommand } from "@salesforce/command"; +import * as puppeteer from "puppeteer"; + +// Initialize Messages with the current plugin directory +core.Messages.importMessagesDirectory(__dirname); + +// Load the specific messages for this file. Messages from @salesforce/command, @salesforce/core, +// or any library that is using the messages framework can also be loaded this way. +const messages = core.Messages.loadMessages( + "texei-sfdx-plugin", + "sharingcalc-resume" +); + +const mapSharingLabel = new Map([ + ['sharingRule', 'Sharing Rule'], + ['groupMembership', 'Group Membership'] + ]); + +export default class Resume extends SfdxCommand { + public static description = messages.getMessage("commandDescription"); + + public static examples = [ + `$ sfdx texei:sharingcalc:resume" \nSharing calculations resumed\n` + ]; + + protected static flagsConfig = { + scope: flags.string({ + char: "s", + description: messages.getMessage("scopeFlagDescription"), + required: false, + options: ["sharingRule", "groupMembership"], + default: "sharingRule" + }) + }; + + // Comment this out if your command does not require an org username + protected static requiresUsername = true; + + // Comment this out if your command does not support a hub org username + protected static requiresDevhubUsername = false; + + // Set this to true if your command requires a project workspace; 'requiresProject' is false by default + protected static requiresProject = false; + + public async run(): Promise { + let result = {}; + + await this.resumeSharingCalc(); + + return result; + } + + private async resumeSharingCalc() { + const instanceUrl = this.org.getConnection().instanceUrl; + + const SHARING_CALC_PATH = "/p/own/DeferSharingSetupPage"; + + this.ux.startSpinner(`Resuming ${mapSharingLabel.get(this.flags.scope)} Calculations`, null, { stdout: true }); + this.debug(`DEBUG Login to Org`); + + const browser = await puppeteer.launch({ + args: ["--no-sandbox", "--disable-setuid-sandbox"], + headless: !(process.env.BROWSER_DEBUG === "true") + }); + const page = await browser.newPage(); + await page.goto( + `${instanceUrl}/secur/frontdoor.jsp?sid=${ + this.org.getConnection().accessToken + }`, + { waitUntil: ["domcontentloaded", "networkidle0"] } + ); + const navigationPromise = page.waitForNavigation(); + + this.debug(`DEBUG Opening Defer Sharing Calculations page`); + + await page.goto(`${instanceUrl + SHARING_CALC_PATH}`); + await navigationPromise; + + this.debug(`DEBUG Clicking 'Resume' button`); + + // Resume either Group Membership or Sharing Rules + if (this.flags.scope === "groupMembership") { + await page.click( + `#gmSect > .pbBody > .pbSubsection > .detailList > tbody > .detailRow > td > input[name="group_resume"].btn` + ); + + // click the yes button to recaulcate group memberships immediately + await page.click( + `div#group_resume_dialog_buttons > input[value=" Yes "]` + ); + } else { + await page.click( + `#ep > .pbBody > .pbSubsection > .detailList > tbody > .detailRow > td > input[name="rule_resume"].btn` + ); + } + + await navigationPromise; + + this.debug(`DEBUG Closing browser`); + + await browser.close(); + + this.ux.stopSpinner("Done."); + + return { message: `Resumed ${mapSharingLabel.get(this.flags.scope)} Calculations` }; + } +} diff --git a/src/commands/texei/sharingcalc/suspend.ts b/src/commands/texei/sharingcalc/suspend.ts index c938f1d..d0ca9c4 100644 --- a/src/commands/texei/sharingcalc/suspend.ts +++ b/src/commands/texei/sharingcalc/suspend.ts @@ -103,4 +103,4 @@ export default class Suspend extends SfdxCommand { return { message: `Suspended ${mapSharingLabel.get(this.flags.scope)} Calculations` }; } -} \ No newline at end of file +} From 5368d33338253c7457a3321e7eeb2632957d953c Mon Sep 17 00:00:00 2001 From: Kyle Thornton Date: Tue, 15 Sep 2020 10:26:39 -0400 Subject: [PATCH 2/3] focus on correct button --- src/commands/texei/sharingcalc/suspend.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/commands/texei/sharingcalc/suspend.ts b/src/commands/texei/sharingcalc/suspend.ts index d0ca9c4..00d8f17 100644 --- a/src/commands/texei/sharingcalc/suspend.ts +++ b/src/commands/texei/sharingcalc/suspend.ts @@ -85,11 +85,11 @@ export default class Suspend extends SfdxCommand { }); await page.click( - "#gmSect > .pbBody > .pbSubsection > .detailList > tbody > .detailRow > td > .btn" + `#gmSect > .pbBody > .pbSubsection > .detailList > tbody > .detailRow > td > input[name="group_suspend"].btn` ); } else { await page.click( - "#ep > .pbBody > .pbSubsection > .detailList > tbody > .detailRow > td > .btn" + '#ep > .pbBody > .pbSubsection > .detailList > tbody > .detailRow > td > input[name="rule_suspend"].btn' ); } From 27616a0061beeb203d426294b457e33ae99c0229 Mon Sep 17 00:00:00 2001 From: Kyle Thornton Date: Wed, 16 Sep 2020 08:16:36 -0400 Subject: [PATCH 3/3] wrap button clicks in try catch to prevent script from hanging --- src/commands/texei/sharingcalc/recalculate.ts | 10 ++++-- src/commands/texei/sharingcalc/resume.ts | 32 +++++++++++-------- src/commands/texei/sharingcalc/suspend.ts | 30 +++++++++-------- 3 files changed, 42 insertions(+), 30 deletions(-) diff --git a/src/commands/texei/sharingcalc/recalculate.ts b/src/commands/texei/sharingcalc/recalculate.ts index f168881..b0fb3ad 100644 --- a/src/commands/texei/sharingcalc/recalculate.ts +++ b/src/commands/texei/sharingcalc/recalculate.ts @@ -77,9 +77,13 @@ export default class Recalculate extends SfdxCommand { this.debug(`DEBUG Clicking 'Recalculate' button`); - await page.click( - `#ep > .pbBody > .pbSubsection > .detailList > tbody > .detailRow > td > input[name="rule_recalc"].btn` - ); + try { + await page.click( + `#ep > .pbBody > .pbSubsection > .detailList > tbody > .detailRow > td > input[name="rule_recalc"].btn` + ); + } catch (ex) { + console.log('Unable to recalculate sharing.', ex.message); + } await navigationPromise; diff --git a/src/commands/texei/sharingcalc/resume.ts b/src/commands/texei/sharingcalc/resume.ts index 33ed39e..1070037 100644 --- a/src/commands/texei/sharingcalc/resume.ts +++ b/src/commands/texei/sharingcalc/resume.ts @@ -78,20 +78,24 @@ export default class Resume extends SfdxCommand { this.debug(`DEBUG Clicking 'Resume' button`); - // Resume either Group Membership or Sharing Rules - if (this.flags.scope === "groupMembership") { - await page.click( - `#gmSect > .pbBody > .pbSubsection > .detailList > tbody > .detailRow > td > input[name="group_resume"].btn` - ); - - // click the yes button to recaulcate group memberships immediately - await page.click( - `div#group_resume_dialog_buttons > input[value=" Yes "]` - ); - } else { - await page.click( - `#ep > .pbBody > .pbSubsection > .detailList > tbody > .detailRow > td > input[name="rule_resume"].btn` - ); + try { + // Resume either Group Membership or Sharing Rules + if (this.flags.scope === "groupMembership") { + await page.click( + `#gmSect > .pbBody > .pbSubsection > .detailList > tbody > .detailRow > td > input[name="group_resume"].btn` + ); + + // click the yes button to recaulcate group memberships immediately + await page.click( + `div#group_resume_dialog_buttons > input[value=" Yes "]` + ); + } else { + await page.click( + `#ep > .pbBody > .pbSubsection > .detailList > tbody > .detailRow > td > input[name="rule_resume"].btn` + ); + } + } catch (ex) { + console.log('Unable to resume sharing.', ex.message); } await navigationPromise; diff --git a/src/commands/texei/sharingcalc/suspend.ts b/src/commands/texei/sharingcalc/suspend.ts index 00d8f17..e58b0cc 100644 --- a/src/commands/texei/sharingcalc/suspend.ts +++ b/src/commands/texei/sharingcalc/suspend.ts @@ -78,19 +78,23 @@ export default class Suspend extends SfdxCommand { this.debug(`DEBUG Clicking 'Suspend' button`); - // Suspend either Group Membership or Sharing Rules - if (this.flags.scope === "groupMembership") { - page.on("dialog", dialog => { - dialog.accept(); - }); - - await page.click( - `#gmSect > .pbBody > .pbSubsection > .detailList > tbody > .detailRow > td > input[name="group_suspend"].btn` - ); - } else { - await page.click( - '#ep > .pbBody > .pbSubsection > .detailList > tbody > .detailRow > td > input[name="rule_suspend"].btn' - ); + try { + // Suspend either Group Membership or Sharing Rules + if (this.flags.scope === "groupMembership") { + page.on("dialog", dialog => { + dialog.accept(); + }); + + await page.click( + `#gmSect > .pbBody > .pbSubsection > .detailList > tbody > .detailRow > td > input[name="group_suspend"].btn` + ); + } else { + await page.click( + '#ep > .pbBody > .pbSubsection > .detailList > tbody > .detailRow > td > input[name="rule_suspend"].btn' + ); + } + } catch (ex) { + console.log('Unable to suspend sharing.', ex.message); } await navigationPromise;