WEBVTT

00:00.110 --> 00:06.290
So now that we've exposed our reservations microservice over our GraphQL Gateway, let's continue and

00:06.290 --> 00:13.610
add the authentication microservice as well so that we can query all the users in our system.

00:14.030 --> 00:20.260
We'll go into the auth module and follow the same process that we did in the reservation service.

00:20.270 --> 00:34.520
So we'll simply add the GraphQL module for route and pass in the Apollo driver config as the options

00:34.520 --> 00:35.120
here.

00:35.780 --> 00:38.360
Now I want to pass in the driver.

00:38.390 --> 00:42.290
That will be the Apollo Federation driver from Nestjs Apollo.

00:43.000 --> 00:49.810
And then we'll specify the auto schema file again where we want to set federation equal to two so that

00:49.810 --> 00:52.810
our schema is automatically generated from our code.

00:52.810 --> 01:00.010
So in our users directory, let's go ahead and create a new users dot resolver.

01:00.050 --> 01:01.090
It's.

01:01.940 --> 01:05.720
And this is going to be just like we did with the reservation service.

01:05.750 --> 01:14.420
We'll use the resolver decorator that will be returning the user document and make sure we import this

01:14.420 --> 01:16.160
from app slash common.

01:16.160 --> 01:24.350
And so we'll go ahead and export the class users resolver and our constructor will go ahead and inject

01:24.350 --> 01:26.180
the user service.

01:28.530 --> 01:35.310
And now I want to add a mutation using the mutation decorator that will return a user document.

01:36.970 --> 01:39.970
And I want to expose the create user method.

01:40.360 --> 01:49.090
So here we'll use the add args decorator again and extract the create user input that we'll call create

01:49.090 --> 01:52.030
user input, but we'll know it will be simply the same.

01:52.030 --> 01:59.690
DTO we've already created the create user DTO so inside of this method we will simply return this dot

01:59.710 --> 02:05.530
user service dot, create and pass in the create user input.

02:06.880 --> 02:15.250
Next up, let's add a new query here using the Add query decorator from Nestjs slash GraphQL, where

02:15.250 --> 02:19.510
we'll go ahead and return an array of user documents.

02:19.780 --> 02:28.870
And I'll give this a custom name of users because we'll create a new find all method here that will

02:28.870 --> 02:36.430
simply return this dot user service dot find all which we haven't implemented yet.

02:36.580 --> 02:43.090
However, we can easily implement this by going to the user service and creating a new async find all

02:43.090 --> 02:53.200
method that will call this dot users repository dot find and pass in an empty filter query object so

02:53.200 --> 02:56.320
that we will find all users in our database.

02:56.320 --> 03:06.340
So now we'll go to our user dot schema file in lib slash common so that we can convert this into a GraphQL

03:06.440 --> 03:11.810
schema type by adding the at object type decorator to it.

03:12.050 --> 03:17.600
And now we will go ahead and expose our properties by using the at field decorator.

03:17.600 --> 03:24.560
Now I don't want to expose the password property here because that is sensitive data, so we can merely

03:24.560 --> 03:29.630
leave off the at field decorator from it and it won't be added to our schema.

03:29.630 --> 03:33.320
So that can be really helpful when we want to leave off certain data.

03:33.710 --> 03:37.610
So I'll go ahead and add the field decorator finally to our roles array.

03:37.850 --> 03:43.760
And because this is a non primitive type, we'll go ahead and explicitly specify the type here of an

03:43.760 --> 03:45.530
array of strings.

03:45.920 --> 03:53.450
Now, finally, back in our users resolver, we'll go into our create user DTO and do the same thing

03:53.570 --> 03:54.830
by decorating it.

03:54.830 --> 04:03.620
We'll add the add input type decorator and add the add field decorator to all of these properties that

04:03.620 --> 04:06.950
we know will be passed in when we create a new user.

04:06.950 --> 04:12.230
And finally, for the roles array, we'll specify that this is an array of strings.

04:12.380 --> 04:18.410
Additionally, in order to specify that this is an optional property and doesn't need to be provided,

04:18.410 --> 04:24.650
we need to provide an options object where we specify nullable to true, which makes it so that this

04:24.650 --> 04:26.820
property can be nullable.

04:26.840 --> 04:34.220
Lastly, make sure we go to the users module and add the newly created users resolver to our providers

04:34.220 --> 04:39.830
array so that all of our types and schemas get registered in our GraphQL schema.

04:39.830 --> 04:46.520
So now that we've correctly exposed our users document using the users resolver, let's go back to the

04:46.550 --> 04:55.460
Gateway module and integrate the newly created auth GraphQL service into our subgraphs array.

04:55.550 --> 05:02.960
By following the same process, we'll provide the name of it and call it off and specify the URL equal

