api/v1/src/accounts/index.js (269 lines of code) (raw):
/**
* Copyright 2020-2022 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
'use strict';
const express = require('express');
const dataManager = require("./dataManager");
const procurementManager = require("./../procurements/dataManager");
const cfg = require('../lib/config');
const { CommonUtil } = require('cds-shared');
const runtimeConfig = require('../lib/runtimeConfig');
const commonUtil = CommonUtil;
/************************************************************
API Endpoints
************************************************************/
// Define the routes for the REST API
var accounts = express.Router();
// methods that require multiple routes
/**
* @swagger
*
*
* definitions:
* ModifyAccountResponse:
* type: object
* description: Account object
* properties:
* email:
* type: string
* description: Account email address
* emailType:
* $ref: '#/definitions/EmailType'
* accountType:
* $ref: '#/definitions/AccountType'
* createdBy:
* type: string
* description: Account created by email
* policies:
* type: array
* description: Account policy IDs
* items:
* type: object
* properties:
* policyId:
* type: string
* description: Policy ID
* marketplace:
* $ref: '#/definitions/Marketplace'
* rowId:
* type: string
* readOnly: true
* description: Account Row ID
* accountId:
* type: string
* readOnly: true
* description: Account ID
* isDeleted:
* type: boolean
* description: Flag indicating deletion status
* createdAt:
* type: integer
* description: Created at time
*
* Account:
* type: object
* description: Account object
* properties:
* rowId:
* type: string
* readOnly: true
* description: Account Row ID
* accountId:
* type: string
* readOnly: true
* description: Account ID
* email:
* type: string
* description: Account email address
* emailType:
* $ref: '#/definitions/EmailType'
* accountType:
* $ref: '#/definitions/AccountType'
* createdBy:
* type: string
* description: Account created by email
* marketplace:
* $ref: '#/definitions/Marketplace'
* createdAt:
* type: integer
* description: Created at time
* version:
* type: integer
* description: The object version
* isDeleted:
* type: boolean
* description: Flag indicating deletion status
* policies:
* type: array
* description: Account policy IDs
* items:
* type: object
* description: Policy ID object
* properties:
* policyId:
* type: string
* description: Policy ID
* name:
* type: string
* description: Policy name
* solutionId:
* type: string
* description: Linked marketplace solution Id
* planId:
* type: string
* description: Linked marketplace plan Id
* marketplaceEntitlementActive:
* type: boolean
* description: Indicates if marketplace entitlements are in sync for policy
* marketplaceSynced:
* type: boolean
* description: Indicates if marketplace entitlements are in sync for account
* marketplaceActivated:
* type: boolean
* description: Indicates if account is linked and activated in marketplace
* required:
* - email
* - emailType
* - accountType
*
*
* EmailType:
* type: string
* description: Account Email Type enum
* enum:
* - user
* - group
* - serviceAccount
*
* AccountType:
* type: string
* description: Account Type enum
* enum:
* - consumer
* - producer
*
* Marketplace:
* type: object
* description: Marketplace object
* properties:
* accountName:
* type: string
* description: The associated marketplace account name
*/
/**
* @swagger
*
* /accounts:
* options:
* summary: CORS support
* description: Enable CORS by returning correct headers
* operationId: optionsAccounts
* tags:
* - accounts
* security: [] # no security for preflight requests
* produces:
* - application/json
* responses:
* 200:
* description: Default response for CORS method
* headers:
* Access-Control-Allow-Headers:
* type: "string"
* Access-Control-Allow-Methods:
* type: "string"
* Access-Control-Allow-Origin:
* type: "string"
* get:
* summary: List Account based off request parameters
* description: Returns the PolicyList response
* operationId: listAccounts
* tags:
* - accounts
* parameters:
* - in: header
* name: x-gcp-project-id
* type: string
* required: true
* description: The GCP projectId of the target project.
* produces:
* - application/json
* responses:
* 200:
* description: Account list
* schema:
* type: object
* properties:
* code:
* type: integer
* default: 200
* description: HTTP status code
* success:
* type: boolean
* description: Success of the request
* data:
* type: array
* items:
* $ref: '#/definitions/Account'
* 500:
* description: Error
* schema:
* $ref: '#/definitions/Error'
*/
accounts.get('/accounts', async (req, res) => {
const projectId = req.header('x-gcp-project-id');
const data = await dataManager.listAccounts(projectId);
var code;
if (data && data.success === false) {
code = (data.code === undefined) ? 500 : data.code;
} else {
code = (data.code === undefined) ? 200 : data.code;
}
res.status(code).json({
code: code,
...data
});
});
/**
* @swagger
*
* /accounts:
* post:
* summary: Create Account based off request body
* description: Returns the Datset response
* operationId: createAccount
* tags:
* - accounts
* parameters:
* - in: header
* name: x-gcp-project-id
* type: string
* required: true
* - in: body
* name: account
* description: Request parameters for Account
* schema:
* type: object
* description: Account object
* properties:
* email:
* type: string
* description: Account email address
* emailType:
* $ref: '#/definitions/EmailType'
* policies:
* type: array
* items:
* type: string
* description: Policy Id
* marketplace:
* $ref: '#/definitions/Marketplace'
* responses:
* 201:
* description: Account
* schema:
* $ref: '#/definitions/ModifyAccountResponse'
* 500:
* description: Error
* schema:
* $ref: '#/definitions/Error'
*/
accounts.post('/accounts', async (req, res) => {
const projectId = req.header('x-gcp-project-id');
if (!req.body.email) {
return res.status(400).json({
success: false,
code: 400,
errors: ['account email parameter is required']
});
}
if (req.body.rowId || req.body.accountId) {
return res.status(400).json({
success: false,
code: 400,
errors: ['rowId and accountId should not be provided']
});
}
const values = {
email: req.body.email,
emailType: req.body.emailType,
accountType: req.body.accountType,
createdBy: res.locals.email,
policies: req.body.policies,
marketplace: req.body.marketplace
};
const data = await dataManager.createOrUpdateAccount(projectId, null, values);
var code;
if (data && data.success === false) {
code = (data.code === undefined) ? 500 : data.code;
} else {
code = (data.code === undefined) ? 201 : data.code;
}
res.status(code).json({
code: code,
...data
});
});
/**
* @swagger
*
* /accounts/{accountId}:
* options:
* summary: CORS support
* description: Enable CORS by returning correct headers
* operationId: optionsAccountByAccountId
* tags:
* - accounts
* security: [] # no security for preflight requests
* parameters:
* - in: path
* name: accountId
* type: string
* required: true
* description: Account Id of the Account request
* produces:
* - application/json
* responses:
* 200:
* description: Default response for CORS method
* headers:
* Access-Control-Allow-Headers:
* type: "string"
* Access-Control-Allow-Methods:
* type: "string"
* Access-Control-Allow-Origin:
* type: "string"
* get:
* summary: Get Account based off accountId
* description: Returns the Datset response
* operationId: getAccountByAccountId
* tags:
* - accounts
* parameters:
* - in: header
* name: x-gcp-project-id
* type: string
* required: true
* - in: path
* name: accountId
* type: string
* required: true
* description: Account Id of the Account request
* produces:
* - application/json
* responses:
* 200:
* description: Account
* schema:
* type: object
* properties:
* code:
* type: integer
* default: 200
* description: HTTP status code
* success:
* type: boolean
* description: Success of the request
* data:
* $ref: '#/definitions/Account'
* 404:
* description: Error
* schema:
* $ref: '#/definitions/Error'
*/
accounts.get('/accounts/:accountId', async (req, res) => {
const projectId = req.header('x-gcp-project-id');
const accountId = req.params.accountId;
const data = await dataManager.getAccount(projectId, accountId);
const success = data !== null;
var code;
if (data && success === false) {
code = 404;
} else {
code = 200;
}
res.status(code).json({
code,
success,
data,
});
});
/**
* @swagger
*
* /accounts/{accountId}:
* put:
* summary: Update Account based off account ID and request body
* description: Returns the Account response
* operationId: updateAccountByAccountId
* tags:
* - accounts
* parameters:
* - in: path
* name: accountId
* type: string
* required: true
* description: Account Id of the Account request
* - in: header
* name: x-gcp-project-id
* type: string
* required: true
* - in: body
* name: account
* description: Request parameters for Account
* schema:
* type: object
* description: Account object
* properties:
* rowId:
* type: string
* description: The rowId of the modified account
* email:
* type: string
* description: Account email address
* emailType:
* $ref: '#/definitions/EmailType'
* policies:
* type: array
* items:
* type: string
* description: Policy Id
* marketplace:
* $ref: '#/definitions/Marketplace'
* produces:
* - application/json
* responses:
* 200:
* description: Account
* schema:
* type: object
* properties:
* code:
* type: integer
* description: HTTP status code
* success:
* type: boolean
* description: Success of the request
* data:
* $ref: '#/definitions/ModifyAccountResponse'
* 500:
* description: Error
* schema:
* $ref: '#/definitions/Error'
*/
accounts.put('/accounts/:accountId', async (req, res) => {
const projectId = req.header('x-gcp-project-id');
const accountId = req.params.accountId;
if (!req.body.email) {
return res.status(400).json({
success: false,
code: 400,
errors: ['account email parameter is required']
});
}
if (!req.body.rowId) {
return res.status(400).json({
success: false,
code: 400,
errors: ['rowId parameter is required']
});
}
const values = {
rowId: req.body.rowId,
email: req.body.email,
emailType: req.body.emailType,
accountType: req.body.accountType,
createdBy: res.locals.email,
policies: req.body.policies,
marketplace: req.body.marketplace
};
const data = await dataManager.createOrUpdateAccount(projectId, accountId, values);
var code;
if (data && data.success === false) {
code = (data.code === undefined) ? 500 : data.code;
} else {
code = (data.code === undefined) ? 200 : data.code;
}
res.status(code).json({
code: code,
...data
});
});
/**
* @swagger
*
* /accounts/{accountId}:
* delete:
* summary: Delete Account based off account ID and request body
* description: Returns the Account response
* operationId: deleteAccountByAccountId
* tags:
* - accounts
* parameters:
* - in: path
* name: accountId
* type: string
* required: true
* description: Account Id of the Account request
* - in: header
* name: x-gcp-project-id
* type: string
* required: true
* - in: body
* name: account
* description: Request parameters for Account deletion
* schema:
* type: object
* properties:
* rowId:
* type: string
* description: The rowId of the account to delete
* produces:
* - application/json
* responses:
* 200:
* description: Account
* schema:
* type: object
* properties:
* success:
* type: boolean
* description: Success of the request
* code:
* type: integer
* description: HTTP status code
* 500:
* description: Error
* schema:
* $ref: '#/definitions/Error'
*/
accounts.delete('/accounts/:accountId', async (req, res) => {
const projectId = req.header('x-gcp-project-id');
const accountId = req.params.accountId;
const values = {
rowId: req.body.rowId,
createdBy: res.locals.email
};
const data = await dataManager.deleteAccount(projectId, accountId, values);
var code;
if (data && data.success === false) {
code = (data.code === undefined) ? 500 : data.code;
} else {
code = (data.code === undefined) ? 200 : data.code;
}
res.status(code).json({
code: code,
...data
});
});
/**
* @swagger
*
* /policies/{policyId}/accounts:
* options:
* summary: CORS support
* description: Enable CORS by returning correct headers
* operationId: optionsAccountByPolicyId
* tags:
* - policies
* security: [] # no security for preflight requests
* parameters:
* - in: path
* name: policyId
* type: string
* required: true
* description: Policy Id of the Policy request
* produces:
* - application/json
* responses:
* 200:
* description: Default response for CORS method
* headers:
* Access-Control-Allow-Headers:
* type: "string"
* Access-Control-Allow-Methods:
* type: "string"
* Access-Control-Allow-Origin:
* type: "string"
* get:
* summary: List Accounts of policy based off policyId and request parameters
* description: Returns the Account list response
* operationId: listAccountsByPolicyId
* tags:
* - policies
* parameters:
* - in: path
* name: policyId
* type: string
* required: true
* description: Policy Id of the Policy request
* - in: header
* name: x-gcp-project-id
* type: string
* required: true
* produces:
* - application/json
* responses:
* 200:
* description: Account list
* schema:
* type: object
* properties:
* code:
* type: integer
* default: 200
* description: HTTP status code
* success:
* type: boolean
* description: Success of the request
* data:
* type: array
* items:
* type: object
* description: Account object
* properties:
* email:
* type: string
* description: Account email address
* emailType:
* $ref: '#/definitions/EmailType'
* marketplace:
* $ref: '#/definitions/Marketplace'
* marketplaceSynced:
* type: boolean
* description: Indicates if marketplace entitlements are in sync for account
* marketplaceActivated:
* type: boolean
* description: Indicates if account is linked and activated in marketplace
* required:
* - email
* - emailType
* - accountType
* 500:
* description: Error
* schema:
* $ref: '#/definitions/Error'
*/
accounts.get('/policies/:policyId/accounts', async (req, res) => {
const projectId = req.header('x-gcp-project-id');
const policyId = req.params.policyId;
const data = await dataManager.listAccounts(projectId, null, policyId);
var code;
if (data && data.success === false) {
code = (data.code === undefined) ? 500 : data.code;
} else {
code = (data.code === undefined) ? 200 : data.code;
}
res.status(code).json({
code: code,
...data
});
});
/**
* @swagger
*
* /datasets/{datasetId}/accounts:
* options:
* summary: CORS support
* description: Enable CORS by returning correct headers
* operationId: optionsAccountByDatasetId
* security: [] # no security for preflight requests
* tags:
* - datasets
* parameters:
* - in: path
* name: datasetId
* type: string
* required: true
* description: Dataset Id of the Account request
* produces:
* - application/json
* responses:
* 200:
* description: Default response for CORS method
* headers:
* Access-Control-Allow-Headers:
* type: "string"
* Access-Control-Allow-Methods:
* type: "string"
* Access-Control-Allow-Origin:
* type: "string"
* get:
* summary: List Accounts based off datasetId and request parameters
* description: Returns the AccountList response
* operationId: listAccountsByDatasetId
* tags:
* - datasets
* parameters:
* - in: path
* name: datasetId
* type: string
* required: true
* description: Dataset Id of the Policy request
* - in: header
* name: x-gcp-project-id
* type: string
* required: true
* produces:
* - application/json
* responses:
* 200:
* description: Account list
* schema:
* type: object
* properties:
* code:
* type: integer
* default: 200
* description: HTTP status code
* success:
* type: boolean
* description: Success of the request
* data:
* type: array
* items:
* $ref: '#/definitions/Account'
* 500:
* description: Error
* schema:
* $ref: '#/definitions/Error'
*/
accounts.get('/datasets/:datasetId/accounts', async (req, res) => {
const projectId = req.header('x-gcp-project-id');
const datasetId = req.params.datasetId;
const data = await dataManager.listAccounts(projectId, datasetId);
var code;
if (data && data.success === false) {
code = (data.code === undefined) ? 500 : data.code;
} else {
code = (data.code === undefined) ? 200 : data.code;
}
res.status(code).json({
code: code,
...data
});
});
/**
* @swagger
*
* /accounts:register:
* options:
* summary: CORS support
* description: Enable CORS by returning correct headers
* operationId: optionsRegisterAccountGet
* tags:
* - accounts
* security: [] # no security for preflight requests
* produces:
* - application/json
* responses:
* 200:
* description: Default response for CORS method
* headers:
* Access-Control-Allow-Headers:
* type: "string"
* Access-Control-Allow-Methods:
* type: "string"
* Access-Control-Allow-Origin:
* type: "string"
* get:
* summary: Register a marketplace account based off request body
* description: Returns a redirect response
* operationId: registerAccountGet
* security: [] # no security for marketplace register get request
* tags:
* - accounts
* parameters:
* - in: header
* name: x-gcp-project-id
* type: string
* required: true
* - in: query
* name: projectId
* type: string
* description: The projectId
* required: false
* - in: query
* name: x-gcp-marketplace-token
* type: string
* description: JWT token provided by marketplace
* required: true
* responses:
* 301:
* description: Account
* headers:
* Set-Cookie:
* type: string
* description: "Example: gmt=jwt_token"
* location:
* type: string
* description: If activation success, will redirect to activation page. If activation fails, will redirect to activation error page.
*/
accounts.get('/accounts:register', async (req, res) => {
const currentProjectId = await runtimeConfig.getCurrentProjectId();
let projectId = req.params.projectId || currentProjectId;
// Check if override for projectId is set
const p = req.query.projectId;
if (p) {
projectId = p;
}
const token = req.query['x-gcp-marketplace-token'];
console.log(`Register called for project ${projectId}, x-gcp-marketplace-token: ${token}, body: ${JSON.stringify(req.body)}`);
const host = commonUtil.extractHostname(req.headers.host);
const data = await dataManager.register(host, token);
console.log(`Data: ${JSON.stringify(data)}`);
if (data && data.success === false) {
res.clearCookie(cfg.gcpMarketplaceTokenCookieName);
res.redirect(cfg.uiBaseUrl + '/activationError');
} else {
const uiHost = commonUtil.extractHostname(cfg.uiBaseUrl);
res.cookie(cfg.gcpMarketplaceTokenCookieName, token, { secure: host == 'localhost' ? false : true, expires: 0, domain: uiHost });
res.redirect(cfg.uiBaseUrl + `/activation?gmt=${token}&projectId=${projectId}`);
}
});
/**
* @swagger
*
* /accounts:register:
* post:
* summary: Register a marketplace account based off request body
* description: Returns a redirect response
* operationId: registerAccount
* security: [] # no security for marketplace register post request
* tags:
* - accounts
* parameters:
* - in: header
* name: x-gcp-project-id
* type: string
* required: true
* - in: query
* name: projectId
* type: string
* description: The projectId
* required: false
* - in: body
* name: account
* description: Request parameters for register account
* schema:
* type: object
* properties:
* x-gcp-marketplace-token:
* type: string
* description: GCP marketplace JWT
* responses:
* 301:
* description: Account
* headers:
* Set-Cookie:
* type: string
* description: "Example: gmt=jwt_token"
* location:
* type: string
* description: If activation success, will redirect to activation page. If activation fails, will redirect to activation error page.
*/
/**
* @swagger
*
* /accounts:activate:
* options:
* summary: CORS support
* description: Enable CORS by returning correct headers
* operationId: optionsActivateAccount
* tags:
* - accounts
* security: [] # no security for preflight requests
* produces:
* - application/json
* responses:
* 200:
* description: Default response for CORS method
* headers:
* Access-Control-Allow-Headers:
* type: "string"
* Access-Control-Allow-Methods:
* type: "string"
* Access-Control-Allow-Origin:
* type: "string"
* post:
* summary: Activates a marketplace account based off request body
* description: Returns a redirect response
* operationId: activateAccount
* tags:
* - accounts
* parameters:
* - in: header
* name: x-gcp-project-id
* type: string
* required: true
* - in: body
* name: account
* description: Request parameters for Account
* schema:
* type: object
* description: Account object
* properties:
* email:
* type: string
* description: Email account for approval
* reason:
* type: string
* description: Procurement approval reason
* responses:
* 200:
* description: Account
* schema:
* type: object
* properties:
* success:
* type: boolean
* description: Success of the request
* code:
* type: integer
* description: HTTP status code
* data:
* type: object
* items:
* $ref: '#/definitions/Account'
* 500:
* description: Error
* schema:
* $ref: '#/definitions/Error'
*/
/**
* @swagger
*
* /accounts:reset:
* options:
* summary: CORS support
* description: Enable CORS by returning correct headers
* operationId: optionsResetAccount
* tags:
* - accounts
* security: [] # no security for preflight requests
* produces:
* - application/json
* responses:
* 200:
* description: Default response for CORS method
* headers:
* Access-Control-Allow-Headers:
* type: "string"
* Access-Control-Allow-Methods:
* type: "string"
* Access-Control-Allow-Origin:
* type: "string"
* post:
* summary: Resets a marketplace account based off request body
* description: Returns a redirect response
* operationId: resetAccount
* tags:
* - accounts
* parameters:
* - in: header
* name: x-gcp-project-id
* type: string
* required: true
* - in: body
* name: account
* description: Request parameters for Account
* schema:
* type: object
* description: Account object
* properties:
* accountId:
* type: string
* description: The datashare accountId
* responses:
* 200:
* description: Account
* schema:
* type: object
* properties:
* success:
* type: boolean
* description: Success of the request
* code:
* type: integer
* description: HTTP status code
* data:
* type: object
* items:
* $ref: '#/definitions/Account'
* 500:
* description: Error
* schema:
* $ref: '#/definitions/Error'
*/
/**
* @swagger
*
* /accounts:syncMarketplace:
* options:
* summary: CORS support
* description: Enable CORS by returning correct headers
* operationId: optionsSyncMarketplace
* tags:
* - accounts
* security: [] # no security for preflight requests
* produces:
* - application/json
* responses:
* 200:
* description: Default response for CORS method
* headers:
* Access-Control-Allow-Headers:
* type: "string"
* Access-Control-Allow-Methods:
* type: "string"
* Access-Control-Allow-Origin:
* type: "string"
* post:
* summary: Syncs a marketplace account permissions based off request body
* description: Returns a redirect response
* operationId: syncMarketplaceAccount
* tags:
* - accounts
* parameters:
* - in: header
* name: x-gcp-project-id
* type: string
* required: true
* - in: body
* name: account
* description: Request parameters for Account
* schema:
* type: object
* description: Account object
* properties:
* accountId:
* type: string
* description: The datashare accountId
* responses:
* 200:
* description: Account
* schema:
* type: object
* properties:
* success:
* type: boolean
* description: Success of the request
* code:
* type: integer
* description: HTTP status code
* 500:
* description: Error
* schema:
* $ref: '#/definitions/Error'
*/
accounts.post('/accounts::custom', async (req, res) => {
let projectId = req.params.projectId || req.header('x-gcp-project-id');
const host = cfg.apiCustomDomain || commonUtil.extractHostname(req.headers.host);
switch (req.params.custom) {
case "register": {
// Check if override for projectId is set
const p = req.query.projectId;
if (p) {
projectId = p;
} else {
projectId = await runtimeConfig.getCurrentProjectId();
}
const token = req.body['x-gcp-marketplace-token'];
console.log(`Register called for project ${projectId}, x-gcp-marketplace-token: ${token}, body: ${JSON.stringify(req.body)}`);
const data = await dataManager.register(host, token);
console.log(`Data: ${JSON.stringify(data)}`);
if (data && data.success === false) {
res.clearCookie(cfg.gcpMarketplaceTokenCookieName);
res.redirect(cfg.uiBaseUrl + '/activationError');
} else {
const uiHost = commonUtil.extractHostname(cfg.uiBaseUrl);
res.cookie(cfg.gcpMarketplaceTokenCookieName, token, { secure: host == 'localhost' ? false : true, expires: 0, domain: uiHost });
res.redirect(cfg.uiBaseUrl + `/activation?gmt=${token}&projectId=${projectId}`);
}
break;
}
case "activate": {
const token = req.body['x-gcp-marketplace-token'];
const email = req.body.email;
const reason = req.body.reason;
console.log(`Activate called for project ${projectId}, token: ${token}, body: ${JSON.stringify(req.body)}`);
const data = await dataManager.activate(projectId, host, token, reason, email);
console.log(`Data: ${JSON.stringify(data)}`);
let code;
if (data && data.success === false) {
code = (data.code === undefined) ? 500 : data.code;
} else {
code = (data.code === undefined) ? 200 : data.code;
}
res.status(code).json({
code: code,
...data
});
break;
}
case "reset": {
const accountId = req.body.accountId;
console.log(`Reset account called for project ${projectId}, accountId: ${accountId}, body: ${JSON.stringify(req.body)}`);
const data = await dataManager.reset(projectId, accountId);
console.log(`Data: ${JSON.stringify(data)}`);
let code;
if (data && data.success === false) {
code = (data.code === undefined) ? 500 : data.code;
} else {
code = (data.code === undefined) ? 200 : data.code;
}
res.status(code).json({
code: code,
...data
});
break;
}
case "syncMarketplace": {
const accountId = req.body.accountId;
console.log(`Sync marketplace entitlements called for project ${projectId}, accountId: ${accountId}, body: ${JSON.stringify(req.body)}`);
const account = await dataManager.getAccount(projectId, accountId);
const data = await procurementManager.syncAccountEntitlements(projectId, account);
console.log(`Data: ${JSON.stringify(data)}`);
let code;
if (data && data.success === false) {
code = (data.code === undefined) ? 500 : data.code;
} else {
code = (data.code === undefined) ? 200 : data.code;
}
res.status(code).json({
code: code,
...data
});
break;
}
default:
res.status(404).json();
break;
}
});
module.exports = accounts;