Skip to content

Commit

Permalink
fix: Make all the response bodies in predictable format [DEV-3494] (#454
Browse files Browse the repository at this point in the history
)

* Move types to validation and types refact

* Fix build

* Add satisfy to all response bodies

* npm run format

* Fix response bodies for /credentials and /presentations endpoints

* Fix suspension response bodies

* Upgrade uint8arrays

* package-lock.json updating

* Return response fields back

* Add types for requests

* revert issue validation back

* npm run format

---------

Co-authored-by: DaevMithran <daevmithran1999@gmail.com>
Co-authored-by: Ankur Banerjee <ankurdotb@users.noreply.github.com>
  • Loading branch information
3 people authored Jan 16, 2024
1 parent 55e6cb7 commit b3549d8
Show file tree
Hide file tree
Showing 25 changed files with 776 additions and 299 deletions.
128 changes: 69 additions & 59 deletions package-lock.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@
"sqlite3": "^5.1.7",
"swagger-ui-express": "^5.0.0",
"typeorm": "^0.3.19",
"uint8arrays": "^4.0.10",
"uint8arrays": "^5.0.1",
"uri-js": "^4.4.1"
},
"devDependencies": {
Expand Down
2 changes: 1 addition & 1 deletion src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ class App {

// Keys API
app.post('/key/create', new KeyController().createKey);
app.post('/key/import', KeyController.importKeyValidator, new KeyController().importKey);
app.post('/key/import', KeyController.keyImportValidator, new KeyController().importKey);
app.get('/key/read/:kid', new KeyController().getKey);

// DIDs API
Expand Down
46 changes: 27 additions & 19 deletions src/controllers/account.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,13 @@ import type { CustomerEntity } from '../database/entities/customer.entity.js';
import type { UserEntity } from '../database/entities/user.entity.js';
import type { PaymentAccountEntity } from '../database/entities/payment.account.entity.js';
import { IdentityServiceStrategySetup } from '../services/identity/index.js';
import type {
QueryCustomerResponseBody,
QueryIdTokenResponseBody,
UnsuccessfulQueryCustomerResponseBody,
UnsuccessfulQueryIdTokenResponseBody,
} from '../types/customer.js';
import type { UnsuccessfulResponseBody } from '../types/shared.js';
import { check, validationResult } from 'express-validator';

export class AccountController {
Expand Down Expand Up @@ -49,10 +56,10 @@ export class AccountController {
try {
if (!response.locals.customer) {
// It's not ok, seems like there no any customer assigned to the user yet
// But it's not an expectede behaviour cause it should be done on bootstrap phase of after migration
// But it's not an expected behaviour cause it should be done on bootstrap phase of after migration
return response.status(StatusCodes.INTERNAL_SERVER_ERROR).json({
error: 'Bad state cause there is no customer assigned to the user yet. Please contact administrator.',
});
} satisfies UnsuccessfulQueryCustomerResponseBody);
}
const paymentAccount = await PaymentAccountService.instance.find({ customer: response.locals.customer });
const result = {
Expand All @@ -63,13 +70,13 @@ export class AccountController {
paymentAccount: {
address: paymentAccount[0].address,
},
};
} satisfies QueryCustomerResponseBody;

return response.status(StatusCodes.OK).json(result);
} catch (error) {
return response.status(StatusCodes.INTERNAL_SERVER_ERROR).json({
error: `Internal error: ${(error as Error)?.message || error}`,
});
} satisfies UnsuccessfulQueryCustomerResponseBody);
}
}

Expand Down Expand Up @@ -99,10 +106,11 @@ export class AccountController {
if (!request.user || !request.session.idToken) {
return response.status(StatusCodes.BAD_REQUEST).json({
error: 'Seems like authorisation process was corrupted. Please contact administrator.',
});
} satisfies UnsuccessfulQueryIdTokenResponseBody);
}

const identityStrategySetup = new IdentityServiceStrategySetup(response.locals.customer.customerId);

