UNPKG

@pnp/cli-microsoft365

Version:

Manage Microsoft 365 and SharePoint Framework projects on any platform

207 lines • 10.1 kB
import { z } from 'zod'; import auth from '../../../../Auth.js'; import { globalOptionsZod } from '../../../../Command.js'; import request from '../../../../request.js'; import { accessToken } from '../../../../utils/accessToken.js'; import { formatting } from '../../../../utils/formatting.js'; import { validation } from '../../../../utils/validation.js'; import GraphCommand from '../../../base/GraphCommand.js'; import commands from '../../commands.js'; export const options = z.looseObject({ ...globalOptionsZod.shape, id: z.uuid().optional().alias('i'), userName: z.string().refine(name => validation.isValidUserPrincipalName(name), { error: e => `'${e.input}' is not a valid userName.` }).optional().alias('n'), accountEnabled: z.boolean().optional(), resetPassword: z.boolean().optional(), forceChangePasswordNextSignIn: z.boolean().optional(), forceChangePasswordNextSignInWithMfa: z.boolean().optional(), currentPassword: z.string().optional(), newPassword: z.string().optional(), displayName: z.string().optional(), firstName: z.string().max(64, { error: `The max length for the firstName option is 64 characters.` }).optional(), lastName: z.string().max(64, { error: `The max length for the lastName option is 64 characters.` }).optional(), usageLocation: z.string().regex(/^[a-zA-Z]{2}$/, { error: e => `'${e.input}' is not a valid usageLocation.` }).optional(), officeLocation: z.string().optional(), jobTitle: z.string().max(128, { error: `The max length for the jobTitle option is 128 characters.` }).optional(), companyName: z.string().max(64, { error: `The max length for the companyName option is 64 characters.` }).optional(), department: z.string().max(64, { error: `The max length for the department option is 64 characters.` }).optional(), preferredLanguage: z.string().min(2, { error: e => `'${e.input}' is not a valid preferredLanguage.` }).optional(), managerUserId: z.uuid().optional(), managerUserName: z.string().refine(name => validation.isValidUserPrincipalName(name), { error: e => `'${e.input}' is not a valid user principal name.` }).optional(), removeManager: z.boolean().optional() }); class EntraUserSetCommand extends GraphCommand { get name() { return commands.USER_SET; } get description() { return 'Updates information about the specified user'; } allowUnknownOptions() { return true; } get schema() { return options; } getRefinedSchema(schema) { return schema .refine(options => [options.id, options.userName].filter(o => o !== undefined).length === 1, { error: `Specify either 'id' or 'userName'.`, params: { customCode: 'optionSet', options: ['id', 'userName'] } }) .refine(options => { if (!options.managerUserId && !options.managerUserName && !options.removeManager) { return true; } return [options.managerUserId, options.managerUserName, options.removeManager].filter(o => o !== undefined).length === 1; }, { error: `Specify either 'managerUserId', 'managerUserName', or 'removeManager'.`, params: { customCode: 'optionSet', options: ['managerUserId', 'managerUserName', 'removeManager'] } }) .refine(options => !(!options.resetPassword && ((options.currentPassword && !options.newPassword) || (options.newPassword && !options.currentPassword))), { error: `Specify both currentPassword and newPassword when you want to change your password.` }) .refine(options => !(options.resetPassword && options.currentPassword), { error: `When resetting a user's password, don't specify the current password.` }) .refine(options => !(options.resetPassword && !options.newPassword), { error: `When resetting a user's password, specify the new password to set for the user, using the newPassword option.` }) .refine(options => !(options.forceChangePasswordNextSignIn && !options.resetPassword), { error: `The option forceChangePasswordNextSignIn can only be used in combination with the resetPassword option.` }) .refine(options => !(options.forceChangePasswordNextSignInWithMfa && !options.resetPassword), { error: `The option forceChangePasswordNextSignInWithMfa can only be used in combination with the resetPassword option.` }); } async commandAction(logger, args) { try { if (args.options.currentPassword) { if (args.options.id && args.options.id !== accessToken.getUserIdFromAccessToken(auth.connection.accessTokens[auth.defaultResource].accessToken)) { throw `You can only change your own password. Please use --id @meId to reference to your own userId`; } else if (args.options.userName && args.options.userName.toLowerCase() !== accessToken.getUserNameFromAccessToken(auth.connection.accessTokens[auth.defaultResource].accessToken).toLowerCase()) { throw 'You can only change your own password. Please use --userName @meUserName to reference to your own user principal name'; } } if (this.verbose) { await logger.logToStderr(`Updating user ${args.options.userName || args.options.id}`); } const requestUrl = `${this.resource}/v1.0/users/${formatting.encodeQueryParameter(args.options.id ? args.options.id : args.options.userName)}`; const manifest = this.mapRequestBody(args.options); if (Object.keys(manifest).some(k => manifest[k] !== undefined)) { if (this.verbose) { await logger.logToStderr(`Setting the updated properties for user ${args.options.userName || args.options.id}`); } const requestOptions = { url: requestUrl, headers: { accept: 'application/json' }, responseType: 'json', data: manifest }; await request.patch(requestOptions); } if (args.options.currentPassword) { await this.changePassword(requestUrl, args.options, logger); } if (args.options.managerUserId || args.options.managerUserName) { if (this.verbose) { await logger.logToStderr(`Updating the manager to ${args.options.managerUserId || args.options.managerUserName}`); } await this.updateManager(args.options); } else if (args.options.removeManager) { if (this.verbose) { await logger.logToStderr('Removing the manager'); } const user = args.options.id || args.options.userName; await this.removeManager(user); } } catch (err) { this.handleRejectedODataJsonPromise(err); } } mapRequestBody(options) { const requestBody = { displayName: options.displayName, givenName: options.firstName, surname: options.lastName, usageLocation: options.usageLocation, officeLocation: options.officeLocation, jobTitle: options.jobTitle, companyName: options.companyName, department: options.department, preferredLanguage: options.preferredLanguage, accountEnabled: options.accountEnabled }; this.addUnknownOptionsToPayloadZod(requestBody, options); if (options.resetPassword) { requestBody.passwordProfile = { forceChangePasswordNextSignIn: options.forceChangePasswordNextSignIn || false, forceChangePasswordNextSignInWithMfa: options.forceChangePasswordNextSignInWithMfa || false, password: options.newPassword }; } // Replace every empty string with null for (const key in requestBody) { if (typeof requestBody[key] === 'string' && requestBody[key].trim() === '') { requestBody[key] = null; } } return requestBody; } async changePassword(requestUrl, options, logger) { if (this.verbose) { await logger.logToStderr(`Changing password for user ${options.userName || options.id}`); } const requestBody = { currentPassword: options.currentPassword, newPassword: options.newPassword }; const requestOptions = { url: `${requestUrl}/changePassword`, headers: { accept: 'application/json;odata.metadata=none' }, responseType: 'json', data: requestBody }; await request.post(requestOptions); } async updateManager(options) { const managerRequestOptions = { url: `${this.resource}/v1.0/users/${options.id || options.userName}/manager/$ref`, headers: { accept: 'application/json;odata.metadata=none' }, data: { '@odata.id': `${this.resource}/v1.0/users/${options.managerUserId || options.managerUserName}` } }; await request.put(managerRequestOptions); } async removeManager(userId) { const managerRequestOptions = { url: `${this.resource}/v1.0/users/${userId}/manager/$ref`, headers: { accept: 'application/json;odata.metadata=none' } }; await request.delete(managerRequestOptions); } } export default new EntraUserSetCommand(); //# sourceMappingURL=user-set.js.map