Jexl expressions as authorization decorators in Ts.ED
Find a file
semantic-release-bot ab88b951ef chore(release): 1.0.0 [skip ci]
# 1.0.0 (2022-12-04)

### Features

* initial release ([a413282](a4132823f0))
2022-12-04 21:01:42 +00:00
.yarn/releases Move from anistats 2022-12-03 12:18:43 +01:00
dist chore(release): 1.0.0 [skip ci] 2022-12-04 21:01:42 +00:00
src Add 'Expression' to classes that wern't updated yet 2022-12-03 17:18:01 +01:00
test Add 'Expression' to classes that wern't updated yet 2022-12-03 17:18:01 +01:00
.barrelsby.json chore(testing): Add Testing, CI, Readme 2022-12-03 16:31:41 +01:00
.gitignore chore(testing): Add Testing, CI, Readme 2022-12-03 16:31:41 +01:00
.gitlab-ci.yml Change AuthMiddleware to AuthExpressionMiddleware 2022-12-03 16:38:40 +01:00
.mocharc.json chore(testing): Add Testing, CI, Readme 2022-12-03 16:31:41 +01:00
.npmignore Add release configuration 2022-12-03 12:47:32 +01:00
.nycrc.json chore(testing): Add Testing, CI, Readme 2022-12-03 16:31:41 +01:00
.releaserc Add release configuration 2022-12-03 12:47:32 +01:00
.yarnrc.yml Move from anistats 2022-12-03 12:18:43 +01:00
CHANGELOG.md chore(release): 1.0.0 [skip ci] 2022-12-04 21:01:42 +00:00
package.json chore(release): 1.0.0 [skip ci] 2022-12-04 21:01:42 +00:00
README.md Add 'Expression' to classes that wern't updated yet 2022-12-03 17:18:01 +01:00
renovate.json Add renovate.json 2022-12-03 12:13:57 +00:00
tsconfig.json chore(testing): Add Testing, CI, Readme 2022-12-03 16:31:41 +01:00
tsconfig.spec.json chore(testing): Add Testing, CI, Readme 2022-12-03 16:31:41 +01:00
yarn.lock chore(testing): Add Testing, CI, Readme 2022-12-03 16:31:41 +01:00

@jojoxd/tsed-auth-expression

status coverage Latest Release

See on NPM

Use Jexl expressions for authorization.

Installation

You can get the latest release and the type definitions using npm:

$ npm install @jojoxd/tsed-auth-expression
// Server.ts
import "@jojoxd/tsed-auth-expression";

// <snip>

@Configuration({
    // No configuration required (yet)
})
export class Server {}

Examples

Creating a Context Provider

The Auth Context Provider provides variables you can use in your expressions. It has access to the container using @Inject(), and has access to the Ts.ED Context.

import { AuthExpressionContextProvider, AuthExpressionContextProviderMethods } from "@jojoxd/tsed-auth-expression";
import { Context } from "@tsed/common";

@AuthExpressionContextProvider()
export class MyAuthContextProvider implements AuthExpressionContextProviderMethods
{
    async getContext(context: Context): Promise<any>
    {
        return {
            variable: 'Hello, World!'
        };
    }
}

Using Expressions

Expressions manage authorization. For example, you could have an AuthContextProvider that provides the current user as a variable, and check if user.isAdmin is true.

Here, we use the above AuthContextProvider to check if variable is "Hello, World!":

import { Controller } from "@tsed/di";
import { Get } from "@tsed/schema";

import { UseAuthExpression } from "@jojoxd/tsed-auth-expression";

@Controller('/')
export class MyController
{
    @Get('/hello-world')
    @UseAuthExpression('variable == "Hello, World!"')
    getHelloWorld() {
        return { message: 'Hello, World!', };
    }
}

Jexl Extensions

To extend Jexl yourself, you can use OverrideProvider for AuthExpressionMiddleware:

import { OverrideProvider } from "@tsed/di"; 
import { AuthExpressionMiddleware } from "@jojoxd/tsed-auth-expression";

@OverrideProvider(AuthExpressionMiddleware)
export class MyAuthExpressionMiddleware extends AuthExpressionMiddleware
{
    constructor()
    {
        super();
        
        // now you can use this.expressionEvaluator to access Jexl
    }
}

Exists

We've added an extra function exists. This can be used to check if a variable exists. (Seems logical to me.)

Usage:

import { Controller } from "@tsed/di";
import { Get } from "@tsed/schema";

import { UseAuth } from "@jojoxd/tsed-auth-expression";

@Controller('/')
export class MyController
{
    @Get('/')
    @UseAuth('currentUser|exists && currentUser.isAdmin')
    getTest() {}
}

Pre-defined variables

explain pre-defined variables (QueryParams, PathParams, Request, etc.)

There are a couple of pre-defined variables available:

  • routeParams: contains the Path Parameters
  • queryParams: contains the Query Parameters
  • session: contains the Session instance.
  • cookies: contains cookies from the request
  • request: contains the full Ts.ED PlatformRequest object.

Example with Path and Query Params:

import { Controller } from "@tsed/di";
import { Get } from "@tsed/schema";

import { UseAuthExpression } from "@jojoxd/tsed-auth-expression";

@Controller('/')
export class MyController
{
    @Get('/:myPathParam')
    @UseAuthExpression('routeParams.myPathParam == 1 && queryParams.hello|exists')
    getMyPathParam() {}
}

Some considerations

Note that we are deviating a bit from the standard Jexl expression language, as we have disabled assignment to not get any pollution.

Roadmap:

Things I'd like to have:

  • Allow grouping providers (Will save on resources)
  • Allow easier Jexl extension (Better DX)
  • Allow deferring getters for variables (Will save on resources)