k2hr3-api
Version:
K2HR3 REST API is K2hdkc based Resource and Roles and policy Rules
895 lines (829 loc) • 27.7 kB
JavaScript
/*
* K2HR3 REST API
*
* Copyright 2017 Yahoo Japan Corporation.
*
* K2HR3 is K2hdkc based Resource and Roles and policy Rules, gathers
* common management information for the cloud.
* K2HR3 can dynamically manage information as "who", "what", "operate".
* These are stored as roles, resources, policies in K2hdkc, and the
* client system can dynamically read and modify these information.
*
* For the full copyright and license information, please view
* the license file that was distributed with this source code.
*
* AUTHOR: Takeshi Nakatani
* CREATE: Wed Nov 1 2017
* REVISION:
*
*/
'use strict';
var express = require('express');
var router = express.Router();
var r3token = require('../lib/k2hr3tokens');
var apiutil = require('../lib/k2hr3apiutil');
var resutil = require('../lib/k2hr3resutil');
var k2hr3 = require('../lib/k2hr3dkc');
var r3keys = require('../lib/k2hr3keys').getK2hr3Keys;
// Debug logging objects
var r3logger = require('../lib/dbglogging');
//
// Common utility function
//
// Convert tenant yrn path to tenant name
//
function rawGetTenantNameFromYrn(tenant)
{
if(!apiutil.isSafeString(tenant)){
return null;
}
var keys = r3keys();
var yrnptn = new RegExp('^' + keys.MATCH_ANY_TENANT_MAIN); // regex = /^yrn:yahoo:(.*)::(.*)/
var matches = tenant.match(yrnptn);
if(apiutil.isEmptyArray(matches) || matches.length < 3){
// not match tenant yrn, then return original tenant
return tenant;
}
tenant = matches[2]; // tenant name
if(!apiutil.isSafeString(tenant)){
return null;
}
return tenant;
}
//
// Common utility function
//
// Create or update service
//
// Result null(succeed) or error message(failed)
//
function rawUpdateService(owner, servicename, verify, tenants, is_clear, is_create)
{
var error = null;
var result= null;
if(!apiutil.isSafeString(owner) || !apiutil.isSafeString(servicename)){
error = new Error('Internal error: rawUpdateService');
return error;
}
if(!apiutil.isSafeEntity(verify)){
verify = null;
}
if(apiutil.isEmptyArray(tenants)){
tenants = null;
}
//------------------------------
// set(update) all field / update verify field
//------------------------------
if(is_create || null !== verify){
//
// [NOTE]
// initService() === updateServiceVerify()
//
result = k2hr3.initService(owner, servicename, verify);
if(!apiutil.isSafeEntity(result) || !apiutil.isSafeEntity(result.result) || false === result.result){
if(!apiutil.isSafeEntity(result)){
error = new Error('Could not get response from initService');
}else{
if(!apiutil.isSafeEntity(result.message)){
error = new Error('Could not get error message in response from initService');
}
}
return error;
}
}
//------------------------------
// add tenants
//------------------------------
var allowtenants= !apiutil.isEmptyArray(tenants) ? tenants : [];
var denytenants = [];
var cnt;
if(is_clear || !apiutil.isEmptyArray(allowtenants)){
// get all service data
var allres = k2hr3.getService(owner, servicename);
if(!apiutil.isSafeEntity(allres) || !apiutil.isSafeEntity(allres.result) || false === allres.result){
if(!apiutil.isSafeEntity(allres)){
error = new Error('Could not get response from getService');
}else{
if(!apiutil.isSafeEntity(allres.message)){
error = new Error('Could not get error message in response from getService');
}else{
error = new Error(allres.message);
}
}
return error;
}
// check
if(apiutil.isSafeEntity(allres.service) && apiutil.isArray(allres.service.tenant)){
var keys = r3keys(null, owner, null);
var cnt2;
var found;
for(cnt = 0; cnt < allres.service.tenant.length; ++cnt){
found = false;
for(cnt2 = 0; cnt2 < allowtenants.length; ++cnt2){
if(apiutil.compareCaseString(allres.service.tenant[cnt], allowtenants[cnt2])){
// cut already existing tenant
allowtenants.splice(cnt2, 1);
found = true;
break;
}
}
if(!found){
// does not remove owner tenant
if(!apiutil.compareCaseString(allres.service.tenant[cnt], keys.MASTER_TENANT_TOP_KEY)){
// add new deny tenant
denytenants.push(allres.service.tenant[cnt]);
}
}
}
}
}
// add new allow tenants
for(cnt = 0; cnt < allowtenants.length; ++cnt){
var addtenant = rawGetTenantNameFromYrn(allowtenants[cnt]);
if(null === addtenant){
error = new Error('To allow Tenant name(' + allowtenants[cnt] + ') is something wrong.');
return error;
}
result = k2hr3.allowTenantToService(owner, servicename, addtenant);
if(!apiutil.isSafeEntity(result) || !apiutil.isSafeEntity(result.result) || false === result.result){
if(!apiutil.isSafeEntity(result)){
error = new Error('Could not get response from allowTenantToService');
}else{
error = new Error('Could not get error message in response from allowTenantToService');
}
return error;
}
}
// remove new deny tenants
if(is_clear && !apiutil.isEmptyArray(denytenants)){
for(cnt = 0; cnt < denytenants.length; ++cnt){
var denytenant = rawGetTenantNameFromYrn(denytenants[cnt]);
if(null === denytenant){
error = new Error('To allow Tenant name(' + denytenants[cnt] + ') is something wrong.');
return error;
}
result = k2hr3.denyTenantFromService(owner, servicename, denytenant);
if(!apiutil.isSafeEntity(result) || !apiutil.isSafeEntity(result.result) || false === result.result){
if(!apiutil.isSafeEntity(result)){
error = new Error('Could not get response from denyTenantToService');
}else{
error = new Error('Could not get error message in response from denyTenantToService');
}
return error;
}
}
}
if(null === result){
error = new Error('Internal error: rawUpdateService');
return error;
}
r3logger.dlog('succeed : ' + result.message);
return null;
}
//
// Mountpath : '/v1/service'
//
// POST '/v1/service' : post service on version 1
// HEADER : X-Auth-Token => Scoped User token
// response body : result => true/false
// message => messages
// body :
// {
// "name": <service name> => key is "yrn:yahoo::::service:<service>"
// "verify": <verify url> => key is "yrn:yahoo::::service:<service>:verify"
// when the value is URL, it is save as URL string.
// the value is allowed null or undefined, then verify url value is null.
// the value is allowed string(not URL), it is saved and converted by JSON.
// }
//
// POST '/v1/service/<service>' : post tenant or verify for service on version 1
// HEADER : X-Auth-Token => Scoped User token
// response body : result => true/false
// message => messages
// body :
// {
// "tenant": <tenant name> or array => key is "yrn:yahoo::::service:<service>:tenant"
// if this key is specified, adding tenants to service
// the value is string for tenant name, or array of tenant name list
// "clear_tenant": true/false => true means clear existing tenant without "tenant".
// default false
// "verify": <verify url> => key is "yrn:yahoo::::service:<service>:verify"
// if this key is specified, updating verify url.
// when the value is URL, it is save as URL string.
// the value is allowed string(not URL), it is saved and converted by JSON.
// }
// }
//
// [NOTE]
// Verify URL is used as following formatted:
//
// GET http://<verify host[:port]>{/<path>}?service=<service name>&tenant=<tenant name>&tenantid=<tenant id>&user=<user name>&userid=<user id>
//
// service : service name
// tenant : tenant name
// tenantid : tenant id
// user : user name
// userid : user id
//
// And it's response is following:
// response body = [ => undefined/null or resource array(if one element, allows only it not array)
// {
// name => resource name which is key name(path) for resource
// expire => undefined/null or integer
// type => resource data type(string or object), if date is null or '', this value must be string.
// data => resource data which must be string or object or null/undefined.
// keys = { => resource has keys(associative array), or null/undefined.
// 'foo': bar, => any value is allowed
// ...
// }
// },
// ...
// ]
//
router.post('/', function(req, res, next) // eslint-disable-line no-unused-vars
{
r3logger.dlog('CALL:', req.method, req.url);
res.type('application/json; charset=utf-8');
var result = { result: true, message: null };
if( !apiutil.isSafeEntity(req) ||
!apiutil.isSafeEntity(req.baseUrl) ||
!apiutil.isSafeEntity(req.body) )
{
result = {
result: false,
message: 'POST body does not exist'
};
r3logger.elog(result.message);
resutil.errResponse(req, res, 400, result); // 400: Bad Request
return;
}
//------------------------------
// check token
//------------------------------
var token_result = r3token.checkToken(req, true, true); // scoped, user token
if(!token_result.result){
r3logger.elog(token_result.message);
var _status = token_result.status;
delete token_result.status;
resutil.errResponse(req, res, _status, token_result);
return;
}
var token_info = token_result.token_info;
//------------------------------
// check service path in url
//------------------------------
var name = null;
var is_create = false;
var requestptn = new RegExp('^/v1/service/(.*)'); // regex = /^\/v1\/service\/(.*)/
var reqmatchs = decodeURI(req.baseUrl).match(requestptn);
if(apiutil.isEmptyArray(reqmatchs) || reqmatchs.length < 2 || '' === apiutil.getSafeString(reqmatchs[1])){
is_create = true;
}else{
name = reqmatchs[1].toLowerCase();
is_create = false;
}
//------------------------------
// check arguments
//------------------------------
var verify = null;
var tenant = null;
var is_clear = false;
var cnt;
if(is_create){
if(!apiutil.isSafeString(req.body.name)){
result = {
result: false,
message: 'service:name field is wrong : ' + JSON.stringify(req.body.name)
};
r3logger.elog(result.message);
resutil.errResponse(req, res, 400, result); // 400: Bad Request
return;
}
name = req.body.name.toLowerCase();
if(apiutil.isSafeEntity(req.body.verify)){
verify = req.body.verify;
}
}else{
if(apiutil.isSafeEntity(req.body.tenant)){
tenant = req.body.tenant;
if(apiutil.checkSimpleJSON(tenant)){
tenant = JSON.parse(tenant);
}
if(apiutil.isArray(tenant)){
var tmparr = [];
for(cnt = 0; cnt < tenant.length; ++cnt){
if(!apiutil.isSafeString(tenant[cnt])){
continue;
}
tmparr.push(tenant[cnt].toLowerCase());
}
tenant = tmparr;
}else if(apiutil.isSafeString(tenant)){
tenant = [tenant.toLowerCase()];
}else{
tenant = null;
}
if(apiutil.isEmptyArray(tenant)){
tenant = null;
}
}
if(apiutil.isSafeEntity(req.body.clear_tenant) && 'boolean' === typeof req.body.clear_tenant && true === req.body.clear_tenant){
is_clear = true;
}
if(apiutil.isSafeEntity(req.body.verify)){
verify = req.body.verify;
}
if(null === tenant && null === verify){
result = {
result: false,
message: 'both tenant and verify are not specified.'
};
r3logger.elog(result.message);
resutil.errResponse(req, res, 400, result); // 400: Bad Request
return;
}
}
//------------------------------
// create/update service
//------------------------------
var error = rawUpdateService(token_info.tenant, name, verify, tenant, is_clear, is_create);
if(null !== error){
result = {
result: false,
message: error.message
};
r3logger.elog(result.message);
resutil.errResponse(req, res, 403, result); // 403: Forbidden(is this status OK?)
return;
}
res.status(201); // 201: Created
res.send(JSON.stringify(result));
});
//
// Mountpath : '/v1/service/*'
//
// PUT '/v1/service' : post service on version 1
// HEADER : X-Auth-Token => Scoped User token
// response body : result => true/false
// message => messages
// URL argument
// "name" : <service name> => key is "yrn:yahoo::::service:<service>"
// "verify" : <verify url> => key is "yrn:yahoo::::service:<service>:verify"
// when the value is URL, it is save as URL string.
// the value is allowed null or undefined, then verify url value is null.
// the value is allowed string(not URL), it is saved and converted by JSON.
//
// PUT '/v1/service/<service>' : post tenant or verify for service on version 1
// HEADER : X-Auth-Token => Scoped User token
// response body : result => true/false
// message => messages
// URL argument
// "tenant" : <tenant name> => key is "yrn:yahoo::::service:<service>:tenant"
// if this key is specified, adding tenants to service
// the value is string for tenant name of tenant name list
// "clear_tenant" : true/false => true means clear existing tenant without "tenant".
// default false
// "verify" : <verify url> => key is "yrn:yahoo::::service:<service>:verify"
// when the value is URL, it is save as URL string.
// the value is allowed string(not URL), it is saved and converted by JSON.
//
// [NOTE] see POST
//
router.put('/', function(req, res, next) // eslint-disable-line no-unused-vars
{
r3logger.dlog('CALL:', req.method, req.url);
res.type('application/json; charset=utf-8');
var result = { result: true, message: null };
if( !apiutil.isSafeEntity(req) ||
!apiutil.isSafeEntity(req.baseUrl) ||
!apiutil.isSafeEntity(req.query) )
{
result = {
result: false,
message: 'PUT argument does not have any data'
};
r3logger.elog(result.message);
resutil.errResponse(req, res, 400, result); // 400: Bad Request
return;
}
//------------------------------
// check token
//------------------------------
var token_result = r3token.checkToken(req, true, true); // scoped, user token
if(!token_result.result){
r3logger.elog(token_result.message);
var _status = token_result.status;
delete token_result.status;
resutil.errResponse(req, res, _status, token_result);
return;
}
var token_info = token_result.token_info;
//------------------------------
// check service path in url
//------------------------------
var name = null;
var is_create = false;
var requestptn = new RegExp('^/v1/service/(.*)'); // regex = /^\/v1\/service\/(.*)/
var reqmatchs = decodeURI(req.baseUrl).match(requestptn);
if(apiutil.isEmptyArray(reqmatchs) || reqmatchs.length < 2 || '' === apiutil.getSafeString(reqmatchs[1])){
is_create = true;
}else{
name = reqmatchs[1].toLowerCase();
is_create = false;
}
//------------------------------
// check arguments
//------------------------------
var verify = null;
var tenant = null;
var is_clear = false;
if(is_create){
if(!apiutil.isSafeString(req.query.name)){
result = {
result: false,
message: 'name argument is wrong : ' + JSON.stringify(req.query.name)
};
r3logger.elog(result.message);
resutil.errResponse(req, res, 400, result); // 400: Bad Request
return;
}
name = req.query.name.toLowerCase();
if(apiutil.isSafeEntity(req.query.verify)){
verify = req.query.verify;
if(apiutil.checkSimpleJSON(verify)){
verify = JSON.parse(verify);
}
}
}else{
if(apiutil.isSafeString(req.query.tenant)){
tenant = req.query.tenant;
if(apiutil.checkSimpleJSON(tenant)){
tenant = JSON.parse(tenant);
}
if(apiutil.isArray(tenant)){
var tmparr = [];
for(var cnt = 0; cnt < tenant.length; ++cnt){
if(!apiutil.isSafeString(tenant[cnt])){
continue;
}
tmparr.push(tenant[cnt].toLowerCase());
}
tenant = tmparr;
}else if(apiutil.isSafeString(tenant)){
tenant = [tenant.toLowerCase()];
}else{
tenant = null;
}
if(apiutil.isEmptyArray(tenant)){
tenant = null;
}
}
if(apiutil.isSafeEntity(req.query.clear_tenant)){
if( ('boolean' === typeof req.query.clear_tenant && true === req.query.clear_tenant) ||
(apiutil.isSafeString(req.query.clear_tenant) && (apiutil.compareCaseString('true', req.query.clear_tenant) || apiutil.compareCaseString('1', req.query.clear_tenant))) )
{
is_clear = true;
}
}
if(apiutil.isSafeEntity(req.query.verify)){
verify = req.query.verify;
if(apiutil.checkSimpleJSON(verify)){
verify = JSON.parse(verify);
}
}
if(null === tenant && null === verify){
result = {
result: false,
message: 'both tenant and verify are not specified.'
};
r3logger.elog(result.message);
resutil.errResponse(req, res, 400, result); // 400: Bad Request
return;
}
}
//------------------------------
// create/update service
//------------------------------
var error = rawUpdateService(token_info.tenant, name, verify, tenant, is_clear, is_create);
if(null !== error){
result = {
result: false,
message: error.message
};
r3logger.elog(result.message);
resutil.errResponse(req, res, 403, result); // 403: Forbidden(is this status OK?)
return;
}
res.status(201); // 201: Created
res.send(JSON.stringify(result));
});
//
// Mountpath : '/v1/service/*'
//
// GET '/v1/service/<service>' : get service on version 1
// HEADER : X-Auth-Token => Scoped User token
// response body : result => true/false
// message => error message
// service => object
// service object
// {
// "verify": <verify url> or <verify object>
// "tenant": [
// <tenant yrn full path>,
// ...
// ]
// }
//
router.get('/', function(req, res, next)
{
r3logger.dlog('CALL:', req.method, req.url);
if('GET' !== req.method){
// HEAD request comes here, so it should be routed to head function.
next();
return;
}
res.type('application/json; charset=utf-8');
var result;
if( !apiutil.isSafeEntity(req) ||
!apiutil.isSafeEntity(req.baseUrl) )
{
result = {
result: false,
message: 'GET request or url is wrong'
};
r3logger.elog(result.message);
resutil.errResponse(req, res, 400, result); // 400: Bad Request
return;
}
//------------------------------
// check token
//------------------------------
var token_result = r3token.checkToken(req, true, true); // scoped, user token
if(!token_result.result){
r3logger.elog(token_result.message);
var _status = token_result.status;
delete token_result.status;
resutil.errResponse(req, res, _status, token_result);
return;
}
var token_info = token_result.token_info;
//------------------------------
// check service path in url
//------------------------------
var requestptn = new RegExp('^/v1/service/(.*)'); // regex = /^\/v1\/service\/(.*)/
var reqmatchs = decodeURI(req.baseUrl).match(requestptn);
if(apiutil.isEmptyArray(reqmatchs) || reqmatchs.length < 2 || '' === apiutil.getSafeString(reqmatchs[1])){
result = {
result: false,
message: 'GET request url does not have service name'
};
r3logger.elog(result.message);
resutil.errResponse(req, res, 400, result); // 400: Bad Request
return;
}
var servicename = reqmatchs[1].toLowerCase();
//------------------------------
// get all service
//------------------------------
result = k2hr3.getService(token_info.tenant, servicename);
if(!apiutil.isSafeEntity(result) || !apiutil.isSafeEntity(result.result) || false === result.result){
if(!apiutil.isSafeEntity(result)){
result = {
result: false,
message: 'Could not get service data from getService'
};
}else{
if(!apiutil.isSafeEntity(result.result)){
result.result = false;
}
if(!apiutil.isSafeEntity(result.message)){
result.message = 'Could not get error message in response from getService';
}
}
r3logger.elog(result.message);
resutil.errResponse(req, res, 403, result); // 403: Forbidden(is this status OK?)
return;
}
//
// Remove owner/name from result
//
if(apiutil.isSafeEntity(result.name)){
delete result.name;
}
if(apiutil.isSafeEntity(result.owner)){
delete result.owner;
}
r3logger.dlog('succeed : ' + result.message);
res.status(200); // 200: OK
res.send(JSON.stringify(result));
});
//
// Mountpath : '/v1/service/*'
//
// HEAD '/v1/service/<service>' : head service on version 1
// HEADER : X-Auth-Token => Scoped User token
//
// HEAD '/v1/service/<service>' : head tenant is allowed in service's tenant list on version 1
// HEADER : X-Auth-Token => Scoped User token
// URL argument :
// "tenant" : <tenant name> => key is "yrn:yahoo::::service:<service>:tenant"
// if this key is specified, check tenant is allowed.
//
router.head('/', function(req, res, next)
{
r3logger.dlog('CALL:', req.method, req.url);
if('HEAD' !== req.method){
// If other method request comes here, so it should be routed another function.
next();
return;
}
res.type('application/json; charset=utf-8');
var result;
if( !apiutil.isSafeEntity(req) ||
!apiutil.isSafeEntity(req.baseUrl) )
{
result = {
result: false,
message: 'HEAD request or url or query is wrong'
};
r3logger.elog(result.message);
resutil.errResponse(req, res, 400, result); // 400: Bad Request
return;
}
//------------------------------
// check token
//------------------------------
var token_result = r3token.checkToken(req, true, true); // scoped, user token
if(!token_result.result){
r3logger.elog(token_result.message);
var _status = token_result.status;
delete token_result.status;
resutil.errResponse(req, res, _status, token_result);
return;
}
var token_info = token_result.token_info;
//------------------------------
// check service path in url
//------------------------------
var requestptn = new RegExp('^/v1/service/(.*)'); // regex = /^\/v1\/service\/(.*)/
var reqmatchs = decodeURI(req.baseUrl).match(requestptn);
if(apiutil.isEmptyArray(reqmatchs) || reqmatchs.length < 2 || '' === apiutil.getSafeString(reqmatchs[1])){
result = {
result: false,
message: 'GET request url does not have service name'
};
r3logger.elog(result.message);
resutil.errResponse(req, res, 400, result); // 400: Bad Request
return;
}
var servicename = reqmatchs[1].toLowerCase();
//------------------------------
// check arguments
//------------------------------
var tenantyrn = null;
if(apiutil.isSafeString(req.query.tenant)){
var keys = r3keys(null, req.query.tenant.toLowerCase(), null);
tenantyrn = keys.MASTER_TENANT_TOP_KEY; // tenant full yrn : "yrn:yahoo:::<tenant>"
}
//------------------------------
// get all service
//------------------------------
result = k2hr3.getService(token_info.tenant, servicename);
if(!apiutil.isSafeEntity(result) || !apiutil.isSafeEntity(result.result) || false === result.result){
if(!apiutil.isSafeEntity(result)){
result = {
result: false,
message: 'Could not get service data from getService'
};
}else{
if(!apiutil.isSafeEntity(result.result)){
result.result = false;
}
if(!apiutil.isSafeEntity(result.message)){
result.message = 'Could not get error message in response from getService';
}
}
r3logger.elog(result.message);
resutil.errResponse(req, res, 400, result); // 400: Bad Request
return;
}
if(null !== tenantyrn){
// tenant check
if(!apiutil.isSafeEntity(result.service) || !apiutil.isArray(result.service.tenant) || !apiutil.findStringInArray(result.service.tenant, tenantyrn)){
result = {
result: false,
message: 'Deny tenant(' + req.query.tenant.toLowerCase() + ') for service(' + servicename + ')'
};
r3logger.elog(result.message);
resutil.errResponse(req, res, 403); // 403: Forbidden(is this status OK?)
return;
}
}
r3logger.dlog('succeed : ' + result.message);
res.status(204); // 204: No Content
res.send();
});
//
// Mountpath : '/v1/service/*'
//
// DELETE '/v1/service/<service>' : delete service on version 1
// remove service and all related to service.
// HEADER : X-Auth-Token => Scoped User token
//
// DELETE '/v1/service/<service>' : delete tenant from service's tenant list on version 1
// HEADER : X-Auth-Token => Scoped User token
// URL argument :
// "tenant" : <tenant name> => key is "yrn:yahoo::::service:<service>:tenant"
// if this key is specified, removing tenant from service
//
router.delete('/', function(req, res, next) // eslint-disable-line no-unused-vars
{
r3logger.dlog('CALL:', req.method, req.url);
res.type('application/json; charset=utf-8');
var result;
if( !apiutil.isSafeEntity(req) ||
!apiutil.isSafeEntity(req.baseUrl) )
{
result = {
result: false,
message: 'DELETE request or url or query is wrong'
};
r3logger.elog(result.message);
resutil.errResponse(req, res, 400); // 400: Bad Request
return;
}
//------------------------------
// check token
//------------------------------
var token_result = r3token.checkToken(req, true, true); // scoped, user token
if(!token_result.result){
r3logger.elog(token_result.message);
var _status = token_result.status;
delete token_result.status;
resutil.errResponse(req, res, _status, token_result);
return;
}
var token_info = token_result.token_info;
//------------------------------
// check service path in url
//------------------------------
var requestptn = new RegExp('^/v1/service/(.*)'); // regex = /^\/v1\/service\/(.*)/
var reqmatchs = decodeURI(req.baseUrl).match(requestptn);
if(apiutil.isEmptyArray(reqmatchs) || reqmatchs.length < 2 || '' === apiutil.getSafeString(reqmatchs[1])){
result = {
result: false,
message: 'DELETE request url does not have service name'
};
r3logger.elog(result.message);
resutil.errResponse(req, res, 400, result); // 400: Bad Request
return;
}
var servicename = reqmatchs[1].toLowerCase();
//------------------------------
// check arguments
//------------------------------
var tenantname = null;
if(apiutil.isSafeString(req.query.tenant)){
tenantname = req.query.tenant.toLowerCase();
}
//------------------------------
// Do remove
//------------------------------
if(null === tenantname){
// remove service and all
result = k2hr3.removeService(token_info.tenant, servicename);
}else{
// remove tenant from service's tenant list
result = k2hr3.removeServiceTenant(token_info.user, tenantname, servicename);
}
if(!apiutil.isSafeEntity(result) || !apiutil.isSafeEntity(result.result) || false === result.result){
if(!apiutil.isSafeEntity(result)){
result = {
result: false,
message: 'Could not remove service data from ' + (null === tenantname ? 'removeService' : 'denyTenantFromService')
};
}else{
if(!apiutil.isSafeEntity(result.result)){
result.result = false;
}
if(!apiutil.isSafeEntity(result.message)){
result.message = 'Could not get error message in response from ' + (null === tenantname ? 'removeService' : 'denyTenantFromService');
}
}
r3logger.elog(result.message);
resutil.errResponse(req, res, 403); // 403: Forbidden(is this status OK?)
return;
}
r3logger.dlog('succeed : ' + result.message);
res.status(204); // 204: No Content
res.send();
});
module.exports = router;
/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* End:
* vim600: noexpandtab sw=4 ts=4 fdm=marker
* vim<600: noexpandtab sw=4 ts=4
*/