@direqt/service-framework
TypeScript icon, indicating that this package has built-in type declarations

16.0.0 • Public • Published

Direqt Service Framework

Common code useful for express/mongo/redis/gae applications.

Updating from 15.x to 16.x

Version 16 changed the module type to NodeNext and the target type to ES2021. This should be appropriate for any library using TypeScript 4.5+ and NodeJS 18+.

Updating from 14.x to 15.x

In version 15.0.0 we updated to required mongoose 8 rather than mongoose 6 that had previously been required. Client projects should update their mongoose dependency to ^8, and go through these two migration guides:

https://mongoosejs.com/docs/migrating_to_7.html https://mongoosejs.com/docs/migrating_to_8.html

Breaking changes:

- See the migration guides for mongoose. 

One notable change to mongoose is that strictQuery has been defaulted to false in mongoose 7. Client projects may wish to add:

mongoose.set('strictQuery', true);

immediately after creating their connection to preserve existing behavior.

Updating from 12.x to 14.x

In version 14.8 we added basic support for child routes for resource controllers. These routes will be attached as subroutes of the resource, invoked only if the parent resource exists and permissions check pass. See ResourceChildRoute.

Breaking changes:

- ValidationError is now a subclass of ApiError and now takes a
message as the first parameter.  Yay for a standard error hierarchy
and standardized API exceptions!

Updating from 11.x to 12.x

Breaking changes:

- SimpleModelController.mapDomainToResource now takes a second parameter
of type VerifiedUserInfo, allowing the implementation to do role/permission-
based conversions. You probably don't have to do anything to support this
unless you are calling the method explicitly.

Updating from 10.x to 11.x

Breaking changes:

- VerifiedUserInfo.verifiedGrants is no more. If you are updating from
a version prior to 10.x, lucky you, because it only existed in 10.x.

Updating from 10.x to 10.1.x

In version 10.1 we started looking for the 'X-Direqt-Roles' header from IAM in proxied requests.

Potentially breaking changes:

- VerifiedUserInfo.verifiedGrants is deprecated (already!). We've added
    a new required `verifiedRoles` property to take its place. This isn't
    strictly a breaking change as VerifiedUserInfo should always be
    readonly to clients, but test cases might need to be updated.

Updating from 9.x to 10.x

Version 10.x introduces support for service role definitions that define the security policy for resource requests via SimpleModelController. Previously, any non-standard permission mapping had to be handled on an ad-hoc basic by controllers (typically by overriding SimpleModelController.hasPermission). With the new service role definition support, non-standard permissions can be assigned to user requests based on the service roles attached to that user.

Breaking changes:

- SimpleModelController constructor has a new required argument `name`.
    This argument is of the form { service: string, resource: string } where
    `name.service` should be the high-level service ('iam', 'chat',
    'gallery', etc) and `name.resource` should be the resource name as
    exposed to the clients (e.g., 'chatApplication', 'gallery').

Other notable changes:

- SimpleModelController constructor has a new optional argument
    `options.roleDefinitions`. All resources in a service should share the
    same role definitions, which allow the role names provided by IAM to be
    mapped to resource-specific permissions.

- VerifiedUserInfo has a new property `verifiedGrants`. This holds
    information about role grants given to the requesting user. The
    property is populated from the secure HTTP headers provided by IAM to
    the service ('X-Direqt-Grants' header). Note especially that this field
    will NOT hold information about basic roles (MemberRole/SystemRole);
    that information remains in the `verifiedRole` field.

Internal changes include the creation of a ResourcePermissionService to factor out logic needed by the controller for determining permissions for requests.

Updating from 8.x to 9.x

The major update in 9.x is the introduction of resource schemas, which allows classes derived from SimpleModelController to specify all resource properties and policies for how they may be used.

When migrating to schemas, keep these things in mind:

- `options.readOnly` and `options.permittedQueryKeys` are now redundant in
the SimpleModelController constructor. Rather than specifying values there,
you should mark the corresponding properties as `readonly` or `queryable`,
respectively, in the provided schema.

- You should not override mapInputToResourceXxx if you have provided a
resource schema. The base class methods will perform the mappings for you
automatically.

Resource schemas are currently optional, and existing classes should be unaffected.

Updating from 7.x to 8.0

Breaking changes:

- SimpleModelController.permittedQueryKeys has been removed. If you have a class
    derived from SimpleModelController that had defined an override of
    `permittedQueryKeys`, you should remove the override and intead pass the
    array to the constructor in the `options` argument.

Updating from 6.x to 7.2+

(Note that the 7.x branch didn't stablize until 7.3, and there are breaking changes between 7.0 and 7.3; since no project updated to any version of 7.x before 7.3, we ignore those changes and just focus on projects migrating from 6.x to 7.3+).

Breaking changes:

- SimpleModelController.mapInternalToPublic has been removed. If you have a class derived from SimpleModelController, you should now override `mapDomainToResource` instead. Be sure to do a global search on any project updating to 7.x, because without the override keyword on your derived class implementation (you should use "noImplicitOverride" in tsconfig!) you may not notice this!

The primary update in this major version is the addition in SimpleModelController of specific types for "create" and "update" params that may be independent from the public resource type. This is implemented with two additional generic types on SimpleModelController which, if not specified, fallback to the existing behavior.

In addition, the pipeline for processing create and update operations has become more structured to aid in ensuring we protect against invalid/malicious inputs. The input pipeline is now:

1. HTTP request received;
2. body, params, and query string are all sanitized via middleware to remove known attack vectors (e.g., mongo-specific injection attacks);
3. untyped inputs are converted to expected resource-specific type with overridable `mapInputToResourceXxx` method;
4. deep validation implemented with overridable `validateResourceUpdate` method.

Controllers are now encouraged to supply four generic types (domain model, resource model, create resource model, and update resource model), and implement the following mapping functions:

mapInputToResourceCreate
    - parse input given to a create operation
mapInputToResourceUpdate
    - parse input given to an update operation

mapResourceCreateToDomain
    - map input for a create operation to the internal domain type used by the associated service
mapResourceUpdateToDomain
    - map input for an update operation to the internal domain type used by the associated service
mapDomainToResource
    - map the output from the associated service to the public resource type exposed by the controller

In addition, many controllers will want to implement:

validateResourceCreate
    - perform additional deep checks on input parameters given to a create operation.
validateResourceUpdate
    - perform additional deep checks on input parameters given to an update operation.

For the most part, any controller currently working with 6.x should work without modification. NOTE HOWEVER THE REMOVAL OF mapInternalToPublic referenced above.

NOTE ALSO that the signature of sterilizeEntity has changed, which may require any controller that had overridden it to tweak their definition. (This method is now deprecated in favor of performing any sterilization in parseResourceXxx).

Finally, note that, if you override mapDomainToResource, the id and network properties will no longer automatically be scrubbed from your resources as they were when mapInternalToPublic was in use. You are expected to perform any scrubbing appropriate if you override these methods.

These methods have been deprecated:

`sterilizeEntity` - we now perform mongo-specific sterilization of body, params, and query strings in middleware that runs for all routes. This method remains in order to filter out properties beginning with underscores, but derived classes should no longer override this method.

For example implementations, see the WidgetController2 class defined in the test cases in SimpleModelController.test.ts.

Updating from 5.x to 6.x

There are several breaking changes in the update to 6.x.

Permission checks are now implemented in the SimpleModelController

Each standard method on resources (get, list, create, update, delete), as well as each custom action, has an associated permission. By default, permissions are assigned to users based on the MemberRole in the VerifiedUserInfo.verifiedRole supplied by IAM in a way that closely mimics the existing behavior.

owner, editor, admin: ['get', 'list', 'create', 'update', delete] viewer: ['get', 'list']

Note, however, that permissions for custom actions are not granted to any users by default. See notes below.

ModelService public methods renamed (getOne, getAll, del)

Any classes that derive from ModelService (or SimpleModelService), or SimpleModelController, will need to rename these methods:

`getOne` -> `get`
`getAll` -> `list`
`del` -> `delete

The behavior of these methods is unchanged.

Change to definition of Controller action handlers

Previously, custom actions could be defined on SimpleModelControllers by supplying the action name as a key:

class MyController extends SimpleModelController<> {
    actions = {
        'bark': async () => null,
        'wag': async () => null,
    }
}

Custom actions must now be defined as an array of ResourceAction objects :

class MyController extends SimpleModelController<> {
    actions = [{
        name: 'bark',
        handler: async () => null,
    }, {
        name: 'wag',
        handler: async () => null,
    }]
}

New class ActionError defined for resource action handlers

When an action handlers (ResourceActions installed with SimpleModelController.actions) wants to return an error to the caller, it should throw an exception of type ActionError, specifying the HTTP status and message to return. InvalidActionState has been removed.

Custom actions require custom permissions

As part of the integration of permission-based authorization checks into the SimpleModelController, invoking a custom action now requires the caller to posess a specific named permission that, by default, has the same name as the action. For example, an action named 'bark' will require that the caller have the '.bark' permission.

By default, the legacy MemberRole roles are mapped to a set of basic permissions that will not include any custom permissions. To enable a custom action for these roles, your override of SimpleModelController must override hasPermission:

class MyController extends SimpleModelController<> {
    // /<resource>/:id/bark will require 'bark' permission
    actions = [{
        name: 'bark',
        handler: async () => null,
    }];

    hasPermission(verb: string, userInfo: VerifiedUserInfo): boolean {
        if (verb === 'bark') {
            // allow 'admin' role the '<resource>.bark' permission
            return userInfo.verifiedRole === MemberRole.admin;
        }
        return super.hasPermission(verb, userInfo);
    }
}

For custom actions that are intended to be callable for users with a standard permission like 'get' or 'update', you can avoid overridding hasPermission and simply provide a permission attribute when defining the action:

    // /<resource>/:id/bark will require 'update' permission
    actions = [{
        name: 'bark',
        permission: 'update',
        handler: async () => null,
    }];

VerifiedUserInfo.verifiedRole is now required

This object should only ever be generated by IAM or trusted IAM client code, so no changes should be required. Some test cases, however, may need to be updated to include a verifiedRole where previously it had been optional.

Mongoose (peer) dependency has been bumped to 6.x

The mongoose peerDependency is now set to the 6.x branch. There are a handful of breaking changes that you will have to confront when making the necessary update to any client service.

See https://mongoosejs.com/docs/migrating_to_6.html

Copyright (c) 2021 Direqt Inc.

Readme

Keywords

none

Package Sidebar

Install

npm i @direqt/service-framework

Weekly Downloads

278

Version

16.0.0

License

UNLICENSED

Unpacked Size

474 kB

Total Files

129

Last publish

Collaborators

  • elias-direqt
  • erichoelscher
  • nb-direqt
  • edleung
  • laurenmmorgan
  • bill-direqt
  • myk