@salesforce/core
Version:
Core libraries to interact with SFDX projects, orgs, and APIs.
191 lines • 8.43 kB
JavaScript
"use strict";
/*
* Copyright (c) 2021, salesforce.com, inc.
* All rights reserved.
* Licensed under the BSD 3-Clause license.
* For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.SfdcUrl = void 0;
const url_1 = require("url");
const kit_1 = require("@salesforce/kit");
const ts_types_1 = require("@salesforce/ts-types");
const myDomainResolver_1 = require("../status/myDomainResolver");
const logger_1 = require("../logger");
const lifecycleEvents_1 = require("../lifecycleEvents");
class SfdcUrl extends url_1.URL {
constructor(input, base) {
super(input.toString(), base);
if (this.protocol !== 'https:' && !SfdcUrl.cache.has(this.origin)) {
SfdcUrl.cache.add(this.origin);
void lifecycleEvents_1.Lifecycle.getInstance().emitWarning(`Using insecure protocol: ${this.protocol} on url: ${this.origin}`);
}
}
/**
* Returns the appropiate jwt audience url for this url
* Use SFDX_AUDIENCE_URL env var to override the audience url
*
* @param createdOrgInstance The Salesforce instance the org was created on. e.g. `cs42`
* @return {Promise<string>} The audience url
*/
async getJwtAudienceUrl(createdOrgInstance) {
this.logger = await logger_1.Logger.child('SfdcUrl');
// environment variable is used as an override
const envVarVal = new kit_1.Env().getString('SFDX_AUDIENCE_URL', '');
if (envVarVal) {
this.logger.debug(`Audience URL overriden by env var SFDX_AUDIENCE_URL=${envVarVal}`);
return envVarVal;
}
if (this.isInternalUrl()) {
// This is for internal developers when just doing authorize
return this.origin;
}
if (await this.resolvesToSandbox(createdOrgInstance)) {
return SfdcUrl.SANDBOX;
}
if ((createdOrgInstance && /^gs1/gi.test(createdOrgInstance)) || /(gs1.my.salesforce.com)/gi.test(this.origin)) {
return 'https://gs1.salesforce.com';
}
return SfdcUrl.PRODUCTION;
}
/**
* Tests whether this url contains a Salesforce owned domain
*
* @return {boolean} true if this is a salesforce domain
*/
isSalesforceDomain() {
// Source https://help.salesforce.com/articleView?id=000003652&type=1
const allowlistOfSalesforceDomainPatterns = [
'.cloudforce.com',
'.content.force.com',
'.force.com',
'.salesforce.com',
'.salesforceliveagent.com',
'.secure.force.com',
'crmforce.mil',
];
const allowlistOfSalesforceHosts = ['developer.salesforce.com', 'trailhead.salesforce.com'];
return allowlistOfSalesforceDomainPatterns.some((pattern) => {
return this.hostname.endsWith(pattern) || allowlistOfSalesforceHosts.includes(this.hostname);
});
}
/**
* Tests whether this url is an internal Salesforce domain
*
* @returns {boolean} true if this is a internal domain
*/
isInternalUrl() {
const INTERNAL_URL_PARTS = [
'.vpod.',
'stm.salesforce.com',
'stm.force.com',
'.blitz.salesforce.com',
'.stm.salesforce.ms',
'.pc-rnd.force.com',
'.pc-rnd.salesforce.com',
];
return (this.origin.startsWith('https://gs1.') ||
this.isLocalUrl() ||
INTERNAL_URL_PARTS.some((part) => this.origin.includes(part)));
}
/**
* Tests whether this url runs on a local machine
*
* @returns {boolean} true if this is a local machine
*/
isLocalUrl() {
const LOCAL_PARTS = ['localhost.sfdcdev.', '.internal.'];
return LOCAL_PARTS.some((part) => this.origin.includes(part));
}
toLightningDomain() {
if (this.origin.endsWith('.my.salesforce.mil')) {
return this.origin.replace('.my.salesforce.mil', '.lightning.crmforce.mil');
}
// all non-mil domains
return `https://${ts_types_1.ensureArray(/https?:\/\/([^.]*)/.exec(this.origin))
.slice(1, 2)
.pop()}.lightning.force.com`;
}
/**
* Tests whether this url has the lightning domain extension
* This method that performs the dns lookup of the host. If the lookup fails the internal polling (1 second), client will try again until timeout
* If SFDX_DOMAIN_RETRY environment variable is set (number) it overrides the default timeout duration (240 seconds)
*
* @returns {Promise<true | never>} The resolved ip address or never
* @throws {@link SfdxError} If can't resolve DNS.
*/
async checkLightningDomain() {
const quantity = ts_types_1.ensureNumber(new kit_1.Env().getNumber('SFDX_DOMAIN_RETRY', 240));
const timeout = new kit_1.Duration(quantity, kit_1.Duration.Unit.SECONDS);
if (this.isInternalUrl() || timeout.seconds === 0) {
return true;
}
const resolver = await myDomainResolver_1.MyDomainResolver.create({
url: new url_1.URL(this.toLightningDomain()),
timeout,
frequency: new kit_1.Duration(1, kit_1.Duration.Unit.SECONDS),
});
await resolver.resolve();
return true;
}
/**
* Method that performs the dns lookup of the host. If the lookup fails the internal polling (1 second), client will try again untill timeout
* If SFDX_DOMAIN_RETRY environment variable is set (number) it overrides the default timeout duration (240 seconds)
*
* @returns the resolved ip address.
* @throws {@link SfdxError} If can't resolve DNS.
*/
async lookup() {
const quantity = ts_types_1.ensureNumber(new kit_1.Env().getNumber('SFDX_DOMAIN_RETRY', 240));
const timeout = new kit_1.Duration(quantity, kit_1.Duration.Unit.SECONDS);
const resolver = await myDomainResolver_1.MyDomainResolver.create({
url: new url_1.URL(this.origin),
timeout,
frequency: new kit_1.Duration(1, kit_1.Duration.Unit.SECONDS),
});
return resolver.resolve();
}
/**
* Tests whether this url is a sandbox url
*
* @param createdOrgInstance The Salesforce instance the org was created on. e.g. `cs42`
* @returns {boolean}
*/
isSandboxUrl(createdOrgInstance) {
return ((createdOrgInstance && /^cs|s$/gi.test(createdOrgInstance)) ||
this.origin.endsWith('sandbox.my.salesforce.mil') ||
/sandbox\.my\.salesforce\.com/gi.test(this.origin) || // enhanced domains >= 230
/(cs[0-9]+(\.my|)\.salesforce\.com)/gi.test(this.origin) || // my domains on CS instance OR CS instance without my domain
/(cs[0-9]+\.force\.com)/gi.test(this.origin) || // sandboxes have cnames like cs123.force.com
/(\w+--\w+\.my\.salesforce\.com)/gi.test(this.origin) || // sandboxes myDomain like foo--bar.my.salesforce.com
/([a-z]{3}[0-9]+s\.sfdc-.+\.salesforce\.com)/gi.test(this.origin) || // falcon sandbox ex: usa2s.sfdc-whatever.salesforce.com
/([a-z]{3}[0-9]+s\.sfdc-.+\.force\.com)/gi.test(this.origin) || // falcon sandbox ex: usa2s.sfdc-whatever.force.com
this.hostname === 'test.salesforce.com');
}
/**
* Tests whether this url is a sandbox url
* otherwise tries to resolve dns cnames and then look if any is sandbox url
*
* @param createdOrgInstance The Salesforce instance the org was created on. e.g. `cs42`
* @returns {Promise<boolean>} true if this domain resolves to sanbox url
*/
async resolvesToSandbox(createdOrgInstance) {
if (this.isSandboxUrl(createdOrgInstance)) {
return true;
}
const myDomainResolver = await myDomainResolver_1.MyDomainResolver.create({ url: this });
const cnames = await myDomainResolver.getCnames();
return cnames.some((cname) => {
const url = new SfdcUrl(`https://${cname}`);
return url.isSandboxUrl();
});
}
}
exports.SfdcUrl = SfdcUrl;
/**
* Salesforce URLs
*/
SfdcUrl.SANDBOX = 'https://test.salesforce.com';
SfdcUrl.PRODUCTION = 'https://login.salesforce.com';
SfdcUrl.cache = new Set();
//# sourceMappingURL=sfdcUrl.js.map