Skip to content

Conversation

@curtwl
Copy link
Contributor

@curtwl curtwl commented Nov 12, 2024

Description

To test this PR

  1. obtain github oauth client id and client secret (on clickup, you can also make your own for dev), and put them in .env
  2. npx prisma db push for both dev and test db
  3. go to http://localhost:8000/api/v1/auth/github/login a github authorization table will pop up, and it should return the user's basic github profile

Issue link

Fixes # (issue)

Type of change

  • Bug fix (non-breaking change which fixes an issue)
  • Feature updates / changes
  • Tests
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • This change requires a documentation update

How Has This Been Tested?

Manually and automated tests

Checklist:

  • [ x] My code follows the style guidelines of this project
  • [ x] I have performed a self-review of my code
  • [ x] I have commented my code, particularly in hard-to-understand areas
  • [ x] I have made corresponding changes to the documentation
  • [ x] My changes generate no new warnings
  • [ x] I have added tests that prove my fix is effective or that my feature works
  • [ x] New and existing tests pass locally with my changes
  • [ x] Any dependent changes have been merged and published in downstream modules
  • [ x] I have updated the change log

@curtwl curtwl requested a review from cherylli November 12, 2024 11:39
@cherylli cherylli requested a review from Ajen07 November 13, 2024 01:12
@github-actions
Copy link
Contributor

@cherylli, @Ajen07
One business day has passed since the review started. Give priority to reviews as much as possible.

Copy link
Contributor

@cherylli cherylli left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

image

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

@cherylli
Copy link
Contributor

image

image

invalid code is not handled - I'm quite sure the discord one also has the same issue

If you can fix both it would be great, if not I can fix the discord one in another PR

@curtwl
Copy link
Contributor Author

curtwl commented Nov 19, 2024

invalid code is not handled - I'm quite sure the discord one also has the same issue

If you can fix both it would be great, if not I can fix the discord one in another PR

Does {"message":"Failed to obtain access token. Possibly because of invalid redirect code.","error":"Bad Request","statusCode":400} work for the error message? I guess other situations could cause the same message since it's just a generic error for the super.canActivate(context) in the AuthGuards.

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;
Copy link
Contributor

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

Copy link
Contributor Author

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?

Copy link
Contributor

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

@cherylli
Copy link
Contributor

@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

@cherylli
Copy link
Contributor

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;
Copy link
Contributor

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.

Copy link
Contributor Author

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.

Copy link
Contributor

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.

@curtwl
Copy link
Contributor Author

curtwl commented Jan 17, 2025

@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

Sure, I've been reading through the docs and it doesn't seem like it'll take long after I understand the workflow.

@cherylli cherylli added the low priority label Feb 1, 2025
});
}

async findUserByEmails(emails): Promise<any | null> {
Copy link

@davideastmond davideastmond Feb 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typescript is complaining.

Suggested change
async findUserByEmails(emails): Promise<any | null> {
async findUserByEmails(emails: string[]): Promise<any | null> {

});
}

async findUserByEmails(emails): Promise<any | null> {
Copy link

@davideastmond davideastmond Feb 19, 2025

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.

Copy link
Contributor

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

image

"[discord-auth.service]: Cannot get email from discord to create a new Chingu account",
);

const existingUser = await this.findUserByEmails([user.email]);
Copy link

@davideastmond davideastmond Feb 19, 2025

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.

Copy link
Contributor

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) {

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

Suggested change
async validateUser(user: GithubUser) {
async validateUser(user: GithubUser): Promise<AuthUserResult> {

Copy link
Contributor

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([
Copy link

@davideastmond davideastmond Feb 19, 2025

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

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment on lines 15 to +26
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;
}

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?

Suggested change
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;
}

Comment on lines +16 to +31
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;
}

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

Comment on lines +26 to +27
accessToken: string,
refreshToken: string,

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;

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants