@@ -78,6 +78,18 @@ Example:
7878 async def foo(self, request: Request) -> Response:
7979 ...
8080` ` `
81+ # # Route path
82+ It is important to know that it is best to define routes with a regular expression when it is an id, uuid or similar. This is to avoid collisions with similar routes.
83+ Instead of using :
84+ ` ` ` python
85+ @enroute.rest.command("/users/{uuid}", "POST")
86+ ` ` `
87+ Use :
88+ ` ` ` python
89+ import re
90+ UUID_REGEX = re.compile(r"\w {8}-\w {4}-\w {4}-\w {4}-\w {12}")
91+ @enroute.rest.command(f"/users/{{uuid:{UUID_REGEX.pattern}}}", "POST")
92+ ` ` `
8193
8294# # Authentication
8395
@@ -118,6 +130,74 @@ discovery:
118130...
119131` ` `
120132
133+ # ## JWT Token creation & refresh
134+ Example on how to create and refresh token. You need to store in database or similar the secret and key returned form kong in order to refresh existing token.
135+ ` ` ` python
136+ from minos.common import (
137+ UUID_REGEX,
138+ NotProvidedException,
139+ Config,
140+ Inject,
141+ )
142+ from minos.cqrs import (
143+ CommandService,
144+ )
145+ from minos.networks import (
146+ Request,
147+ Response,
148+ enroute,
149+ )
150+
151+ from ..aggregates import (
152+ User,
153+ )
154+ from minos.plugins.kong import KongClient
155+
156+ class UserCommandService(CommandService):
157+ """UserCommandService class."""
158+
159+ def __init__(self, *args, **kwargs):
160+ super().__init__(*args, **kwargs)
161+ self.kong = self._get_kong_client()
162+
163+ @staticmethod
164+ @Inject()
165+ def _get_kong_client(config: Config) -> KongClient:
166+ """Get the service name."""
167+ if config is None:
168+ raise NotProvidedException("The config object must be provided.")
169+ return KongClient.from_config(config)
170+
171+ @enroute.rest.command(f"/users/{{uuid:{UUID_REGEX.pattern}}}/jwt", "POST", authenticated=True,
172+ authorized_groups=["admin"], regex_priority=3)
173+ @enroute.broker.command("GetUserJWT")
174+ async def create_user_jwt(self, request: Request) -> Response:
175+ params = await request.params()
176+ uuid = params["uuid"]
177+ user = await User.get(uuid)
178+
179+ if user.uuid == request.user:
180+ token = await self.add_jwt_to_consumer(request.headers.get("X-Consumer-ID"))
181+ return Response({"token": token})
182+ else:
183+ return Response(status=404)
184+
185+ async def add_jwt_to_consumer(self, consumer: str):
186+ resp = await self.kong.add_jwt_to_consumer(consumer=consumer)
187+ res = resp.json()
188+ self.key = res['key']
189+ self.secret = res['secret']
190+ token = await self.kong.generate_jwt_token(key=self.key, secret=self.secret)
191+ return token
192+
193+ @enroute.rest.command(f"/users/{{uuid:{UUID_REGEX.pattern}}}/refresh-jwt", "POST", authenticated=True,
194+ authorized_groups=["admin"], regex_priority=3)
195+ @enroute.broker.command("RefreshJWT")
196+ async def refresh_jwt(self, request: Request) -> Response:
197+ token = await self.kong.generate_jwt_token(key=self.key, secret=self.secret)
198+ return Response({"token": token})
199+ ` ` `
200+
121201For the route to be authenticated with the method specified above, a parameter called `authenticated` must be passed :
122202` ` ` python
123203class CategoryCommandService(CommandService):
0 commit comments