npm package: @jojoxd/tsed-auth-expression
Description: Add scripting to your authorization
Author: Joey Vos
Latest version: 1.0.0

# @jojoxd/tsed-auth-expression

![status](https://gitlab.jojoxd.nl/jojoxd-npm/tsed/tsed-auth-expression/badges/main/pipeline.svg) ![coverage](https://gitlab.jojoxd.nl/jojoxd-npm/tsed/tsed-auth-expression/badges/main/coverage.svg) ![Latest Release](https://gitlab.jojoxd.nl/jojoxd-npm/tsed/tsed-auth-expression/-/badges/release.svg)

[See on NPM](https://www.npmjs.com/package/@jojoxd/tsed-auth-expression)

Use _[Jexl](https://www.npmjs.com/package/jexl)_ expressions for authorization.

## Installation

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

```
$ npm install @jojoxd/tsed-auth-expression
```

```typescript
// 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.

```typescript
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!"`:

```typescript
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](https://tsed.io/docs/middlewares.html#override-existing-middlewares) for `AuthExpressionMiddleware`:

```typescript
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:
```typescript
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:
```typescript
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)