Skip to content

Commit ad6b3a4

Browse files
committed
Add --insecure flag instead of NODE_TLS_REJECT_UNAUTHORIZED=0
1 parent a0294da commit ad6b3a4

7 files changed

+42
-27
lines changed

CHANGELOG.md

+9
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1010
### Added
1111

1212
- Added config option `personalAccessToken` and environment variable `CONFLUENCE_PERSONAL_ACCESS_TOKEN` in order to support authentication using [personal access tokens](https://confluence.atlassian.com/enterprise/using-personal-access-tokens-1026032365.html). (solves [#26](https://github.com/mihaeu/cosmere/issues/26))
13+
- Added `--insecure` flag in order to not have to use `NODE_TLS_REJECT_UNAUTHORIZED=0` in cases where it's needed.
14+
15+
### Changed
16+
17+
- Pictures are now only uploaded if they differ in filename or size. Only pictures that do not match will be deleted remotely (previously all pictures were deleted, then all were uploaded).
18+
19+
### Fixed
20+
21+
- Fixed cache check so that only real changes in files require an update.
1322

1423
## [0.14.1] - 2021-08-25
1524

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ or create an alias:
118118
119119
### Custom certificates on Confluence instance
120120
121-
Prepend `NODE_TLS_REJECT_UNAUTHORIZED=0` to your `cosmere` call in order to not reject invalid certificates. This is risky and it's preferable to get proper certificates.
121+
Use the `--insecure` option for your `cosmere` call in order to not reject invalid certificates. This is risky, and it's preferable to get proper certificates.
122122
123123
## Need new features?
124124

bin/cosmere

+3-2
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,19 @@
33
const docopt = require('docopt');
44
const options = docopt.docopt(`
55
Usage:
6-
cosmere [--force] [--config=<path>]
6+
cosmere [--force] [--insecure] [--config=<path>]
77
cosmere generate-config [--config=<path>]
88
99
Options:
1010
--force always upload even if the file looks the same
11+
--insecure disables certificate verification (!this makes the transfer insecure!)
1112
--config=<path> specify the path to the config
1213
`);
1314

1415
if (options['generate-config']) {
1516
require('../dist/src/cli/GenerateCommand').default(options['--config']);
1617
} else {
17-
require('../dist/src/cli/MainCommand').default(options['--config'], options['--force'])
18+
require('../dist/src/cli/MainCommand').default(options['--config'], options['--force'], options['--insecure'])
1819
.then()
1920
.catch(e => {
2021
require('signale').fatal(e);

src/api/ConfluenceAPI.ts

+22-20
Original file line numberDiff line numberDiff line change
@@ -3,49 +3,42 @@ import * as fs from "fs";
33
import signale from "signale";
44
import { GetAttachmentsResult } from "./GetAttachmentsResult";
55
import { Attachment } from "./Attachment";
6+
import { Agent } from "https";
67

78
export class ConfluenceAPI {
89
private readonly baseUrl: string;
910
private readonly authHeader: {
1011
Authorization: string;
1112
};
13+
private readonly agent: Agent;
1214

13-
constructor(baseUrl: string, authorizationToken: string) {
15+
constructor(baseUrl: string, authorizationToken: string, insecure: boolean) {
1416
this.baseUrl = baseUrl;
1517
this.authHeader = {
1618
Authorization: authorizationToken,
1719
};
20+
this.agent = new (require("https").Agent)({
21+
rejectUnauthorized: !insecure,
22+
});
1823
}
1924

2025
async updateConfluencePage(pageId: string, newPage: any) {
21-
const config = {
22-
headers: {
23-
...this.authHeader,
24-
"Content-Type": "application/json",
25-
},
26-
};
2726
try {
28-
await axios.put(`${this.baseUrl}/content/${pageId}`, newPage, config);
27+
await axios.put(`${this.baseUrl}/content/${pageId}`, newPage, this.config());
2928
} catch (e) {
3029
signale.await(`First attempt failed, retrying ...`);
31-
await axios.put(`${this.baseUrl}/content/${pageId}`, newPage, config);
30+
await axios.put(`${this.baseUrl}/content/${pageId}`, newPage, this.config());
3231
}
3332
}
3433

3534
async getAttachments(pageId: string): Promise<GetAttachmentsResult> {
36-
return (
37-
await axios.get(`${this.baseUrl}/content/${pageId}/child/attachment`, {
38-
headers: this.authHeader,
39-
})
40-
).data;
35+
return (await axios.get(`${this.baseUrl}/content/${pageId}/child/attachment`, this.config())).data;
4136
}
4237

4338
async deleteAttachment(attachment: Attachment) {
4439
try {
4540
signale.await(`Deleting attachment "${attachment.title}" ...`);
46-
await axios.delete(`${this.baseUrl}/content/${attachment.id}`, {
47-
headers: this.authHeader,
48-
});
41+
await axios.delete(`${this.baseUrl}/content/${attachment.id}`, this.config());
4942
} catch (e) {
5043
signale.error(`Deleting attachment "${attachment.title}" failed ...`);
5144
}
@@ -60,6 +53,7 @@ export class ConfluenceAPI {
6053
"X-Atlassian-Token": "nocheck",
6154
...this.authHeader,
6255
},
56+
httpsAgent: this.agent,
6357
data: {
6458
file: fs.createReadStream(filename),
6559
},
@@ -70,8 +64,16 @@ export class ConfluenceAPI {
7064
}
7165

7266
async currentPage(pageId: string) {
73-
return axios.get(`${this.baseUrl}/content/${pageId}?expand=body.storage,version`, {
74-
headers: this.authHeader,
75-
});
67+
return axios.get(`${this.baseUrl}/content/${pageId}?expand=body.storage,version`, this.config());
68+
}
69+
70+
private config() {
71+
return {
72+
headers: {
73+
...this.authHeader,
74+
"Content-Type": "application/json",
75+
},
76+
httpsAgent: this.agent,
77+
};
7678
}
7779
}

src/cli/MainCommand.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@ import { ConfigLoader } from "../ConfigLoader";
33
import { ConfluenceAPI } from "../api/ConfluenceAPI";
44
import { updatePage } from "../UpdatePage";
55

6-
export default async function(configPath: string | null, force: boolean = false) {
6+
export default async function(configPath: string | null, force: boolean = false, insecure: boolean = false) {
77
const config: Config = await ConfigLoader.load(configPath);
8-
const confluenceAPI = new ConfluenceAPI(config.baseUrl, config.authorizationToken);
8+
const confluenceAPI = new ConfluenceAPI(config.baseUrl, config.authorizationToken, insecure);
99

1010
for (const pageData of config.pages) {
1111
await updatePage(confluenceAPI, pageData, config, force);

tests/UpdatePage.test.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,6 @@ describe("UpdatePage", () => {
1717
configPath: "...",
1818
authorizationToken: "Bearer unbearable",
1919
};
20-
expect(updatePage(new ConfluenceAPI("", "Bearer unbearable"), pageData, config, false)).toBeFalsy();
20+
expect(updatePage(new ConfluenceAPI("", "Bearer unbearable", false), pageData, config, false)).toBeFalsy();
2121
});
2222
});

tests/api/ConfluenceAPI.test.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { ConfluenceAPI } from "../../src/api/ConfluenceAPI";
22
import axios from "axios";
33
import { mocked } from "ts-jest/utils";
4+
import { Agent } from "https";
45

56
jest.mock("axios");
67
const axiosMock = mocked(axios, true);
@@ -9,12 +10,14 @@ describe("ConfluenceAPI", () => {
910
it("fetches current version of confluence page", async () => {
1011
axiosMock.get.mockResolvedValue({ data: "Test" });
1112

12-
const confluenceAPI = new ConfluenceAPI("", "Bearer unbearable");
13+
const confluenceAPI = new ConfluenceAPI("", "Bearer unbearable", false);
1314
await confluenceAPI.currentPage("2");
1415
expect(axiosMock.get).toHaveBeenCalledWith("/content/2?expand=body.storage,version", {
1516
headers: {
1617
Authorization: "Bearer unbearable",
18+
"Content-Type": "application/json",
1719
},
20+
httpsAgent: expect.any(Agent),
1821
});
1922
});
2023
});

0 commit comments

Comments
 (0)