try {
// Get the API key for the customer
let apiKey = await identityStrategySetup.agent.getAPIKey(response.locals.customer, response.locals.user);
Expand All @@ -119,11 +127,11 @@ export class AccountController {
}
return response.status(StatusCodes.OK).json({
idToken: apiKey?.apiKey,
});
} satisfies QueryIdTokenResponseBody);
} catch (error) {
return response.status(StatusCodes.INTERNAL_SERVER_ERROR).json({
error: `Internal error: ${(error as Error)?.message || error}`,
});
} satisfies UnsuccessfulQueryIdTokenResponseBody);
}
}

Expand Down Expand Up @@ -156,15 +164,15 @@ export class AccountController {
if (!request.body.user || !request.body.user.id || !request.body.user.primaryEmail) {
return response.status(StatusCodes.BAD_REQUEST).json({
error: 'User id is not specified or primaryEmail is not set',
});
} satisfies UnsuccessfulResponseBody);
}
const logToUserId = request.body.user.id;
const logToUserEmail = request.body.user.primaryEmail;
const defaultRole = await RoleService.instance.getDefaultRole();
if (!defaultRole) {
return response.status(StatusCodes.BAD_REQUEST).json({
error: 'Default role is not set on Credential Service side',
});
} satisfies UnsuccessfulResponseBody);
}
// 2. Check if such row exists in the DB
user = await UserService.instance.get(logToUserId);
Expand All @@ -179,14 +187,14 @@ export class AccountController {
if (!customer) {
return response.status(StatusCodes.BAD_REQUEST).json({
error: 'User is not found in db: Customer was not created',
});
} satisfies UnsuccessfulResponseBody);
}
// 2.2. Create user
user = await UserService.instance.create(logToUserId, customer, defaultRole);
if (!user) {
return response.status(StatusCodes.BAD_REQUEST).json({
error: 'User is not found in db: User was not created',
});
} satisfies UnsuccessfulResponseBody);
}
}
// 3. If yes - check that there is customer associated with such user
Expand All @@ -197,7 +205,7 @@ export class AccountController {
if (!customer) {
return response.status(StatusCodes.BAD_REQUEST).json({
error: 'User exists in db: Customer was not created',
});
} satisfies UnsuccessfulResponseBody);
}
// 3.1.2. Assign customer to the user
user.customer = customer;
Expand All @@ -216,7 +224,7 @@ export class AccountController {
if (!key) {
return response.status(StatusCodes.BAD_REQUEST).json({
error: 'PaymentAccount is not found in db: Key was not created',
});
} satisfies UnsuccessfulResponseBody);
}
paymentAccount = (await PaymentAccountService.instance.create(
CheqdNetwork.Testnet,
Expand All @@ -227,7 +235,7 @@ export class AccountController {
if (!paymentAccount) {
return response.status(StatusCodes.BAD_REQUEST).json({
error: 'PaymentAccount is not found in db: Payment account was not created',
});
} satisfies UnsuccessfulResponseBody);
}
} else {
paymentAccount = accounts[0];
Expand All @@ -238,15 +246,15 @@ export class AccountController {
if (_r.status !== StatusCodes.OK) {
return response.status(StatusCodes.BAD_GATEWAY).json({
error: _r.error,
});
} satisfies UnsuccessfulResponseBody);
}
// 5. Assign default role on LogTo
// 5.1 Get user's roles
const roles = await logToHelper.getRolesForUser(user.logToId);
if (roles.status !== StatusCodes.OK) {
return response.status(StatusCodes.BAD_GATEWAY).json({
error: roles.error,
});
} satisfies UnsuccessfulResponseBody);
}

// 5.2 If list of roles is empty and the user is not suspended - assign default role
Expand All @@ -255,7 +263,7 @@ export class AccountController {
if (_r.status !== StatusCodes.OK) {
return response.status(StatusCodes.BAD_GATEWAY).json({
error: _r.error,
});
} satisfies UnsuccessfulResponseBody);
}
}

Expand All @@ -276,7 +284,7 @@ export class AccountController {
if (_r.status !== 200) {
return response.status(_r.status).json({
error: _r.error,
});
} satisfies UnsuccessfulResponseBody);
}
}

