@salesforce/plugin-user
Version:
Commands to interact with Users and Permission Sets
122 lines • 4.96 kB
JavaScript
/*
* Copyright 2026, Salesforce, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { Lifecycle, Logger, Messages, SfError, StateAggregator } from '@salesforce/core';
import { Ux } from '@salesforce/sf-plugins-core';
Messages.importMessagesDirectoryFromMetaUrl(import.meta.url);
const messages = Messages.loadMessages('@salesforce/plugin-user', 'permsetlicense.assign');
export const assignPSL = async ({ conn, pslName, usernamesOrAliases, }) => {
const logger = await Logger.child('assignPSL');
logger.debug(`will assign perm set license "${pslName}" to users: ${usernamesOrAliases.join(', ')}`);
const queryResult = await queryPsl({ conn, pslName, usernamesOrAliases });
return typeof queryResult === 'string'
? aggregate(await Promise.all(usernamesOrAliases.map((usernameOrAlias) => usernameToPSLAssignment({
pslName,
usernameOrAlias,
pslId: queryResult,
conn,
}))))
: queryResult;
};
/** reduce an array of PSLResult to a single one */
export const aggregate = (results) => ({
successes: results.flatMap((r) => r.successes),
failures: results.flatMap((r) => r.failures),
});
export const resultsToExitCode = (results) => {
if (results.failures.length && results.successes.length) {
return 68;
}
else if (results.failures.length) {
return 1;
}
else if (results.successes.length) {
return 0;
}
throw new SfError('Unexpected state: no successes and no failures. This should not happen.');
};
export const print = (results) => {
const ux = new Ux();
if (results.failures.length > 0 && results.successes.length > 0) {
ux.styledHeader('Partial Success');
}
if (results.successes.length > 0) {
ux.table({
data: results.successes,
columns: [
{ key: 'name', name: 'Username' },
{ key: 'value', name: 'Permission Set License Assignment' },
],
title: 'Permset Licenses Assigned',
});
}
if (results.failures.length > 0) {
if (results.successes.length > 0) {
ux.log('');
}
ux.table({
data: results.failures,
columns: [
{ key: 'name', name: 'Username' },
{ key: 'message', name: 'Error Message' },
],
title: 'Failures',
});
}
};
// handles one username/psl combo so these can run in parallel
const usernameToPSLAssignment = async ({ pslName, usernameOrAlias, pslId, conn, }) => {
// Convert any aliases to usernames
const resolvedUsername = (await StateAggregator.getInstance()).aliases.resolveUsername(usernameOrAlias);
try {
const AssigneeId = (await conn.singleRecordQuery(`select Id from User where Username = '${resolvedUsername}'`)).Id;
await conn.sobject('PermissionSetLicenseAssign').create({
AssigneeId,
PermissionSetLicenseId: pslId,
});
return toResult({
name: resolvedUsername,
value: pslName,
});
}
catch (e) {
// idempotency. If user(s) already have PSL, the API will throw an error about duplicate value.
// but we're going to call that a success
if (e instanceof Error && e.message.startsWith('duplicate value found')) {
await Lifecycle.getInstance().emitWarning(messages.getMessage('duplicateValue', [resolvedUsername, pslName]));
return toResult({
name: resolvedUsername,
value: pslName,
});
}
else {
return toResult({
name: resolvedUsername,
message: e instanceof Error ? e.message : 'error contained no message',
});
}
}
};
const toResult = (input) => isSuccess(input) ? { successes: [input], failures: [] } : { successes: [], failures: [input] };
const isSuccess = (input) => input.value !== undefined;
const queryPsl = async ({ conn, pslName, usernamesOrAliases, }) => {
try {
return (await conn.singleRecordQuery(`select Id from PermissionSetLicense where DeveloperName = '${pslName}' or MasterLabel = '${pslName}'`)).Id;
}
catch (e) {
return aggregate(usernamesOrAliases.map((name) => toResult({ name, message: `PermissionSetLicense not found: ${pslName}` })));
}
};
//# sourceMappingURL=assign.js.map