Update the REST Example (#689)

1. The default chaincode use Capitalized JSON Names, whereas for new asset the REST validation didn't.. Adjusted
so it matches the chaincode

Signed-off-by: Matthew B White <whitemat@uk.ibm.com>
This commit is contained in:
Matthew B White 2022-03-31 13:19:34 +01:00 committed by GitHub
parent 57919f528d
commit 9fa171f824
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 68 additions and 67 deletions

View file

@ -185,7 +185,7 @@ curl --include --header "X-Api-Key: ${SAMPLE_APIKEY}" --request OPTIONS http://l
### Create an asset...
```shell
curl --include --header "Content-Type: application/json" --header "X-Api-Key: ${SAMPLE_APIKEY}" --request POST --data '{"id":"asset7","color":"red","size":42,"owner":"Jean","appraisedValue":101}' http://localhost:3000/api/assets
curl --include --header "Content-Type: application/json" --header "X-Api-Key: ${SAMPLE_APIKEY}" --request POST --data '{"ID":"asset7","Color":"red","Size":42,"Owner":"Jean","AppraisedValue":101}' http://localhost:3000/api/assets
```
The response should include a `jobId` which you can use to check the job status in next step
@ -237,13 +237,13 @@ You should see the newly created asset, for example
### Update an asset...
```shell
curl --include --header "Content-Type: application/json" --header "X-Api-Key: ${SAMPLE_APIKEY}" --request PUT --data '{"id":"asset7","color":"red","size":11,"owner":"Jean","appraisedValue":101}' http://localhost:3000/api/assets/asset7
curl --include --header "Content-Type: application/json" --header "X-Api-Key: ${SAMPLE_APIKEY}" --request PUT --data '{"ID":"asset7","Color":"red","Size":11,"Owner":"Jean","AppraisedValue":101}' http://localhost:3000/api/assets/asset7
```
### Transfer an asset...
```shell
curl --include --header "Content-Type: application/json" --header "X-Api-Key: ${SAMPLE_APIKEY}" --request PATCH --data '[{"op":"replace","path":"/owner","value":"Ashleigh"}]' http://localhost:3000/api/assets/asset7
curl --include --header "Content-Type: application/json" --header "X-Api-Key: ${SAMPLE_APIKEY}" --request PATCH --data '[{"op":"replace","path":"/Owner","value":"Ashleigh"}]' http://localhost:3000/api/assets/asset7
```
### Delete an asset...

View file

@ -33,11 +33,11 @@ content-type: application/json
X-Api-Key: {{api-key}}
{
"id": "asset7",
"color": "red",
"size": 42,
"owner": "Jean",
"appraisedValue": 101
"ID": "asset7",
"Color": "red",
"Size": 42,
"Owner": "Jean",
"AppraisedValue": 101
}
### Read job status
@ -62,11 +62,11 @@ content-type: application/json
X-Api-Key: {{api-key}}
{
"id": "asset7",
"color": "red",
"size": 11,
"owner": "Jean",
"appraisedValue": 101
"ID": "asset7",
"Color": "red",
"Size": 11,
"Owner": "Jean",
"AppraisedValue": 101
}
### Transfer asset
@ -78,7 +78,7 @@ X-Api-Key: {{api-key}}
[
{
"op": "replace",
"path": "/owner",
"path": "/Owner",
"value": "Ashleigh"
}
]

View file

@ -208,11 +208,11 @@ describe('Asset Transfer Besic REST API', () => {
const response = await request(app)
.post('/api/assets')
.send({
identifier: 'asset3',
color: 'red',
size: 5,
owner: 'Brad',
appraisedValue: 400,
wrongidfield: 'asset3',
Color: 'red',
Size: 5,
Owner: 'Brad',
AppraisedValue: 400,
})
.set('X-Api-Key', 'ORG1MOCKAPIKEY');
expect(response.statusCode).toEqual(400);
@ -227,7 +227,7 @@ describe('Asset Transfer Besic REST API', () => {
{
location: 'body',
msg: 'must be a string',
param: 'id',
param: 'ID',
},
],
message: 'Invalid request body',
@ -239,11 +239,11 @@ describe('Asset Transfer Besic REST API', () => {
const response = await request(app)
.post('/api/assets')
.send({
id: 'asset3',
color: 'red',
size: 5,
owner: 'Brad',
appraisedValue: 400,
ID: 'asset3',
Color: 'red',
Size: 5,
Owner: 'Brad',
AppraisedValue: 400,
})
.set('X-Api-Key', 'ORG1MOCKAPIKEY');
expect(response.statusCode).toEqual(202);
@ -401,11 +401,11 @@ describe('Asset Transfer Besic REST API', () => {
const response = await request(app)
.put('/api/assets/asset1')
.send({
id: 'asset3',
color: 'red',
size: 5,
owner: 'Brad',
appraisedValue: 400,
ID: 'asset3',
Color: 'red',
Size: 5,
Owner: 'Brad',
AppraisedValue: 400,
})
.set('X-Api-Key', 'NOTTHERIGHTAPIKEY');
expect(response.statusCode).toEqual(401);
@ -424,11 +424,11 @@ describe('Asset Transfer Besic REST API', () => {
const response = await request(app)
.put('/api/assets/asset1')
.send({
id: 'asset2',
color: 'red',
size: 5,
owner: 'Brad',
appraisedValue: 400,
ID: 'asset2',
Color: 'red',
Size: 5,
Owner: 'Brad',
AppraisedValue: 400,
})
.set('X-Api-Key', 'ORG1MOCKAPIKEY');
expect(response.statusCode).toEqual(400);
@ -448,11 +448,11 @@ describe('Asset Transfer Besic REST API', () => {
const response = await request(app)
.put('/api/assets/asset1')
.send({
identifier: 'asset1',
color: 'red',
size: 5,
owner: 'Brad',
appraisedValue: 400,
wrongID: 'asset1',
Color: 'red',
Size: 5,
Owner: 'Brad',
AppraisedValue: 400,
})
.set('X-Api-Key', 'ORG1MOCKAPIKEY');
expect(response.statusCode).toEqual(400);
@ -467,7 +467,7 @@ describe('Asset Transfer Besic REST API', () => {
{
location: 'body',
msg: 'must be a string',
param: 'id',
param: 'ID',
},
],
message: 'Invalid request body',
@ -479,11 +479,11 @@ describe('Asset Transfer Besic REST API', () => {
const response = await request(app)
.put('/api/assets/asset1')
.send({
id: 'asset1',
color: 'red',
size: 5,
owner: 'Brad',
appraisedValue: 400,
ID: 'asset1',
Color: 'red',
Size: 5,
Owner: 'Brad',
AppraisedValue: 400,
})
.set('X-Api-Key', 'ORG1MOCKAPIKEY');
expect(response.statusCode).toEqual(202);
@ -501,7 +501,7 @@ describe('Asset Transfer Besic REST API', () => {
it('PATCH should respond with 401 unauthorized json when an invalid API key is specified', async () => {
const response = await request(app)
.patch('/api/assets/asset1')
.send([{ op: 'replace', path: '/owner', value: 'Ashleigh' }])
.send([{ op: 'replace', path: '/Owner', value: 'Ashleigh' }])
.set('X-Api-Key', 'NOTTHERIGHTAPIKEY');
expect(response.statusCode).toEqual(401);
expect(response.header).toHaveProperty(
@ -531,7 +531,7 @@ describe('Asset Transfer Besic REST API', () => {
errors: [
{
location: 'body',
msg: "path must be '/owner'",
msg: "path must be '/Owner'",
param: '[0].path',
value: '/color',
},
@ -544,7 +544,7 @@ describe('Asset Transfer Besic REST API', () => {
it('PATCH should respond with 202 accepted json', async () => {
const response = await request(app)
.patch('/api/assets/asset1')
.send([{ op: 'replace', path: '/owner', value: 'Ashleigh' }])
.send([{ op: 'replace', path: '/Owner', value: 'Ashleigh' }])
.set('X-Api-Key', 'ORG1MOCKAPIKEY');
expect(response.statusCode).toEqual(202);
expect(response.header).toHaveProperty(

View file

@ -35,7 +35,6 @@ export const assetsRouter = express.Router();
assetsRouter.get('/', async (req: Request, res: Response) => {
logger.debug('Get all assets request received');
try {
const mspId = req.user as string;
const contract = req.app.locals[mspId]?.assetContract as Contract;
@ -59,11 +58,11 @@ assetsRouter.get('/', async (req: Request, res: Response) => {
assetsRouter.post(
'/',
body().isObject().withMessage('body must contain an asset object'),
body('id', 'must be a string').notEmpty(),
body('color', 'must be a string').notEmpty(),
body('size', 'must be a number').isNumeric(),
body('owner', 'must be a string').notEmpty(),
body('appraisedValue', 'must be a number').isNumeric(),
body('ID', 'must be a string').notEmpty(),
body('Color', 'must be a string').notEmpty(),
body('Size', 'must be a number').isNumeric(),
body('Owner', 'must be a string').notEmpty(),
body('AppraisedValue', 'must be a number').isNumeric(),
async (req: Request, res: Response) => {
logger.debug(req.body, 'Create asset request received');
@ -79,7 +78,7 @@ assetsRouter.post(
}
const mspId = req.user as string;
const assetId = req.body.id;
const assetId = req.body.ID;
try {
const submitQueue = req.app.locals.jobq as Queue;
@ -88,10 +87,10 @@ assetsRouter.post(
mspId,
'CreateAsset',
assetId,
req.body.color,
req.body.size,
req.body.owner,
req.body.appraisedValue
req.body.Color,
req.body.Size,
req.body.Owner,
req.body.AppraisedValue
);
return res.status(ACCEPTED).json({
@ -190,11 +189,11 @@ assetsRouter.get('/:assetId', async (req: Request, res: Response) => {
assetsRouter.put(
'/:assetId',
body().isObject().withMessage('body must contain an asset object'),
body('id', 'must be a string').notEmpty(),
body('color', 'must be a string').notEmpty(),
body('size', 'must be a number').isNumeric(),
body('owner', 'must be a string').notEmpty(),
body('appraisedValue', 'must be a number').isNumeric(),
body('ID', 'must be a string').notEmpty(),
body('Color', 'must be a string').notEmpty(),
body('Size', 'must be a number').isNumeric(),
body('Owner', 'must be a string').notEmpty(),
body('AppraisedValue', 'must be a number').isNumeric(),
async (req: Request, res: Response) => {
logger.debug(req.body, 'Update asset request received');
@ -209,7 +208,7 @@ assetsRouter.put(
});
}
if (req.params.assetId != req.body.id) {
if (req.params.assetId != req.body.ID) {
return res.status(BAD_REQUEST).json({
status: getReasonPhrase(BAD_REQUEST),
reason: 'ASSET_ID_MISMATCH',
@ -263,7 +262,7 @@ assetsRouter.patch(
})
.withMessage('body must contain an array with a single patch operation'),
body('*.op', "operation must be 'replace'").equals('replace'),
body('*.path', "path must be '/owner'").equals('/owner'),
body('*.path', "path must be '/Owner'").equals('/Owner'),
body('*.value', 'must be a string').isString(),
async (req: Request, res: Response) => {
logger.debug(req.body, 'Transfer asset request received');

View file

@ -19,6 +19,8 @@ const { BAD_REQUEST, INTERNAL_SERVER_ERROR, NOT_FOUND } = StatusCodes;
export const createServer = async (): Promise<Application> => {
const app = express();
// Remember for production usage, to check any TLS or CORS requirements
app.use(
pinoMiddleware({
logger,