Hi Ben, I woke up with a sore throat this morning. Probably will develop into full blown cold and will take about two weeks to get over. Your video classes are always great.
Great setup! Couple questions: 1. Do you validate incoming parameters using yup or some other validator? For example, email may not be an actual email. 2. I throw custom Errors for all errors and allow graphql to manage the error. I have three so far (Authentication, Authorization, Field). The frontend than parses and handles the error. Still not sure if this is best implementation. I haven't yet figured out how to block all other error types for production. How do you handle uncaught errors like from faulty code, db, etc? 3. If a malicious user somehow does copy the 7 year old cookie and uses it on their end, would you recommend checking ip and/or other specs to further validate cookie? Maybe I'm overthinking it... Your voice still sounds a bit rough. Rest well.
1. yeah yup 2. The convention I like to use is throw an error in middleware or if an unexpected error is encountered and return errors if I expect they could happen. Here's how I handle unexpected errors ruclips.net/video/7oLczJD6zZI/видео.html 3. maybe, depending on the type of application. I feel like in most cases it's overkill and ip can change so it can be hard to get a good fingerprint (though maybe some users don't want you to fingerprint them). yeah going to rest it, still feels weird
Hard to say until we see http2 become more mainstream, but I still see graphql being useful it has more benefits than just reducing the number of requests to the server
Why do you integrate the errors into the schema and don't throw an Apollo error if the login fails or the email has already been used? If you make both properties optional in the response object, theoretically both could be null, would a union be better?
1. The convention I like to use is throw an Apollo error in middleware or if an unexpected error is encountered and return errors if I expect they could happen. But it's just a convention, you could throw all your errors if you want 2. Yeah I think a union describes it better (and is probably the correct choice), but I find objects easier to work with
There is an error, or at least an unwise decision in the code, which defines MyContext as { req: Request, res: Response }. That isn't exactly so. For many of the functions to work, "session" must be set on the request, and the type does not reflect that requirement. I think the definition of MyContext should be changed to { req: Request & {session: Session}, res: Response } and the context function in the Apollo middleware should cast or assert that session is set. This change is a sounder alternative to using the "!" everywhere.
hi, happy yoyu've done this because I'm facing a major perf issue when comparing the password with bcrypt. It takes almost 10s to decrypt a hashed password of 10 characters using a 16 length salt. Are you facing a similar issue before? The server where app is running is quite powerful, so I guess the issue might be in the decryption algorithm. In your video, comparison is fast. thks
Hi Ben. Thanks for amazing video. Would you know why the cookie will not set in browser (the way you showed at end). I can create user, i can log in and see the cookie being returned from the server (localhost:4000) but it doesn't get stored. Hence any authenticated requests like me, and book returns error.
First of all, thank you for sharing this video. One point for improvement for the login resolver could be to also trigger bcrypt hash(password) when no matching user has been found. This way, you make the login requests for existing users quite a bit more indistinguishable from requests without a matching user in the database. Furthermore, I hope that you will be considering CSRF protection in some way?
@@bawad I think could be a good step in the right direction indeed. You still would have to consider the actual value of the header and it's impact on the browser policy. Setting strict would mean that users coming from somewhere else through a link would not be logged in. Setting it to lax could mean that it might be a good thing to let apollo server to accept POST requests only. Another option to improve the situation could be a referrer check and using CSRF tokens when using sessions. Those things can also be combined. Django in fact does put a sameorigin lax on it's CSRF cookie IIRC. Anyway. Keep up the good work!
Hey man, thanks for this, this package looks really cool, I am so excited to use it, can you share your thoughts about how to avoid n+1 problems in this model. I really expect you to evolve this... because it is really amazing
@@bawad tell, please, how you pass project colors throughout the project components? What you do if you should change any color after project completed? Thanks!
What was your solution ultimately? I'm trying to make a graphql apollo typescript api for my react frontend and have so many differing guides out there)
Good afternoon ben awad. And again thank you for your amazing videos, i learnt a lot from you. Just , it seems typeorm transactions are very tricky, sometime i've problem to deal with it with apollo server. Can you, please, if are you are not busy, make a video about that ?.thank you
did you format it like this try { // execute some operations on this transaction: await queryRunner.manager.save(user1); await queryRunner.manager.save(user2); await queryRunner.manager.save(photos); // commit transaction now: await queryRunner.commitTransaction(); } catch (err) { // since we have errors lets rollback changes we made await queryRunner.rollbackTransaction(); } finally { // you need to release query runner which is manually created: await queryRunner.release(); }
Hello Ben! Thank you for your work and inspiration! Can you tell me how you test authentication? When I use `createTestClient` from `apollo-server-express` context get empty object, without `express` `req` and I can't find solution to run `query` or `mutation` and pass headers with them. This is my get context function: github.com/team-organizer/team-organizer.core/blob/master/src/app/lib/get-context.ts Test: github.com/team-organizer/team-organizer.core/blob/e161d6b346095331f153d9e65ce4e16e66c6769e/src/auth/__tests__/auth.resolver.test.ts#L107
@@bawad Thank you! If you interest I found a solution with supertest, github.com/apollographql/apollo-server/issues/2277#issuecomment-598293528, that's like full e2e test
Hi Ben, I woke up with a sore throat this morning. Probably will develop into full blown cold and will take about two weeks to get over. Your video classes are always great.
oh, now I understand why you disappeared. Hope you will be well now. Thanks for all you do
You got code burn man. Please take a strict rest calendar
Welcome back Ben. Love you man
❤
Great setup! Couple questions:
1. Do you validate incoming parameters using yup or some other validator? For example, email may not be an actual email.
2. I throw custom Errors for all errors and allow graphql to manage the error. I have three so far (Authentication, Authorization, Field). The frontend than parses and handles the error. Still not sure if this is best implementation. I haven't yet figured out how to block all other error types for production. How do you handle uncaught errors like from faulty code, db, etc?
3. If a malicious user somehow does copy the 7 year old cookie and uses it on their end, would you recommend checking ip and/or other specs to further validate cookie? Maybe I'm overthinking it...
Your voice still sounds a bit rough. Rest well.
1. yeah yup
2. The convention I like to use is throw an error in middleware or if an unexpected error is encountered and return errors if I expect they could happen. Here's how I handle unexpected errors ruclips.net/video/7oLczJD6zZI/видео.html
3. maybe, depending on the type of application. I feel like in most cases it's overkill and ip can change so it can be hard to get a good fingerprint (though maybe some users don't want you to fingerprint them).
yeah going to rest it, still feels weird
@@bawad Why did you add the FieldError in the user response instead of actually throwing an error? Also why yup and not joi
1. preference
2. tried yup first
Do you have any upgraded guides or tools for generating a graphql apollo typescript api to be used with a typescript react/redux frontend?
Aye your back man!!!
Get well soon BruH
Hope you feel better.
thanks
Would you consider adding Redis as an optional dependency? like give another parameter --redis for session storage
Do you think it's worth add a flag for it?
The only difference would be swapping the connect package and installing ioredis
@
Ben Awad This is my first time working with node.js, apollo-server, graphql. And now I also choose a framework. What to choose and why?
ruclips.net/video/VnG7ej56lWw/видео.html
@@bawad Thank you
I really appreciate this, thank you!
Hello Ben! There's a lot of talking about http2 vs graphql, what do you think about that? Will graphql be still usefull?
Hard to say until we see http2 become more mainstream, but I still see graphql being useful it has more benefits than just reducing the number of requests to the server
@@bawad thanks
Why do you integrate the errors into the schema and don't throw an Apollo error if the login fails or the email has already been used?
If you make both properties optional in the response object, theoretically both could be null, would a union be better?
1. The convention I like to use is throw an Apollo error in middleware or if an unexpected error is encountered and return errors if I expect they could happen. But it's just a convention, you could throw all your errors if you want
2. Yeah I think a union describes it better (and is probably the correct choice), but I find objects easier to work with
great video, looking forward for more content on this subject, maybe how to aggregate data while avoiding n+1 problem with graphql ?
I just saw he usually uses loaders to avoid it like in this ruclips.net/video/8kZ7W-bI5qQ/видео.html
There is an error, or at least an unwise decision in the code, which defines MyContext as { req: Request, res: Response }. That isn't exactly so. For many of the functions to work, "session" must be set on the request, and the type does not reflect that requirement. I think the definition of MyContext should be changed to { req: Request & {session: Session}, res: Response } and the context function in the Apollo middleware should cast or assert that session is set. This change is a sounder alternative to using the "!" everywhere.
I like it, thanks for the suggestion
Welcome back king!
thanks
hi, happy yoyu've done this because I'm facing a major perf issue when comparing the password with bcrypt. It takes almost 10s to decrypt a hashed password of 10 characters using a 16 length salt. Are you facing a similar issue before? The server where app is running is quite powerful, so I guess the issue might be in the decryption algorithm. In your video, comparison is fast. thks
I'm not
are you using bcryptjs? You could try switching to bcrypt or vice versa
also lowering your salt will help
glad your better now :)
🙌
Hi Ben. Thanks for amazing video. Would you know why the cookie will not set in browser (the way you showed at end). I can create user, i can log in and see the cookie being returned from the server (localhost:4000) but it doesn't get stored. Hence any authenticated requests like me, and book returns error.
Assuming you set credentials to include in your settings I'm not sure
Have you tried a different browser?
First of all, thank you for sharing this video. One point for improvement for the login resolver could be to also trigger bcrypt hash(password) when no matching user has been found. This way, you make the login requests for existing users quite a bit more indistinguishable from requests without a matching user in the database. Furthermore, I hope that you will be considering CSRF protection in some way?
Good point!
Add same site to your cookie?
@@bawad I think could be a good step in the right direction indeed. You still would have to consider the actual value of the header and it's impact on the browser policy. Setting strict would mean that users coming from somewhere else through a link would not be logged in. Setting it to lax could mean that it might be a good thing to let apollo server to accept POST requests only. Another option to improve the situation could be a referrer check and using CSRF tokens when using sessions. Those things can also be combined. Django in fact does put a sameorigin lax on it's CSRF cookie IIRC. Anyway. Keep up the good work!
Hey man, thanks for this, this package looks really cool, I am so excited to use it, can you share your thoughts about how to avoid n+1 problems in this model. I really expect you to evolve this... because it is really amazing
I just saw you usually use loaders to avoid it like in this ruclips.net/video/8kZ7W-bI5qQ/видео.html
Hi Ben!
Could you explain please how correctly to use global sass variables in next ts project, thanks!
sorry, I've never used sass before
@@bawad tell, please, how you pass project colors throughout the project components? What you do if you should change any color after project completed? Thanks!
I use styled-components and a theme provider for that
Hi Ben, can you show us how do you make Queries with React Hook (experimental mode) and Apollo, thanks.
what trouble are you running into with apollo hooks?
@@bawad no trouble, just wanna see how you do it, I appreciate the way you code and theres no much videos about it
"My Thoughts on The Unofficial React Apollo Hooks Library" already helps me thanks again
This boilerplate is seriously convoluted (after spending a few days trying to connect a frontend)
What was your solution ultimately? I'm trying to make a graphql apollo typescript api for my react frontend and have so many differing guides out there)
Good afternoon ben awad. And again thank you for your amazing videos, i learnt a lot from you. Just , it seems typeorm transactions are very tricky, sometime i've problem to deal with it with apollo server. Can you, please, if are you are not busy, make a video about that ?.thank you
What problem have you run into?
@@bawad after queryRunnerCommittransaction, i cant render the result, its seems an infinite loop
did you format it like this
try {
// execute some operations on this transaction:
await queryRunner.manager.save(user1);
await queryRunner.manager.save(user2);
await queryRunner.manager.save(photos);
// commit transaction now:
await queryRunner.commitTransaction();
} catch (err) {
// since we have errors lets rollback changes we made
await queryRunner.rollbackTransaction();
} finally {
// you need to release query runner which is manually created:
await queryRunner.release();
}
i did this createMessage: requireAuth.createResolver(
async (
_parent,
{ product_id, text, seller_id, username },
{ user_id: client_id }
) => {
const queryRunner = await getConnection().createQueryRunner();
await queryRunner.startTransaction();
try {
const transactionalEntityManager = queryRunner.manager;
const repo = getRepository(Conversation);
const isConversation = await repo.findOne({
where: { product_id, seller_id, client_id },
});
if (isConversation) {
const message = new Message();
message.author_id = client_id;
message.text = text;
message.conversation_id = isConversation.id;
await transactionalEntityManager.save(message);
await queryRunner.commitTransaction();
emitter.emit('newMessage', {
destinator_id: seller_id,
username,
conversation_id: isConversation.id,
});
return {
ok: true,
message,
conversation: isConversation,
};
}
const conversation = new Conversation();
conversation.seller_id = seller_id;
conversation.client_id = client_id;
conversation.product_id = product_id;
await transactionalEntityManager.save(conversation);
const message = new Message();
message.author_id = client_id;
message.text = text;
message.conversation_id = conversation.id;
await transactionalEntityManager.save(message);
await queryRunner.commitTransaction();
emitter.emit('newMessage', {
destinator_id: seller_id,
username,
conversation_id: conversation.id,
});
return {
ok: true,
message,
conversation,
};
} catch (error) {
await queryRunner.rollbackTransaction();
return {
ok: false,
errors: [{ path: 'global', message: error.message }],
};
}
}
),
do you get an error?
Next great step would be SSO!
I should do that, it would be fun to make
Almost sounds like you could have caught a little strep.
yeah this was my guess
thanks
Hello Ben! Thank you for your work and inspiration! Can you tell me how you test authentication?
When I use `createTestClient` from `apollo-server-express` context get empty object, without `express` `req` and I can't find solution to run `query` or `mutation` and pass headers with them.
This is my get context function: github.com/team-organizer/team-organizer.core/blob/master/src/app/lib/get-context.ts
Test: github.com/team-organizer/team-organizer.core/blob/e161d6b346095331f153d9e65ce4e16e66c6769e/src/auth/__tests__/auth.resolver.test.ts#L107
ruclips.net/video/fxYcbw56mbk/видео.html
ruclips.net/video/zR8jKR9hnFA/видео.html
@@bawad Thank you! If you interest I found a solution with supertest, github.com/apollographql/apollo-server/issues/2277#issuecomment-598293528, that's like full e2e test