npm package: @madxnl/madhatter-auth
Description: This package is meant to be used hand in hand with `@madxnl/madhatter` to simplify setting up authorization for the consumer app.
Latest version: 0.0.7

# Madhatter-auth

This package is meant to be used hand in hand with `@madxnl/madhatter` to simplify setting up authorization for the consumer app.

## How to use

### Define the auth relations on your models

Add the `Role` and `PermissionNode` relations to your models according to your domain needs. As an example you can add it to an `ApiKey` model:

```typescript
@Entity()
import { Role } from '@madxnl/madhatter-auth'

export class ApiKey extends BaseModel {
  _modelName = 'apiKey'

    @Column()
    apiKey: string

    @ManyToMany(() => Role)
    @JoinTable()
    roles: Role[]

    @ManyToMany(() => PermissionNode)
    @JoinTable()
    nodes: PermissionNode[]
}
```

Then register the entities with TypeORM and generate the necessary migrations.

In our madhatter based projects that are built on on `typeorm@0.3.x` (`madhatter@0.7.x`), we auto load the entities, and use the TypeORM CLI in combination with a `config.typeorm.ts` file to generate the migrations.

```bash
yarn typeorm-ts-node-commonjs migration:generate -d config.typeorm.ts migrations/<name>
```

```typescript
// config.typeorm.ts

import { PermissionNode, Role } from '@madxnl/madhatter-auth'

function getConfig() {
  return {
    ...
    entities: [... , Role, PermissionNode],
  } as DataSourceOptions
}

const datasource = new DataSource(getConfig()) // config is one that is defined in datasource.config.ts file

datasource.initialize()
export default datasource
```

### Configure the auth module

To use the package simply import the `MadhatterAuthModule` in your `AppModule` with a configuration object.

Example:

```typescript
@Module({
        imports: [
            ...,
            MadhatterAuthModule.forRoot({
                TypeOrmModule,
                hostModules: [
                  UserModule,
                ],
                guardConfig: [
                    {
                        name: 'api',
                        useACL: true,
                        logACL: true,
                        injectable: ApiKeyService,
                        accessEntityMethodName: 'getAccessEntity',
                        roleRelation: 'roles',
                        permissionNodeRelation: 'nodes',
                    },
                ],
            }),
            ...,
      ], 
      ...,
})
export class AppModule { }
```

The configuration object must include the `TypeOrmModule` instance, provide all the modules that register `Role` or `PermissionNode` relations under the `hostModules` key, and also provide an array to specify auth guards you want to implement under the `guardConfig` key.

About the keys in the `guardConfig` object:

- `name`: The name of the guard. The guard will be registered with an injection token of `"MadhatterAuthGuard" + 'name'`, therefore it must be unique within the project. The guard will also append this value to the `req` object with a `accessKeyType` key, for you to be able to differentiate between request types in the project.
- `useACL`: Whether to use ACL (Access Control List) or not. If set to `true`, the guard will check if the user has access to the requested resource. If set to `false`, the guard will only check if the user is authenticated or not.
- `logACL`: Whether to log the ACL checks or not.
- `injectable`: The service that will be injected into the guard. This service must implement a method that fetches the access entity based on the authorization header with the proper relations.
- `accessEntityMethodName`: The name of the method in the service that fetches the access entity.
- `roleRelation`: The name of the relation on the access entity that holds the roles. If omitted, permission nodes belonging to roles will not be checked! If not omitted the provided access entity must also include the corresponding relation!
- `permissionNodeRelation`: The name of the relation on the access entity that holds the permission nodes. If omitted, the permission nodes directly in relation with the access entity will not be checked! If not ommitted the provided access entity must include the corresponding relation!

Both `roleRelation` and `permissionNodeRelation` only supports `ManyToMany` relations.