Expand All @@ -290,7 +298,7 @@ export class AccountController {
if (resp.status !== StatusCodes.OK) {
return response.status(StatusCodes.BAD_GATEWAY).json({
error: resp.error,
});
} satisfies UnsuccessfulResponseBody);
}
}
}
Expand Down
33 changes: 23 additions & 10 deletions src/controllers/credential-status.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { check, validationResult, query } from './validator/index.js';
import { fromString } from 'uint8arrays';
import { StatusCodes } from 'http-status-codes';
import { IdentityServiceStrategySetup } from '../services/identity/index.js';
import type { ITrackOperation } from '../types/shared.js';
import type { ITrackOperation, ValidationErrorResponseBody } from '../types/shared.js';
import type { CheckStatusListSuccessfulResponseBody, FeePaymentOptions } from '../types/credential-status.js';
import {
DefaultStatusAction,
Expand Down Expand Up @@ -496,7 +496,9 @@ export class CredentialStatusController {

// handle error
if (!result.isEmpty()) {
return response.status(StatusCodes.BAD_REQUEST).json({ error: result.array().pop()?.msg });
return response.status(StatusCodes.BAD_REQUEST).json({
error: result.array().pop()?.msg,
} satisfies ValidationErrorResponseBody);
}

// collect request parameters - case: body
Expand Down Expand Up @@ -627,7 +629,9 @@ export class CredentialStatusController {

// handle error
if (!result.isEmpty()) {
return response.status(StatusCodes.BAD_REQUEST).json({ error: result.array().pop()?.msg });
return response.status(StatusCodes.BAD_REQUEST).json({
error: result.array().pop()?.msg,
} satisfies ValidationErrorResponseBody);
}

// collect request parameters - case: body
Expand Down Expand Up @@ -761,7 +765,9 @@ export class CredentialStatusController {

// handle error
if (!result.isEmpty()) {
return response.status(StatusCodes.BAD_REQUEST).json({ error: result.array().pop()?.msg });
return response.status(StatusCodes.BAD_REQUEST).json({
error: result.array().pop()?.msg,
} satisfies ValidationErrorResponseBody);
}

// collect request parameters - case: body
Expand Down Expand Up @@ -792,9 +798,10 @@ export class CredentialStatusController {
}

// handle generic error
return response
.status(StatusCodes.BAD_REQUEST)
.json({ updated: false, error: `update: error: ${unencrypted.error}` });
return response.status(StatusCodes.BAD_REQUEST).json({
updated: false,
error: `update: error: ${unencrypted.error}`,
} satisfies UpdateUnencryptedStatusListUnsuccessfulResponseBody);
}

// validate unencrypted
Expand Down Expand Up @@ -940,7 +947,9 @@ export class CredentialStatusController {

// handle error
if (!result.isEmpty()) {
return response.status(StatusCodes.BAD_REQUEST).json({ error: result.array().pop()?.msg });
return response.status(StatusCodes.BAD_REQUEST).json({
error: result.array().pop()?.msg,
} satisfies ValidationErrorResponseBody);
}

// collect request parameters - case: body
Expand Down Expand Up @@ -1140,7 +1149,9 @@ export class CredentialStatusController {

// handle error
if (!result.isEmpty()) {
return response.status(StatusCodes.BAD_REQUEST).json({ error: result.array()[0].msg });
return response.status(StatusCodes.BAD_REQUEST).json({
error: result.array()[0].msg,
} satisfies ValidationErrorResponseBody);
}

// collect request parameters - case: body
Expand Down Expand Up @@ -1302,7 +1313,9 @@ export class CredentialStatusController {

// handle error
if (!result.isEmpty()) {
return response.status(StatusCodes.BAD_REQUEST).json({ error: result.array().pop()?.msg });
return response.status(StatusCodes.BAD_REQUEST).json({
error: result.array().pop()?.msg,
} satisfies ValidationErrorResponseBody);
}

// collect request parameters - case: query
Expand Down
Loading

0 comments on commit b3549d8

Please sign in to comment.