05:02.960 --> 05:12.950
to config service dot getter throw and now we'll provide the auth GraphQL URL.

05:13.190 --> 05:22.520
So now we need to go into the dot m file for our gateway and make sure we add the auth GraphQL URL,

05:22.520 --> 05:30.800
which will be our Http protocol and it's going to be the name of the auth service and this will be on

05:30.800 --> 05:32.540
Port 3001.

05:32.750 --> 05:40.340
We can go to the auth M file to remind yourself that our Http server is listening on 3001 and we'll

05:40.340 --> 05:42.260
target slash GraphQL.

05:42.740 --> 05:52.100
Finally, go ahead and restart our Docker services so that we now have access to the auth GraphQL server.

05:52.250 --> 05:59.000
So now that our services have started up, let's go back to our GraphQL server and refresh it.

05:59.000 --> 06:08.900
And now if we look at our docs, we can see we have the user's query and mutation added to our super

06:08.900 --> 06:12.050
graph in our gateway schema.

06:12.050 --> 06:15.830
So as an end user, this is all just one schema.

06:15.860 --> 06:21.320
Even though these are from different services underneath, it's all abstracted away, which makes this

06:21.320 --> 06:24.620
a great solution for exposing APIs like this.

06:24.620 --> 06:32.780
So of course we can query all of the users in our system now by executing a new user's query and pulling

06:32.780 --> 06:37.400
back everything we want in this user, the ID and email.

06:37.400 --> 06:43.670
And of course there is no password on the user and we can even see this by looking at the raw schema

06:43.670 --> 06:44.990
for the user document.

06:45.020 --> 06:50.600
There is no password exposed so we can pull the roles off as well.

06:50.600 --> 06:56.270
And now if we query the users, we can see the user that we've created earlier.

06:56.270 --> 07:03.770
And notice this is the same user ID associated with the reservation that we created so we can see our

07:03.770 --> 07:06.320
current user decorator is working.

07:06.430 --> 07:12.430
As expected because it's pulling the user off and the auth context from the auth service and sending

07:12.430 --> 07:16.150
it to the underlying services, in this case the reservation service.

07:16.150 --> 07:23.410
So this is great to see and we can quickly check to see that our create user mutation is also working.

07:23.410 --> 07:28.030
So we'll pass in a create user input that has a user email.

07:28.030 --> 07:40.360
So I'll use some test email at test.com and make sure we have a strong password with some special characters

07:40.360 --> 07:49.930
in it and then specify we want the ID, email and roles to come back and we can add some roles as well

07:50.920 --> 07:54.040
to make sure the roles array looks correct.

07:54.040 --> 08:01.120
And now we can see the user is created and if we execute this query, we can see the new user in our

08:01.120 --> 08:01.870
response.

08:01.870 --> 08:03.650
So this is excellent.

08:03.670 --> 08:07.940
Okay, so finally, let's go ahead and expose one more microservice.

08:07.940 --> 08:13.430
The payments microservice, which is currently actually locked down to the outside world because there's

08:13.430 --> 08:18.560
no way for an external service to call this TCP, TCP microservice.

08:18.560 --> 08:25.430
So it's a great candidate for adding it to our API gateway to, for example, query the list of all

08:25.430 --> 08:27.470
payments we have in our system.

08:27.470 --> 08:34.880
So let's go ahead and follow our standard procedure so we can actually go into the auth module and I'll

08:34.880 --> 08:43.040
simply copy the GraphQL module that we set up and let's paste it in to the payments module and make

08:43.040 --> 08:46.460
sure we import the necessary files here.

08:46.460 --> 08:51.050
So we have the driver, the options and the GraphQL module that we just imported.

08:51.080 --> 08:58.520
So next up I want to go to our Main.ts where currently we are not listening on an Http port.

08:58.520 --> 09:00.050
So let's change this.

09:00.050 --> 09:06.680
In addition to calling start all microservices, we need to make sure we call await app dot listen.

09:06.680 --> 09:13.220
So that we listen on an Http port where our GraphQL server will be running on so that the gateway microservice

09:13.220 --> 09:14.000
can reach it.

09:14.000 --> 09:23.060
So let's call config service dot getter throw and call the port dot http and then I'll also rename the

09:23.060 --> 09:29.630
existing port and MV to port TCP to make sure this is a bit more clear that these are two separate ports

09:29.630 --> 09:35.600
and we'll go back to our payments module and make sure we change the validation schema to also be port

09:35.630 --> 09:36.410
TCP.

09:36.770 --> 09:40.370
So now we'll go into our Env and make this change as well.

09:40.370 --> 09:50.270
So we'll add a port dot TCP equal to 3003 and then our port dot http I'll say will be on 3005 and now

