From a3429d06ab58382b6633950082c8997ff242286b Mon Sep 17 00:00:00 2001 From: Miklos Sagi Date: Sat, 13 Apr 2024 14:45:30 +0100 Subject: [PATCH 1/2] fix: config schema --- config.schema.json | 64 +++++++++++++++----------------- index.js | 18 +++------ src/config/file.js | 20 ++++++++++ test/proxy.config.invalid-1.json | 9 +++++ test/proxy.config.invalid-2.json | 9 +++++ test/proxy.config.valid-1.json | 1 + test/proxy.config.valid-2.json | 14 +++++++ test/testConfig.js | 31 ++++++++++++++++ 8 files changed, 119 insertions(+), 47 deletions(-) create mode 100644 test/proxy.config.invalid-1.json create mode 100644 test/proxy.config.invalid-2.json create mode 100644 test/proxy.config.valid-1.json create mode 100644 test/proxy.config.valid-2.json diff --git a/config.schema.json b/config.schema.json index 9a187ae4..9784f397 100644 --- a/config.schema.json +++ b/config.schema.json @@ -4,44 +4,40 @@ "title": "Git Proxy configuration file", "description": "Configuration for customizing git-proxy", "type": "object", - "oneOf": [ - { + "properties": { + "authorisedList": { + "description": "List of repositories that are authorised to be pushed to through the proxy.", + "type": "array", + "items": { + "$ref": "#/definitions/authorisedRepo" + } + }, + "sink": { + "description": "List of database sources. The first source in the configuration with enabled=true will be used.", + "type": "array", + "items": { + "$ref": "#/definitions/database" + } + }, + "authentication": { + "description": "List of authentication sources. The first source in the configuration with enabled=true will be used.", + "type": "array", + "items": { + "$ref": "#/definitions/authentication" + } + }, + "tempPassword": { + "description": "Toggle the generation of temporary password for git-proxy admin user", + "type": "object", "properties": { - "authorisedList": { - "description": "List of repositories that are authorised to be pushed to through the proxy.", - "type": "array", - "items": { - "$ref": "#/definitions/authorisedRepo" - } - }, - "sink": { - "description": "List of database sources. The first source in the configuration with enabled=true will be used.", - "type": "array", - "items": { - "$ref": "#/definitions/database" - } - }, - "authentication": { - "description": "List of authentication sources. The first source in the configuration with enabled=true will be used.", - "type": "array", - "items": { - "$ref": "#/definitions/authentication" - } - }, - "tempPassword": { - "description": "Toggle the generation of temporary password for git-proxy admin user", - "type": "object", - "properties": { - "sendEmail": { "type": "boolean" }, - "emailConfig": { - "description": "Generic object to configure nodemailer. For full type information, please see https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/nodemailer", - "type": "object" - } - } + "sendEmail": { "type": "boolean" }, + "emailConfig": { + "description": "Generic object to configure nodemailer. For full type information, please see https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/nodemailer", + "type": "object" } } } - ], + }, "definitions": { "authorisedRepo": { "type": "object", diff --git a/index.js b/index.js index 144f9b06..a6ccdd50 100755 --- a/index.js +++ b/index.js @@ -22,25 +22,17 @@ require('./src/config/file').configFile = argv.c ? argv.c : undefined; if (argv.v) { const fs = require('fs'); - const path = require('path'); - const validate = require('jsonschema').validate; - const configFile = require('./src/config/file').configFile; + const config = require('./src/config/file'); - if (!fs.existsSync(configFile)) { + if (!fs.existsSync(config.configFile)) { console.error( - `Config file ${configFile} doesn't exist, nothing to validate! Did you forget -c/--config?`, + `Config file ${config.configFile} doesn't exist, nothing to validate! Did you forget -c/--config?`, ); process.exit(1); } - const config = JSON.parse(fs.readFileSync(configFile)); - const schema = JSON.parse( - fs.readFileSync(path.join(__dirname, 'config.schema.json')), - ); - - validate(config, schema, { required: true, throwError: true }); - - console.log(`${configFile} is valid`); + config.validate(); + console.log(`${config.configFile} is valid`); process.exit(0); } diff --git a/src/config/file.js b/src/config/file.js index fd1f284d..8779e604 100644 --- a/src/config/file.js +++ b/src/config/file.js @@ -2,6 +2,25 @@ const path = require('path'); // eslint-disable-next-line prefer-const let configFile = undefined; +/** + * Validate config file. + * @param {string} configFilePath - The path to the config file. + * @return {boolean} - Returns true if validation is successful. + * @throws Will throw an error if the validation fails. + */ +function validate(configFilePath = configFile) { + const fs = require('fs'); + const path = require('path'); + const validate = require('jsonschema').validate; + + const config = JSON.parse(fs.readFileSync(configFilePath)); + const schema = JSON.parse( + fs.readFileSync(path.join(__dirname, '..', '..', 'config.schema.json')), + ); + validate(config, schema, { required: true, throwError: true }); + return true; +} + module.exports = { get configFile() { return configFile @@ -11,4 +30,5 @@ module.exports = { set configFile(file) { configFile = file; }, + validate, }; diff --git a/test/proxy.config.invalid-1.json b/test/proxy.config.invalid-1.json new file mode 100644 index 00000000..541044ab --- /dev/null +++ b/test/proxy.config.invalid-1.json @@ -0,0 +1,9 @@ +{ + "invalidProperty": [ + { + "project": "finos", + "name": "git-proxy", + "url": "https://www.github.com/finos/git-proxy.git" + } + ] +} \ No newline at end of file diff --git a/test/proxy.config.invalid-2.json b/test/proxy.config.invalid-2.json new file mode 100644 index 00000000..fa3e48bb --- /dev/null +++ b/test/proxy.config.invalid-2.json @@ -0,0 +1,9 @@ +{ + "authorisedList": [ + { + "project": "finos", + "name": "git-proxy", + "link": "https://www.github.com/finos/git-proxy" + } + ] +} \ No newline at end of file diff --git a/test/proxy.config.valid-1.json b/test/proxy.config.valid-1.json new file mode 100644 index 00000000..9e26dfee --- /dev/null +++ b/test/proxy.config.valid-1.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/test/proxy.config.valid-2.json b/test/proxy.config.valid-2.json new file mode 100644 index 00000000..c18dc1ea --- /dev/null +++ b/test/proxy.config.valid-2.json @@ -0,0 +1,14 @@ +{ + "authorisedList": [ + { + "project": "finos", + "name": "git-proxy", + "url": "https://github.com/finos/git-proxy.git" + }, + { + "project": "finos", + "name": "git-proxy-test", + "url": "git@github.com:finos/git-proxy-test.git" + } + ] +} \ No newline at end of file diff --git a/test/testConfig.js b/test/testConfig.js index d0afb061..69fbdc22 100644 --- a/test/testConfig.js +++ b/test/testConfig.js @@ -113,3 +113,34 @@ describe('user configuration', function () { delete require.cache[require.resolve('../src/config')]; }); }); + +describe('validate config files', function () { + const config = require('../src/config/file'); + + it('all valid config files should pass validation', function () { + const validConfigFiles = [ + 'proxy.config.valid-1.json', + 'proxy.config.valid-2.json', + ]; + for (const testConfigFile of validConfigFiles) { + expect(config.validate(path.join(__dirname, testConfigFile))).to.be.true; + } + }); + + it('all invalid config files should fail validation', function () { + const invalidConfigFiles = [ + 'proxy.config.invalid-1.json', + 'proxy.config.invalid-2.json', + ]; + for (const testConfigFile of invalidConfigFiles) { + const test = function () { + config.validate(path.join(__dirname, testConfigFile)); + }; + expect(test).to.throw(); + } + }); + + after(function () { + delete require.cache[require.resolve('../src/config')]; + }); +}); From f9c456dc708a67a688a21f3d706a71026349f179 Mon Sep 17 00:00:00 2001 From: Miklos Sagi Date: Fri, 19 Apr 2024 10:36:25 +0100 Subject: [PATCH 2/2] fix: review comments --- index.js | 6 ++++-- test/{ => fixtures}/proxy.config.invalid-1.json | 0 test/{ => fixtures}/proxy.config.invalid-2.json | 0 test/{ => fixtures}/proxy.config.valid-1.json | 0 test/{ => fixtures}/proxy.config.valid-2.json | 0 test/testConfig.js | 7 +++++-- 6 files changed, 9 insertions(+), 4 deletions(-) rename test/{ => fixtures}/proxy.config.invalid-1.json (100%) rename test/{ => fixtures}/proxy.config.invalid-2.json (100%) rename test/{ => fixtures}/proxy.config.valid-1.json (100%) rename test/{ => fixtures}/proxy.config.valid-2.json (100%) diff --git a/index.js b/index.js index a6ccdd50..c86c0425 100755 --- a/index.js +++ b/index.js @@ -18,11 +18,11 @@ const argv = require('yargs/yargs')(process.argv.slice(2)) }) .strict().argv; -require('./src/config/file').configFile = argv.c ? argv.c : undefined; +const config = require('./src/config/file'); +config.configFile = argv.c ? argv.c : undefined; if (argv.v) { const fs = require('fs'); - const config = require('./src/config/file'); if (!fs.existsSync(config.configFile)) { console.error( @@ -36,6 +36,8 @@ if (argv.v) { process.exit(0); } +config.validate(); + const proxy = require('./src/proxy'); const service = require('./src/service'); diff --git a/test/proxy.config.invalid-1.json b/test/fixtures/proxy.config.invalid-1.json similarity index 100% rename from test/proxy.config.invalid-1.json rename to test/fixtures/proxy.config.invalid-1.json diff --git a/test/proxy.config.invalid-2.json b/test/fixtures/proxy.config.invalid-2.json similarity index 100% rename from test/proxy.config.invalid-2.json rename to test/fixtures/proxy.config.invalid-2.json diff --git a/test/proxy.config.valid-1.json b/test/fixtures/proxy.config.valid-1.json similarity index 100% rename from test/proxy.config.valid-1.json rename to test/fixtures/proxy.config.valid-1.json diff --git a/test/proxy.config.valid-2.json b/test/fixtures/proxy.config.valid-2.json similarity index 100% rename from test/proxy.config.valid-2.json rename to test/fixtures/proxy.config.valid-2.json diff --git a/test/testConfig.js b/test/testConfig.js index 69fbdc22..072f8a66 100644 --- a/test/testConfig.js +++ b/test/testConfig.js @@ -3,6 +3,7 @@ const chai = require('chai'); const fs = require('fs'); const path = require('path'); const defaultSettings = require('../proxy.config.json'); +const fixtures = 'fixtures'; chai.should(); const expect = chai.expect; @@ -10,6 +11,7 @@ const expect = chai.expect; describe('default configuration', function () { it('should use default values if no user-settings.json file exists', function () { const config = require('../src/config'); + config.logConfiguration(); expect(config.getAuthentication()).to.be.eql( defaultSettings.authentication[0], @@ -123,7 +125,8 @@ describe('validate config files', function () { 'proxy.config.valid-2.json', ]; for (const testConfigFile of validConfigFiles) { - expect(config.validate(path.join(__dirname, testConfigFile))).to.be.true; + expect(config.validate(path.join(__dirname, fixtures, testConfigFile))).to + .be.true; } }); @@ -134,7 +137,7 @@ describe('validate config files', function () { ]; for (const testConfigFile of invalidConfigFiles) { const test = function () { - config.validate(path.join(__dirname, testConfigFile)); + config.validate(path.join(__dirname, fixtures, testConfigFile)); }; expect(test).to.throw(); }