Skip to content

Commit 7fcb7df

Browse files
committed
Obtain public IP address from ipify
1 parent 66a9747 commit 7fcb7df

File tree

8 files changed

+52
-51
lines changed

8 files changed

+52
-51
lines changed

lib/Constants.js

+1-5
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,11 @@
11
"use strict";
22
Object.defineProperty(exports, "__esModule", { value: true });
3-
exports.PsqlConstants = exports.FirewallConstants = exports.FileConstants = void 0;
3+
exports.PsqlConstants = exports.FileConstants = void 0;
44
class FileConstants {
55
}
66
exports.FileConstants = FileConstants;
77
// regex checks that string should end with .sql and if folderPath is present, * should not be included in folderPath
88
FileConstants.singleParentDirRegex = /^((?!\*\/).)*(\.sql)$/g;
9-
class FirewallConstants {
10-
}
11-
exports.FirewallConstants = FirewallConstants;
12-
FirewallConstants.ipv4MatchPattern = /\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b/;
139
class PsqlConstants {
1410
}
1511
exports.PsqlConstants = PsqlConstants;

lib/Utils/PsqlUtils/PsqlUtils.js

+9-7
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,11 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
1313
};
1414
Object.defineProperty(exports, "__esModule", { value: true });
1515
const Constants_1 = require("../../Constants");
16-
const Constants_2 = require("../../Constants");
1716
const PsqlToolRunner_1 = __importDefault(require("./PsqlToolRunner"));
17+
const http_client_1 = require("@actions/http-client");
1818
class PsqlUtils {
1919
static detectIPAddress(connectionString) {
20+
var _a;
2021
return __awaiter(this, void 0, void 0, function* () {
2122
let psqlError = '';
2223
let ipAddress = '';
@@ -33,14 +34,15 @@ class PsqlUtils {
3334
yield PsqlToolRunner_1.default.init();
3435
yield PsqlToolRunner_1.default.executePsqlCommand(connectionString, Constants_1.PsqlConstants.SELECT_1, options);
3536
}
36-
catch (err) {
37+
catch (_b) {
3738
if (psqlError) {
38-
const ipAddresses = psqlError.match(Constants_2.FirewallConstants.ipv4MatchPattern);
39-
if (ipAddresses) {
40-
ipAddress = ipAddresses[0];
39+
const http = new http_client_1.HttpClient();
40+
try {
41+
const ipv4 = yield http.getJson('https://api.ipify.org?format=json');
42+
ipAddress = ((_a = ipv4.result) === null || _a === void 0 ? void 0 : _a.ip) || '';
4143
}
42-
else {
43-
throw new Error(`Unable to detect client IP Address: ${psqlError}`);
44+
catch (err) {
45+
throw new Error(`Unable to detect client IP Address: ${err.message}`);
4446
}
4547
}
4648
}

package-lock.json

+8
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
"dependencies": {
1212
"@actions/core": "^1.2.6",
1313
"@actions/exec": "^1.0.4",
14+
"@actions/http-client": "^2.0.1",
1415
"@actions/io": "^1.0.2",
1516
"azure-actions-webclient": "^1.0.11",
1617
"crypto": "^1.0.1",

src/Constants.ts

-4
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,6 @@ export class FileConstants {
33
static readonly singleParentDirRegex = /^((?!\*\/).)*(\.sql)$/g;
44
}
55

6-
export class FirewallConstants {
7-
static readonly ipv4MatchPattern = /\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b/;
8-
}
9-
106
export class PsqlConstants {
117
static readonly SELECT_1 = "SELECT 1";
128
// host, port, dbname, user, password must be present in connection string in any order.

src/Utils/PsqlUtils/PsqlUtils.ts

+12-7
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { PsqlConstants } from "../../Constants";
2-
import { FirewallConstants } from "../../Constants";
32
import PsqlToolRunner from "./PsqlToolRunner";
3+
import { HttpClient } from '@actions/http-client';
44

55
export default class PsqlUtils {
66
static async detectIPAddress(connectionString: string): Promise<string> {
@@ -18,17 +18,22 @@ export default class PsqlUtils {
1818
try {
1919
await PsqlToolRunner.init();
2020
await PsqlToolRunner.executePsqlCommand(connectionString, PsqlConstants.SELECT_1, options);
21-
} catch(err) {
21+
} catch {
2222
if (psqlError) {
23-
const ipAddresses = psqlError.match(FirewallConstants.ipv4MatchPattern);
24-
if (ipAddresses) {
25-
ipAddress = ipAddresses[0];
26-
} else {
27-
throw new Error(`Unable to detect client IP Address: ${psqlError}`);
23+
const http = new HttpClient();
24+
try {
25+
const ipv4 = await http.getJson<IPResponse>('https://api.ipify.org?format=json');
26+
ipAddress = ipv4.result?.ip || '';
27+
} catch(err) {
28+
throw new Error(`Unable to detect client IP Address: ${err.message}`);
2829
}
2930
}
3031
}
3132
return ipAddress;
3233
}
3334

35+
}
36+
37+
export interface IPResponse {
38+
ip: string;
3439
}

src/__tests__/Utils/PsqlUtils.test.ts

+20-27
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,35 @@
1-
import PsqlUtils from "../../Utils/PsqlUtils/PsqlUtils";
2-
import { FirewallConstants } from "../../Constants";
1+
import { HttpClient } from '@actions/http-client';
2+
import PsqlToolRunner from "../../Utils/PsqlUtils/PsqlToolRunner";
3+
import PsqlUtils, { IPResponse } from "../../Utils/PsqlUtils/PsqlUtils";
34

45
jest.mock('../../Utils/PsqlUtils/PsqlToolRunner');
5-
const CONFIGURED = "configured";
6+
jest.mock('@actions/http-client');
67

78
describe('Testing PsqlUtils', () => {
89
afterEach(() => {
9-
jest.clearAllMocks()
10+
jest.resetAllMocks();
1011
});
1112

12-
let detectIPAddressSpy: any;
13-
beforeAll(() => {
14-
detectIPAddressSpy = PsqlUtils.detectIPAddress = jest.fn().mockImplementation( (connString: string) => {
15-
let psqlError;
16-
if (connString != CONFIGURED) {
17-
psqlError = `psql: error: could not connect to server: FATAL: no pg_hba.conf entry for host "1.2.3.4", user "<user>", database "<db>"`;
18-
}
19-
let ipAddress = '';
20-
if (psqlError) {
21-
const ipAddresses = psqlError.match(FirewallConstants.ipv4MatchPattern);
22-
if (ipAddresses) {
23-
ipAddress = ipAddresses[0];
24-
} else {
25-
throw new Error(`Unable to detect client IP Address: ${psqlError}`);
26-
}
27-
}
28-
return ipAddress;
13+
test('detectIPAddress should return ip address', async () => {
14+
const psqlError: string = `psql: error: could not connect to server: FATAL: no pg_hba.conf entry for host "1.2.3.4", user "<user>", database "<db>"`;
15+
16+
jest.spyOn(PsqlToolRunner, 'executePsqlCommand').mockImplementation(async (_connectionString: string, _command: string, options: any = {}) => {
17+
options.listeners.stderr(Buffer.from(psqlError));
18+
throw new Error(psqlError);
19+
});
20+
jest.spyOn(HttpClient.prototype, 'getJson').mockResolvedValue({
21+
statusCode: 200,
22+
result: {
23+
ip: '1.2.3.4',
24+
},
25+
headers: {},
2926
});
30-
});
3127

32-
test('detectIPAddress should return ip address', async () => {
33-
await PsqlUtils.detectIPAddress("");
34-
expect(detectIPAddressSpy).toReturnWith("1.2.3.4");
28+
return PsqlUtils.detectIPAddress("").then(ipAddress => expect(ipAddress).toEqual("1.2.3.4"));
3529
});
3630

3731
test('detectIPAddress should return empty string', async () => {
38-
await PsqlUtils.detectIPAddress(CONFIGURED);
39-
expect(detectIPAddressSpy).toReturnWith("");
32+
return PsqlUtils.detectIPAddress("").then(ipAddress => expect(ipAddress).toEqual(""));
4033
})
4134

4235
});

tsconfig.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
// "incremental": true, /* Enable incremental compilation */
55
"target": "es6", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */
66
"module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */
7-
"lib": ["es2020.string"], /* Specify library files to be included in the compilation. */
7+
"lib": ["es2020.string", "dom"], /* Specify library files to be included in the compilation. */
88
// "allowJs": true, /* Allow javascript files to be compiled. */
99
// "checkJs": true, /* Report errors in .js files. */
1010
// "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */

0 commit comments

Comments
 (0)