Skip to content

Commit

Permalink
Merge pull request #1198 from FoalTS/3-2-0
Browse files Browse the repository at this point in the history
v3.2.0
  • Loading branch information
LoicPoullain authored Apr 4, 2023
2 parents 41b4003 + 18795d8 commit 97c83de
Show file tree
Hide file tree
Showing 63 changed files with 3,862 additions and 106 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ jobs:
run: cd packages/jwt && npm run test
- name: Run unit tests of @foal/mongodb
run: cd packages/mongodb && npm run test
- name: Run unit tests of @foal/password
run: cd packages/password && npm run test
- name: Run unit tests of @foal/redis
run: cd packages/redis && npm run test
- name: Run unit tests of @foal/social
Expand Down
Binary file modified backers.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
33 changes: 33 additions & 0 deletions docs/blog/2023-04-04-version-3.2-release-notes copy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
---
title: Version 3.2 release notes
author: Loïc Poullain
author_title: Creator of FoalTS. Software engineer.
author_url: https://loicpoullain.com
author_image_url: https://avatars1.githubusercontent.com/u/13604533?v=4
image: blog/twitter-banners/version-3.2-release-notes.png
tags: [release]
---

![Banner](./assets/version-3.2-is-here/banner.png)

Version 3.2 of [Foal](https://foalts.org/) is out! Here are the improvements that it brings:

<!--truncate-->

## New package `@foal/password`

The `foal/password` package, which was removed in v3.0, has been re-added. It offers an `isCommon` method to check if a password is too common:

```typescript
const isPasswordTooCommon = await isCommon(password);
```

## Read the controller and the controller method names in request contexts

The `Context` and `WebsocketContext` have two new properties:


| Name | Type | Description |
| --- | --- | --- |
| `controllerName` | `string` | The name of the controller class. |
| `controllerMethodName` | `string` | The name of the controller method. |
Binary file added docs/blog/assets/version-3.2-is-here/banner.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 3 additions & 1 deletion docs/docs/architecture/controllers.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ export class AppController implements IAppController {

On every request, the controller method is called with a `Context` object. This context is unique and specific to the request.

It has five properties:
It has seven properties:

| Name | Type | Description |
| --- | --- | --- |
Expand All @@ -104,6 +104,8 @@ It has five properties:
| `user` | `{ [key: string]: any }`\|`null` | The current user (see [Authentication](../authentication/quick-start.md)). |
| `session`| `Session`\|`null` | The session object if you use sessions. |
| `files` | `FileList` | A list of file paths or buffers if you uploaded files (see [Upload and download files](../common/file-storage/upload-and-download-files.md)). |
| `controllerName` | `string` | The name of the controller class. |
| `controllerMethodName` | `string` | The name of the controller method. |

The types of the `user` and `state` properties are generic. You override their types if needed:

Expand Down
13 changes: 13 additions & 0 deletions docs/docs/authentication/password-management.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,3 +56,16 @@ if (passwordHashNeedsToBeRefreshed(user.password)) {

// Log the user in.
```


## Forbid Overly Common Passwords

```
npm install @foal/password
```

To prevent users from using very weak passwords such as `123456` or `password`, you can call the `isCommon` function. This utility checks if the given password is part of the 10000 most common passwords listed [here](https://github.com/danielmiessler/SecLists/blob/master/Passwords/Common-Credentials/10-million-password-list-top-10000.txt).

```typescript
const isPasswordTooCommon = await isCommon(password);
```
1 change: 1 addition & 0 deletions docs/docs/community/awesome-foal.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ A collection of official and unofficial libraries and resources about Foal.
- [@foal/jwks-rsa](https://www.npmjs.com/package/@foal/jwks-rsa): retrieve RSA signing keys from a JWKS endpoint.
- [@foal/jwt](https://www.npmjs.com/package/@foal/jwt): authenticate users with JWT.
- [@foal/mongodb](https://www.npmjs.com/package/@foal/mongodb): session store for MongoDB.
- [@foal/password](https://www.npmjs.com/package/@foal/password): hash, salt and check passwords.
- [@foal/redis](https://www.npmjs.com/package/@foal/redis): session store for redis.
- [@foal/social](https://www.npmjs.com/package/@foal/social): authenticate users with Facebook, Github, Google and LinkedIn.
- [@foal/storage](https://www.npmjs.com/package/@foal/storage): manage file upload and storage in local and in the Cloud.
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion lerna.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@
"packages": [
"packages/*"
],
"version": "3.1.0"
"version": "3.2.0"
}
4 changes: 2 additions & 2 deletions packages/acceptance-tests/package-lock.json

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

24 changes: 12 additions & 12 deletions packages/acceptance-tests/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@foal/acceptance-tests",
"private": true,
"version": "3.1.0",
"version": "3.2.0",
"description": "Acceptance tests of the framework",
"scripts": {
"test": "mocha --require ts-node/register \"./src/**/*.{spec,feature}.{ts,tsx}\"",
Expand All @@ -14,17 +14,17 @@
"node": ">=16.0.0"
},
"dependencies": {
"@foal/core": "^3.1.0",
"@foal/graphiql": "^3.1.0",
"@foal/jwks-rsa": "^3.1.0",
"@foal/jwt": "^3.1.0",
"@foal/mongodb": "^3.1.0",
"@foal/redis": "^3.1.0",
"@foal/social": "^3.1.0",
"@foal/socket.io": "^3.1.0",
"@foal/storage": "^3.1.0",
"@foal/typeorm": "^3.1.0",
"@foal/typestack": "^3.1.0",
"@foal/core": "^3.2.0",
"@foal/graphiql": "^3.2.0",
"@foal/jwks-rsa": "^3.2.0",
"@foal/jwt": "^3.2.0",
"@foal/mongodb": "^3.2.0",
"@foal/redis": "^3.2.0",
"@foal/social": "^3.2.0",
"@foal/socket.io": "^3.2.0",
"@foal/storage": "^3.2.0",
"@foal/typeorm": "^3.2.0",
"@foal/typestack": "^3.2.0",
"@grpc/grpc-js": "~1.6.7",
"@grpc/proto-loader": "~0.6.13",
"@socket.io/redis-adapter": "~7.2.0",
Expand Down
4 changes: 2 additions & 2 deletions packages/aws-s3/package-lock.json

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

6 changes: 3 additions & 3 deletions packages/aws-s3/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@foal/aws-s3",
"version": "3.1.0",
"version": "3.2.0",
"description": "AWS S3 storage components for FoalTS",
"main": "./lib/index.js",
"types": "./lib/index.d.ts",
Expand Down Expand Up @@ -45,8 +45,8 @@
"dependencies": {
"@aws-sdk/client-s3": "~3.198.0",
"@aws-sdk/lib-storage": "~3.198.0",
"@foal/core": "^3.1.0",
"@foal/storage": "^3.1.0"
"@foal/core": "^3.2.0",
"@foal/storage": "^3.2.0"
},
"devDependencies": {
"@types/mocha": "9.1.1",
Expand Down
4 changes: 2 additions & 2 deletions packages/cli/package-lock.json

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

2 changes: 1 addition & 1 deletion packages/cli/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@foal/cli",
"version": "3.1.0",
"version": "3.2.0",
"description": "CLI tool for FoalTS",
"main": "./lib/index.js",
"types": "./lib/index.d.ts",
Expand Down
4 changes: 2 additions & 2 deletions packages/core/package-lock.json

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

4 changes: 2 additions & 2 deletions packages/core/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@foal/core",
"version": "3.1.0",
"version": "3.2.0",
"description": "Full-featured Node.js framework, with no complexity",
"main": "./lib/index.js",
"types": "./lib/index.d.ts",
Expand Down Expand Up @@ -86,7 +86,7 @@
"reflect-metadata": "~0.1.13"
},
"devDependencies": {
"@foal/internal-test": "^3.1.0",
"@foal/internal-test": "^3.2.0",
"@types/mocha": "9.1.1",
"@types/node": "16.11.7",
"@types/supertest": "2.0.12",
Expand Down
6 changes: 6 additions & 0 deletions packages/core/src/core/http/context.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,12 @@ describe('Context', () => {
strictEqual(actual.user, null);
strictEqual(actual.session, null);
strictEqual(actual.files instanceof FileList, true);
strictEqual(actual.controllerName, '');
strictEqual(actual.controllerMethodName, '');

const actual2 = new Context(request, 'AppController', 'foobar');
strictEqual(actual2.controllerName, 'AppController');
strictEqual(actual2.controllerMethodName, 'foobar');
});

});
11 changes: 10 additions & 1 deletion packages/core/src/core/http/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ interface Request extends IncomingMessage {
* - the user object if available,
* - the session object if available,
* - a file list object,
* - the name of the controller and the name of the method,
* - and a `state` object that can be used to pass data across several hooks.
*
* @export
Expand All @@ -118,17 +119,25 @@ export class Context<User = { [key: string]: any } | null, ContextState = { [key
readonly state: ContextState;
readonly files: FileList;

readonly controllerName: string;
readonly controllerMethodName: string;

/**
* Creates an instance of Context.
* @param {*} request - Either the express request object or a mock (for testing).
* @param {string} [controllerName=''] - The name of the controller.
* @param {string} [controllerMethodName=''] - The name of the method.
* @memberof Context
*/
constructor(request: any) {
constructor(request: any, controllerName: string = '', controllerMethodName: string = '') {
this.request = request;
this.session = null;

this.user = null as any;
this.state = {} as any;
this.files = new FileList();

this.controllerName = controllerName;
this.controllerMethodName = controllerMethodName;
}
}
24 changes: 15 additions & 9 deletions packages/core/src/express/create-app.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -195,44 +195,47 @@ describe('createApp', () => {
it(
'should respond on DELETE, GET, PATCH, POST, PUT, HEAD, OPTIONS and "ALL" requests if a handler exists.',
async () => {
let actualGetContext: Context|undefined;

class MyController {
@Head('/foo')
head() {
headSomething() {
// A HEAD response does not have a body.
return new HttpResponseOK()
.setHeader('foo', 'bar');
}
@Get('/foo')
get() {
getSomething(ctx: Context) {
actualGetContext = ctx;
return new HttpResponseOK('get');
}
@Post('/foo')
post() {
postSomething() {
return new HttpResponseOK('post');
}
@Patch('/foo')
patch() {
patchSomething() {
return new HttpResponseOK('patch');
}
@Put('/foo')
put() {
putSomething() {
return new HttpResponseOK('put');
}
@Delete('/foo')
delete() {
deleteSomething() {
return new HttpResponseOK('delete');
}
@Options('/foo')
options() {
optionsSomething() {
return new HttpResponseOK('options');
}
@All('/bar')
all() {
allSomething() {
return new HttpResponseOK('all');
}
}
const app = await createApp(MyController);
return Promise.all([
await Promise.all([
request(app).get('/foo').expect('get'),
request(app).post('/foo').expect('post'),
request(app).patch('/foo').expect('patch'),
Expand All @@ -244,6 +247,9 @@ describe('createApp', () => {
request(app).get('/bar').expect('all'),
request(app).post('/bar').expect('all'),
]);

strictEqual(actualGetContext?.controllerName, 'MyController');
strictEqual(actualGetContext?.controllerMethodName, 'getSomething');
}
);

Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/express/create-app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ export async function createApp(
for (const { route } of routes) {
app[route.httpMethod.toLowerCase()](route.path, async (req: any, res: any, next: (err?: any) => any) => {
try {
const ctx = new Context(req);
const ctx = new Context(req, route.controller.constructor.name, route.propertyKey);
// TODO: better test this line.
const response = await getResponse(route, ctx, services, appController);
sendResponse(response, res);
Expand Down
4 changes: 2 additions & 2 deletions packages/examples/package-lock.json

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

Loading

0 comments on commit 97c83de

Please sign in to comment.