Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: config schema #526

Merged
merged 4 commits into from
Apr 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 30 additions & 34 deletions config.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
22 changes: 8 additions & 14 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,32 +18,26 @@ 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 path = require('path');
const validate = require('jsonschema').validate;
const configFile = require('./src/config/file').configFile;

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);
}

config.validate();

const proxy = require('./src/proxy');
const service = require('./src/service');

Expand Down
20 changes: 20 additions & 0 deletions src/config/file.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -11,4 +30,5 @@ module.exports = {
set configFile(file) {
configFile = file;
},
validate,
};
9 changes: 9 additions & 0 deletions test/fixtures/proxy.config.invalid-1.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"invalidProperty": [
{
"project": "finos",
"name": "git-proxy",
"url": "https://www.github.com/finos/git-proxy.git"
}
]
}
9 changes: 9 additions & 0 deletions test/fixtures/proxy.config.invalid-2.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"authorisedList": [
{
"project": "finos",
"name": "git-proxy",
"link": "https://www.github.com/finos/git-proxy"
}
]
}
1 change: 1 addition & 0 deletions test/fixtures/proxy.config.valid-1.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{}
14 changes: 14 additions & 0 deletions test/fixtures/proxy.config.valid-2.json
Original file line number Diff line number Diff line change
@@ -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": "[email protected]:finos/git-proxy-test.git"
}
]
}
34 changes: 34 additions & 0 deletions test/testConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@ 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;

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],
Expand Down Expand Up @@ -113,3 +115,35 @@ 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, fixtures, 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, fixtures, testConfigFile));
};
expect(test).to.throw();
}
});

after(function () {
delete require.cache[require.resolve('../src/config')];
});
});
Loading