Skip to content
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

feat: add getUserByEmail function to GoTrueAdminApi #949

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 33 additions & 1 deletion src/GoTrueAdminApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import {
AuthMFAAdminListFactorsResponse,
PageParams,
} from './lib/types'
import { AuthError, isAuthError } from './lib/errors'
import { AuthError, CustomAuthError, isAuthError, UserNotFoundError } from './lib/errors'

export default class GoTrueAdminApi {
/** Contains all MFA administration methods. */
Expand Down Expand Up @@ -233,6 +233,38 @@ export default class GoTrueAdminApi {
}
}

/**
* Get user by email.
*
* @param email The user's email
*
* This function should only be called on a server. Never expose your `service_role` key in the browser.
*/
async getUserByEmail(email: string): Promise<UserResponse> {
try {
const response = await _request(this.fetch, 'GET', `${this.url}/admin/users`, {
headers: this.headers,
xform: _userResponse,
query: {
filter: 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.

Dropped the URL Encode on email as _request seems to do URLEncoding here

Passing in an encoded email seems to lead to double encoding for me locally

},
})

const users = response?.data?.user?.users || []
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Changed this to a nullish check.

if (users.length > 0) {
return { data: { user: users[0] }, error: null }
}

throw new UserNotFoundError()
Copy link
Contributor Author

@J0 J0 Aug 29, 2024

Choose a reason for hiding this comment

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

Moved the initialization of the custom error to errors.ts for easier tracking and re-use

} catch (error) {
if (isAuthError(error)) {
return { data: { user: null }, error }
}

throw error
}
}

/**
* Updates the user data.
*
Expand Down
6 changes: 6 additions & 0 deletions src/lib/errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,12 @@ export function isAuthSessionMissingError(error: any): error is AuthSessionMissi
return isAuthError(error) && error.name === 'AuthSessionMissingError'
}

export class UserNotFoundError extends CustomAuthError {
constructor() {
super('User not found', 'UserNotFoundError', 404, 'user_not_found')
}
}

export class AuthInvalidTokenResponseError extends CustomAuthError {
constructor() {
super('Auth session or user missing', 'AuthInvalidTokenResponseError', 500, undefined)
Expand Down
8 changes: 7 additions & 1 deletion src/lib/types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { AuthError } from './errors'
import { AuthError, CustomAuthError } from './errors'
import { Fetch } from './fetch'

/** One of the providers supported by GoTrue. */
Expand Down Expand Up @@ -224,6 +224,12 @@ export type UserResponse =
}
error: AuthError
}
| {
data: {
user: null
}
error: CustomAuthError
}

export interface Session {
/**
Expand Down
16 changes: 16 additions & 0 deletions test/GoTrueApi.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,22 @@ describe('GoTrueAdminApi', () => {
expect(foundUser).not.toBeUndefined()
expect(foundUser.user?.email).toEqual(email)
})

test('getUserByEmail() should a registered user given its email', async () => {
const { email } = mockUserCredentials()
const { error: createError, data: createdUser } = await createNewUserWithEmail({ email })

expect(createError).toBeNull()
expect(createdUser.user).not.toBeUndefined()

const { error: foundError, data: foundUser } = await serviceRoleApiClient.getUserByEmail(
email
)

expect(foundError).toBeNull()
expect(foundUser).not.toBeUndefined()
expect(foundUser.user?.email).toEqual(email)
})
})

describe('User updates', () => {
Expand Down