@gearedminds/tsed-api-support v2.0.0
TSED Api Support
This module is used to secure any nodejs express API using TSED node module (https://tsed.io/). It handles :
Each one is a middleware.
It also provides a set of HTTP errors, Probes, a Logger factory and a swagger generator tool (related to TSED).
Token introspection service
This service is used to introspect the provided user token.
Builder options required by this middleware :
// skip all checks if set to false
authenticationMW_enabled: boolean;
// URL of the oAuth service
authenticationMW_oauthServiceURL: string;
// uri(s) for which all checks are disabled
authenticationMW_unprotectedPaths: string[];
If the user token is not successfully introspected or the authentication failed, a 401
error code is returned.
Permit service
This service is used to get roles of the calling user for a given application
After getting roles, the middleware checks if the method & the path are authorized for this user (crossing data with returned roles). If the endpoint does not require specific permission, the user is authorized by default.
Builder options required by this middleware :
// skip all checks if set to false
accessControlMW_enabled: boolean;
// skip all Headers checks if set to false
headerMW_enabled: boolean;
// URL of the permit service
accessControlMW_permissionServiceURL: string;
// uri(s) for which all checks are disabled
accessControlMW_unprotectedPaths: string[];
// roles/path/method mapping to know if the user is authorized to access this endpoint
accessControlMW_roleMappings: any[];
// the name of the application
accessControlMW_enclosingAppName: string;
// x-api-key of calling api
accessControlMW_enclosingAppApiKey: string;
Header service
This service is used to get information about enclosing app and user
Builder options required by this middleware :
// skip all Headers checks if set to false
headerMW_enabled: boolean;
MuteAllRoutesMiddleware
This middleware is used to allow the start of an API when database is not totally up (migration in progress)
It allows to serve the /_health only endpoint when some migrations are running
// enable the middleware
muteAllRoutesMW_enabled: boolean;
When using this middleware, the ApiStatusProbe will now show a warning
status when the API is not totally up
When you're ready to unleash your routes (allow access to any other routes than just /_health
), you have the responsibility to call the unMute
method of this middleware.
Middlewares.MuteAllRoutesMiddleware.unMute();
While this method is not called, all another route than /_health
will return a 503 error code
HTTP Errors
By importing Errors
from this module, the following errors are available:
NoContentFoundError
returning a204
response. It is often used for empty search result.ValidationError
returning a400
response. It is often used for request parameters/body validation errors.NotFoundError
returning a404
response. It is often used when getting/updating/deleting an unknown resource.ConflictError
returning a409
response. It is often used when updating a resource which is in conflict with another one.TechnicalError
returning a500
response. It is used for internal server error.ServiceUnavailableError
returning a503
response. It is used when API can't answer due to server side errors.
When combined with the ErrorTranslationMiddleware
, these errors are automatically handled as valid json output with the matching status code.
Probes
Probes are used for the endpoint /_health
in order to have a quick check up of an API
The model of a probe is defined as follow :
name: string; // The name of the probe
description: string; // A quick description
value: any; // It's value (could be a number for a ping, or an enum, ...)
status: "OK" | "WARNING" | "CRITICAL"; // A value that speaks for itself
start: number; // The begin time of the probe
end: number; // The end time of the probe
Probes are wrapped in a HealthProbeResponse
HealthProbeResponse
export interface HealthProbeResponse {
version: string;
probes: AbstractProbe[];
status: ProbeStatus;
}
You can use it like this
const version = Env.getVersion();
const result: Probes.HealthProbeResponse = {
version,
probes: [],
status: "OK"
};
ApiStatusProbe
This probe has en empty constructor, so you can't define its name and description Value and status are set in the constructor whith the value of the MuteAllRoutesMiddleware
- When routes are muted, value will have the value
starting
and status the valueWARNING
- When routes are unmuted, value will have the value
running
and status the valueOK
You can use it like this
ProbeFactory.getApiStatusProbe()
.then((probe) => {
result.probes.push(probe);
});
In case of you're using several probes in your /_health
endpoint, you can quickly find this one by searching on its name
const probes: Probes.AbstractProbe[] = res.body.probes;
const statusProbe = probes.find(probe => probe.name === Probes.ApiStatusProbe.NAME);
DbPingProbe
A probe that is used to get the response time of a database.
This probe uses the 3 states of status with default values as follows:
duration | status |
---|---|
> 1s | CRITICAL |
> 100ms | WARNING |
≤ 100ms | OK |
This probe needs a Promise<number>
in order to retrieve the correct status. You can set your own limit values for WARNING
and CRITICAL
status with optional parameters.
// MyDatabaseClass.ts
public async ping(): Promise<number> {
const pingStart = moment();
return this.sequelize.query("select * from types")
.then(() => {
const pingEnd = moment();
return pingEnd.diff(pingStart, "milliseconds");
})
.catch(() => -1);
}
// HealthController.ts
ProbeFactory.getDbPingProbe(() => ping) // For default values
.then((probe) => {
result.probes.push(probe);
});
const criticalPing = 2000;
const warningPing = 500;
ProbeFactory.getDbPingProbe(() => ping, criticalPing, warningPing) // For custom values
.then((probe) => {
result.probes.push(probe);
});
You can find it by its name as the ApiStatusProbe
const probes: Probes.AbstractProbe[] = res.body.probes;
const dbPingProbe = probes.find(probe => probe.name === Probes.DbPingProbe.NAME);
GenericProbe
A probe in which you can define its name and description. It allows you to define your own Probes when needed
A Factory is available in order to set properly all attributes of a probe
ProbeFactory.getGenericProbe("PgDbProbe", "A simple ping of the Postgresql database", () => SequelizeManager.ping())
.then((probe: Probes.GenericProbe) => {
if (probe.value > 100000000) {
probe.status = "WARNING";
}
probe.value = `${probe.value} nanoseconds`;
probeResult.probes.push(probe);
})
Logger factory
By importing Logger
from this module, you can get a logger with getLogger("...")
method and use common logger methods on it (error
, warn
, debug
; info
, ...). The name given to getLogger(name)
is traced in logs and is usefull for debug.
Swagger generator tool
The tsed-api-support swagger-file
command generates the swagger.json file
Version file generator
The lib also comes with another bin that generates a version file (version.json
) that could prove very handy when exposing a project's current version through an endpoint without having to embed/parse/read the whole package package.json
file.
Just try the following command : > tsed-api-support version-file ./package.json > version.json
Installation
Just either add the component to your package.json file (recommended way) or issue an npm install
command.
npm install @gearedminds/tsed-api-support
3 years ago