@pnp/cli-microsoft365 5.2.0-beta.0f1c454 → 5.2.0-beta.a4da212
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.js +1 -0
- package/.mocharc.json +1 -0
- package/dist/Auth.js +2 -1
- package/dist/Command.js +10 -1
- package/dist/cli/Cli.js +2 -18
- package/dist/m365/app/commands/app-get.js +3 -0
- package/dist/m365/cli/commands/cli-reconsent.js +20 -2
- package/dist/m365/cli/commands/config/config-set.js +1 -0
- package/dist/m365/spfx/commands/project/project-upgrade.js +4 -1
- package/dist/m365/spo/commands/file/file-checkout.js +2 -2
- package/dist/m365/spo/commands/site/site-remove.js +4 -3
- package/dist/m365/spo/commands/tenant/tenant-recyclebinitem-restore.js +10 -44
- package/dist/m365/spo/commands/tenant/tenant-settings-set.js +21 -0
- package/dist/m365/teams/commands/channel/channel-membership-list.js +150 -0
- package/dist/m365/teams/commands/chat/chat-get.js +143 -0
- package/dist/m365/teams/commands/chat/chat-message-send.js +5 -30
- package/dist/m365/teams/commands/chat/chatUtil.js +62 -0
- package/dist/m365/teams/commands.js +2 -0
- package/dist/settingsNames.js +1 -0
- package/dist/utils/index.js +1 -0
- package/dist/utils/md.js +81 -0
- package/docs/docs/cmd/spo/tenant/tenant-settings-set.md +52 -33
- package/docs/docs/cmd/teams/channel/channel-membership-list.md +48 -0
- package/docs/docs/cmd/teams/chat/chat-get.md +53 -0
- package/npm-shrinkwrap.json +22 -736
- package/package.json +2 -3
package/.eslintrc.js
CHANGED
package/.mocharc.json
CHANGED
package/dist/Auth.js
CHANGED
|
@@ -301,7 +301,8 @@ class Auth {
|
|
|
301
301
|
logger.logToStderr('');
|
|
302
302
|
}
|
|
303
303
|
logger.log(response.message);
|
|
304
|
-
if (cli_1.Cli.getInstance().getSettingWithDefaultValue(settingsNames_1.settingsNames.autoOpenBrowserOnLogin, false)
|
|
304
|
+
if (cli_1.Cli.getInstance().getSettingWithDefaultValue(settingsNames_1.settingsNames.autoOpenBrowserOnLogin, false)
|
|
305
|
+
|| cli_1.Cli.getInstance().getSettingWithDefaultValue(settingsNames_1.settingsNames.autoOpenLinksInBrowser, false)) {
|
|
305
306
|
// _open is never set before hitting this line, but this check
|
|
306
307
|
// is implemented so that we can support lazy loading
|
|
307
308
|
// but also stub it for testing
|
package/dist/Command.js
CHANGED
|
@@ -47,6 +47,10 @@ class Command {
|
|
|
47
47
|
logger.logToStderr(chalk.yellow(`Command '${deprecated}' is deprecated. Please use '${recommended}' instead`));
|
|
48
48
|
}
|
|
49
49
|
}
|
|
50
|
+
warn(logger, warning) {
|
|
51
|
+
const chalk = require('chalk');
|
|
52
|
+
logger.logToStderr(chalk.yellow(warning));
|
|
53
|
+
}
|
|
50
54
|
getUsedCommandName() {
|
|
51
55
|
const cli = cli_1.Cli.getInstance();
|
|
52
56
|
const commandName = this.getCommandName();
|
|
@@ -144,7 +148,12 @@ class Command {
|
|
|
144
148
|
return __awaiter(this, void 0, void 0, function* () {
|
|
145
149
|
});
|
|
146
150
|
}
|
|
147
|
-
getCommandName() {
|
|
151
|
+
getCommandName(alias) {
|
|
152
|
+
var _a;
|
|
153
|
+
if (alias &&
|
|
154
|
+
((_a = this.alias()) === null || _a === void 0 ? void 0 : _a.includes(alias))) {
|
|
155
|
+
return alias;
|
|
156
|
+
}
|
|
148
157
|
let commandName = this.name;
|
|
149
158
|
let pos = commandName.indexOf('<');
|
|
150
159
|
const pos1 = commandName.indexOf('[');
|
package/dist/cli/Cli.js
CHANGED
|
@@ -202,7 +202,7 @@ class Cli {
|
|
|
202
202
|
// the command to execute
|
|
203
203
|
const cli = Cli.getInstance();
|
|
204
204
|
const parentCommandName = cli.currentCommandName;
|
|
205
|
-
cli.currentCommandName = command.getCommandName();
|
|
205
|
+
cli.currentCommandName = command.getCommandName(cli.currentCommandName);
|
|
206
206
|
command.action(logger, args, (err) => {
|
|
207
207
|
// restore the original command name
|
|
208
208
|
cli.currentCommandName = parentCommandName;
|
|
@@ -586,23 +586,7 @@ class Cli {
|
|
|
586
586
|
helpFilePath = path.join(...pathChunks);
|
|
587
587
|
if (fs.existsSync(helpFilePath)) {
|
|
588
588
|
Cli.log();
|
|
589
|
-
|
|
590
|
-
// let's lazy-load it only when it's needed (help was requested)
|
|
591
|
-
const markshell = require('markshell');
|
|
592
|
-
const chalk = require('chalk');
|
|
593
|
-
const theme = markshell.getTheme();
|
|
594
|
-
const admonitionStyles = theme.admonitions.getStyles();
|
|
595
|
-
admonitionStyles.indent.beforeIndent = 0;
|
|
596
|
-
admonitionStyles.indent.titleIndent = 3;
|
|
597
|
-
admonitionStyles.indent.afterIndent = 0;
|
|
598
|
-
theme.admonitions.setStyles(admonitionStyles);
|
|
599
|
-
theme.indents.definitionList = 2;
|
|
600
|
-
theme.headline = chalk.white;
|
|
601
|
-
theme.inlineCode = chalk.cyan;
|
|
602
|
-
theme.sourceCodeTheme = 'solarizelight';
|
|
603
|
-
theme.includePath = path.join(this.commandsFolder, '..', '..', 'docs');
|
|
604
|
-
markshell.setTheme(theme);
|
|
605
|
-
Cli.log(markshell.toRawContent(helpFilePath));
|
|
589
|
+
Cli.log(utils_1.md.md2plain(fs.readFileSync(helpFilePath, 'utf8'), path.join(this.commandsFolder, '..', '..', 'docs')));
|
|
606
590
|
}
|
|
607
591
|
}
|
|
608
592
|
printAvailableCommands() {
|
|
@@ -21,6 +21,9 @@ class AppGetCommand extends AppCommand_1.default {
|
|
|
21
21
|
cli_1.Cli
|
|
22
22
|
.executeCommandWithOutput(AadAppGetCommand, { options: Object.assign(Object.assign({}, options), { _: [] }) })
|
|
23
23
|
.then((appGetOutput) => {
|
|
24
|
+
if (this.verbose) {
|
|
25
|
+
logger.logToStderr(appGetOutput.stderr);
|
|
26
|
+
}
|
|
24
27
|
logger.log(JSON.parse(appGetOutput.stdout));
|
|
25
28
|
cb();
|
|
26
29
|
}, (err) => this.handleRejectedODataJsonPromise(err, logger, cb));
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const cli_1 = require("../../../cli");
|
|
3
4
|
const config_1 = require("../../../config");
|
|
5
|
+
const settingsNames_1 = require("../../../settingsNames");
|
|
4
6
|
const AnonymousCommand_1 = require("../../base/AnonymousCommand");
|
|
5
7
|
const commands_1 = require("../commands");
|
|
6
8
|
class CliReconsentCommand extends AnonymousCommand_1.default {
|
|
@@ -11,8 +13,24 @@ class CliReconsentCommand extends AnonymousCommand_1.default {
|
|
|
11
13
|
return 'Returns Azure AD URL to open in the browser to re-consent CLI for Microsoft 365 permissions';
|
|
12
14
|
}
|
|
13
15
|
commandAction(logger, args, cb) {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
+
const url = `https://login.microsoftonline.com/${config_1.default.tenant}/oauth2/authorize?client_id=${config_1.default.cliAadAppId}&response_type=code&prompt=admin_consent`;
|
|
17
|
+
if (cli_1.Cli.getInstance().getSettingWithDefaultValue(settingsNames_1.settingsNames.autoOpenLinksInBrowser, false) === false) {
|
|
18
|
+
logger.log(`To re-consent the PnP Microsoft 365 Management Shell Azure AD application navigate in your web browser to ${url}`);
|
|
19
|
+
return cb();
|
|
20
|
+
}
|
|
21
|
+
logger.log(`Opening the following page in your browser: ${url}`);
|
|
22
|
+
// _open is never set before hitting this line, but this check
|
|
23
|
+
// is implemented so that we can support lazy loading
|
|
24
|
+
// but also stub it for testing
|
|
25
|
+
/* c8 ignore next 3 */
|
|
26
|
+
if (!this._open) {
|
|
27
|
+
this._open = require('open');
|
|
28
|
+
}
|
|
29
|
+
this._open(url).then(() => {
|
|
30
|
+
cb();
|
|
31
|
+
}, (error) => {
|
|
32
|
+
this.handleRejectedODataJsonPromise(error, logger, cb);
|
|
33
|
+
});
|
|
16
34
|
}
|
|
17
35
|
}
|
|
18
36
|
module.exports = new CliReconsentCommand();
|
|
@@ -20,6 +20,7 @@ class CliConfigSetCommand extends AnonymousCommand_1.default {
|
|
|
20
20
|
let value = undefined;
|
|
21
21
|
switch (args.options.key) {
|
|
22
22
|
case settingsNames_1.settingsNames.autoOpenBrowserOnLogin:
|
|
23
|
+
case settingsNames_1.settingsNames.autoOpenLinksInBrowser:
|
|
23
24
|
case settingsNames_1.settingsNames.copyDeviceCodeToClipboard:
|
|
24
25
|
case settingsNames_1.settingsNames.csvHeader:
|
|
25
26
|
case settingsNames_1.settingsNames.csvQuoted:
|
|
@@ -242,6 +242,9 @@ class SpfxProjectUpgradeCommand extends base_project_command_1.BaseProjectComman
|
|
|
242
242
|
}
|
|
243
243
|
});
|
|
244
244
|
switch (args.options.output) {
|
|
245
|
+
case 'text':
|
|
246
|
+
logger.log(this.getTextReport(findingsToReport));
|
|
247
|
+
break;
|
|
245
248
|
case 'json':
|
|
246
249
|
logger.log(findingsToReport);
|
|
247
250
|
break;
|
|
@@ -252,7 +255,7 @@ class SpfxProjectUpgradeCommand extends base_project_command_1.BaseProjectComman
|
|
|
252
255
|
logger.log(this.getMdReport(findingsToReport));
|
|
253
256
|
break;
|
|
254
257
|
default:
|
|
255
|
-
logger.log(
|
|
258
|
+
logger.log(findingsToReport);
|
|
256
259
|
}
|
|
257
260
|
cb();
|
|
258
261
|
}
|
|
@@ -62,10 +62,10 @@ class SpoFileCheckoutCommand extends SpoCommand_1.default {
|
|
|
62
62
|
}
|
|
63
63
|
}
|
|
64
64
|
if (args.options.id && args.options.fileUrl) {
|
|
65
|
-
return 'Specify either
|
|
65
|
+
return 'Specify either id or fileUrl but not both';
|
|
66
66
|
}
|
|
67
67
|
if (!args.options.id && !args.options.fileUrl) {
|
|
68
|
-
return 'Specify
|
|
68
|
+
return 'Specify id or fileUrl, one is required';
|
|
69
69
|
}
|
|
70
70
|
return true;
|
|
71
71
|
}
|
|
@@ -50,7 +50,7 @@ class SpoSiteRemoveCommand extends SpoCommand_1.default {
|
|
|
50
50
|
if (args.options.skipRecycleBin || args.options.wait) {
|
|
51
51
|
logger.logToStderr(chalk.yellow(`Entered site is a groupified site. Hence, the parameters 'skipRecycleBin' and 'wait' will not be applicable.`));
|
|
52
52
|
}
|
|
53
|
-
return this.
|
|
53
|
+
return this.deleteGroup(group.id, logger);
|
|
54
54
|
})
|
|
55
55
|
.catch((err) => {
|
|
56
56
|
if (err.response.status === 404) {
|
|
@@ -79,7 +79,8 @@ class SpoSiteRemoveCommand extends SpoCommand_1.default {
|
|
|
79
79
|
else {
|
|
80
80
|
return Promise.reject(err);
|
|
81
81
|
}
|
|
82
|
-
})
|
|
82
|
+
})
|
|
83
|
+
.then(_ => this.deleteSite(args.options.url, args.options.wait, logger));
|
|
83
84
|
}
|
|
84
85
|
})
|
|
85
86
|
.then(_ => cb(), (err) => this.handleRejectedPromise(err, logger, cb));
|
|
@@ -296,7 +297,7 @@ class SpoSiteRemoveCommand extends SpoCommand_1.default {
|
|
|
296
297
|
}
|
|
297
298
|
});
|
|
298
299
|
}
|
|
299
|
-
|
|
300
|
+
deleteGroup(groupId, logger) {
|
|
300
301
|
if (this.verbose) {
|
|
301
302
|
logger.logToStderr(`Removing Microsoft 365 Group: ${groupId}...`);
|
|
302
303
|
}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const config_1 = require("../../../../config");
|
|
4
3
|
const request_1 = require("../../../../request");
|
|
5
4
|
const utils_1 = require("../../../../utils");
|
|
6
5
|
const SpoCommand_1 = require("../../../base/SpoCommand");
|
|
@@ -18,58 +17,25 @@ class SpoTenantRecycleBinItemRestoreCommand extends SpoCommand_1.default {
|
|
|
18
17
|
return telemetryProps;
|
|
19
18
|
}
|
|
20
19
|
commandAction(logger, args, cb) {
|
|
21
|
-
this.dots = '';
|
|
22
20
|
utils_1.spo
|
|
23
21
|
.getSpoAdminUrl(logger, this.debug)
|
|
24
22
|
.then((adminUrl) => {
|
|
25
|
-
this.spoAdminUrl = adminUrl;
|
|
26
|
-
return utils_1.spo.ensureFormDigest(this.spoAdminUrl, logger, this.context, this.debug);
|
|
27
|
-
})
|
|
28
|
-
.then((res) => {
|
|
29
|
-
this.context = res;
|
|
30
|
-
if (this.verbose) {
|
|
31
|
-
logger.logToStderr(`Restoring deleted site collection ${args.options.url}...`);
|
|
32
|
-
}
|
|
33
23
|
const requestOptions = {
|
|
34
|
-
url: `${
|
|
24
|
+
url: `${adminUrl}/_api/SPOInternalUseOnly.Tenant/RestoreDeletedSite`,
|
|
35
25
|
headers: {
|
|
36
|
-
'
|
|
26
|
+
accept: 'application/json;odata=nometadata',
|
|
27
|
+
'content-type': 'application/json;charset=utf-8'
|
|
37
28
|
},
|
|
38
|
-
data:
|
|
29
|
+
data: {
|
|
30
|
+
siteUrl: args.options.url
|
|
31
|
+
}
|
|
39
32
|
};
|
|
40
33
|
return request_1.default.post(requestOptions);
|
|
41
34
|
})
|
|
42
|
-
.then(
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
if (response.ErrorInfo) {
|
|
47
|
-
reject(response.ErrorInfo.ErrorMessage);
|
|
48
|
-
}
|
|
49
|
-
else {
|
|
50
|
-
const operation = json[json.length - 1];
|
|
51
|
-
const isComplete = operation.IsComplete;
|
|
52
|
-
if (!args.options.wait || isComplete) {
|
|
53
|
-
resolve();
|
|
54
|
-
return;
|
|
55
|
-
}
|
|
56
|
-
setTimeout(() => {
|
|
57
|
-
utils_1.spo.waitUntilFinished({
|
|
58
|
-
operationId: JSON.stringify(operation._ObjectIdentity_),
|
|
59
|
-
siteUrl: this.spoAdminUrl,
|
|
60
|
-
resolve,
|
|
61
|
-
reject,
|
|
62
|
-
logger,
|
|
63
|
-
currentContext: this.context,
|
|
64
|
-
dots: this.dots,
|
|
65
|
-
debug: this.debug,
|
|
66
|
-
verbose: this.verbose
|
|
67
|
-
});
|
|
68
|
-
}, operation.PollingInterval);
|
|
69
|
-
}
|
|
70
|
-
});
|
|
71
|
-
})
|
|
72
|
-
.then(_ => cb(), (err) => this.handleRejectedPromise(err, logger, cb));
|
|
35
|
+
.then(res => {
|
|
36
|
+
logger.log(JSON.parse(res));
|
|
37
|
+
cb();
|
|
38
|
+
}, (err) => this.handleRejectedODataJsonPromise(err, logger, cb));
|
|
73
39
|
}
|
|
74
40
|
options() {
|
|
75
41
|
const options = [
|
|
@@ -13,6 +13,14 @@ class SpoTenantSettingsSetCommand extends SpoCommand_1.default {
|
|
|
13
13
|
get description() {
|
|
14
14
|
return 'Sets tenant global settings';
|
|
15
15
|
}
|
|
16
|
+
types() {
|
|
17
|
+
return {
|
|
18
|
+
boolean: [
|
|
19
|
+
'EnableAzureADB2BIntegration',
|
|
20
|
+
'SyncAadB2BManagementPolicy'
|
|
21
|
+
]
|
|
22
|
+
};
|
|
23
|
+
}
|
|
16
24
|
getTelemetryProperties(args) {
|
|
17
25
|
const telemetryProps = super.getTelemetryProperties(args);
|
|
18
26
|
telemetryProps.MinCompatibilityLevel = (!(!args.options.MinCompatibilityLevel)).toString();
|
|
@@ -97,6 +105,8 @@ class SpoTenantSettingsSetCommand extends SpoCommand_1.default {
|
|
|
97
105
|
telemetryProps.DisabledWebPartIds = (!(!args.options.DisabledWebPartIds)).toString();
|
|
98
106
|
telemetryProps.AllowedDomainListForSyncClient = (!(!args.options.AllowedDomainListForSyncClient)).toString();
|
|
99
107
|
telemetryProps.DisableCustomAppAuthentication = (!(!args.options.DisableCustomAppAuthentication)).toString();
|
|
108
|
+
telemetryProps.EnableAzureADB2BIntegration = typeof args.options.EnableAzureADB2BIntegration !== 'undefined';
|
|
109
|
+
telemetryProps.SyncAadB2BManagementPolicy = typeof args.options.SyncAadB2BManagementPolicy !== 'undefined';
|
|
100
110
|
return telemetryProps;
|
|
101
111
|
}
|
|
102
112
|
getAllEnumOptions() {
|
|
@@ -176,6 +186,9 @@ class SpoTenantSettingsSetCommand extends SpoCommand_1.default {
|
|
|
176
186
|
cb(new Command_1.CommandError(response.ErrorInfo.ErrorMessage));
|
|
177
187
|
return;
|
|
178
188
|
}
|
|
189
|
+
if (args.options.EnableAzureADB2BIntegration === true) {
|
|
190
|
+
this.warn(logger, 'WARNING: Make sure to also enable the Azure AD one-time passcode authentication preview. If it is not enabled then SharePoint will not use Azure AD B2B even if EnableAzureADB2BIntegration is set to true. Learn more at http://aka.ms/spo-b2b-integration.');
|
|
191
|
+
}
|
|
179
192
|
cb();
|
|
180
193
|
}, (err) => this.handleRejectedPromise(err, logger, cb));
|
|
181
194
|
}
|
|
@@ -490,6 +503,14 @@ class SpoTenantSettingsSetCommand extends SpoCommand_1.default {
|
|
|
490
503
|
{
|
|
491
504
|
option: '--DisableCustomAppAuthentication [DisableCustomAppAuthentication]',
|
|
492
505
|
autocomplete: ['true', 'false']
|
|
506
|
+
},
|
|
507
|
+
{
|
|
508
|
+
option: '--EnableAzureADB2BIntegration [EnableAzureADB2BIntegration]',
|
|
509
|
+
autocomplete: ['true', 'false']
|
|
510
|
+
},
|
|
511
|
+
{
|
|
512
|
+
option: '--SyncAadB2BManagementPolicy [SyncAadB2BManagementPolicy]',
|
|
513
|
+
autocomplete: ['true', 'false']
|
|
493
514
|
}
|
|
494
515
|
];
|
|
495
516
|
const parentOptions = super.options();
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const utils_1 = require("../../../../utils");
|
|
4
|
+
const GraphCommand_1 = require("../../../base/GraphCommand");
|
|
5
|
+
const commands_1 = require("../../commands");
|
|
6
|
+
const request_1 = require("../../../../request");
|
|
7
|
+
class TeamsChannelMembershipListCommand extends GraphCommand_1.default {
|
|
8
|
+
constructor() {
|
|
9
|
+
super(...arguments);
|
|
10
|
+
this.teamId = '';
|
|
11
|
+
}
|
|
12
|
+
get name() {
|
|
13
|
+
return commands_1.default.CHANNEL_MEMBERSHIP_LIST;
|
|
14
|
+
}
|
|
15
|
+
get description() {
|
|
16
|
+
return 'Lists memberships in the specified Microsoft Teams team channel';
|
|
17
|
+
}
|
|
18
|
+
defaultProperties() {
|
|
19
|
+
return ['id', 'roles', 'displayName', 'userId', 'email'];
|
|
20
|
+
}
|
|
21
|
+
getTelemetryProperties(args) {
|
|
22
|
+
const telemetryProps = super.getTelemetryProperties(args);
|
|
23
|
+
telemetryProps.teamId = typeof args.options.teamId !== 'undefined';
|
|
24
|
+
telemetryProps.teamName = typeof args.options.teamName !== 'undefined';
|
|
25
|
+
telemetryProps.channelId = typeof args.options.channelId !== 'undefined';
|
|
26
|
+
telemetryProps.channelName = typeof args.options.channelName !== 'undefined';
|
|
27
|
+
telemetryProps.role = typeof args.options.role;
|
|
28
|
+
return telemetryProps;
|
|
29
|
+
}
|
|
30
|
+
commandAction(logger, args, cb) {
|
|
31
|
+
this
|
|
32
|
+
.getTeamId(args)
|
|
33
|
+
.then((teamId) => {
|
|
34
|
+
this.teamId = teamId;
|
|
35
|
+
return this.getChannelId(args);
|
|
36
|
+
})
|
|
37
|
+
.then((channelId) => {
|
|
38
|
+
const endpoint = `${this.resource}/v1.0/teams/${this.teamId}/channels/${channelId}/members`;
|
|
39
|
+
return utils_1.odata.getAllItems(endpoint, logger);
|
|
40
|
+
})
|
|
41
|
+
.then((memberships) => {
|
|
42
|
+
if (args.options.role) {
|
|
43
|
+
if (args.options.role === 'member') {
|
|
44
|
+
// Members have no role value
|
|
45
|
+
memberships = memberships.filter(i => i.roles.length === 0);
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
memberships = memberships.filter(i => i.roles.indexOf(args.options.role) !== -1);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
logger.log(memberships);
|
|
52
|
+
cb();
|
|
53
|
+
}, (err) => this.handleRejectedODataJsonPromise(err, logger, cb));
|
|
54
|
+
}
|
|
55
|
+
getTeamId(args) {
|
|
56
|
+
if (args.options.teamId) {
|
|
57
|
+
return Promise.resolve(args.options.teamId);
|
|
58
|
+
}
|
|
59
|
+
const requestOptions = {
|
|
60
|
+
url: `${this.resource}/v1.0/groups?$filter=displayName eq '${encodeURIComponent(args.options.teamName)}'`,
|
|
61
|
+
headers: {
|
|
62
|
+
accept: 'application/json;odata.metadata=none'
|
|
63
|
+
},
|
|
64
|
+
responseType: 'json'
|
|
65
|
+
};
|
|
66
|
+
return request_1.default
|
|
67
|
+
.get(requestOptions)
|
|
68
|
+
.then(response => {
|
|
69
|
+
const groupItem = response.value[0];
|
|
70
|
+
if (!groupItem) {
|
|
71
|
+
return Promise.reject(`The specified team does not exist in the Microsoft Teams`);
|
|
72
|
+
}
|
|
73
|
+
if (groupItem.resourceProvisioningOptions.indexOf('Team') === -1) {
|
|
74
|
+
return Promise.reject(`The specified team does not exist in the Microsoft Teams`);
|
|
75
|
+
}
|
|
76
|
+
if (response.value.length > 1) {
|
|
77
|
+
return Promise.reject(`Multiple Microsoft Teams teams with name ${args.options.teamName} found: ${response.value.map(x => x.id)}`);
|
|
78
|
+
}
|
|
79
|
+
return Promise.resolve(groupItem.id);
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
getChannelId(args) {
|
|
83
|
+
if (args.options.channelId) {
|
|
84
|
+
return Promise.resolve(args.options.channelId);
|
|
85
|
+
}
|
|
86
|
+
const channelRequestOptions = {
|
|
87
|
+
url: `${this.resource}/v1.0/teams/${encodeURIComponent(this.teamId)}/channels?$filter=displayName eq '${encodeURIComponent(args.options.channelName)}'`,
|
|
88
|
+
headers: {
|
|
89
|
+
accept: 'application/json;odata.metadata=none'
|
|
90
|
+
},
|
|
91
|
+
responseType: 'json'
|
|
92
|
+
};
|
|
93
|
+
return request_1.default
|
|
94
|
+
.get(channelRequestOptions)
|
|
95
|
+
.then(response => {
|
|
96
|
+
const channelItem = response.value[0];
|
|
97
|
+
if (!channelItem) {
|
|
98
|
+
return Promise.reject(`The specified channel does not exist in the Microsoft Teams team`);
|
|
99
|
+
}
|
|
100
|
+
return Promise.resolve(channelItem.id);
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
options() {
|
|
104
|
+
const options = [
|
|
105
|
+
{
|
|
106
|
+
option: '--teamId [teamId]'
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
option: '--teamName [teamName]'
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
option: '--channelId [channelId]'
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
option: '--channelName [channelName]'
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
option: '-r, --role [role]',
|
|
119
|
+
autocomplete: ['owner', 'member', 'guest']
|
|
120
|
+
}
|
|
121
|
+
];
|
|
122
|
+
const parentOptions = super.options();
|
|
123
|
+
return options.concat(parentOptions);
|
|
124
|
+
}
|
|
125
|
+
validate(args) {
|
|
126
|
+
if (args.options.teamId && args.options.teamName) {
|
|
127
|
+
return 'Specify either teamId or teamName, but not both';
|
|
128
|
+
}
|
|
129
|
+
if (!args.options.teamId && !args.options.teamName) {
|
|
130
|
+
return 'Specify teamId or teamName, one is required';
|
|
131
|
+
}
|
|
132
|
+
if (args.options.teamId && !utils_1.validation.isValidGuid(args.options.teamId)) {
|
|
133
|
+
return `${args.options.teamId} is not a valid GUID`;
|
|
134
|
+
}
|
|
135
|
+
if (args.options.channelId && args.options.channelName) {
|
|
136
|
+
return 'Specify either channelId or channelName, but not both';
|
|
137
|
+
}
|
|
138
|
+
if (!args.options.channelId && !args.options.channelName) {
|
|
139
|
+
return 'Specify channelId or channelName, one is required';
|
|
140
|
+
}
|
|
141
|
+
if (args.options.role) {
|
|
142
|
+
if (['owner', 'member', 'guest'].indexOf(args.options.role) === -1) {
|
|
143
|
+
return `${args.options.role} is not a valid role value. Allowed values owner|member|guest`;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
return true;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
module.exports = new TeamsChannelMembershipListCommand();
|
|
150
|
+
//# sourceMappingURL=channel-membership-list.js.map
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
const Auth_1 = require("../../../../Auth");
|
|
13
|
+
const os = require("os");
|
|
14
|
+
const request_1 = require("../../../../request");
|
|
15
|
+
const GraphCommand_1 = require("../../../base/GraphCommand");
|
|
16
|
+
const commands_1 = require("../../commands");
|
|
17
|
+
const validation_1 = require("../../../../utils/validation");
|
|
18
|
+
const accessToken_1 = require("../../../../utils/accessToken");
|
|
19
|
+
const chatUtil_1 = require("./chatUtil");
|
|
20
|
+
class TeamsChatGetCommand extends GraphCommand_1.default {
|
|
21
|
+
get name() {
|
|
22
|
+
return commands_1.default.CHAT_GET;
|
|
23
|
+
}
|
|
24
|
+
get description() {
|
|
25
|
+
return 'Get a Microsoft Teams chat conversation by id, participants or chat name.';
|
|
26
|
+
}
|
|
27
|
+
getTelemetryProperties(args) {
|
|
28
|
+
const telemetryProps = super.getTelemetryProperties(args);
|
|
29
|
+
telemetryProps.id = typeof args.options.id !== 'undefined';
|
|
30
|
+
telemetryProps.participants = typeof args.options.participants !== 'undefined';
|
|
31
|
+
telemetryProps.name = typeof args.options.name !== 'undefined';
|
|
32
|
+
return telemetryProps;
|
|
33
|
+
}
|
|
34
|
+
commandAction(logger, args, cb) {
|
|
35
|
+
this
|
|
36
|
+
.getChatId(logger, args)
|
|
37
|
+
.then(chatId => this.getChatDetailsById(chatId))
|
|
38
|
+
.then((chat) => {
|
|
39
|
+
logger.log(chat);
|
|
40
|
+
cb();
|
|
41
|
+
}, (err) => this.handleRejectedODataJsonPromise(err, logger, cb));
|
|
42
|
+
}
|
|
43
|
+
options() {
|
|
44
|
+
const options = [
|
|
45
|
+
{
|
|
46
|
+
option: '-i, --id [id]'
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
option: '-p, --participants [participants]'
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
option: '-n, --name [name]'
|
|
53
|
+
}
|
|
54
|
+
];
|
|
55
|
+
const parentOptions = super.options();
|
|
56
|
+
return options.concat(parentOptions);
|
|
57
|
+
}
|
|
58
|
+
validate(args) {
|
|
59
|
+
if (!args.options.id && !args.options.participants && !args.options.name) {
|
|
60
|
+
return 'Specify id or participants or name, one is required.';
|
|
61
|
+
}
|
|
62
|
+
let nrOfMutuallyExclusiveOptionsInUse = 0;
|
|
63
|
+
if (args.options.id) {
|
|
64
|
+
nrOfMutuallyExclusiveOptionsInUse++;
|
|
65
|
+
}
|
|
66
|
+
if (args.options.participants) {
|
|
67
|
+
nrOfMutuallyExclusiveOptionsInUse++;
|
|
68
|
+
}
|
|
69
|
+
if (args.options.name) {
|
|
70
|
+
nrOfMutuallyExclusiveOptionsInUse++;
|
|
71
|
+
}
|
|
72
|
+
if (nrOfMutuallyExclusiveOptionsInUse > 1) {
|
|
73
|
+
return 'Specify either id or participants or name, but not multiple.';
|
|
74
|
+
}
|
|
75
|
+
if (args.options.id && !validation_1.validation.isValidTeamsChatId(args.options.id)) {
|
|
76
|
+
return `${args.options.id} is not a valid Teams ChatId.`;
|
|
77
|
+
}
|
|
78
|
+
if (args.options.participants) {
|
|
79
|
+
const participants = chatUtil_1.chatUtil.convertParticipantStringToArray(args.options.participants);
|
|
80
|
+
if (!participants || participants.length === 0 || participants.some(e => !validation_1.validation.isValidUserPrincipalName(e))) {
|
|
81
|
+
return `${args.options.participants} contains one or more invalid email addresses.`;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return true;
|
|
85
|
+
}
|
|
86
|
+
getChatId(logger, args) {
|
|
87
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
88
|
+
if (args.options.id) {
|
|
89
|
+
return args.options.id;
|
|
90
|
+
}
|
|
91
|
+
return args.options.participants
|
|
92
|
+
? this.getChatIdByParticipants(args.options.participants, logger)
|
|
93
|
+
: this.getChatIdByName(args.options.name, logger);
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
getChatDetailsById(id) {
|
|
97
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
98
|
+
const requestOptions = {
|
|
99
|
+
url: `${this.resource}/v1.0/chats/${encodeURIComponent(id)}`,
|
|
100
|
+
headers: {
|
|
101
|
+
accept: 'application/json;odata.metadata=none'
|
|
102
|
+
},
|
|
103
|
+
responseType: 'json'
|
|
104
|
+
};
|
|
105
|
+
return request_1.default.get(requestOptions);
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
getChatIdByParticipants(participantsString, logger) {
|
|
109
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
110
|
+
const participants = chatUtil_1.chatUtil.convertParticipantStringToArray(participantsString);
|
|
111
|
+
const currentUserEmail = accessToken_1.accessToken.getUserNameFromAccessToken(Auth_1.default.service.accessTokens[this.resource].accessToken).toLowerCase();
|
|
112
|
+
const existingChats = yield chatUtil_1.chatUtil.findExistingChatsByParticipants([currentUserEmail, ...participants], logger);
|
|
113
|
+
if (!existingChats || existingChats.length === 0) {
|
|
114
|
+
throw new Error('No chat conversation was found with these participants.');
|
|
115
|
+
}
|
|
116
|
+
if (existingChats.length === 1) {
|
|
117
|
+
return existingChats[0].id;
|
|
118
|
+
}
|
|
119
|
+
const disambiguationText = existingChats.map(c => {
|
|
120
|
+
return `- ${c.id}${c.topic && ' - '}${c.topic} - ${c.createdDateTime && new Date(c.createdDateTime).toLocaleString()}`;
|
|
121
|
+
}).join(os.EOL);
|
|
122
|
+
throw new Error(`Multiple chat conversations with these participants found. Please disambiguate:${os.EOL}${disambiguationText}`);
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
getChatIdByName(name, logger) {
|
|
126
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
127
|
+
const existingChats = yield chatUtil_1.chatUtil.findExistingGroupChatsByName(name, logger);
|
|
128
|
+
if (!existingChats || existingChats.length === 0) {
|
|
129
|
+
throw new Error('No chat conversation was found with this name.');
|
|
130
|
+
}
|
|
131
|
+
if (existingChats.length === 1) {
|
|
132
|
+
return existingChats[0].id;
|
|
133
|
+
}
|
|
134
|
+
const disambiguationText = existingChats.map(c => {
|
|
135
|
+
const memberstring = c.members.map(m => m.email).join(', ');
|
|
136
|
+
return `- ${c.id} - ${c.createdDateTime && new Date(c.createdDateTime).toLocaleString()} - ${memberstring}`;
|
|
137
|
+
}).join(os.EOL);
|
|
138
|
+
throw new Error(`Multiple chat conversations with this name found. Please disambiguate:${os.EOL}${disambiguationText}`);
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
module.exports = new TeamsChatGetCommand();
|
|
143
|
+
//# sourceMappingURL=chat-get.js.map
|