Tsed: Context

Created on 2 Apr 2019  Â·  12Comments  Â·  Source: tsedio/tsed

I was just wondering what would be the best way to store something that should be available in the whole context during a request (like the Authenticated Princial for example) ?

Also, where do you prefer I ask questions regarding your framework ? I didn't see any group/tag on stackoverflow ?

question

Most helpful comment

Great thanks.

I think it is interesting to have the ability to share data between
different levels of the applications (Application, Security, WebRequest,
... like Spring does for example).
This is especially interesting for cross-cutting concerns like security for
example.

In my particular use case, a user a some permissions or roles (authorities)
that allows him to perform some actions.
I don't like to pass the user and it's associated roles/permissions to
every layer (controllers, services, facades, ...) of the application to
perform some validations. Security being a cross-cutting concern, I find
that cleaner to be able to retrieve the user associated with the request
from a shared context.

Thanks again for the great example.
It will allows me to do more advanced stuff (I'd like to implement a
@Transactional decorator for typeorm).

On Tue, Apr 2, 2019 at 11:27 PM Romain Lenzotti notifications@github.com
wrote:

Good question. Currently, tsed doesn't have a Context service, but it's
possible to implement this feature. Actually, for each incoming request,
tsed create a new container, a logger and an endpoint metadata (which can
be used by middleware and endpoint's controller).
A context can be created by a global middleware like what is done by the
LogIncomingRequest class.

Middleware:

@Middleware()
export class CreateContextMiddleware {

use(@Req() req: Express.Request) {

    req.context = new ContextModel() // implement your own Context class

}

}

Filter:

import {getValue} from "@tsed/core";

@Filter()
export class ContextFilter implements IFilter {

transform(expression: string, request: any, response: any) {

if (expression) {

  return request.context && getValue(expression, request.context);

}



return request.context;

}

}

Decorator:

function Context() {

return (target: any, propertyKey: string, parameterIndex: number): void => {

    ParamRegistry.useFilter(ContextFilter, {

        propertyKey,

        parameterIndex,

        target,

        useConverter: false,

        paramType: "context"

      });

}

}

And finally the server:

import "./filters/ContextFilter"
import {CreateContextMiddleware} "./middlewares/CreateContextMiddleware"

@ServerSettings({})
export class Server extends ServerLoader{

$onMountingMiddlewares () {

   this.use(CreateContextMiddleware)

   // ... other middlewares

}

}

Usage:

import {Context} from "./decorators/Context";
import {ContextModel} from "./models/ContextModel";

@Controller("/")
class MyCtrl {

@Get("/")

get(@Context() context: ContextModel) {

}

@Get("/")

get(@Context("somethin") something: any) {

}

}

I don't know if you have to implement this feature directly in tsed?
because Context is depend on the application that you will develop... What
do you think?

we don't have a group/tag on stackoverflow, we never thought about that ^^.

See you
Romain

—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
https://github.com/TypedProject/ts-express-decorators/issues/530#issuecomment-479210712,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AF4GXfmp0snvUhgkdeT0ANq59xeExmrzks5vc8tUgaJpZM4cY6Gc
.

--
Jean Chapelle

All 12 comments

Good question. Currently, tsed doesn't have a Context service, but it's possible to implement this feature. Actually, for each incoming request, tsed create a new container, a logger and an endpoint metadata (which can be used by middleware and endpoint's controller).
A context can be created by a global middleware like what is done by the LogIncomingRequest class.

Middleware:

@Middleware()
export class CreateContextMiddleware {
    use(@Req() req: Express.Request) {
        req.context = new ContextModel() // implement your own Context class
   }
}

Filter:

import {getValue} from "@tsed/core";
@Filter()
export class ContextFilter implements IFilter {
  transform(expression: string, request: any, response: any) {
    if (expression) {
      return request.context && getValue(expression, request.context);
    }

    return request.context;
  }
}

Decorator:

function Context() {
   return (target: any, propertyKey: string, parameterIndex: number): void => {
        ParamRegistry.useFilter(ContextFilter, {
            propertyKey,
            parameterIndex,
            target,
            useConverter: false,
            paramType: "context"
          });
   }
}

And finally the server:

import "./filters/ContextFilter"
import {CreateContextMiddleware} from "./middlewares/CreateContextMiddleware"

@ServerSettings({})
export class Server extends ServerLoader{
   $onMountingMiddlewares () {
       this.use(CreateContextMiddleware)
       // ... other middlewares
   }
}

Usage:

import {Context} from "./decorators/Context";
import {ContextModel} from "./models/ContextModel";

@Controller("/")
class MyCtrl {
   @Get("/")
   get(@Context()  context: ContextModel) {

   }
   @Get("/")
   get(@Context("somethin")  something: any) {

   }
}

I don't know if you have to implement this feature directly in tsed? because Context is depend on the application that you will develop... What do you think?

we don't have a group/tag on stackoverflow, we never thought about that ^^.

See you
Romain

Great thanks.

I think it is interesting to have the ability to share data between
different levels of the applications (Application, Security, WebRequest,
... like Spring does for example).
This is especially interesting for cross-cutting concerns like security for
example.

In my particular use case, a user a some permissions or roles (authorities)
that allows him to perform some actions.
I don't like to pass the user and it's associated roles/permissions to
every layer (controllers, services, facades, ...) of the application to
perform some validations. Security being a cross-cutting concern, I find
that cleaner to be able to retrieve the user associated with the request
from a shared context.

Thanks again for the great example.
It will allows me to do more advanced stuff (I'd like to implement a
@Transactional decorator for typeorm).

On Tue, Apr 2, 2019 at 11:27 PM Romain Lenzotti notifications@github.com
wrote:

Good question. Currently, tsed doesn't have a Context service, but it's
possible to implement this feature. Actually, for each incoming request,
tsed create a new container, a logger and an endpoint metadata (which can
be used by middleware and endpoint's controller).
A context can be created by a global middleware like what is done by the
LogIncomingRequest class.

Middleware:

@Middleware()
export class CreateContextMiddleware {

use(@Req() req: Express.Request) {

    req.context = new ContextModel() // implement your own Context class

}

}

Filter:

import {getValue} from "@tsed/core";

@Filter()
export class ContextFilter implements IFilter {

transform(expression: string, request: any, response: any) {

if (expression) {

  return request.context && getValue(expression, request.context);

}



return request.context;

}

}

Decorator:

function Context() {

return (target: any, propertyKey: string, parameterIndex: number): void => {

    ParamRegistry.useFilter(ContextFilter, {

        propertyKey,

        parameterIndex,

        target,

        useConverter: false,

        paramType: "context"

      });

}

}

And finally the server:

import "./filters/ContextFilter"
import {CreateContextMiddleware} "./middlewares/CreateContextMiddleware"

@ServerSettings({})
export class Server extends ServerLoader{

$onMountingMiddlewares () {

   this.use(CreateContextMiddleware)

   // ... other middlewares

}

}

Usage:

import {Context} from "./decorators/Context";
import {ContextModel} from "./models/ContextModel";

@Controller("/")
class MyCtrl {

@Get("/")

get(@Context() context: ContextModel) {

}

@Get("/")

get(@Context("somethin") something: any) {

}

}

I don't know if you have to implement this feature directly in tsed?
because Context is depend on the application that you will develop... What
do you think?

we don't have a group/tag on stackoverflow, we never thought about that ^^.

See you
Romain

—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
https://github.com/TypedProject/ts-express-decorators/issues/530#issuecomment-479210712,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AF4GXfmp0snvUhgkdeT0ANq59xeExmrzks5vc8tUgaJpZM4cY6Gc
.

--
Jean Chapelle

@jchapelle No problem ;)

I think, I'll keep this example for the website, if it works for you :D

Sure, that's great ;-)

On Wed, Apr 3, 2019 at 10:26 AM Romain Lenzotti notifications@github.com
wrote:

I think, I'll keep this example for the website, if it works for you :D

—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/TypedProject/ts-express-decorators/issues/530#issuecomment-479390793,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AF4GXXvPxPfETM6385fq4r3FtXc7NeG_ks5vdGWygaJpZM4cY6Gc
.

--
Jean Chapelle

I realize I have a question regarding this.

Is it possible to secify an order in Middleware execution ?

The @Secure middleware seems to be execute before middlewares setup in
Server configuration.
It would be great to be able to setup the context before going to the
AuthenticatedMiddleware

On Wed, Apr 3, 2019 at 10:28 AM Jean Chapelle jean.chapelle@gmail.com
wrote:

Sure, that's great ;-)

On Wed, Apr 3, 2019 at 10:26 AM Romain Lenzotti notifications@github.com
wrote:

I think, I'll keep this example for the website, if it works for you :D

—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/TypedProject/ts-express-decorators/issues/530#issuecomment-479390793,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AF4GXXvPxPfETM6385fq4r3FtXc7NeG_ks5vdGWygaJpZM4cY6Gc
.

--
Jean Chapelle

--
Jean Chapelle

Hey Romain,

The code you shared previously does not really do the job I was expecting.
With your code, you can create a context and access it in a controller
method. That's very fine but not enough for my use case.
The problem I'm facing is : what if I want to extract data from the context
in children methods ? Then, I must pass the data I'm interested in all the
way down to the method that will access the data. Another way to do it
would be to implement a closure.

This morning, I've read a very interesting article about this concern :
https://datahero.com/blog/2014/05/22/node-js-preserving-data-across-async-callbacks/
With that in place, you can create a context in a middleware and access it
later in any method. This looks like the spring contexts stuff.

Personally, I'm using a microservices system in which microservices calls
each other on behalf of the user initiating a request. In order to ensure
the user is properly authenticated and has sufficient rights, I must pass
data (Authorization credentials) all the way down to methods calling other
microservices.
Now, I will be able to extract the credentials of the user in the method
that needs it.

I thought you would be interested by this so I'm sharing it ...

Cheers

On Wed, Apr 3, 2019 at 2:51 PM Jean Chapelle jean.chapelle@gmail.com
wrote:

I realize I have a question regarding this.

Is it possible to secify an order in Middleware execution ?

The @Secure middleware seems to be execute before middlewares setup in
Server configuration.
It would be great to be able to setup the context before going to the
AuthenticatedMiddleware

On Wed, Apr 3, 2019 at 10:28 AM Jean Chapelle jean.chapelle@gmail.com
wrote:

Sure, that's great ;-)

On Wed, Apr 3, 2019 at 10:26 AM Romain Lenzotti notifications@github.com
wrote:

I think, I'll keep this example for the website, if it works for you :D

—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/TypedProject/ts-express-decorators/issues/530#issuecomment-479390793,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AF4GXXvPxPfETM6385fq4r3FtXc7NeG_ks5vdGWygaJpZM4cY6Gc
.

--
Jean Chapelle

--
Jean Chapelle

--
Jean Chapelle

@jchapelle Im facing the exact same problem and wondered if you found any solution ?

@Hadard753 Ts.ed has now a @Context decorator to any data. His life is limited to the request life itself.

You can use it ;)

Nice ;-)

On Thu, Jul 30, 2020 at 7:25 PM Romain Lenzotti notifications@github.com
wrote:

@Hadard753 https://github.com/Hadard753 Ts.ed has now a @context
https://github.com/context decorator to any data. His life is limited
to the request life itself.

You can use it ;)

—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/TypedProject/tsed/issues/530#issuecomment-666543370,
or unsubscribe
https://github.com/notifications/unsubscribe-auth/ABPAMXMYK7ML5DCAOMGL6P3R6GUH3ANCNFSM4HDDUGOA
.

--
Jean Chapelle

@Romakita
Hi thanks for your quick reply this sounds like the perfect solution for me but when trying to inject the context param in my service I get the following error:
image

and here are the relevant parts of my code:

the service where I want to access the token :
image

the middleware where i save into the context:
image

@Context cannot be injected in services only in on controller method.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

yangukmo picture yangukmo  Â·  5Comments

m0uneer picture m0uneer  Â·  5Comments

tobiasmuecksch picture tobiasmuecksch  Â·  6Comments

Ionaru picture Ionaru  Â·  5Comments

vorph1 picture vorph1  Â·  6Comments