Skip to content

Commit

Permalink
feat: support authentication for rest-crud based APIs
Browse files Browse the repository at this point in the history
Signed-off-by: Muhammad Aaqil <[email protected]>
  • Loading branch information
aaqilniz committed Aug 19, 2024
1 parent 9ac691e commit 3187229
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 2 deletions.
1 change: 1 addition & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 11 additions & 1 deletion packages/rest-crud/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ export class TryApplication extends BootMixin(

Create a new file for the configuration, e.g.
`src/model-endpoints/product.rest-config.ts` that defines the `model`,
`pattern`, `dataSource`, `basePath`, and `readonly` properties:
`pattern`, `dataSource`, `basePath`, `readonly` and `auth` properties:

```ts
import {ModelCrudRestApiConfig} from '@loopback/rest-crud';
Expand All @@ -55,6 +55,16 @@ module.exports = <ModelCrudRestApiConfig>{
dataSource: 'db',
basePath: '/products',
readonly: false,
auth: {
count: true,
get: true,
getById: true,
post: true,
patch: true,
patchById: true,
putById: true,
deleteById: true,
},
};
```

Expand Down
1 change: 1 addition & 0 deletions packages/rest-crud/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
"@loopback/rest": "^14.0.0"
},
"dependencies": {
"@loopback/authentication": "^11.0.2",
"@loopback/model-api-builder": "^6.0.2",
"debug": "^4.3.4",
"tslib": "^2.6.2"
Expand Down
30 changes: 29 additions & 1 deletion packages/rest-crud/src/crud-rest.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import {
SchemaObject,
} from '@loopback/rest';
import assert from 'assert';
import {authenticate} from '@loopback/authentication';

// Ideally, this file should simply `export class CrudRestController<...>{}`
// Unfortunately, that's not possible for several reasons.
Expand Down Expand Up @@ -105,6 +106,19 @@ export interface CrudRestControllerOptions {
* Whether to generate readonly APIs
*/
readonly?: boolean;
/**
* Whether to add authentication decorator or not
*/
auth?: {
count?: boolean;
get?: boolean;
getById?: boolean;
post?: boolean;
patch?: boolean;
patchById?: boolean;
putById?: boolean;
deleteById?: boolean;
};
}

/**
Expand Down Expand Up @@ -154,7 +168,7 @@ export function defineCrudRestController<
constructor(
public readonly repository: EntityCrudRepository<T, IdType, Relations>,
) {}

@authenticatedMethod(options.auth?.get)
@get('/', {
...response.array(200, `Array of ${modelName} instances`, modelCtor, {
includeRelations: true,
Expand All @@ -172,6 +186,7 @@ export function defineCrudRestController<
includeRelations: true,
}),
})
@authenticatedMethod(options.auth?.getById)
async findById(
@param(idPathParam) id: IdType,
@param.query.object(
Expand All @@ -186,6 +201,7 @@ export function defineCrudRestController<
@get('/count', {
...response(200, `${modelName} count`, {schema: CountSchema}),
})
@authenticatedMethod(options.auth?.count)
async count(
@param.where(modelCtor)
where?: Where<T>,
Expand All @@ -205,6 +221,7 @@ export function defineCrudRestController<
@post('/', {
...response.model(200, `${modelName} instance created`, modelCtor),
})
@authenticatedMethod(options?.auth?.post)
async create(
@body(modelCtor, {
title: `New${modelName}`,
Expand All @@ -224,6 +241,7 @@ export function defineCrudRestController<
schema: CountSchema,
}),
})
@authenticatedMethod(options?.auth?.patch)
async updateAll(
@body(modelCtor, {partial: true}) data: Partial<T>,
@param.where(modelCtor)
Expand All @@ -242,6 +260,7 @@ export function defineCrudRestController<
'204': {description: `${modelName} was updated`},
},
})
@authenticatedMethod(options?.auth?.patchById)
async updateById(
@param(idPathParam) id: IdType,
@body(modelCtor, {partial: true}) data: Partial<T>,
Expand All @@ -259,6 +278,7 @@ export function defineCrudRestController<
'204': {description: `${modelName} was updated`},
},
})
@authenticatedMethod(options.auth?.putById)
async replaceById(
@param(idPathParam) id: IdType,
@body(modelCtor) data: T,
Expand All @@ -271,6 +291,7 @@ export function defineCrudRestController<
'204': {description: `${modelName} was deleted`},
},
})
@authenticatedMethod(options.auth?.deleteById)
async deleteById(@param(idPathParam) id: IdType): Promise<void> {
await this.repository.deleteById(id);
}
Expand Down Expand Up @@ -361,3 +382,10 @@ namespace response {
});
}
}

// Helper function to conditionally add @authenticate decorator
function authenticatedMethod(applyAuth: boolean | undefined) {
return applyAuth
? authenticate('jwt')
: (target: Object, key: string, descriptor: PropertyDescriptor) => {};
}

0 comments on commit 3187229

Please sign in to comment.