registry config: create table and migrate existing setting
This commit is contained in:
@@ -0,0 +1,123 @@
|
||||
'use strict';
|
||||
|
||||
exports = module.exports = {
|
||||
removePrivateFields,
|
||||
|
||||
list,
|
||||
add,
|
||||
get,
|
||||
del,
|
||||
update,
|
||||
};
|
||||
|
||||
const assert = require('assert'),
|
||||
BoxError = require('./boxerror.js'),
|
||||
constants = require('./constants.js'),
|
||||
database = require('./database.js'),
|
||||
Docker = require('dockerode'),
|
||||
eventlog = require('./eventlog.js'),
|
||||
paths = require('./paths.js'),
|
||||
safe = require('safetydance'),
|
||||
tld = require('tldjs'),
|
||||
uuid = require('uuid');
|
||||
|
||||
const REGISTRY_FIELDS = [ 'id', 'provider', 'serverAddress', 'username', 'email', 'password' ].join(',');
|
||||
|
||||
function removePrivateFields(registryConfig) {
|
||||
assert.strictEqual(typeof registryConfig, 'object');
|
||||
|
||||
if (registryConfig.password) registryConfig.password = constants.SECRET_PLACEHOLDER;
|
||||
|
||||
return registryConfig;
|
||||
}
|
||||
|
||||
async function get(id) {
|
||||
assert.strictEqual(typeof id, 'string');
|
||||
|
||||
const result = await database.query(`SELECT ${REGISTRY_FIELDS} FROM dockerRegistries WHERE id=?`, [ id ]);
|
||||
if (result.length === 0) return null;
|
||||
return result[0];
|
||||
}
|
||||
|
||||
async function list() {
|
||||
const result = await database.query(`SELECT ${REGISTRY_FIELDS} FROM dockerRegistries`);
|
||||
return result;
|
||||
}
|
||||
|
||||
function validateServerAddress(serverAddress) {
|
||||
assert.strictEqual(typeof serverAddress, 'string');
|
||||
|
||||
// workaround https://github.com/oncletom/tld.js/issues/73
|
||||
const tmp = serverAddress.replace('_', '-');
|
||||
if (!tld.isValid(tmp)) return new BoxError(BoxError.BAD_FIELD, 'Hostname is not a valid domain name');
|
||||
if (tmp.length > 253) return new BoxError(BoxError.BAD_FIELD, 'Hostname length exceeds 253 characters');
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
async function testRegistryConfig(config) {
|
||||
assert.strictEqual(typeof config, 'object');
|
||||
|
||||
if (constants.TEST) return;
|
||||
|
||||
const connection = new Docker({ socketPath: paths.DOCKER_SOCKET_PATH, timeout: 3000 });
|
||||
const [error] = await safe(connection.checkAuth(config)); // this returns a 500 even for auth errors
|
||||
if (error) throw new BoxError(BoxError.BAD_FIELD, `Invalid serverAddress: ${error.message}`);
|
||||
}
|
||||
|
||||
function injectPrivateFields(newConfig, currentConfig) {
|
||||
if (newConfig.password === constants.SECRET_PLACEHOLDER) newConfig.password = currentConfig.password;
|
||||
}
|
||||
|
||||
async function add(registry, auditSource) {
|
||||
assert.strictEqual(typeof registry, 'object');
|
||||
assert(auditSource && typeof auditSource === 'object');
|
||||
|
||||
const error = validateServerAddress(registry.serverAddress);
|
||||
if (error) throw error;
|
||||
|
||||
await testRegistryConfig(registry);
|
||||
|
||||
const id = `rc-${uuid.v4()}`;
|
||||
await database.query('INSERT INTO dockerRegistries (id, provider, serverAddress, username, email, password) VALUES (?, ?, ?, ?, ?, ?)',
|
||||
[ id , registry.provider, registry.serverAddress, registry.username || null, registry.email || null, registry.password || null ]);
|
||||
|
||||
await eventlog.add(eventlog.ACTION_REGISTRY_ADD, auditSource, { registry: removePrivateFields(registry) });
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
async function update(oldConfig, newConfig, auditSource) {
|
||||
assert.strictEqual(typeof oldConfig, 'object');
|
||||
assert.strictEqual(typeof newConfig, 'object');
|
||||
assert(auditSource && typeof auditSource === 'object');
|
||||
|
||||
const error = validateServerAddress(newConfig.serverAddress);
|
||||
if (error) throw error;
|
||||
|
||||
injectPrivateFields(newConfig, oldConfig);
|
||||
|
||||
await testRegistryConfig(newConfig);
|
||||
|
||||
const args = [], fields = [];
|
||||
for (const k in newConfig) {
|
||||
fields.push(k + ' = ?');
|
||||
args.push(newConfig[k]);
|
||||
}
|
||||
args.push(oldConfig.id);
|
||||
|
||||
const result = await database.query('UPDATE dockerRegistries SET ' + fields.join(', ') + ' WHERE id=?', args);
|
||||
if (result.affectedRows === 0) throw new BoxError(BoxError.NOT_FOUND, 'Registry not found');
|
||||
|
||||
await eventlog.add(eventlog.ACTION_REGISTRY_DEL, auditSource, { oldRegistry: removePrivateFields(oldConfig), newRegistry: removePrivateFields(newConfig) });
|
||||
}
|
||||
|
||||
async function del(registry, auditSource) {
|
||||
assert.strictEqual(typeof registry, 'object');
|
||||
assert(auditSource && typeof auditSource === 'object');
|
||||
|
||||
const result = await database.query(`DELETE FROM dockerRegistries WHERE id=?`, [ registry.id ]);
|
||||
if (result.affectedRows !== 1) throw new BoxError(BoxError.NOT_FOUND, 'Registry not found');
|
||||
|
||||
await eventlog.add(eventlog.ACTION_REGISTRY_DEL, auditSource, { registry: removePrivateFields(registry) });
|
||||
}
|
||||
Reference in New Issue
Block a user