-
Notifications
You must be signed in to change notification settings - Fork 7
Feature/oauth GitHub #222
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: dev
Are you sure you want to change the base?
Feature/oauth GitHub #222
Conversation
cherylli
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suggest adding a more desciptive error message for this error: upsert error because there's no github in the provider database
We need to update prisma/seed/data/oauth-providers.ts to include github. We also need to delete the file prisma/seed/oauth.ts as it's not used (mistake from a previous PR)
everything else work fine
Does |
| const { username, id, photos, emails } = profile; | ||
|
|
||
| const avatar = photos && photos.length > 0 ? photos[0].value : null; | ||
| const email = emails && emails.length > 0 ? emails[0].value : null; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if we should match/check all the (github verified) emails with existing users in the database, instead of just the first email.
If none of them is found in the database we can create a new account with the primary email
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does discord need this functionality too?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
probably, but I don't think discord lets you have multiple emails
|
@curtwl do you feel like squashing the commits? This might be a good practice if you want to try it out. Otherwise we can probably just leave it, next release notes will probably be manually updated combining our changelog and release please change log |
|
One more question - do you know if oauth only returns verified emails? or is there a way to check if the emails are verified? Otherwise if users add emails which do not belong to them we don't want to automatically link to an existing account |
| refreshToken: string, | ||
| profile: GithubProfile, | ||
| ): Promise<any> { | ||
| const { username, id, photos, emails } = profile; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm getting an error saying that "'username, id, photos' properties does not exist on type GitHubProfile". Also I found a types package for passport-github2 at @types/passport-github2 on yarn.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the types package got lost resolving a merge conflict, oops! Definitely had that installed while developing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok, I'll look at again once you install the types package.
Sure, I've been reading through the docs and it doesn't seem like it'll take long after I understand the workflow. |
| }); | ||
| } | ||
|
|
||
| async findUserByEmails(emails): Promise<any | null> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typescript is complaining.
| async findUserByEmails(emails): Promise<any | null> { | |
| async findUserByEmails(emails: string[]): Promise<any | null> { |
| }); | ||
| } | ||
|
|
||
| async findUserByEmails(emails): Promise<any | null> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm wondering if we can get a better return type for this method? Can we actually return a properly typed user?
If we're going to use any as a return type here, we shouldn't need the union with null, since any should cover the null type.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Currently, this is a prisma User Model type, I think there's one we could use, for reference: https://www.prisma.io/docs/orm/prisma-client/type-safety. The current implicit type is this
| "[discord-auth.service]: Cannot get email from discord to create a new Chingu account", | ||
| ); | ||
|
|
||
| const existingUser = await this.findUserByEmails([user.email]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it possible that this could return null?
To be safe we could make sure that this value is not null.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| private prisma: PrismaService, | ||
| @Inject("OAuth-Config") private oAuthConfig: OAuthConfig, | ||
| ) {} | ||
| async validateUser(user: GithubUser) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a tiny suggestion to make the intelliSense clearer, since Typescript was inferring unnecessarily a union type of objects with the same properties
| async validateUser(user: GithubUser) { | |
| async validateUser(user: GithubUser): Promise<AuthUserResult> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is AuthUserResult something built in or something we have to define?
I think this might be same as the prisma User model type
| "[github-auth.service]: Cannot get email from github to create a new Chingu account", | ||
| ); | ||
|
|
||
| const existingUser = await this.findUserByEmails([ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should check for null to be safe
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes according to the Prisma API https://www.prisma.io/docs/orm/reference/prisma-client-reference#findfirst
| async canActivate(context: ExecutionContext): Promise<boolean> { | ||
| const activate = (await super.canActivate(context)) as boolean; | ||
| let activate; | ||
| try { | ||
| activate = (await super.canActivate(context)) as boolean; | ||
| } catch (e) { | ||
| if (e.code == "invalid_grant") { | ||
| throw new BadRequestException( | ||
| `Invalid code in redirect query param.`, | ||
| ); | ||
| } | ||
| throw e; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For readability, could we move line 27 and 28 into the try block?
| async canActivate(context: ExecutionContext): Promise<boolean> { | |
| const activate = (await super.canActivate(context)) as boolean; | |
| let activate; | |
| try { | |
| activate = (await super.canActivate(context)) as boolean; | |
| } catch (e) { | |
| if (e.code == "invalid_grant") { | |
| throw new BadRequestException( | |
| `Invalid code in redirect query param.`, | |
| ); | |
| } | |
| throw e; | |
| } | |
| try { | |
| const activate = await super.canActivate(context) as boolean | |
| const request = context.switchToHttp().getRequest(); | |
| await super.logIn(request); | |
| return activate; | |
| } catch (e) { | |
| if (e.code == "invalid_grant") { | |
| throw new BadRequestException( | |
| `Invalid code in redirect query param.`, | |
| ); | |
| } | |
| throw e; | |
| } |
| let activate; | ||
| try { | ||
| activate = (await super.canActivate(context)) as boolean; | ||
| } catch (e) { | ||
| if (e.message.includes("Failed to obtain access token")) { | ||
| throw new BadRequestException( | ||
| `Failed to obtain access token. Possibly because of invalid redirect code.`, | ||
| ); | ||
| } | ||
| throw e; | ||
| } | ||
| const request = context.switchToHttp().getRequest(); | ||
| await super.logIn(request); | ||
|
|
||
| return activate; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Similar comment here that I made in the file src/auth/guards/discord-auth.guard.ts
| accessToken: string, | ||
| refreshToken: string, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It doesn't look like we're using these variables?
| profile: GithubProfile, | ||
| ): Promise<any> { | ||
| const { username, id, photos, emails } = profile; | ||
| const avatar = photos && photos.length > 0 ? photos[0].value : null; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Might be related to the comment above about the types packages - for readability I think we should explicitly declare what the type of avatar is




Description
To test this PR
npx prisma db pushfor both dev and test dbhttp://localhost:8000/api/v1/auth/github/logina github authorization table will pop up, and it should return the user's basic github profileIssue link
Fixes # (issue)
Type of change
How Has This Been Tested?
Manually and automated tests
Checklist: