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

EWC-300 registry patch endpoint & some fixes #327

Merged
merged 1 commit into from
Nov 6, 2018
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
33 changes: 32 additions & 1 deletion specs/swagger.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1867,7 +1867,38 @@ paths:
'401':
description: Not Authorized
'404':
description: Invalid Node Id
description: Invalid Registry Id
'500':
description: Internal Server Error
patch:
tags:
- Registries
description: Updates a registry
operationId: updateRegistry
parameters:
- in: path
name: id
description: Registry id
required: true
type: string
- in: header
name: Authorization
description: User token
required: true
type: string
responses:
'204':
description: Updated
headers:
X-Timestamp:
type: number
description: FogController server timestamp
'400':
description: Bad Request
'401':
description: Not Authorized
'404':
description: Invalid Registry Id
'500':
description: Internal Server Error
'/user/login':
Expand Down
105 changes: 60 additions & 45 deletions src/cli/registry.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,43 +16,50 @@ const constants = require('../helpers/constants');
const logger = require('../logger');
const CliDecorator = require('../decorators/cli-decorator');
const RegistryService = require('../services/registry-service');
const AppHelper = require('../helpers/app-helper');

class Registry extends BaseCLIHandler {
constructor() {
super();

this.name = constants.CMD_REGISTRY
this.name = constants.CMD_REGISTRY;
this.commandDefinitions = [
{ name: 'command', defaultOption: true, group: [constants.CMD] },
{ name: 'uri', alias: 'u', type: String, description: 'Registry URI', group: [constants.CMD_ADD] },
{ name: 'public', alias: 'b', type: Boolean, description: 'Set registry as public', group: [constants.CMD_ADD] },
{ name: 'private', alias: 'r', type: Boolean, description: 'Set registry as private', group: [constants.CMD_ADD] },
{ name: 'username', alias: 'l', type: String, description: 'Registry\'s user name', group: [constants.CMD_ADD] },
{ name: 'password', alias: 'p', type: String, description: 'Password', group: [constants.CMD_ADD] },
{ name: 'email', alias: 'e', type: String, description: 'Email address', group: [constants.CMD_ADD] },
{ name: 'user-id', alias: 'i', type: Number, description: 'User\'s id', group: [constants.CMD_ADD] },
{ name: 'item-id', alias: 'd', type: Number, description: 'Item\'s id', group: [constants.CMD_REMOVE] },
{name: 'command', defaultOption: true, group: [constants.CMD]},
{name: 'uri', alias: 'u', type: String, description: 'Registry URI', group: [constants.CMD_ADD, constants.CMD_UPDATE]},
{name: 'public', alias: 'b', type: Boolean, description: 'Set registry as public', group: [constants.CMD_ADD, constants.CMD_UPDATE]},
{name: 'private', alias: 'r', type: Boolean, description: 'Set registry as private', group: [constants.CMD_ADD, constants.CMD_UPDATE]},
{name: 'username', alias: 'l', type: String, description: 'Registry\'s user name', group: [constants.CMD_ADD, constants.CMD_UPDATE]},
{name: 'password', alias: 'p', type: String, description: 'Password', group: [constants.CMD_ADD, constants.CMD_UPDATE]},
{name: 'requires-certificate', alias: 'c', type: Boolean, description: 'Requires certificate', group: [constants.CMD_ADD, constants.CMD_UPDATE]},
{name: 'certificate', alias: 'C', type: String, description: 'Certificate', group: [constants.CMD_ADD, constants.CMD_UPDATE]},
{name: 'email', alias: 'e', type: String, description: 'Email address', group: [constants.CMD_ADD, constants.CMD_UPDATE]},
{name: 'user-id', alias: 'i', type: Number, description: 'User\'s id', group: [constants.CMD_ADD]},
{name: 'item-id', alias: 'd', type: Number, description: 'Item\'s id', group: [constants.CMD_REMOVE, constants.CMD_UPDATE]}
];
this.commands = {
[constants.CMD_ADD]: 'Add a new Registry.',
[constants.CMD_REMOVE]: 'Delete a Registry.',
[constants.CMD_UPDATE]: 'Update a Registry',
[constants.CMD_LIST]: 'List all Registries.',
}
}

async run(args) {
const registryCommand = this.parseCommandLineArgs(this.commandDefinitions, { argv: args.argv })
const registryCommand = this.parseCommandLineArgs(this.commandDefinitions, {argv: args.argv})

switch (registryCommand.command.command) {
case constants.CMD_ADD:
await _executeCase(registryCommand, constants.CMD_ADD, _createRegistry, true);
break;
await _executeCase(registryCommand, constants.CMD_ADD, _createRegistry, true);
break;
case constants.CMD_REMOVE:
await _executeCase(registryCommand, constants.CMD_REMOVE, _deleteRegistry, false);
break;
await _executeCase(registryCommand, constants.CMD_REMOVE, _deleteRegistry, false);
break;
case constants.CMD_UPDATE:
await _executeCase(registryCommand, constants.CMD_UPDATE, _updateRegistry, false);
break;
case constants.CMD_LIST:
await _executeCase(registryCommand, constants.CMD_LIST, _getRegistries, false);
break;
await _executeCase(registryCommand, constants.CMD_LIST, _getRegistries, false);
break;
case constants.CMD_HELP:
default:
return this.help([constants.CMD_LIST])
Expand All @@ -62,48 +69,56 @@ class Registry extends BaseCLIHandler {
}

async function _createRegistry(obj, user) {
const registry = _createRegistryObject(obj);
logger.info(JSON.stringify(registry));
const response = await RegistryService.createRegistry(registry, user);
logger.info('Registry has been created successfully.');
logger.info('Registry id: ' + response.id);
const registry = _createRegistryObject(obj);
logger.info(JSON.stringify(registry));
const response = await RegistryService.createRegistry(registry, user);
logger.info('Registry has been created successfully.');
logger.info('Registry id: ' + response.id);
}

async function _getRegistries(obj, user) {
const result = await RegistryService.findRegistries(user, true);
logger.info(JSON.stringify(result));
logger.info('List of Registries has been received successfully.');
const result = await RegistryService.findRegistries(user, true);
logger.info(JSON.stringify(result));
logger.info('List of Registries has been received successfully.');
}

async function _deleteRegistry(obj, user) {
await RegistryService.deleteRegistry({id: obj.itemId}, user, true);
logger.info('Registry has been removed successfully.');
await RegistryService.deleteRegistry({id: obj.itemId}, user, true);
logger.info('Registry has been removed successfully.');
}

async function _updateRegistry (obj) {
const registry = _createRegistryObject(obj);
logger.info(JSON.stringify(registry));
await RegistryService.updateRegistry(registry, obj.itemId, {}, true);
logger.info('Registry has been updated successfully.');
}

async function _executeCase(commands, commandName, f, isUserRequired) {
try {
const obj = commands[commandName];
try {
const obj = commands[commandName];

if (isUserRequired) {
const decoratedFunction = CliDecorator.prepareUserById(f);
await decoratedFunction(obj);
} else {
await f(obj);
}
} catch (error) {
logger.error(error.message);
if (isUserRequired) {
const decoratedFunction = CliDecorator.prepareUserById(f);
await decoratedFunction(obj);
} else {
await f(obj);
}
} catch (error) {
logger.error(error.message);
}
}

function _createRegistryObject(cliData) {
const registryObj = {
url: cliData.uri,
username: cliData.username,
password: cliData.password,
isPublic: cliData.public,
email: cliData.email
};
return registryObj;
return {
url: cliData.uri,
username: cliData.username,
password: cliData.password,
isPublic: AppHelper.validateBooleanCliOptions(cliData.public, cliData.private),
email: cliData.email,
requiresCert: cliData.requiresCertificate,
certificate: cliData.certificate
};
}

module.exports = new Registry();
21 changes: 16 additions & 5 deletions src/controllers/registry-controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,24 @@ const getRegistriesEndPoint = async function (req, user) {

const deleteRegistryEndPoint = async function (req, user) {
const deleteRegistry = {
id: parseInt(req.params.id)
}
id: parseInt(req.params.id)
};
return await RegistryService.deleteRegistry(deleteRegistry, user, false);
};

const updateRegistryEndPoint = async function (req, user) {
const registry = req.body;
const registryId = req.params.id;

logger.info("Parameters:" + JSON.stringify(registry));
logger.info("Registry id:" + JSON.stringify(registryId));

return await RegistryService.updateRegistry(registry, registryId, user, false)
};

module.exports = {
createRegistryEndPoint: AuthDecorator.checkAuthToken(createRegistryEndPoint),
getRegistriesEndPoint: AuthDecorator.checkAuthToken(getRegistriesEndPoint),
deleteRegistryEndPoint: AuthDecorator.checkAuthToken(deleteRegistryEndPoint)
createRegistryEndPoint: AuthDecorator.checkAuthToken(createRegistryEndPoint),
getRegistriesEndPoint: AuthDecorator.checkAuthToken(getRegistriesEndPoint),
deleteRegistryEndPoint: AuthDecorator.checkAuthToken(deleteRegistryEndPoint),
updateRegistryEndPoint: AuthDecorator.checkAuthToken(updateRegistryEndPoint)
};
1 change: 1 addition & 0 deletions src/helpers/error-messages.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ module.exports = {
STRACE_NOT_FOUND: 'Strace not found',
INVALID_CONTENT_TYPE: 'Invalid content type',
UPLOADED_FILE_NOT_FOUND: 'Uploaded image snapshot file not found',
REGISTRY_NOT_FOUND: 'Registry not found',
CLI: {
INVALID_PORT_MAPPING: 'Port mapping parsing error. Please provide valid port mapping.',
INVALID_VOLUME_MAPPING: 'Volume mapping parsing error. Please provide valid volume mapping.',
Expand Down
21 changes: 11 additions & 10 deletions src/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,16 @@ function main() {

daemon
.on('starting', () => {
logger.silly('Starting iofog-controller...')
logger.silly('Starting iofog-controller...');

db.sequelize
.sync()
.then(db.migrate)
.then(db.seed)
.catch((err) => {
logger.silly('Unable to initialize the database.', err);
process.exit(1)
});
})
.on('stopping', () => {
logger.silly('Stopping iofog-controller...')
Expand All @@ -55,12 +64,4 @@ function main() {
cli.run(daemon)
}

db.sequelize
.sync()
.then(db.migrate)
.then(db.seed)
.then(main)
.catch((err) => {
logger.silly('Unable to initialize the database.', err)
process.exit(1)
});
main();
28 changes: 27 additions & 1 deletion src/routes/registries.js
Original file line number Diff line number Diff line change
Expand Up @@ -86,4 +86,30 @@ module.exports = [
.send(responseObject.body)
}
},
]
{
method: 'patch',
path: '/api/v3/registries/:id',
middleware: async (req, res) => {
const successCode = constants.HTTP_CODE_NO_CONTENT;
const errorCodes = [
{
code: constants.HTTP_CODE_BAD_REQUEST,
errors: [Errors.ValidationError]
},
{
code: constants.HTTP_CODE_UNAUTHORIZED,
errors: [Errors.AuthenticationError]
},
{
code: constants.HTTP_CODE_NOT_FOUND,
errors: [Errors.NotFoundError]
}
];
const updateRegistryEndPoint = ResponseDecorator.handleErrors(RegistryController.updateRegistryEndPoint, successCode, errorCodes);
const responseObject = await updateRegistryEndPoint(req);
res
.status(responseObject.code)
.send(responseObject.body)
}
}
];
17 changes: 16 additions & 1 deletion src/schemas/registry.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,21 @@ const registryDelete = {
"additionalProperties": false
};

const registryUpdate = {
"id": "/registryUpdate",
"type": "object",
"properties": {
"url": {"type": "string", "minLength": 1},
"isPublic": {"type": "boolean"},
"username": {"type": "string", "minLength": 1},
"password": {"type": "string"},
"email": {"type": "string"},
"requiresCert": {"type": "boolean"},
"certificate": {"type": "string"}
},
"additionalProperties": false
};

module.exports = {
mainSchemas: [registryCreate, registryDelete]
mainSchemas: [registryCreate, registryDelete, registryUpdate]
};
44 changes: 43 additions & 1 deletion src/services/registry-service.js
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,50 @@ const deleteRegistry = async function (registryData, user, isCli, transaction) {
await updateChangeTracking(user, transaction);
};

const updateRegistry = async function (registry, registryId, user, isCLI, transaction) {
await Validator.validate(registry, Validator.schemas.registryUpdate);

if (registry.requiresCert && registry.certificate === undefined) {
throw new Errors.ValidationError(ErrorMessages.CERT_PROPERTY_REQUIRED);
}

const existingRegistry = await RegistryManager.findOne({
id: registryId
}, transaction);
if (!existingRegistry) {
throw new Errors.NotFoundError(ErrorMessages.REGISTRY_NOT_FOUND)
}

let registryUpdate = {
url: registry.url,
username: registry.username,
password: registry.password,
isPublic: registry.isPublic,
userEmail: registry.email,
requiresCert: registry.requiresCert,
certificate: registry.certificate
};

registryUpdate = AppHelper.deleteUndefinedFields(registryUpdate);

const where = isCLI ?
{
id: registryId
}
:
{
id: registryId,
userId: user.id
};

await RegistryManager.update(where, registryUpdate, transaction);

await updateChangeTracking(user, transaction);
};

module.exports = {
findRegistries: TransactionDecorator.generateTransaction(findRegistries),
createRegistry: TransactionDecorator.generateTransaction(createRegistry),
deleteRegistry: TransactionDecorator.generateTransaction(deleteRegistry)
deleteRegistry: TransactionDecorator.generateTransaction(deleteRegistry),
updateRegistry: TransactionDecorator.generateTransaction(updateRegistry)
};
Loading