@adobe/ccweb-add-on-ssl 2.5.0 → 3.0.0
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/.mocharc.json +9 -2
- package/README.md +5 -4
- package/bin/run.js +3 -2
- package/dist/AnalyticsMarkers.d.ts +5 -2
- package/dist/AnalyticsMarkers.d.ts.map +1 -1
- package/dist/AnalyticsMarkers.js +3 -0
- package/dist/app/CommandExecutor.d.ts +1 -1
- package/dist/app/CommandExecutor.d.ts.map +1 -1
- package/dist/app/PurgeCommandExecutor.d.ts +53 -0
- package/dist/app/PurgeCommandExecutor.d.ts.map +1 -0
- package/dist/app/PurgeCommandExecutor.js +125 -0
- package/dist/app/SSLReader.d.ts +2 -1
- package/dist/app/SSLReader.d.ts.map +1 -1
- package/dist/app/SetupCommandExecutor.d.ts.map +1 -1
- package/dist/app/SetupCommandExecutor.js +10 -7
- package/dist/app/WxpSSLReader.d.ts +8 -1
- package/dist/app/WxpSSLReader.d.ts.map +1 -1
- package/dist/app/WxpSSLReader.js +59 -5
- package/dist/app/index.d.ts +2 -1
- package/dist/app/index.d.ts.map +1 -1
- package/dist/app/index.js +2 -1
- package/dist/commands/purge.d.ts +41 -0
- package/dist/commands/purge.d.ts.map +1 -0
- package/dist/commands/purge.js +56 -0
- package/dist/commands/setup.d.ts +5 -10
- package/dist/commands/setup.d.ts.map +1 -1
- package/dist/commands/setup.js +5 -32
- package/dist/config/inversify.config.d.ts +2 -1
- package/dist/config/inversify.config.d.ts.map +1 -1
- package/dist/config/inversify.config.js +6 -1
- package/dist/config/inversify.types.d.ts.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/models/Types.d.ts +0 -1
- package/dist/models/Types.d.ts.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +14 -12
- package/src/AnalyticsMarkers.ts +5 -2
- package/src/app/CommandExecutor.ts +1 -1
- package/src/app/PurgeCommandExecutor.ts +144 -0
- package/src/app/SSLReader.ts +2 -1
- package/src/app/SetupCommandExecutor.ts +10 -7
- package/src/app/WxpSSLReader.ts +71 -5
- package/src/app/index.ts +2 -1
- package/src/commands/purge.ts +72 -0
- package/src/commands/setup.ts +12 -40
- package/src/config/inversify.config.ts +9 -2
- package/src/config/inversify.types.ts +5 -1
- package/src/index.ts +2 -0
- package/src/test/app/PurgeCommandExecutor.spec.ts +195 -0
- package/src/test/app/SetupCommandExecutor.spec.ts +141 -34
- package/src/test/app/WxpSSLReader.spec.ts +107 -33
- package/src/test/commands/command.spec.ts +108 -0
- package/src/test/commands/purge.spec.ts +132 -0
- package/src/test/commands/setup.spec.ts +28 -29
- package/tsconfig.json +3 -1
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
/********************************************************************************
|
|
2
|
+
* MIT License
|
|
3
|
+
|
|
4
|
+
* © Copyright 2025 Adobe. All rights reserved.
|
|
5
|
+
|
|
6
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
|
+
* of this software and associated documentation files (the "Software"), to deal
|
|
8
|
+
* in the Software without restriction, including without limitation the rights
|
|
9
|
+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
10
|
+
* copies of the Software, and to permit persons to whom the Software is
|
|
11
|
+
* furnished to do so, subject to the following conditions:
|
|
12
|
+
*
|
|
13
|
+
* The above copyright notice and this permission notice shall be included in all
|
|
14
|
+
* copies or substantial portions of the Software.
|
|
15
|
+
*
|
|
16
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
17
|
+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
18
|
+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
19
|
+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
20
|
+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
21
|
+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
22
|
+
* SOFTWARE.
|
|
23
|
+
********************************************************************************/
|
|
24
|
+
|
|
25
|
+
import type { AnalyticsService } from "@adobe/ccweb-add-on-analytics";
|
|
26
|
+
import { PreferenceJson, type Logger, type Preferences } from "@adobe/ccweb-add-on-core";
|
|
27
|
+
import devcert from "@adobe/ccweb-add-on-devcert";
|
|
28
|
+
import { assert } from "chai";
|
|
29
|
+
import chalk from "chalk";
|
|
30
|
+
import fs from "fs-extra";
|
|
31
|
+
import "mocha";
|
|
32
|
+
import path from "path";
|
|
33
|
+
import prompts from "prompts";
|
|
34
|
+
import type { SinonSandbox } from "sinon";
|
|
35
|
+
import sinon from "sinon";
|
|
36
|
+
import type { StubbedInstance } from "ts-sinon";
|
|
37
|
+
import { stubInterface } from "ts-sinon";
|
|
38
|
+
import { AnalyticsErrorMarkers, AnalyticsSuccessMarkers } from "../../AnalyticsMarkers.js";
|
|
39
|
+
import type { CommandExecutor } from "../../app/index.js";
|
|
40
|
+
import { PurgeCommandExecutor } from "../../app/index.js";
|
|
41
|
+
import { SSLRemoveOption } from "../../models/index.js";
|
|
42
|
+
|
|
43
|
+
describe("PurgeCommandExecutor", () => {
|
|
44
|
+
describe("execute", () => {
|
|
45
|
+
let sandbox: SinonSandbox;
|
|
46
|
+
|
|
47
|
+
let preferences: StubbedInstance<Preferences>;
|
|
48
|
+
let analyticsService: StubbedInstance<AnalyticsService>;
|
|
49
|
+
let logger: StubbedInstance<Logger>;
|
|
50
|
+
|
|
51
|
+
let commandExecutor: CommandExecutor;
|
|
52
|
+
|
|
53
|
+
beforeEach(() => {
|
|
54
|
+
sandbox = sinon.createSandbox();
|
|
55
|
+
|
|
56
|
+
preferences = stubInterface();
|
|
57
|
+
analyticsService = stubInterface();
|
|
58
|
+
logger = stubInterface();
|
|
59
|
+
|
|
60
|
+
commandExecutor = new PurgeCommandExecutor(preferences, analyticsService, logger);
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
afterEach(() => {
|
|
64
|
+
sandbox.restore();
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
const shouldPurgePrompt = {
|
|
68
|
+
type: "select",
|
|
69
|
+
name: "purgeConfirmation",
|
|
70
|
+
message: promptMessage("Are you sure you want to remove all SSL artifacts from your system"),
|
|
71
|
+
choices: [
|
|
72
|
+
{ title: promptMessageOption("No, keep existing SSL artifacts"), value: SSLRemoveOption.Keep },
|
|
73
|
+
{ title: promptMessageOption("Yes, remove all SSL artifacts"), value: SSLRemoveOption.Remove }
|
|
74
|
+
],
|
|
75
|
+
initial: 0
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
it("should prompt on whether to remove SSL artifacts and log warning and exit when user does not select any option.", async () => {
|
|
79
|
+
const promptStub = sandbox.stub(prompts, "prompt");
|
|
80
|
+
promptStub.withArgs(shouldPurgePrompt).resolves({ purgeConfirmation: undefined });
|
|
81
|
+
|
|
82
|
+
analyticsService.postEvent.resolves();
|
|
83
|
+
|
|
84
|
+
await commandExecutor.execute();
|
|
85
|
+
|
|
86
|
+
assert.equal(
|
|
87
|
+
analyticsService.postEvent.calledOnceWith(
|
|
88
|
+
AnalyticsErrorMarkers.ERROR_SSL_PURGE,
|
|
89
|
+
"SSL purge option is not specified.",
|
|
90
|
+
false
|
|
91
|
+
),
|
|
92
|
+
true
|
|
93
|
+
);
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
it("should prompt on whether to remove SSL artifacts and exit when user chooses to keep the existing.", async () => {
|
|
97
|
+
const promptStub = sandbox.stub(prompts, "prompt");
|
|
98
|
+
promptStub.withArgs(shouldPurgePrompt).resolves({ purgeConfirmation: SSLRemoveOption.Keep });
|
|
99
|
+
|
|
100
|
+
await commandExecutor.execute();
|
|
101
|
+
|
|
102
|
+
assert.equal(analyticsService.postEvent.notCalled, true);
|
|
103
|
+
assert.equal(logger.information.notCalled, true);
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
it("should prompt on whether to remove SSL artifacts and remove both custom and WXP SSL artifacts when user chooses to remove.", async () => {
|
|
107
|
+
const promptStub = sandbox.stub(prompts, "prompt");
|
|
108
|
+
promptStub.withArgs(shouldPurgePrompt).resolves({ purgeConfirmation: SSLRemoveOption.Remove });
|
|
109
|
+
|
|
110
|
+
const preferenceJson = new PreferenceJson({
|
|
111
|
+
ssl: [
|
|
112
|
+
[
|
|
113
|
+
"localhost",
|
|
114
|
+
{
|
|
115
|
+
certificatePath: path.join("custom", "localhost", "certificate.cert"),
|
|
116
|
+
keyPath: path.join("custom", "localhost", "private-key.key")
|
|
117
|
+
}
|
|
118
|
+
],
|
|
119
|
+
[
|
|
120
|
+
"localhost.adobe.com",
|
|
121
|
+
{
|
|
122
|
+
certificatePath: path.join("custom", "localhost.adobe.com", "certificate.cert"),
|
|
123
|
+
keyPath: path.join("custom", "localhost.adobe.com", "private-key.key")
|
|
124
|
+
}
|
|
125
|
+
]
|
|
126
|
+
]
|
|
127
|
+
});
|
|
128
|
+
preferences.get.returns(preferenceJson);
|
|
129
|
+
|
|
130
|
+
const wxpSSLLocation = path.join("wxp", "devcert");
|
|
131
|
+
sandbox.stub(devcert, "location").returns(wxpSSLLocation);
|
|
132
|
+
|
|
133
|
+
const existsStub = sandbox.stub(fs, "existsSync");
|
|
134
|
+
existsStub.withArgs(wxpSSLLocation).returns(true);
|
|
135
|
+
|
|
136
|
+
const removeAllStub = sandbox.stub(devcert, "removeAll");
|
|
137
|
+
removeAllStub.returns();
|
|
138
|
+
|
|
139
|
+
await commandExecutor.execute();
|
|
140
|
+
|
|
141
|
+
assert.equal(
|
|
142
|
+
logger.information.calledOnceWith("Removing and invalidating all SSL artifacts from your system ...", {
|
|
143
|
+
prefix: "\n"
|
|
144
|
+
}),
|
|
145
|
+
true
|
|
146
|
+
);
|
|
147
|
+
assert.equal(
|
|
148
|
+
logger.message.getCall(0).calledWith("This may require you to enter your system's password,"),
|
|
149
|
+
true
|
|
150
|
+
);
|
|
151
|
+
assert.equal(
|
|
152
|
+
logger.message
|
|
153
|
+
.getCall(1)
|
|
154
|
+
.calledWith(
|
|
155
|
+
"so that the SSL certificate can be removed from your system's trusted certificate path."
|
|
156
|
+
),
|
|
157
|
+
true
|
|
158
|
+
);
|
|
159
|
+
assert.equal(
|
|
160
|
+
logger.message.getCall(2).calledWith("[If this takes longer than expected, please break and retry]"),
|
|
161
|
+
true
|
|
162
|
+
);
|
|
163
|
+
|
|
164
|
+
preferenceJson.ssl = undefined;
|
|
165
|
+
assert.equal(preferences.set.calledOnceWith(preferenceJson), true);
|
|
166
|
+
assert.equal(
|
|
167
|
+
analyticsService.postEvent
|
|
168
|
+
.getCall(0)
|
|
169
|
+
.calledWith(AnalyticsSuccessMarkers.SUCCESSFUL_SSL_MANUAL_PURGE, "", true),
|
|
170
|
+
true
|
|
171
|
+
);
|
|
172
|
+
|
|
173
|
+
assert.equal(removeAllStub.calledOnce, true);
|
|
174
|
+
assert.equal(
|
|
175
|
+
analyticsService.postEvent
|
|
176
|
+
.getCall(1)
|
|
177
|
+
.calledWith(AnalyticsSuccessMarkers.SUCCESSFUL_SSL_AUTOMATIC_PURGE, "", true),
|
|
178
|
+
true
|
|
179
|
+
);
|
|
180
|
+
|
|
181
|
+
assert.equal(
|
|
182
|
+
logger.success.calledWith("Removed all SSL artifacts.", { prefix: "\n", postfix: "\n" }),
|
|
183
|
+
true
|
|
184
|
+
);
|
|
185
|
+
});
|
|
186
|
+
});
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
function promptMessage(message: string): string {
|
|
190
|
+
return chalk.hex("#E59400")(message);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
function promptMessageOption(message: string): string {
|
|
194
|
+
return chalk.green.bold(message);
|
|
195
|
+
}
|
|
@@ -25,10 +25,10 @@
|
|
|
25
25
|
import type { AnalyticsService } from "@adobe/ccweb-add-on-analytics";
|
|
26
26
|
import type { Logger, Preferences } from "@adobe/ccweb-add-on-core";
|
|
27
27
|
import { ADD_ON_PREFERENCES_FILE, PreferenceJson } from "@adobe/ccweb-add-on-core";
|
|
28
|
+
import devcert from "@adobe/ccweb-add-on-devcert";
|
|
28
29
|
import chai, { assert, expect } from "chai";
|
|
29
30
|
import chaiAsPromised from "chai-as-promised";
|
|
30
31
|
import chalk from "chalk";
|
|
31
|
-
import devcert from "@adobe/ccweb-add-on-devcert";
|
|
32
32
|
import type { Stats } from "fs-extra";
|
|
33
33
|
import fs from "fs-extra";
|
|
34
34
|
import "mocha";
|
|
@@ -47,7 +47,7 @@ import { SSLRemoveOption, SSLSetupOption, SetupCommandOptions } from "../../mode
|
|
|
47
47
|
|
|
48
48
|
chai.use(chaiAsPromised);
|
|
49
49
|
|
|
50
|
-
describe("
|
|
50
|
+
describe("SetupCommandExecutor", () => {
|
|
51
51
|
let sandbox: SinonSandbox;
|
|
52
52
|
|
|
53
53
|
let preferences: StubbedInstance<Preferences>;
|
|
@@ -140,8 +140,6 @@ describe("SSLSetupCommandExecutor", () => {
|
|
|
140
140
|
|
|
141
141
|
analyticsService.postEvent.resolves();
|
|
142
142
|
|
|
143
|
-
logger.warning.returns();
|
|
144
|
-
|
|
145
143
|
const processExitStub = sandbox.stub(process, "exit");
|
|
146
144
|
|
|
147
145
|
const options = new SetupCommandOptions(hostname, true, false);
|
|
@@ -191,7 +189,6 @@ describe("SSLSetupCommandExecutor", () => {
|
|
|
191
189
|
|
|
192
190
|
analyticsService.postEvent.resolves();
|
|
193
191
|
|
|
194
|
-
logger.warning.returns();
|
|
195
192
|
logger.error.returns();
|
|
196
193
|
|
|
197
194
|
const processExitStub = sandbox.stub(process, "exit");
|
|
@@ -280,7 +277,6 @@ describe("SSLSetupCommandExecutor", () => {
|
|
|
280
277
|
|
|
281
278
|
analyticsService.postEvent.resolves();
|
|
282
279
|
|
|
283
|
-
logger.warning.returns();
|
|
284
280
|
logger.error.returns();
|
|
285
281
|
|
|
286
282
|
const processExitStub = sandbox.stub(process, "exit");
|
|
@@ -355,9 +351,6 @@ describe("SSLSetupCommandExecutor", () => {
|
|
|
355
351
|
|
|
356
352
|
analyticsService.postEvent.resolves();
|
|
357
353
|
|
|
358
|
-
logger.warning.returns();
|
|
359
|
-
logger.success.returns();
|
|
360
|
-
|
|
361
354
|
const existsStub = sandbox.stub(fs, "existsSync");
|
|
362
355
|
existsStub.withArgs(certificatePath).returns(true);
|
|
363
356
|
existsStub.withArgs(keyPath).returns(true);
|
|
@@ -422,10 +415,6 @@ describe("SSLSetupCommandExecutor", () => {
|
|
|
422
415
|
|
|
423
416
|
analyticsService.postEvent.resolves();
|
|
424
417
|
|
|
425
|
-
logger.warning.returns();
|
|
426
|
-
logger.success.returns();
|
|
427
|
-
logger.message.returns();
|
|
428
|
-
|
|
429
418
|
const options = new SetupCommandOptions(hostname, true, false);
|
|
430
419
|
await commandExecutor.execute(options);
|
|
431
420
|
|
|
@@ -444,7 +433,9 @@ describe("SSLSetupCommandExecutor", () => {
|
|
|
444
433
|
assert.equal(
|
|
445
434
|
logger.message
|
|
446
435
|
.getCall(0)
|
|
447
|
-
.calledWith(
|
|
436
|
+
.calledWith(
|
|
437
|
+
"This is only a one time step and may require you to enter your system's password,"
|
|
438
|
+
),
|
|
448
439
|
true
|
|
449
440
|
);
|
|
450
441
|
assert.equal(
|
|
@@ -505,7 +496,7 @@ describe("SSLSetupCommandExecutor", () => {
|
|
|
505
496
|
initial: 0
|
|
506
497
|
};
|
|
507
498
|
|
|
508
|
-
it("should prompt on whether to remove existing SSL and
|
|
499
|
+
it("should prompt on whether to remove existing SSL and exit when user does not select any option.", async () => {
|
|
509
500
|
const hostname = "localhost";
|
|
510
501
|
sslReader.isCustomSSL.withArgs(hostname).returns(true);
|
|
511
502
|
sslReader.isWxpSSL.withArgs(hostname).returns(false);
|
|
@@ -515,8 +506,6 @@ describe("SSLSetupCommandExecutor", () => {
|
|
|
515
506
|
|
|
516
507
|
analyticsService.postEvent.resolves();
|
|
517
508
|
|
|
518
|
-
logger.warning.returns();
|
|
519
|
-
|
|
520
509
|
const processExitStub = sandbox.stub(process, "exit");
|
|
521
510
|
|
|
522
511
|
const exitError = new Error("Process exit.");
|
|
@@ -562,8 +551,6 @@ describe("SSLSetupCommandExecutor", () => {
|
|
|
562
551
|
|
|
563
552
|
analyticsService.postEvent.resolves();
|
|
564
553
|
|
|
565
|
-
logger.warning.returns();
|
|
566
|
-
|
|
567
554
|
const options = new SetupCommandOptions(hostname, false, false);
|
|
568
555
|
await commandExecutor.execute(options);
|
|
569
556
|
|
|
@@ -597,8 +584,6 @@ describe("SSLSetupCommandExecutor", () => {
|
|
|
597
584
|
|
|
598
585
|
analyticsService.postEvent.resolves();
|
|
599
586
|
|
|
600
|
-
logger.warning.returns();
|
|
601
|
-
|
|
602
587
|
preferences.get.onCall(0).returns(
|
|
603
588
|
new PreferenceJson({
|
|
604
589
|
ssl: {
|
|
@@ -620,9 +605,6 @@ describe("SSLSetupCommandExecutor", () => {
|
|
|
620
605
|
|
|
621
606
|
analyticsService.postEvent.resolves();
|
|
622
607
|
|
|
623
|
-
logger.warning.returns();
|
|
624
|
-
logger.success.returns();
|
|
625
|
-
|
|
626
608
|
const existsStub = sandbox.stub(fs, "existsSync");
|
|
627
609
|
existsStub.withArgs(certificatePath).returns(true);
|
|
628
610
|
existsStub.withArgs(keyPath).returns(true);
|
|
@@ -657,7 +639,12 @@ describe("SSLSetupCommandExecutor", () => {
|
|
|
657
639
|
true
|
|
658
640
|
);
|
|
659
641
|
|
|
660
|
-
assert.equal(
|
|
642
|
+
assert.equal(
|
|
643
|
+
logger.success
|
|
644
|
+
.getCall(0)
|
|
645
|
+
.calledWith("Removed existing SSL certificate.", { prefix: "\n", postfix: "\n" }),
|
|
646
|
+
true
|
|
647
|
+
);
|
|
661
648
|
|
|
662
649
|
assert.equal(
|
|
663
650
|
logger.success
|
|
@@ -674,7 +661,7 @@ describe("SSLSetupCommandExecutor", () => {
|
|
|
674
661
|
);
|
|
675
662
|
});
|
|
676
663
|
|
|
677
|
-
it("should
|
|
664
|
+
it("should re-create an SSL certificate when user chooses to remove a valid, automatically set up SSL.", async () => {
|
|
678
665
|
const hostname = "localhost";
|
|
679
666
|
|
|
680
667
|
// SSL remove.
|
|
@@ -686,8 +673,6 @@ describe("SSLSetupCommandExecutor", () => {
|
|
|
686
673
|
|
|
687
674
|
analyticsService.postEvent.resolves();
|
|
688
675
|
|
|
689
|
-
logger.warning.returns();
|
|
690
|
-
|
|
691
676
|
// SSL setup.
|
|
692
677
|
promptStub.withArgs(sslSetupTypePrompt).resolves({
|
|
693
678
|
sslSetupType: SSLSetupOption.Automatically
|
|
@@ -705,6 +690,8 @@ describe("SSLSetupCommandExecutor", () => {
|
|
|
705
690
|
// @ts-ignore -- IReturnData mock response
|
|
706
691
|
.resolves({ cert: <Buffer>{}, key: <Buffer>{}, caPath });
|
|
707
692
|
|
|
693
|
+
sandbox.stub(devcert, "caExpiryInDays").returns(100);
|
|
694
|
+
|
|
708
695
|
const removeDomainStub = sandbox.stub(devcert, "removeDomain");
|
|
709
696
|
removeDomainStub.withArgs(hostname).resolves();
|
|
710
697
|
|
|
@@ -712,10 +699,6 @@ describe("SSLSetupCommandExecutor", () => {
|
|
|
712
699
|
|
|
713
700
|
analyticsService.postEvent.resolves();
|
|
714
701
|
|
|
715
|
-
logger.warning.returns();
|
|
716
|
-
logger.success.returns();
|
|
717
|
-
logger.message.returns();
|
|
718
|
-
|
|
719
702
|
const options = new SetupCommandOptions(hostname, false, false);
|
|
720
703
|
await commandExecutor.execute(options);
|
|
721
704
|
|
|
@@ -741,13 +724,137 @@ describe("SSLSetupCommandExecutor", () => {
|
|
|
741
724
|
true
|
|
742
725
|
);
|
|
743
726
|
|
|
744
|
-
assert.equal(
|
|
727
|
+
assert.equal(
|
|
728
|
+
logger.success
|
|
729
|
+
.getCall(0)
|
|
730
|
+
.calledWith("Removed existing SSL certificate.", { prefix: "\n", postfix: "\n" }),
|
|
731
|
+
true
|
|
732
|
+
);
|
|
733
|
+
assert.equal(logger.success.getCall(1).calledWith("SSL setup complete!", { prefix: "\n" }), true);
|
|
734
|
+
|
|
735
|
+
assert.equal(
|
|
736
|
+
logger.message
|
|
737
|
+
.getCall(0)
|
|
738
|
+
.calledWith(
|
|
739
|
+
"This is only a one time step and may require you to enter your system's password,"
|
|
740
|
+
),
|
|
741
|
+
true
|
|
742
|
+
);
|
|
743
|
+
assert.equal(
|
|
744
|
+
logger.message
|
|
745
|
+
.getCall(1)
|
|
746
|
+
.calledWith(
|
|
747
|
+
"so that the SSL certificate can be added to your system's trusted certificate path."
|
|
748
|
+
),
|
|
749
|
+
true
|
|
750
|
+
);
|
|
751
|
+
assert.equal(
|
|
752
|
+
logger.message
|
|
753
|
+
.getCall(2)
|
|
754
|
+
.calledWith("[If this takes longer than expected, please break and retry]"),
|
|
755
|
+
true
|
|
756
|
+
);
|
|
757
|
+
|
|
758
|
+
assert.equal(
|
|
759
|
+
logger.information
|
|
760
|
+
.getCall(0)
|
|
761
|
+
.calledWith("Setting up self-signed SSL certificate ...", { prefix: "\n" }),
|
|
762
|
+
true
|
|
763
|
+
);
|
|
764
|
+
assert.equal(
|
|
765
|
+
logger.information
|
|
766
|
+
.getCall(1)
|
|
767
|
+
.calledWith(format("You can find the SSL certificate in {sslDirectory}.", { sslDirectory }), {
|
|
768
|
+
postfix: "\n"
|
|
769
|
+
}),
|
|
770
|
+
true
|
|
771
|
+
);
|
|
772
|
+
|
|
773
|
+
assert.equal(
|
|
774
|
+
analyticsService.postEvent
|
|
775
|
+
.getCall(1)
|
|
776
|
+
.calledWith(AnalyticsSuccessMarkers.SUCCESSFUL_SSL_AUTOMATIC_SETUP, options.hostname, true),
|
|
777
|
+
true
|
|
778
|
+
);
|
|
779
|
+
});
|
|
780
|
+
|
|
781
|
+
it("should re-create an SSL certificate when user chooses to remove an expired, automatically set up SSL.", async () => {
|
|
782
|
+
const hostname = "localhost";
|
|
783
|
+
|
|
784
|
+
// SSL remove.
|
|
785
|
+
sslReader.isCustomSSL.withArgs(hostname).returns(false);
|
|
786
|
+
sslReader.isWxpSSL.withArgs(hostname).returns(true);
|
|
787
|
+
|
|
788
|
+
const promptStub = sandbox.stub(prompts, "prompt");
|
|
789
|
+
promptStub.withArgs(shouldRemovePrompt).resolves({ shouldRemove: SSLRemoveOption.Remove });
|
|
790
|
+
|
|
791
|
+
analyticsService.postEvent.resolves();
|
|
792
|
+
|
|
793
|
+
// SSL setup.
|
|
794
|
+
promptStub.withArgs(sslSetupTypePrompt).resolves({
|
|
795
|
+
sslSetupType: SSLSetupOption.Automatically
|
|
796
|
+
});
|
|
797
|
+
|
|
798
|
+
preferences.get.onCall(1).returns(new PreferenceJson({}));
|
|
799
|
+
preferences.set.returns();
|
|
800
|
+
|
|
801
|
+
const caPath = "/some-directory/certificate-authority/certificate.cert";
|
|
802
|
+
const sslDirectory = `/some-directory/domains/${hostname}`;
|
|
803
|
+
|
|
804
|
+
sandbox
|
|
805
|
+
.stub(devcert, "certificateFor")
|
|
806
|
+
.withArgs(hostname, { getCaPath: true })
|
|
807
|
+
// @ts-ignore -- IReturnData mock response
|
|
808
|
+
.resolves({ cert: <Buffer>{}, key: <Buffer>{}, caPath });
|
|
809
|
+
|
|
810
|
+
sandbox.stub(devcert, "caExpiryInDays").returns(0);
|
|
811
|
+
|
|
812
|
+
const removeAllStub = sandbox.stub(devcert, "removeAll");
|
|
813
|
+
removeAllStub.returns();
|
|
814
|
+
|
|
815
|
+
sandbox.stub(path, "resolve").withArgs(caPath, "..", "..", "domains", hostname).returns(sslDirectory);
|
|
816
|
+
|
|
817
|
+
analyticsService.postEvent.resolves();
|
|
818
|
+
|
|
819
|
+
const options = new SetupCommandOptions(hostname, false, false);
|
|
820
|
+
await commandExecutor.execute(options);
|
|
821
|
+
|
|
822
|
+
assert.equal(removeAllStub.calledOnce, true);
|
|
823
|
+
|
|
824
|
+
assert.equal(
|
|
825
|
+
logger.warning.calledOnceWith(
|
|
826
|
+
format(
|
|
827
|
+
"A trusted SSL certificate is already configured for the Add-on to run on https://{hostname}",
|
|
828
|
+
{ hostname: options.hostname }
|
|
829
|
+
),
|
|
830
|
+
{
|
|
831
|
+
prefix: "\n"
|
|
832
|
+
}
|
|
833
|
+
),
|
|
834
|
+
true
|
|
835
|
+
);
|
|
836
|
+
|
|
837
|
+
assert.equal(
|
|
838
|
+
analyticsService.postEvent
|
|
839
|
+
.getCall(0)
|
|
840
|
+
.calledWith(AnalyticsSuccessMarkers.SUCCESSFUL_SSL_AUTOMATIC_REMOVE, options.hostname, true),
|
|
841
|
+
true
|
|
842
|
+
);
|
|
843
|
+
|
|
844
|
+
assert.equal(
|
|
845
|
+
logger.success
|
|
846
|
+
.getCall(0)
|
|
847
|
+
.calledWith("Removed existing SSL certificate.", { prefix: "\n", postfix: "\n" }),
|
|
848
|
+
true
|
|
849
|
+
);
|
|
745
850
|
assert.equal(logger.success.getCall(1).calledWith("SSL setup complete!", { prefix: "\n" }), true);
|
|
746
851
|
|
|
747
852
|
assert.equal(
|
|
748
853
|
logger.message
|
|
749
854
|
.getCall(0)
|
|
750
|
-
.calledWith(
|
|
855
|
+
.calledWith(
|
|
856
|
+
"This is only a one time step and may require you to enter your system's password,"
|
|
857
|
+
),
|
|
751
858
|
true
|
|
752
859
|
);
|
|
753
860
|
assert.equal(
|