09:50.270 --> 09:57.650
we can go ahead and create our payments resolver inside of our payment source folder that will go ahead

09:57.650 --> 10:02.840
and expose our payment intents that are coming from our Stripe API.

10:02.930 --> 10:09.320
So let's go ahead and firstly define what this payment intent entity will look like.

10:09.320 --> 10:22.100
So I'll create a new file called Payment Intent dot Entity Dot TS, and this will be an Add object type.

10:22.940 --> 10:26.990
And now we'll export a class called Payment Intent.

10:27.020 --> 10:33.760
So if we look in the payment service, we can see the payment intent that gets returned from the Create

10:33.770 --> 10:39.140
call has a bunch of different properties on it that we really don't care about.

10:39.140 --> 10:40.060
Most of them.

10:40.070 --> 10:47.780
All I really want is the amount on the payment intent and the ID of the payment intent so we can make

10:47.810 --> 10:56.450
sure we just expose these two properties by adding a field decorator, set an ID equal to string, and

10:56.450 --> 11:01.250
then the Add field decorator to set the amount to type number.

11:01.250 --> 11:04.760
So we really only care about these two properties on the payment intent.

11:04.790 --> 11:11.060
Let's go ahead and expose them in our payment intent object type, which will be added to our GraphQL

11:11.060 --> 11:11.900
schema.

11:11.930 --> 11:15.710
So let's go to our payment resolver now and flesh this out.

11:15.740 --> 11:22.710
We'll add the resolver decorator as we're used to doing that will return the payment intent that we

11:22.710 --> 11:23.840
just created.

11:23.850 --> 11:33.630
So we'll export a class called payments resolver and we'll inject the payments service in this resolver

11:33.630 --> 11:35.130
so that we can call it.

11:35.430 --> 11:43.590
And now we'll expose our one query in here using the Nestjs GraphQL query decorator that will return

11:43.590 --> 11:46.770
an array of payment intent.

11:47.190 --> 11:54.240
Now also query this and I'll also give this a custom name of payments.

11:55.130 --> 11:57.890
And then we'll create this function called find all.

11:57.890 --> 12:04.970
And then in here we will return this dot payment service dot, get payments, which we haven't set up

12:04.970 --> 12:05.540
yet.

12:05.540 --> 12:12.410
So let's go ahead and do that next by going into the payments service and creating this function.

12:12.680 --> 12:22.020
So in here I'll create a new async get payments method that is going to be very simple.

12:22.040 --> 12:29.870
It's going to get all of the payment intents from our Stripe API by creating a new const called Payments.

12:29.900 --> 12:38.270
We'll set it equal to await this dot stripe dot payment intents dot list, which will retrieve a list

12:38.270 --> 12:39.620
of payment intents.

12:39.890 --> 12:46.430
And then we're going to return payments dot data, which contains all of our payment intents, which

12:46.430 --> 12:50.330
includes the ID and amount on each payment intent.

12:50.450 --> 12:57.750
So lastly, in our payments module, don't forget to add the payments resolver to the providers array.

12:58.080 --> 13:06.330
Let's go back to the gateway now, the Gateway module and add the last object to our subgraph that will

13:06.330 --> 13:14.700
contain the payments service, we'll call it payments, and then the URL will be config service, dot

13:14.700 --> 13:21.360
getter throw and extract the payments GraphQL URL and variable.

13:21.480 --> 13:32.490
So we'll go to the MV and now get the payments GraphQL URL and set this equal to Http.

13:32.490 --> 13:34.200
Colon slash slash.

13:35.030 --> 13:40.490
The name of the payment service, which we know is payments and then the port it's exposed on which

13:40.490 --> 13:47.780
we just created, which was 3005 and then reached the GraphQL endpoint, which is called GraphQL.

13:47.870 --> 13:53.180
So I'll go ahead and do one last restart of my containers and let them start up.

13:53.180 --> 13:55.630
So now our services have started up.

13:55.640 --> 14:04.820
I'll go back and refresh the GraphQL playground and now if we query the docs, we can see we have the

14:04.820 --> 14:08.870
new payment query that's been added with our payment intent.

14:09.720 --> 14:10.710
Entity.

14:11.310 --> 14:13.710
So let's go ahead and test this out.

14:13.740 --> 14:17.700
I'll create a new query called.

14:18.970 --> 14:27.280
Payments, we query all payments and then I want to pull back the ID and the amount for each payment.

14:27.310 --> 14:29.200
So I'll go ahead and execute this.

14:29.200 --> 14:35.470
And now you can see we have a list of all the payments I've ever created on the Stripe API.

14:35.830 --> 14:40.030
So you can see the ID and the amount for each one, which is super useful.
