@pnp/cli-microsoft365 7.2.0 → 7.3.0-beta.01256d2
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/allCommands.json +1 -1
- package/allCommandsFull.json +1 -1
- package/dist/appInsights.js +2 -1
- package/dist/cli/Cli.js +14 -13
- package/dist/index.js +1 -9
- package/dist/m365/aad/commands/group/group-list.js +69 -1
- package/dist/m365/external/commands/connection/connection-doctor.js +424 -0
- package/dist/m365/external/commands/item/item-add.js +144 -0
- package/dist/m365/external/commands.js +3 -1
- package/dist/m365/teams/commands/meeting/meeting-add.js +151 -0
- package/dist/m365/teams/commands/user/user-app-remove.js +33 -2
- package/dist/m365/teams/commands.js +2 -1
- package/dist/telemetry.js +0 -8
- package/dist/utils/validation.js +5 -2
- package/docs/docs/cmd/aad/group/group-list.mdx +11 -0
- package/docs/docs/cmd/external/connection/connection-doctor.mdx +179 -0
- package/docs/docs/cmd/external/item/item-add.mdx +145 -0
- package/docs/docs/cmd/onedrive/report/report-activityfilecounts.mdx +0 -3
- package/docs/docs/cmd/onedrive/report/report-activityusercounts.mdx +0 -3
- package/docs/docs/cmd/onedrive/report/report-activityuserdetail.mdx +0 -3
- package/docs/docs/cmd/onedrive/report/report-usageaccountcounts.mdx +0 -3
- package/docs/docs/cmd/onedrive/report/report-usageaccountdetail.mdx +0 -3
- package/docs/docs/cmd/onedrive/report/report-usagefilecounts.mdx +0 -3
- package/docs/docs/cmd/onedrive/report/report-usagestorage.mdx +0 -3
- package/docs/docs/cmd/outlook/report/report-mailactivitycounts.mdx +0 -3
- package/docs/docs/cmd/outlook/report/report-mailactivityusercounts.mdx +0 -3
- package/docs/docs/cmd/outlook/report/report-mailactivityuserdetail.mdx +0 -3
- package/docs/docs/cmd/outlook/report/report-mailappusageappsusercounts.mdx +0 -3
- package/docs/docs/cmd/outlook/report/report-mailappusageusercounts.mdx +0 -3
- package/docs/docs/cmd/outlook/report/report-mailappusageuserdetail.mdx +0 -3
- package/docs/docs/cmd/outlook/report/report-mailappusageversionsusercounts.mdx +0 -3
- package/docs/docs/cmd/outlook/report/report-mailboxusagedetail.mdx +0 -3
- package/docs/docs/cmd/outlook/report/report-mailboxusagemailboxcount.mdx +0 -3
- package/docs/docs/cmd/outlook/report/report-mailboxusagequotastatusmailboxcounts.mdx +0 -3
- package/docs/docs/cmd/outlook/report/report-mailboxusagestorage.mdx +0 -3
- package/docs/docs/cmd/skype/report/report-activitycounts.mdx +0 -2
- package/docs/docs/cmd/skype/report/report-activityusercounts.mdx +0 -3
- package/docs/docs/cmd/skype/report/report-activityuserdetail.mdx +0 -3
- package/docs/docs/cmd/spo/report/report-activityfilecounts.mdx +0 -3
- package/docs/docs/cmd/spo/report/report-activitypages.mdx +0 -3
- package/docs/docs/cmd/spo/report/report-activityusercounts.mdx +0 -3
- package/docs/docs/cmd/spo/report/report-activityuserdetail.mdx +0 -3
- package/docs/docs/cmd/spo/report/report-siteusagedetail.mdx +0 -3
- package/docs/docs/cmd/spo/report/report-siteusagefilecounts.mdx +0 -3
- package/docs/docs/cmd/spo/report/report-siteusagepages.mdx +0 -3
- package/docs/docs/cmd/spo/report/report-siteusagesitecounts.mdx +0 -3
- package/docs/docs/cmd/spo/report/report-siteusagestorage.mdx +0 -3
- package/docs/docs/cmd/teams/meeting/meeting-add.mdx +283 -0
- package/docs/docs/cmd/teams/report/report-deviceusagedistributionusercounts.mdx +0 -3
- package/docs/docs/cmd/teams/report/report-deviceusageusercounts.mdx +0 -3
- package/docs/docs/cmd/teams/report/report-deviceusageuserdetail.mdx +0 -3
- package/docs/docs/cmd/teams/report/report-useractivitycounts.mdx +0 -3
- package/docs/docs/cmd/teams/report/report-useractivityusercounts.mdx +0 -3
- package/docs/docs/cmd/teams/report/report-useractivityuserdetail.mdx +0 -3
- package/docs/docs/cmd/teams/user/user-app-remove.mdx +13 -4
- package/docs/docs/cmd/tenant/report/report-activeusercounts.mdx +0 -3
- package/docs/docs/cmd/tenant/report/report-activeuserdetail.mdx +0 -3
- package/docs/docs/cmd/tenant/report/report-servicesusercounts.mdx +0 -3
- package/docs/docs/cmd/yammer/report/report-activitycounts.mdx +0 -3
- package/docs/docs/cmd/yammer/report/report-activityusercounts.mdx +0 -3
- package/docs/docs/cmd/yammer/report/report-activityuserdetail.mdx +0 -3
- package/docs/docs/cmd/yammer/report/report-deviceusagedistributionusercounts.mdx +0 -3
- package/docs/docs/cmd/yammer/report/report-deviceusageusercounts.mdx +0 -3
- package/docs/docs/cmd/yammer/report/report-deviceusageuserdetail.mdx +0 -3
- package/docs/docs/cmd/yammer/report/report-groupsactivitycounts.mdx +0 -3
- package/docs/docs/cmd/yammer/report/report-groupsactivitydetail.mdx +0 -3
- package/docs/docs/cmd/yammer/report/report-groupsactivitygroupcounts.mdx +0 -3
- package/npm-shrinkwrap.json +6 -6
- package/package.json +4 -3
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
2
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
3
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
4
|
+
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
5
|
+
};
|
|
6
|
+
var _ExternalItemAddCommand_instances, _a, _ExternalItemAddCommand_initTelemetry, _ExternalItemAddCommand_initOptions, _ExternalItemAddCommand_initValidators;
|
|
7
|
+
import request from '../../../../request.js';
|
|
8
|
+
import GraphCommand from '../../../base/GraphCommand.js';
|
|
9
|
+
import commands from '../../commands.js';
|
|
10
|
+
class ExternalItemAddCommand extends GraphCommand {
|
|
11
|
+
get name() {
|
|
12
|
+
return commands.ITEM_ADD;
|
|
13
|
+
}
|
|
14
|
+
get description() {
|
|
15
|
+
return 'Creates external item';
|
|
16
|
+
}
|
|
17
|
+
constructor() {
|
|
18
|
+
super();
|
|
19
|
+
_ExternalItemAddCommand_instances.add(this);
|
|
20
|
+
__classPrivateFieldGet(this, _ExternalItemAddCommand_instances, "m", _ExternalItemAddCommand_initTelemetry).call(this);
|
|
21
|
+
__classPrivateFieldGet(this, _ExternalItemAddCommand_instances, "m", _ExternalItemAddCommand_initOptions).call(this);
|
|
22
|
+
__classPrivateFieldGet(this, _ExternalItemAddCommand_instances, "m", _ExternalItemAddCommand_initValidators).call(this);
|
|
23
|
+
}
|
|
24
|
+
allowUnknownOptions() {
|
|
25
|
+
return true;
|
|
26
|
+
}
|
|
27
|
+
async commandAction(logger, args) {
|
|
28
|
+
const acls = args.options.acls
|
|
29
|
+
.split(';')
|
|
30
|
+
.map(acl => {
|
|
31
|
+
const aclParts = acl.split(',');
|
|
32
|
+
return {
|
|
33
|
+
accessType: aclParts[0],
|
|
34
|
+
type: aclParts[1],
|
|
35
|
+
value: aclParts[2]
|
|
36
|
+
};
|
|
37
|
+
});
|
|
38
|
+
const requestBody = {
|
|
39
|
+
id: args.options.id,
|
|
40
|
+
content: {
|
|
41
|
+
value: args.options.content,
|
|
42
|
+
type: args.options.contentType ?? 'text'
|
|
43
|
+
},
|
|
44
|
+
acl: acls,
|
|
45
|
+
properties: {}
|
|
46
|
+
};
|
|
47
|
+
// we need to rewrite the @odata properties to the correct format
|
|
48
|
+
// because . in @odata.type is interpreted by minimist as a child property
|
|
49
|
+
// we also need to extract multiple values for collections into arrays
|
|
50
|
+
this.rewriteCollectionProperties(args.options);
|
|
51
|
+
this.addUnknownOptionsToPayload(requestBody.properties, args.options);
|
|
52
|
+
const requestOptions = {
|
|
53
|
+
url: `${this.resource}/v1.0/external/connections/${args.options.externalConnectionId}/items/${args.options.id}`,
|
|
54
|
+
headers: {
|
|
55
|
+
accept: 'application/json;odata.metadata=none',
|
|
56
|
+
'content-type': 'application/json'
|
|
57
|
+
},
|
|
58
|
+
responseType: 'json',
|
|
59
|
+
data: requestBody
|
|
60
|
+
};
|
|
61
|
+
try {
|
|
62
|
+
const externalItem = await request.put(requestOptions);
|
|
63
|
+
if (args.options.output === 'csv' || args.options.output === 'md') {
|
|
64
|
+
// for CSV and md, we need to bring the properties to the main object
|
|
65
|
+
// and convert arrays to comma-separated strings or they will be dropped
|
|
66
|
+
// from the output
|
|
67
|
+
Object.getOwnPropertyNames(externalItem.properties).forEach(name => {
|
|
68
|
+
if (Array.isArray(externalItem.properties[name])) {
|
|
69
|
+
externalItem[name] = externalItem.properties[name].join(', ');
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
externalItem[name] = externalItem.properties[name];
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
await logger.log(externalItem);
|
|
77
|
+
}
|
|
78
|
+
catch (err) {
|
|
79
|
+
this.handleRejectedODataJsonPromise(err);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
rewriteCollectionProperties(options) {
|
|
83
|
+
Object.getOwnPropertyNames(options).forEach(name => {
|
|
84
|
+
if (!name.endsWith('@odata')) {
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
options[`${name}.type`] = options[name].type;
|
|
88
|
+
delete options[name];
|
|
89
|
+
// convert the value of a collection to an array
|
|
90
|
+
const nameWithoutOData = name.substring(0, name.indexOf('@odata'));
|
|
91
|
+
if (options[nameWithoutOData]) {
|
|
92
|
+
options[nameWithoutOData] = options[nameWithoutOData].split(';#');
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
_a = ExternalItemAddCommand, _ExternalItemAddCommand_instances = new WeakSet(), _ExternalItemAddCommand_initTelemetry = function _ExternalItemAddCommand_initTelemetry() {
|
|
98
|
+
this.telemetry.push((args) => {
|
|
99
|
+
Object.assign(this.telemetryProperties, {
|
|
100
|
+
contentType: typeof args.options.contentType
|
|
101
|
+
});
|
|
102
|
+
});
|
|
103
|
+
}, _ExternalItemAddCommand_initOptions = function _ExternalItemAddCommand_initOptions() {
|
|
104
|
+
this.options.unshift({
|
|
105
|
+
option: '--id <id>'
|
|
106
|
+
}, {
|
|
107
|
+
option: '--externalConnectionId <externalConnectionId>'
|
|
108
|
+
}, {
|
|
109
|
+
option: '--content <content>'
|
|
110
|
+
}, {
|
|
111
|
+
option: '--contentType [contentType]',
|
|
112
|
+
autocomplete: _a.contentType
|
|
113
|
+
}, {
|
|
114
|
+
option: '--acls <acls>'
|
|
115
|
+
});
|
|
116
|
+
}, _ExternalItemAddCommand_initValidators = function _ExternalItemAddCommand_initValidators() {
|
|
117
|
+
this.validators.push(async (args) => {
|
|
118
|
+
if (args.options.contentType &&
|
|
119
|
+
_a.contentType.indexOf(args.options.contentType) < 0) {
|
|
120
|
+
return `${args.options.contentType} is not a valid value for contentType. Allowed values are ${_a.contentType.join(', ')}`;
|
|
121
|
+
}
|
|
122
|
+
// verify that each value for ACLs consists of three parts
|
|
123
|
+
// and that the values are correct
|
|
124
|
+
const acls = args.options.acls.split(';');
|
|
125
|
+
for (let i = 0; i < acls.length; i++) {
|
|
126
|
+
const acl = acls[i].split(',');
|
|
127
|
+
if (acl.length !== 3) {
|
|
128
|
+
return `The value ${acls[i]} for option acls is not in the correct format. The correct format is "accessType,type,value", eg. "grant,everyone,everyone"`;
|
|
129
|
+
}
|
|
130
|
+
const accessTypeValues = ['grant', 'deny'];
|
|
131
|
+
if (accessTypeValues.indexOf(acl[0]) < 0) {
|
|
132
|
+
return `The value ${acl[0]} for option acls is not valid. Allowed values are ${accessTypeValues.join(', ')}}`;
|
|
133
|
+
}
|
|
134
|
+
const aclTypeValues = ['user', 'group', 'everyone', 'everyoneExceptGuests', 'externalGroup'];
|
|
135
|
+
if (aclTypeValues.indexOf(acl[1]) < 0) {
|
|
136
|
+
return `The value ${acl[1]} for option acls is not valid. Allowed values are ${aclTypeValues.join(', ')}}`;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
return true;
|
|
140
|
+
});
|
|
141
|
+
};
|
|
142
|
+
ExternalItemAddCommand.contentType = ['text', 'html'];
|
|
143
|
+
export default new ExternalItemAddCommand();
|
|
144
|
+
//# sourceMappingURL=item-add.js.map
|
|
@@ -2,6 +2,7 @@ const prefix = 'external';
|
|
|
2
2
|
const searchPrefix = 'search';
|
|
3
3
|
export default {
|
|
4
4
|
CONNECTION_ADD: `${prefix} connection add`,
|
|
5
|
+
CONNECTION_DOCTOR: `${prefix} connection doctor`,
|
|
5
6
|
CONNECTION_GET: `${prefix} connection get`,
|
|
6
7
|
CONNECTION_LIST: `${prefix} connection list`,
|
|
7
8
|
CONNECTION_REMOVE: `${prefix} connection remove`,
|
|
@@ -10,6 +11,7 @@ export default {
|
|
|
10
11
|
EXTERNALCONNECTION_GET: `${searchPrefix} externalconnection get`,
|
|
11
12
|
EXTERNALCONNECTION_LIST: `${searchPrefix} externalconnection list`,
|
|
12
13
|
EXTERNALCONNECTION_REMOVE: `${searchPrefix} externalconnection remove`,
|
|
13
|
-
EXTERNALCONNECTION_SCHEMA_ADD: `${searchPrefix} externalconnection schema add
|
|
14
|
+
EXTERNALCONNECTION_SCHEMA_ADD: `${searchPrefix} externalconnection schema add`,
|
|
15
|
+
ITEM_ADD: `${prefix} item add`
|
|
14
16
|
};
|
|
15
17
|
//# sourceMappingURL=commands.js.map
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
2
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
3
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
4
|
+
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
5
|
+
};
|
|
6
|
+
var _TeamsMeetingAddCommand_instances, _TeamsMeetingAddCommand_initTelemetry, _TeamsMeetingAddCommand_initOptions, _TeamsMeetingAddCommand_initValidators;
|
|
7
|
+
import auth from '../../../../Auth.js';
|
|
8
|
+
import { aadUser } from '../../../../utils/aadUser.js';
|
|
9
|
+
import { accessToken } from '../../../../utils/accessToken.js';
|
|
10
|
+
import { validation } from '../../../../utils/validation.js';
|
|
11
|
+
import GraphCommand from "../../../base/GraphCommand.js";
|
|
12
|
+
import commands from '../../commands.js';
|
|
13
|
+
import request from '../../../../request.js';
|
|
14
|
+
class TeamsMeetingAddCommand extends GraphCommand {
|
|
15
|
+
get name() {
|
|
16
|
+
return commands.MEETING_ADD;
|
|
17
|
+
}
|
|
18
|
+
get description() {
|
|
19
|
+
return 'Creates a new online meeting';
|
|
20
|
+
}
|
|
21
|
+
constructor() {
|
|
22
|
+
super();
|
|
23
|
+
_TeamsMeetingAddCommand_instances.add(this);
|
|
24
|
+
__classPrivateFieldGet(this, _TeamsMeetingAddCommand_instances, "m", _TeamsMeetingAddCommand_initTelemetry).call(this);
|
|
25
|
+
__classPrivateFieldGet(this, _TeamsMeetingAddCommand_instances, "m", _TeamsMeetingAddCommand_initOptions).call(this);
|
|
26
|
+
__classPrivateFieldGet(this, _TeamsMeetingAddCommand_instances, "m", _TeamsMeetingAddCommand_initValidators).call(this);
|
|
27
|
+
}
|
|
28
|
+
async commandAction(logger, args) {
|
|
29
|
+
try {
|
|
30
|
+
const isAppOnlyAccessToken = accessToken.isAppOnlyAccessToken(auth.service.accessTokens[this.resource].accessToken);
|
|
31
|
+
if (isAppOnlyAccessToken && !args.options.organizerEmail) {
|
|
32
|
+
throw `The option 'organizerEmail' is required when creating a meeting using app only permissions`;
|
|
33
|
+
}
|
|
34
|
+
if (!isAppOnlyAccessToken && args.options.organizerEmail) {
|
|
35
|
+
throw `The option 'organizerEmail' is not supported when creating a meeting using delegated permissions`;
|
|
36
|
+
}
|
|
37
|
+
const meeting = await this.createMeeting(logger, args.options);
|
|
38
|
+
await logger.log(meeting);
|
|
39
|
+
}
|
|
40
|
+
catch (err) {
|
|
41
|
+
this.handleRejectedODataJsonPromise(err);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Creates a new online meeting
|
|
46
|
+
* @param logger
|
|
47
|
+
* @param options
|
|
48
|
+
* @returns MS Graph online meeting response
|
|
49
|
+
*/
|
|
50
|
+
async createMeeting(logger, options) {
|
|
51
|
+
let requestUrl = `${this.resource}/v1.0/me`;
|
|
52
|
+
if (options.organizerEmail) {
|
|
53
|
+
if (this.verbose) {
|
|
54
|
+
await logger.logToStderr(`Retrieving Organizer Id...`);
|
|
55
|
+
}
|
|
56
|
+
const organizerId = await aadUser.getUserIdByEmail(options.organizerEmail);
|
|
57
|
+
requestUrl = `${this.resource}/v1.0/users/${organizerId}`;
|
|
58
|
+
}
|
|
59
|
+
if (this.verbose) {
|
|
60
|
+
await logger.logToStderr(`Creating the meeting...`);
|
|
61
|
+
}
|
|
62
|
+
const requestData = {};
|
|
63
|
+
if (options.participantUserNames) {
|
|
64
|
+
const attendees = options.participantUserNames.trim().toLowerCase().split(',').map(p => ({
|
|
65
|
+
upn: p.trim()
|
|
66
|
+
}));
|
|
67
|
+
requestData.participants = { attendees };
|
|
68
|
+
}
|
|
69
|
+
if (options.startTime) {
|
|
70
|
+
requestData.startDateTime = options.startTime;
|
|
71
|
+
}
|
|
72
|
+
if (options.endTime) {
|
|
73
|
+
requestData.endDateTime = options.endTime;
|
|
74
|
+
if (!options.startTime) {
|
|
75
|
+
requestData.startDateTime = new Date().toISOString();
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
if (options.subject) {
|
|
79
|
+
requestData.subject = options.subject;
|
|
80
|
+
}
|
|
81
|
+
if (options.recordAutomatically !== undefined) {
|
|
82
|
+
requestData.recordAutomatically = true;
|
|
83
|
+
}
|
|
84
|
+
const requestOptions = {
|
|
85
|
+
headers: {
|
|
86
|
+
accept: 'application/json;odata.metadata=none',
|
|
87
|
+
'content-type': 'application/json'
|
|
88
|
+
},
|
|
89
|
+
responseType: 'json',
|
|
90
|
+
url: `${requestUrl}/onlineMeetings`,
|
|
91
|
+
data: requestData
|
|
92
|
+
};
|
|
93
|
+
return request.post(requestOptions);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
_TeamsMeetingAddCommand_instances = new WeakSet(), _TeamsMeetingAddCommand_initTelemetry = function _TeamsMeetingAddCommand_initTelemetry() {
|
|
97
|
+
this.telemetry.push((args) => {
|
|
98
|
+
Object.assign(this.telemetryProperties, {
|
|
99
|
+
startTime: typeof args.options.startTime !== 'undefined',
|
|
100
|
+
endTime: typeof args.options.endTime !== 'undefined',
|
|
101
|
+
subject: typeof args.options.subject !== 'undefined',
|
|
102
|
+
participantUserNames: typeof args.options.participantUserNames !== 'undefined',
|
|
103
|
+
organizerEmail: typeof args.options.organizerEmail !== 'undefined',
|
|
104
|
+
recordAutomatically: !!args.options.recordAutomatically
|
|
105
|
+
});
|
|
106
|
+
});
|
|
107
|
+
}, _TeamsMeetingAddCommand_initOptions = function _TeamsMeetingAddCommand_initOptions() {
|
|
108
|
+
this.options.unshift({
|
|
109
|
+
option: '-s, --startTime [startTime]'
|
|
110
|
+
}, {
|
|
111
|
+
option: '-e, --endTime [endTime]'
|
|
112
|
+
}, {
|
|
113
|
+
option: '--subject [subject]'
|
|
114
|
+
}, {
|
|
115
|
+
option: '-p, --participantUserNames [participantUserNames]'
|
|
116
|
+
}, {
|
|
117
|
+
option: '--organizerEmail [organizerEmail]'
|
|
118
|
+
}, {
|
|
119
|
+
option: '-r, --recordAutomatically'
|
|
120
|
+
});
|
|
121
|
+
}, _TeamsMeetingAddCommand_initValidators = function _TeamsMeetingAddCommand_initValidators() {
|
|
122
|
+
this.validators.push(async (args) => {
|
|
123
|
+
if (args.options.startTime && !validation.isValidISODateTime(args.options.startTime)) {
|
|
124
|
+
return `'${args.options.startTime}' is not a valid ISO date string for startTime.`;
|
|
125
|
+
}
|
|
126
|
+
if (args.options.endTime && !validation.isValidISODateTime(args.options.endTime)) {
|
|
127
|
+
return `'${args.options.endTime}' is not a valid ISO date string for endTime.`;
|
|
128
|
+
}
|
|
129
|
+
if (args.options.startTime && args.options.endTime && new Date(args.options.startTime) >= new Date(args.options.endTime)) {
|
|
130
|
+
return 'The startTime value must be before endTime.';
|
|
131
|
+
}
|
|
132
|
+
if (args.options.startTime && new Date() >= new Date(args.options.startTime)) {
|
|
133
|
+
return 'The startTime value must be in the future.';
|
|
134
|
+
}
|
|
135
|
+
if (args.options.endTime && new Date() >= new Date(args.options.endTime)) {
|
|
136
|
+
return 'The endTime value must be in the future.';
|
|
137
|
+
}
|
|
138
|
+
if (args.options.participantUserNames) {
|
|
139
|
+
const participants = args.options.participantUserNames.trim().toLowerCase().split(',').filter(e => e && e !== '');
|
|
140
|
+
if (!participants || participants.length === 0 || participants.some(e => !validation.isValidUserPrincipalName(e))) {
|
|
141
|
+
return `'${args.options.participantUserNames}' contains one or more invalid UPN.`;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
if (args.options.organizerEmail && !validation.isValidUserPrincipalName(args.options.organizerEmail)) {
|
|
145
|
+
return `'${args.options.organizerEmail}' is not a valid email for organizerEmail.`;
|
|
146
|
+
}
|
|
147
|
+
return true;
|
|
148
|
+
});
|
|
149
|
+
};
|
|
150
|
+
export default new TeamsMeetingAddCommand();
|
|
151
|
+
//# sourceMappingURL=meeting-add.js.map
|
|
@@ -27,11 +27,15 @@ class TeamsUserAppRemoveCommand extends GraphCommand {
|
|
|
27
27
|
}
|
|
28
28
|
async commandAction(logger, args) {
|
|
29
29
|
const removeApp = async () => {
|
|
30
|
+
const appId = await this.getAppId(args);
|
|
30
31
|
// validation ensures that here we have either userId or userName
|
|
31
32
|
const userId = (args.options.userId ?? args.options.userName);
|
|
32
33
|
const endpoint = `${this.resource}/v1.0`;
|
|
34
|
+
if (this.verbose) {
|
|
35
|
+
await logger.logToStderr(`Removing app with ID ${args.options.id} for user ${args.options.userId}`);
|
|
36
|
+
}
|
|
33
37
|
const requestOptions = {
|
|
34
|
-
url: `${endpoint}/users/${formatting.encodeQueryParameter(userId)}/teamwork/installedApps/${
|
|
38
|
+
url: `${endpoint}/users/${formatting.encodeQueryParameter(userId)}/teamwork/installedApps/${appId}`,
|
|
35
39
|
headers: {
|
|
36
40
|
'accept': 'application/json;odata.metadata=none'
|
|
37
41
|
},
|
|
@@ -54,10 +58,34 @@ class TeamsUserAppRemoveCommand extends GraphCommand {
|
|
|
54
58
|
}
|
|
55
59
|
}
|
|
56
60
|
}
|
|
61
|
+
async getAppId(args) {
|
|
62
|
+
if (args.options.id) {
|
|
63
|
+
return args.options.id;
|
|
64
|
+
}
|
|
65
|
+
const requestOptions = {
|
|
66
|
+
url: `${this.resource}/v1.0/users/${args.options.userId}/teamwork/installedApps?$expand=teamsAppDefinition&$filter=teamsAppDefinition/displayName eq '${formatting.encodeQueryParameter(args.options.name)}'`,
|
|
67
|
+
headers: {
|
|
68
|
+
accept: 'application/json;odata.metadata=none'
|
|
69
|
+
},
|
|
70
|
+
responseType: 'json'
|
|
71
|
+
};
|
|
72
|
+
const response = await request.get(requestOptions);
|
|
73
|
+
if (response.value.length === 1) {
|
|
74
|
+
return response.value[0].id;
|
|
75
|
+
}
|
|
76
|
+
if (response.value.length === 0) {
|
|
77
|
+
throw `The specified Teams app does not exist`;
|
|
78
|
+
}
|
|
79
|
+
const resultAsKeyValuePair = formatting.convertArrayToHashTable('id', response.value);
|
|
80
|
+
const result = (await Cli.handleMultipleResultsFound(`Multiple Teams apps with name '${args.options.name}' found.`, resultAsKeyValuePair));
|
|
81
|
+
return result.id;
|
|
82
|
+
}
|
|
57
83
|
}
|
|
58
84
|
_TeamsUserAppRemoveCommand_instances = new WeakSet(), _TeamsUserAppRemoveCommand_initTelemetry = function _TeamsUserAppRemoveCommand_initTelemetry() {
|
|
59
85
|
this.telemetry.push((args) => {
|
|
60
86
|
Object.assign(this.telemetryProperties, {
|
|
87
|
+
id: typeof args.options.id !== 'undefined',
|
|
88
|
+
name: typeof args.options.name !== 'undefined',
|
|
61
89
|
userId: typeof args.options.userId !== 'undefined',
|
|
62
90
|
userName: typeof args.options.userName !== 'undefined',
|
|
63
91
|
force: (!!args.options.force).toString()
|
|
@@ -65,7 +93,9 @@ _TeamsUserAppRemoveCommand_instances = new WeakSet(), _TeamsUserAppRemoveCommand
|
|
|
65
93
|
});
|
|
66
94
|
}, _TeamsUserAppRemoveCommand_initOptions = function _TeamsUserAppRemoveCommand_initOptions() {
|
|
67
95
|
this.options.unshift({
|
|
68
|
-
option: '--id
|
|
96
|
+
option: '--id [id]'
|
|
97
|
+
}, {
|
|
98
|
+
option: '--name [name]'
|
|
69
99
|
}, {
|
|
70
100
|
option: '--userId [userId]'
|
|
71
101
|
}, {
|
|
@@ -84,6 +114,7 @@ _TeamsUserAppRemoveCommand_instances = new WeakSet(), _TeamsUserAppRemoveCommand
|
|
|
84
114
|
return true;
|
|
85
115
|
});
|
|
86
116
|
}, _TeamsUserAppRemoveCommand_initOptionSets = function _TeamsUserAppRemoveCommand_initOptionSets() {
|
|
117
|
+
this.optionSets.push({ options: ['id', 'name'] });
|
|
87
118
|
this.optionSets.push({ options: ['userId', 'userName'] });
|
|
88
119
|
};
|
|
89
120
|
export default new TeamsUserAppRemoveCommand();
|
|
@@ -27,9 +27,10 @@ export default {
|
|
|
27
27
|
FUNSETTINGS_SET: `${prefix} funsettings set`,
|
|
28
28
|
GUESTSETTINGS_LIST: `${prefix} guestsettings list`,
|
|
29
29
|
GUESTSETTINGS_SET: `${prefix} guestsettings set`,
|
|
30
|
-
|
|
30
|
+
MEETING_ADD: `${prefix} meeting add`,
|
|
31
31
|
MEETING_GET: `${prefix} meeting get`,
|
|
32
32
|
MEETING_LIST: `${prefix} meeting list`,
|
|
33
|
+
MEETING_ATTENDANCEREPORT_LIST: `${prefix} meeting attendancereport list`,
|
|
33
34
|
MEETING_TRANSCRIPT_LIST: `${prefix} meeting transcript list`,
|
|
34
35
|
MEMBERSETTINGS_LIST: `${prefix} membersettings list`,
|
|
35
36
|
MEMBERSETTINGS_SET: `${prefix} membersettings set`,
|
package/dist/telemetry.js
CHANGED
|
@@ -29,14 +29,6 @@ export const telemetry = {
|
|
|
29
29
|
commandName,
|
|
30
30
|
properties
|
|
31
31
|
});
|
|
32
|
-
},
|
|
33
|
-
trackException: (exception) => {
|
|
34
|
-
if (Cli.getInstance().getSettingWithDefaultValue(settingsNames.disableTelemetry, false)) {
|
|
35
|
-
return;
|
|
36
|
-
}
|
|
37
|
-
trackTelemetry({
|
|
38
|
-
exception
|
|
39
|
-
});
|
|
40
32
|
}
|
|
41
33
|
};
|
|
42
34
|
//# sourceMappingURL=telemetry.js.map
|
package/dist/utils/validation.js
CHANGED
|
@@ -7,8 +7,11 @@ export const validation = {
|
|
|
7
7
|
return false;
|
|
8
8
|
}
|
|
9
9
|
const guidRegEx = new RegExp(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i);
|
|
10
|
-
// verify if the guid is a valid guid. @meid will be replaced in a later
|
|
11
|
-
|
|
10
|
+
// verify if the guid is a valid guid. @meid will be replaced in a later
|
|
11
|
+
// stage with the actual user id of the logged in user
|
|
12
|
+
// we also need to make it toString in case the args is resolved as number
|
|
13
|
+
// or boolean
|
|
14
|
+
return guidRegEx.test(guid) || guid.toString().toLowerCase().trim() === '@meid';
|
|
12
15
|
},
|
|
13
16
|
isValidTeamsChannelId(guid) {
|
|
14
17
|
const guidRegEx = new RegExp(/^19:[0-9a-zA-Z-_]+@thread\.(skype|tacv2)$/i);
|
|
@@ -14,6 +14,11 @@ m365 aad group list [options]
|
|
|
14
14
|
|
|
15
15
|
## Options
|
|
16
16
|
|
|
17
|
+
```md definition-list
|
|
18
|
+
`--type [type]`
|
|
19
|
+
: Filter the results to only groups of a given type. Allowed values: `microsoft365`, `security`, `distribution`, `mailEnabledSecurity`. By default, all groups are listed.
|
|
20
|
+
```
|
|
21
|
+
|
|
17
22
|
<Global />
|
|
18
23
|
|
|
19
24
|
## Examples
|
|
@@ -24,6 +29,12 @@ Lists all groups defined in Azure Active Directory.
|
|
|
24
29
|
m365 aad group list
|
|
25
30
|
```
|
|
26
31
|
|
|
32
|
+
List all security groups defined in Azure Active Directory.
|
|
33
|
+
|
|
34
|
+
```sh
|
|
35
|
+
m365 aad group list --type security
|
|
36
|
+
```
|
|
37
|
+
|
|
27
38
|
## Response
|
|
28
39
|
|
|
29
40
|
<Tabs>
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import Global from '/docs/cmd/_global.mdx';
|
|
2
|
+
|
|
3
|
+
# external connection doctor
|
|
4
|
+
|
|
5
|
+
Checks if the external connection is correctly configured for use with a specified user experience in Microsoft 365
|
|
6
|
+
|
|
7
|
+
## Usage
|
|
8
|
+
|
|
9
|
+
```sh
|
|
10
|
+
m365 external connection doctor [options]
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Options
|
|
14
|
+
|
|
15
|
+
```md definition-list
|
|
16
|
+
`-i, --id <id>`
|
|
17
|
+
: The ID of the external connection to check.
|
|
18
|
+
|
|
19
|
+
`--ux [ux]`
|
|
20
|
+
: Microsoft 365 experience for which to check compatibility. Allowed values `copilot`, `search`, `all` (default)
|
|
21
|
+
|
|
22
|
+
<Global />
|
|
23
|
+
|
|
24
|
+
## Remarks
|
|
25
|
+
|
|
26
|
+
The `external connection doctor` command runs several automated checks to verify if an external connection is correctly configured for use with a user experience in Microsoft 365.
|
|
27
|
+
|
|
28
|
+
Check|ID|UX|Type|Description
|
|
29
|
+
-----|--|:--:|--|------------
|
|
30
|
+
Required semantic labels|`copilotRequiredSemanticLabels`|Copilot|Required|Checks if the external connection schema has the required semantic labels configured: `title`, `url` and `iconUrl`
|
|
31
|
+
Searchable properties|Copilot|`searchableProperties`|Required|Checks if the external connection schema has at least one searchable property
|
|
32
|
+
Items have content ingested|`contentIngested`|Copilot|Required|Checks if external items have content ingested
|
|
33
|
+
Connection configured for inline results|`enabledForInlineResults`|Copilot|Required (manual)|Check if the external connection is configured for inline results
|
|
34
|
+
Items have activities recorded|`itemsHaveActivities`|Copilot|Recommended (manual)|Check if external items have activities recorded
|
|
35
|
+
Meaningful connection name and description|`meaningfulNameAndDescription`|Copilot|Required (manual)|Check if the external connection has a meaningful name and description
|
|
36
|
+
Semantic labels|`semanticLabels`|Search|Recommended|Checks if the external connection schema uses semantic labels
|
|
37
|
+
Searchable properties|`searchableProperties`|Search|Recommended|Checks if the external connection schema has at least one searchable property
|
|
38
|
+
Result types|`resultType`|Search|Recommended|Checks if the external connection has a result type configured
|
|
39
|
+
Items have content ingested|`contentIngested`|Search|Recommended|Checks if external items have content ingested
|
|
40
|
+
Items have activities recorded|`itemsHaveActivities`|Search|Recommended|Check if external items have activities recorded
|
|
41
|
+
urlToItemResolver configured|`urlToItemResolver`|All|Recommended|Checks if the external connection has at least one urlToItemResolver configured
|
|
42
|
+
|
|
43
|
+
Required checks must pass for the external connection to be compatible with the specified user experience. Recommended checks are optional, but recommended for optimal user experience.
|
|
44
|
+
|
|
45
|
+
Some checks must be done manually, because there are no APIs available to verify the configuration automatically.
|
|
46
|
+
|
|
47
|
+
When you check the compatibility with all UXs, and there are multiple checks with the same ID, the command will use the first matching check, following the order listed above.
|
|
48
|
+
|
|
49
|
+
## Examples
|
|
50
|
+
|
|
51
|
+
Checks if the external connection with the specified ID is correctly configured for use with Copilot for Microsoft 365.
|
|
52
|
+
|
|
53
|
+
```sh
|
|
54
|
+
m365 external connection doctor --id contosoproducts --ux copilot
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Response
|
|
58
|
+
|
|
59
|
+
<Tabs>
|
|
60
|
+
<TabItem value="JSON">
|
|
61
|
+
|
|
62
|
+
```json
|
|
63
|
+
[
|
|
64
|
+
{
|
|
65
|
+
"id": "loadExternalConnection",
|
|
66
|
+
"text": "Load connection",
|
|
67
|
+
"type": "required",
|
|
68
|
+
"status": "passed"
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
"id": "loadSchema",
|
|
72
|
+
"text": "Load schema",
|
|
73
|
+
"type": "required",
|
|
74
|
+
"status": "passed"
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
"id": "copilotRequiredSemanticLabels",
|
|
78
|
+
"text": "Required semantic labels",
|
|
79
|
+
"type": "required",
|
|
80
|
+
"errorMessage": "Missing label iconUrl",
|
|
81
|
+
"status": "failed"
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
"id": "searchableProperties",
|
|
85
|
+
"text": "Searchable properties",
|
|
86
|
+
"type": "required",
|
|
87
|
+
"status": "passed"
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
"id": "contentIngested",
|
|
91
|
+
"text": "Items have content ingested",
|
|
92
|
+
"type": "required",
|
|
93
|
+
"status": "passed"
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
"id": "enabledForInlineResults",
|
|
97
|
+
"text": "Connection configured for inline results",
|
|
98
|
+
"type": "required",
|
|
99
|
+
"status": "manual"
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
"id": "itemsHaveActivities",
|
|
103
|
+
"text": "Items have activities recorded",
|
|
104
|
+
"type": "recommended",
|
|
105
|
+
"status": "manual"
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
"id": "meaningfulNameAndDescription",
|
|
109
|
+
"text": "Meaningful connection name and description",
|
|
110
|
+
"type": "required",
|
|
111
|
+
"status": "manual"
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
"id": "urlToItemResolver",
|
|
115
|
+
"text": "urlToItemResolver configured",
|
|
116
|
+
"type": "recommended",
|
|
117
|
+
"status": "passed"
|
|
118
|
+
}
|
|
119
|
+
]
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
</TabItem>
|
|
123
|
+
<TabItem value="Text">
|
|
124
|
+
|
|
125
|
+
```text
|
|
126
|
+
✔ Load connection
|
|
127
|
+
✔ Load schema
|
|
128
|
+
✖ Required semantic labels: Missing label iconUrl
|
|
129
|
+
✔ Searchable properties
|
|
130
|
+
✔ Items have content ingested
|
|
131
|
+
ℹ Connection configured for inline results (manual)
|
|
132
|
+
ℹ Items have activities recorded (manual)
|
|
133
|
+
ℹ Meaningful connection name and description (manual)
|
|
134
|
+
✔ urlToItemResolver configured
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
</TabItem>
|
|
138
|
+
<TabItem value="CSV">
|
|
139
|
+
|
|
140
|
+
```csv
|
|
141
|
+
id,text,type,status,errorMessage
|
|
142
|
+
loadExternalConnection,Load connection,required,passed,
|
|
143
|
+
loadSchema,Load schema,required,passed,
|
|
144
|
+
copilotRequiredSemanticLabels,Required semantic labels,required,failed,Missing label iconUrl
|
|
145
|
+
searchableProperties,Searchable properties,required,passed,
|
|
146
|
+
contentIngested,Items have content ingested,required,passed,
|
|
147
|
+
enabledForInlineResults,Connection configured for inline results,required,manual,
|
|
148
|
+
itemsHaveActivities,Items have activities recorded,recommended,manual,
|
|
149
|
+
meaningfulNameAndDescription,Meaningful connection name and description,required,manual,
|
|
150
|
+
urlToItemResolver,urlToItemResolver configured,recommended,passed,
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
</TabItem>
|
|
154
|
+
<TabItem value="Markdown">
|
|
155
|
+
|
|
156
|
+
```md
|
|
157
|
+
# external connection doctor --id "msgraphdocs" --ux "copilot"
|
|
158
|
+
|
|
159
|
+
Date: 11/23/2023
|
|
160
|
+
|
|
161
|
+
Check|Type|Status|Error message
|
|
162
|
+
:----|:--:|:----:|:------------
|
|
163
|
+
Load connection|required|passed|
|
|
164
|
+
Load schema|required|passed|
|
|
165
|
+
Required semantic labels|required|failed|Missing label iconUrl
|
|
166
|
+
Searchable properties|required|passed|
|
|
167
|
+
Items have content ingested|required|passed|
|
|
168
|
+
Connection configured for inline results|required|manual|
|
|
169
|
+
Items have activities recorded|recommended|manual|
|
|
170
|
+
Meaningful connection name and description|required|manual|
|
|
171
|
+
urlToItemResolver configured|recommended|passed|
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
</TabItem>
|
|
175
|
+
</Tabs>
|
|
176
|
+
|
|
177
|
+
## More information
|
|
178
|
+
|
|
179
|
+
- Microsoft Graph connector experiences: [https://learn.microsoft.com/graph/connecting-external-content-experiences](https://learn.microsoft.com/graph/connecting-external-content-experiences)
|