1
+ import assert from 'assert' ;
2
+ import sinon from 'sinon' ;
3
+ import { telemetry } from '../../../../telemetry.js' ;
4
+ import auth from '../../../../Auth.js' ;
5
+ import { cli } from '../../../../cli/cli.js' ;
6
+ import { CommandInfo } from '../../../../cli/CommandInfo.js' ;
7
+ import { Logger } from '../../../../cli/Logger.js' ;
8
+ import { CommandError } from '../../../../Command.js' ;
9
+ import request from '../../../../request.js' ;
10
+ import { pid } from '../../../../utils/pid.js' ;
11
+ import { sinonUtil } from '../../../../utils/sinonUtil.js' ;
12
+ import { session } from '../../../../utils/session.js' ;
13
+ import { accessToken } from '../../../../utils/accessToken.js' ;
14
+ import fs from 'fs' ;
15
+ import commands from '../../commands.js' ;
16
+ import command from './threatassessment-add.js' ;
17
+
18
+ describe ( commands . THREATASSESSMENT_ADD , ( ) => {
19
+
20
+ let log : string [ ] ;
21
+ let logger : Logger ;
22
+ let loggerLogSpy : sinon . SinonSpy ;
23
+ let commandInfo : CommandInfo ;
24
+
25
+ before ( ( ) => {
26
+ sinon . stub ( auth , 'restoreAuth' ) . resolves ( ) ;
27
+ sinon . stub ( telemetry , 'trackEvent' ) . returns ( ) ;
28
+ sinon . stub ( pid , 'getProcessName' ) . returns ( '' ) ;
29
+ sinon . stub ( session , 'getId' ) . returns ( '' ) ;
30
+ auth . service . connected = true ;
31
+ auth . service . accessTokens [ ( command as any ) . resource ] = {
32
+ accessToken : 'abc' ,
33
+ expiresOn : new Date ( )
34
+ } ;
35
+ commandInfo = cli . getCommandInfo ( command ) ;
36
+ } ) ;
37
+
38
+ beforeEach ( ( ) => {
39
+ log = [ ] ;
40
+ logger = {
41
+ log : async ( msg : string ) => {
42
+ log . push ( msg ) ;
43
+ } ,
44
+ logRaw : async ( msg : string ) => {
45
+ log . push ( msg ) ;
46
+ } ,
47
+ logToStderr : async ( msg : string ) => {
48
+ log . push ( msg ) ;
49
+ }
50
+ } ;
51
+ loggerLogSpy = sinon . spy ( logger , 'log' ) ;
52
+ ( command as any ) . items = [ ] ;
53
+ sinon . stub ( accessToken , 'isAppOnlyAccessToken' ) . returns ( false ) ;
54
+ sinon . stub ( fs , 'existsSync' ) . returns ( true ) ;
55
+ sinon . stub ( fs , 'readFileSync' ) . returns ( 'VGhpcyBpcyBhIHRlc3QgZmlsZQ==' ) ;
56
+ } ) ;
57
+
58
+ afterEach ( ( ) => {
59
+ sinonUtil . restore ( [
60
+ accessToken . isAppOnlyAccessToken ,
61
+ fs . existsSync ,
62
+ fs . readFileSync ,
63
+ request . post
64
+ ] ) ;
65
+ } ) ;
66
+
67
+ after ( ( ) => {
68
+ sinon . restore ( ) ;
69
+ auth . service . connected = false ;
70
+ auth . service . accessTokens = { } ;
71
+ } ) ;
72
+
73
+ it ( 'has correct name' , ( ) => {
74
+ assert . strictEqual ( command . name . startsWith ( commands . THREATASSESSMENT_ADD ) , true ) ;
75
+ } ) ;
76
+
77
+ it ( 'has a description' , ( ) => {
78
+ assert . notStrictEqual ( command . description , null ) ;
79
+ } ) ;
80
+
81
+ it ( 'creates a file assessment request' , async ( ) => {
82
+ const fileThreatAssessmentRequest = {
83
+ '@odata.context' : 'https://graph.microsoft.com/v1.0/$metadata#informationProtection/threatAssessmentRequests/$entity' ,
84
+ '@odata.type' : '#microsoft.graph.fileAssessmentRequest' ,
85
+ 'id' : '18406a56-7209-4720-a250-08d772fccdaa' ,
86
+ 'createdDateTime' : '2019-11-27T05:44:00.4051536Z' ,
87
+ 'contentType' : 'file' ,
88
+ 'expectedAssessment' : 'block' ,
89
+ 'category' : 'malware' ,
90
+ 'status' : 'completed' ,
91
+ 'requestSource' : 'administrator' ,
92
+ 'fileName' : 'illegalfile.txt' ,
93
+ 'contentData' : '' ,
94
+ 'createdBy' : {
95
+ 'user' : {
96
+ 'id' : 'c52ce8db-3e4b-4181-93c4-7d6b6bffaf60' ,
97
+ 'displayName' : 'John Doe'
98
+ }
99
+ }
100
+ } ;
101
+
102
+ const postStub = sinon . stub ( request , 'post' ) . callsFake ( async ( opts ) => {
103
+ if ( opts . url === `https://graph.microsoft.com/v1.0/informationProtection/threatAssessmentRequests` ) {
104
+ return fileThreatAssessmentRequest ;
105
+ }
106
+
107
+ throw 'Invalid request' ;
108
+ } ) ;
109
+
110
+ await command . action ( logger , { options : { type : 'file' , expectedAssessment : 'block' , category : 'malware' , path : 'C:\\Temp\\DummyFile.txt' , verbose : true } } ) ;
111
+ assert . strictEqual ( postStub . lastCall . args [ 0 ] . data [ '@odata.type' ] , '#microsoft.graph.fileAssessmentRequest' ) ;
112
+ assert ( loggerLogSpy . calledWith ( fileThreatAssessmentRequest ) ) ;
113
+ } ) ;
114
+
115
+ it ( 'creates an url assessment request' , async ( ) => {
116
+ const urlThreatAssessmentRequest = {
117
+ '@odata.context' : 'https://graph.microsoft.com/v1.0/$metadata#informationProtection/threatAssessmentRequests/$entity' ,
118
+ '@odata.type' : '#microsoft.graph.urlAssessmentRequest' ,
119
+ 'id' : '8d87d2b2-ca4d-422c-f8df-08d774a5c9ac' ,
120
+ 'createdDateTime' : '2019-11-29T08:26:09.8196703Z' ,
121
+ 'contentType' : 'url' ,
122
+ 'expectedAssessment' : 'block' ,
123
+ 'category' : 'phishing' ,
124
+ 'status' : 'pending' ,
125
+ 'requestSource' : 'administrator' ,
126
+ 'url' : 'http://test.com' ,
127
+ 'createdBy' : {
128
+ 'user' : {
129
+ 'id' : 'c52ce8db-3e4b-4181-93c4-7d6b6bffaf60' ,
130
+ 'displayName' : 'John Doe'
131
+ }
132
+ }
133
+ } ;
134
+
135
+ const postStub = sinon . stub ( request , 'post' ) . callsFake ( async ( opts ) => {
136
+ if ( opts . url === `https://graph.microsoft.com/v1.0/informationProtection/threatAssessmentRequests` ) {
137
+ return urlThreatAssessmentRequest ;
138
+ }
139
+
140
+ throw 'Invalid request' ;
141
+ } ) ;
142
+
143
+ await command . action ( logger , { options : { type : 'url' , expectedAssessment : 'block' , category : 'phishing' , url : 'https://phisingurl.be' , verbose : true } } ) ;
144
+ assert . strictEqual ( postStub . lastCall . args [ 0 ] . data [ '@odata.type' ] , '#microsoft.graph.urlAssessmentRequest' ) ;
145
+ assert ( loggerLogSpy . calledWith ( urlThreatAssessmentRequest ) ) ;
146
+ } ) ;
147
+
148
+ it ( 'passes validation if all options are passed propertly' , async ( ) => {
149
+ const actual = await command . validate ( { options : { type : 'url' , expectedAssessment : 'block' , category : 'spam' , url : 'https://pnp.github.io/cli-microsoft365/' } } , commandInfo ) ;
150
+ assert . strictEqual ( actual , true ) ;
151
+ } ) ;
152
+
153
+ it ( 'fails validation if type is not a valid type' , async ( ) => {
154
+ const actual = await command . validate ( { options : { type : 'invalid' , expectedAssessment : 'block' , category : 'spam' , url : 'https://pnp.github.io/cli-microsoft365/' } } , commandInfo ) ;
155
+ assert . notStrictEqual ( actual , true ) ;
156
+ } ) ;
157
+
158
+ it ( 'fails validation if expectedAssessment is not a valid expectedAssessment' , async ( ) => {
159
+ const actual = await command . validate ( { options : { type : 'url' , expectedAssessment : 'invalid' , category : 'spam' , url : 'https://pnp.github.io/cli-microsoft365/' } } , commandInfo ) ;
160
+ assert . notStrictEqual ( actual , true ) ;
161
+ } ) ;
162
+
163
+ it ( 'fails validation if category is not a valid category' , async ( ) => {
164
+ const actual = await command . validate ( { options : { type : 'url' , expectedAssessment : 'block' , category : 'invalid' , url : 'https://pnp.github.io/cli-microsoft365/' } } , commandInfo ) ;
165
+ assert . notStrictEqual ( actual , true ) ;
166
+ } ) ;
167
+
168
+ it ( 'fails validation if path is specified and file does not exist' , async ( ) => {
169
+ sinonUtil . restore ( fs . existsSync ) ;
170
+ sinon . stub ( fs , 'existsSync' ) . returns ( false ) ;
171
+ const actual = await command . validate ( { options : { type : 'file' , expectedAssessment : 'block' , category : 'malware' , path : 'C:\\Path\\That\\Does\\Not\\Exist' } } , commandInfo ) ;
172
+ assert . notStrictEqual ( actual , true ) ;
173
+ } ) ;
174
+
175
+ it ( 'throws an error when we execute the command using application permissions' , async ( ) => {
176
+ sinonUtil . restore ( accessToken . isAppOnlyAccessToken ) ;
177
+ sinon . stub ( accessToken , 'isAppOnlyAccessToken' ) . returns ( true ) ;
178
+ await assert . rejects ( command . action ( logger , { options : { type : 'url' , expectedAssessment : 'block' , category : 'spam' , url : 'https://pnp.github.io/cli-microsoft365/' } } ) ,
179
+ new CommandError ( 'This command currently does not support app only permissions.' ) ) ;
180
+ } ) ;
181
+ } ) ;
0 commit comments