remove login gql resolver
This commit is contained in:
committed by
Jackson Harper
parent
86b950183c
commit
abb1a414c1
@ -50,7 +50,6 @@ import {
|
||||
googleLoginResolver,
|
||||
googleSignupResolver,
|
||||
labelsResolver,
|
||||
loginResolver,
|
||||
logOutResolver,
|
||||
mergeHighlightResolver,
|
||||
newsletterEmailsResolver,
|
||||
@ -153,7 +152,6 @@ export const functionResolvers = {
|
||||
createLabel: createLabelResolver,
|
||||
updateLabel: updateLabelResolver,
|
||||
deleteLabel: deleteLabelResolver,
|
||||
login: loginResolver,
|
||||
setLabels: setLabelsResolver,
|
||||
generateApiKey: generateApiKeyResolver,
|
||||
unsubscribe: unsubscribeResolver,
|
||||
@ -570,7 +568,6 @@ export const functionResolvers = {
|
||||
...resultResolveTypeResolver('Labels'),
|
||||
...resultResolveTypeResolver('CreateLabel'),
|
||||
...resultResolveTypeResolver('DeleteLabel'),
|
||||
...resultResolveTypeResolver('Login'),
|
||||
...resultResolveTypeResolver('SetLabels'),
|
||||
...resultResolveTypeResolver('GenerateApiKey'),
|
||||
...resultResolveTypeResolver('Search'),
|
||||
|
||||
@ -10,7 +10,6 @@ import {
|
||||
MutationDeleteAccountArgs,
|
||||
MutationGoogleLoginArgs,
|
||||
MutationGoogleSignupArgs,
|
||||
MutationLoginArgs,
|
||||
MutationUpdateUserArgs,
|
||||
MutationUpdateUserProfileArgs,
|
||||
QueryUserArgs,
|
||||
@ -35,7 +34,6 @@ import { env } from '../../env'
|
||||
import { validateUsername } from '../../utils/usernamePolicy'
|
||||
import * as jwt from 'jsonwebtoken'
|
||||
import { createUser } from '../../services/create_user'
|
||||
import { comparePassword } from '../../utils/auth'
|
||||
import { deletePagesByParam } from '../../elastic/pages'
|
||||
import { setClaims } from '../../entity/utils'
|
||||
import { User as UserEntity } from '../../entity/user'
|
||||
@ -295,37 +293,6 @@ export function isErrorWithCode(error: unknown): error is ErrorWithCode {
|
||||
)
|
||||
}
|
||||
|
||||
export const loginResolver: ResolverFn<
|
||||
LoginResult,
|
||||
unknown,
|
||||
WithDataSourcesContext,
|
||||
MutationLoginArgs
|
||||
> = async (_obj, { input }, { models, setAuth }) => {
|
||||
const { email, password } = input
|
||||
|
||||
const user = await models.user.getWhere({
|
||||
email,
|
||||
})
|
||||
if (!user?.id) {
|
||||
return { errorCodes: [LoginErrorCode.UserNotFound] }
|
||||
}
|
||||
|
||||
if (!user?.password) {
|
||||
// user has no password, so they need to set one
|
||||
return { errorCodes: [LoginErrorCode.WrongSource] }
|
||||
}
|
||||
|
||||
// check if password is correct
|
||||
const validPassword = await comparePassword(password, user.password)
|
||||
if (!validPassword) {
|
||||
return { errorCodes: [LoginErrorCode.InvalidCredentials] }
|
||||
}
|
||||
|
||||
// set auth cookie in response header
|
||||
await setAuth({ uid: user.id })
|
||||
return { me: userDataToUser(user) }
|
||||
}
|
||||
|
||||
export const deleteAccountResolver = authorized<
|
||||
DeleteAccountSuccess,
|
||||
DeleteAccountError,
|
||||
|
||||
@ -37,9 +37,10 @@ import {
|
||||
RegistrationType,
|
||||
UserData,
|
||||
} from '../../datalayer/user/model'
|
||||
import { hashPassword } from '../../utils/auth'
|
||||
import { comparePassword, hashPassword } from '../../utils/auth'
|
||||
import { createUser } from '../../services/create_user'
|
||||
import { isErrorWithCode } from '../../resolvers'
|
||||
import { initModels } from '../../server'
|
||||
|
||||
const logger = buildLogger('app.dispatch')
|
||||
const signToken = promisify(jwt.sign)
|
||||
@ -359,56 +360,42 @@ export function authRouter() {
|
||||
cors<express.Request>(corsConfig),
|
||||
async (req: express.Request, res: express.Response) => {
|
||||
const { email, password } = req.body
|
||||
if (!email || !password) {
|
||||
res.redirect(`${env.client.url}/email-login?errorCodes=AUTH_FAILED`)
|
||||
return
|
||||
}
|
||||
|
||||
const query = `
|
||||
mutation login{
|
||||
login(input: {
|
||||
email: "${email}",
|
||||
password: "${password}"
|
||||
}) {
|
||||
__typename
|
||||
... on LoginError { errorCodes }
|
||||
... on LoginSuccess {
|
||||
me {
|
||||
id
|
||||
name
|
||||
profile {
|
||||
username
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}`
|
||||
|
||||
try {
|
||||
const result = await axios.post(env.server.gateway_url + '/graphql', {
|
||||
query,
|
||||
const models = initModels(kx, false)
|
||||
const user = await models.user.getWhere({
|
||||
email,
|
||||
})
|
||||
const { data } = result.data
|
||||
|
||||
if (data.login.__typename === 'LoginError') {
|
||||
const errorCodes = data.login.errorCodes.join(',')
|
||||
if (!user?.id) {
|
||||
return res.redirect(
|
||||
`${env.client.url}/email-login?errorCodes=${errorCodes}`
|
||||
`${env.client.url}/email-login?errorCodes=${LoginErrorCode.UserNotFound}`
|
||||
)
|
||||
}
|
||||
|
||||
if (!result.headers['set-cookie']) {
|
||||
if (!user?.password) {
|
||||
// user has no password, so they need to set one
|
||||
return res.redirect(
|
||||
`${env.client.url}/${
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
(req.params as any)?.action
|
||||
}?errorCodes=unknown`
|
||||
`${env.client.url}/email-login?errorCodes=${LoginErrorCode.WrongSource}`
|
||||
)
|
||||
}
|
||||
|
||||
res.setHeader('set-cookie', result.headers['set-cookie'])
|
||||
// check if password is correct
|
||||
const validPassword = await comparePassword(password, user.password)
|
||||
if (!validPassword) {
|
||||
return res.redirect(
|
||||
`${env.client.url}/email-login?errorCodes=${LoginErrorCode.InvalidCredentials}`
|
||||
)
|
||||
}
|
||||
|
||||
await handleSuccessfulLogin(req, res, data.login.me, false)
|
||||
// set auth cookie in response header
|
||||
const token = await signToken({ uid: user.id }, env.server.jwtSecret)
|
||||
|
||||
res.cookie('auth', token, {
|
||||
httpOnly: true,
|
||||
expires: new Date(new Date().getTime() + 365 * 24 * 60 * 60 * 1000),
|
||||
})
|
||||
|
||||
await handleSuccessfulLogin(req, res, user, false)
|
||||
} catch (e) {
|
||||
logger.info('email-login exception:', e)
|
||||
res.redirect(`${env.client.url}/email-login?errorCodes=AUTH_FAILED`)
|
||||
|
||||
@ -1410,11 +1410,6 @@ const schema = gql`
|
||||
|
||||
union UpdateLabelResult = UpdateLabelSuccess | UpdateLabelError
|
||||
|
||||
input LoginInput {
|
||||
password: String!
|
||||
email: String!
|
||||
}
|
||||
|
||||
input SetLabelsInput {
|
||||
pageId: ID!
|
||||
labelIds: [ID!]!
|
||||
@ -1825,7 +1820,6 @@ const schema = gql`
|
||||
createLabel(input: CreateLabelInput!): CreateLabelResult!
|
||||
updateLabel(input: UpdateLabelInput!): UpdateLabelResult!
|
||||
deleteLabel(id: ID!): DeleteLabelResult!
|
||||
login(input: LoginInput!): LoginResult!
|
||||
setLabels(input: SetLabelsInput!): SetLabelsResult!
|
||||
generateApiKey(input: GenerateApiKeyInput!): GenerateApiKeyResult!
|
||||
unsubscribe(name: String!): UnsubscribeResult!
|
||||
|
||||
@ -147,6 +147,6 @@ export const sendConfirmationEmail = async (user: User): Promise<boolean> => {
|
||||
from: `Omnivore <${env.sender.message}>`,
|
||||
to: user.email,
|
||||
subject: 'Confirm your email',
|
||||
text: `Hey ${user.name},\nPlease confirm your email by clicking the link below:\n\n${confirmationLink}\n\n`,
|
||||
text: `Hey ${user.name},\n\nPlease confirm your email by clicking the link below:\n\n${confirmationLink}\n\n`,
|
||||
})
|
||||
}
|
||||
|
||||
@ -2,7 +2,6 @@ import { createTestUser, deleteTestUser, getProfile, getUser } from '../db'
|
||||
import { graphqlRequest, request } from '../util'
|
||||
import { expect } from 'chai'
|
||||
import {
|
||||
LoginErrorCode,
|
||||
UpdateUserErrorCode,
|
||||
UpdateUserProfileErrorCode,
|
||||
} from '../../src/generated/graphql'
|
||||
@ -238,89 +237,4 @@ describe('User API', () => {
|
||||
return graphqlRequest(query, invalidAuthToken).expect(500)
|
||||
})
|
||||
})
|
||||
|
||||
describe('login', () => {
|
||||
let query: string
|
||||
let email: string
|
||||
let password: string
|
||||
|
||||
beforeEach(() => {
|
||||
query = `
|
||||
mutation {
|
||||
login(
|
||||
input: {
|
||||
email: "${email}"
|
||||
password: "${password}"
|
||||
}
|
||||
) {
|
||||
... on LoginSuccess {
|
||||
me {
|
||||
id
|
||||
name
|
||||
profile {
|
||||
username
|
||||
}
|
||||
}
|
||||
}
|
||||
... on LoginError {
|
||||
errorCodes
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
})
|
||||
|
||||
context('when email and password are valid', () => {
|
||||
before(() => {
|
||||
email = user.email
|
||||
password = correctPassword
|
||||
})
|
||||
|
||||
it('responds with 200', async () => {
|
||||
const res = await graphqlRequest(query).expect(200)
|
||||
expect(res.body.data.login.me.id).to.eql(user.id)
|
||||
})
|
||||
})
|
||||
|
||||
context('when user not exists', () => {
|
||||
before(() => {
|
||||
email = 'Some email'
|
||||
})
|
||||
|
||||
it('responds with error code UserNotFound', async () => {
|
||||
const response = await graphqlRequest(query).expect(200)
|
||||
expect(response.body.data.login.errorCodes).to.eql([
|
||||
LoginErrorCode.UserNotFound,
|
||||
])
|
||||
})
|
||||
})
|
||||
|
||||
context('when user has no password stored in db', () => {
|
||||
before(() => {
|
||||
email = anotherUser.email
|
||||
password = 'Some password'
|
||||
})
|
||||
|
||||
it('responds with error code WrongSource', async () => {
|
||||
const response = await graphqlRequest(query).expect(200)
|
||||
expect(response.body.data.login.errorCodes).to.eql([
|
||||
LoginErrorCode.WrongSource,
|
||||
])
|
||||
})
|
||||
})
|
||||
|
||||
context('when password is wrong', () => {
|
||||
before(() => {
|
||||
email = user.email
|
||||
password = 'Some password'
|
||||
})
|
||||
|
||||
it('responds with error code UserNotFound', async () => {
|
||||
const response = await graphqlRequest(query).expect(200)
|
||||
expect(response.body.data.login.errorCodes).to.eql([
|
||||
LoginErrorCode.InvalidCredentials,
|
||||
])
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@ -8,6 +8,7 @@ import { MailDataRequired } from '@sendgrid/helpers/classes/mail'
|
||||
import sinon from 'sinon'
|
||||
import * as util from '../../src/utils/sendEmail'
|
||||
import supertest from 'supertest'
|
||||
import { hashPassword } from '../../src/utils/auth'
|
||||
|
||||
describe('auth router', () => {
|
||||
const route = '/api/auth'
|
||||
@ -139,4 +140,85 @@ describe('auth router', () => {
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('login', () => {
|
||||
const loginRequest = (email: string, password: string): supertest.Test => {
|
||||
return request.post(`${route}/email-login`).send({
|
||||
email,
|
||||
password,
|
||||
})
|
||||
}
|
||||
const correctPassword = 'correctPassword'
|
||||
|
||||
let user: User
|
||||
let email: string
|
||||
let password: string
|
||||
|
||||
before(async () => {
|
||||
const hashedPassword = await hashPassword(correctPassword)
|
||||
user = await createTestUser('login_test_user', undefined, hashedPassword)
|
||||
})
|
||||
|
||||
after(async () => {
|
||||
await deleteTestUser(user.name)
|
||||
})
|
||||
|
||||
context('when email and password are valid', () => {
|
||||
before(() => {
|
||||
email = user.email
|
||||
password = correctPassword
|
||||
})
|
||||
|
||||
it('redirects to waitlist page', async () => {
|
||||
const res = await loginRequest(email, password).expect(302)
|
||||
expect(res.header.location).to.endWith('/waitlist')
|
||||
})
|
||||
})
|
||||
|
||||
context('when user not exists', () => {
|
||||
before(() => {
|
||||
email = 'Some email'
|
||||
})
|
||||
|
||||
it('redirects with error code UserNotFound', async () => {
|
||||
const res = await loginRequest(email, password).expect(302)
|
||||
expect(res.header.location).to.endWith(
|
||||
'/email-login?errorCodes=USER_NOT_FOUND'
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
context('when user has no password stored in db', () => {
|
||||
before(async () => {
|
||||
const anotherUser = await createTestUser('another_user')
|
||||
email = anotherUser.email
|
||||
password = 'Some password'
|
||||
})
|
||||
|
||||
after(async () => {
|
||||
await deleteTestUser('another_user')
|
||||
})
|
||||
|
||||
it('redirects with error code WrongSource', async () => {
|
||||
const res = await loginRequest(email, password).expect(302)
|
||||
expect(res.header.location).to.endWith(
|
||||
'/email-login?errorCodes=WRONG_SOURCE'
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
context('when password is wrong', () => {
|
||||
before(() => {
|
||||
email = user.email
|
||||
password = 'Wrong password'
|
||||
})
|
||||
|
||||
it('redirects with error code InvalidCredentials', async () => {
|
||||
const res = await loginRequest(email, password).expect(302)
|
||||
expect(res.header.location).to.endWith(
|
||||
'/email-login?errorCodes=INVALID_CREDENTIALS'
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user