Merge pull request #2128 from omnivore-app/fix/trim-user-email-sign-up

fix/trim user email sign up
This commit is contained in:
Hongbo Wu 2023-04-27 16:01:52 +08:00 committed by GitHub
commit f6a17bdc33
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 45 additions and 51 deletions

View file

@ -54,6 +54,15 @@ import {
import { createWebAuthToken } from './jwt_helpers'
import { createSsoToken, ssoRedirectURL } from '../../utils/sso'
export interface SignupRequest {
email: string
password: string
name: string
username: string
bio?: string
pictureUrl?: string
}
const logger = buildLogger('app.dispatch')
const signToken = promisify(jwt.sign)
@ -62,6 +71,19 @@ const cookieParams = {
maxAge: 365 * 24 * 60 * 60 * 1000,
}
export const isValidSignupRequest = (obj: any): obj is SignupRequest => {
return (
'email' in obj &&
obj.email.trim().length > 0 && // email must not be empty
'password' in obj &&
obj.password.length >= 8 && // password must be at least 8 characters
'name' in obj &&
obj.name.trim().length > 0 && // name must not be empty
'username' in obj &&
obj.username.trim().length > 0 // username must not be empty
)
}
export function authRouter() {
const router = express.Router()
@ -443,26 +465,6 @@ export function authRouter() {
'/email-signup',
cors<express.Request>(corsConfig),
async (req: express.Request, res: express.Response) => {
interface SignupRequest {
email: string
password: string
name: string
username: string
bio?: string
pictureUrl?: string
}
function isValidSignupRequest(obj: any): obj is SignupRequest {
return (
'email' in obj &&
obj.email.trim().length > 0 && // email must not be empty
'password' in obj &&
obj.password.length >= 8 && // password must be at least 8 characters
'name' in obj &&
obj.name.trim().length > 0 && // name must not be empty
'username' in obj &&
obj.username.trim().length > 0 // username must not be empty
)
}
if (!isValidSignupRequest(req.body)) {
return res.redirect(
`${env.client.url}/auth/email-signup?errorCodes=INVALID_CREDENTIALS`

View file

@ -32,13 +32,8 @@ export function mobileAuthRouter() {
})
router.post('/email-sign-up', async (req, res) => {
const { email, password, username, name } = req.body
const payload = await createMobileEmailSignUpResponse(
email,
password,
username,
name
)
const payload = await createMobileEmailSignUpResponse(req.body)
res.status(payload.statusCode).json(payload.json)
})

View file

@ -1,18 +1,17 @@
/* eslint-disable @typescript-eslint/restrict-template-expressions */
import UserModel from '../../../datalayer/user'
import { StatusType } from '../../../datalayer/user/model'
import { getUserByEmail } from '../../../services/create_user'
import { sendConfirmationEmail } from '../../../services/send_emails'
import { comparePassword } from '../../../utils/auth'
import { decodeAppleToken } from '../apple_auth'
import { decodeGoogleToken } from '../google_auth'
import {
AuthProvider,
DecodeTokenResult,
JsonResponsePayload,
AuthProvider,
} from '../auth_types'
import { decodeGoogleToken } from '../google_auth'
import { createMobileAuthPayload } from '../jwt_helpers'
import UserModel from '../../../datalayer/user'
import { initModels } from '../../../server'
import { sendConfirmationEmail } from '../../../services/send_emails'
import { kx } from '../../../datalayer/knex_config'
import { StatusType } from '../../../datalayer/user/model'
import { comparePassword } from '../../../utils/auth'
export async function createMobileSignInResponse(
isAndroid: boolean,
@ -46,11 +45,7 @@ export async function createMobileEmailSignInResponse(
throw new Error('Missing username or password')
}
const models = initModels(kx, false)
const user = await models.user.getWhere({
email,
})
const user = await getUserByEmail(email.trim())
if (!user?.id || !user?.password) {
throw new Error('user not found')
}

View file

@ -11,6 +11,7 @@ import { createPendingUserToken, suggestedUsername } from '../jwt_helpers'
import UserModel from '../../../datalayer/user'
import { hashPassword } from '../../../utils/auth'
import { createUser } from '../../../services/create_user'
import { isValidSignupRequest } from '../auth_router'
export async function createMobileSignUpResponse(
isAndroid: boolean,
@ -45,24 +46,24 @@ export async function createMobileSignUpResponse(
}
export async function createMobileEmailSignUpResponse(
email?: string,
password?: string,
username?: string,
name?: string
requestBody: any
): Promise<JsonResponsePayload> {
try {
if (!email || !password || !username || !name) {
if (!isValidSignupRequest(requestBody)) {
throw new Error('Missing username, password, name, or username')
}
const { email, password, name, username } = requestBody
// trim whitespace in email address
const trimmedEmail = email.trim()
const hashedPassword = await hashPassword(password)
await createUser({
email,
email: trimmedEmail,
provider: 'EMAIL',
sourceUserId: email,
name,
username: username.toLowerCase(),
sourceUserId: trimmedEmail,
name: name.trim(),
username: username.trim().toLowerCase(),
password: hashedPassword,
pendingConfirmation: true,
})

View file

@ -24,7 +24,8 @@ export const createUser = async (input: {
password?: string
pendingConfirmation?: boolean
}): Promise<[User, Profile]> => {
const existingUser = await getUserByEmail(input.email)
const trimmedEmail = input.email.trim()
const existingUser = await getUserByEmail(trimmedEmail)
if (existingUser) {
if (existingUser.profile) {
return Promise.reject({ errorCode: SignupErrorCode.UserExists })
@ -63,7 +64,7 @@ export const createUser = async (input: {
const user = await t.getRepository(User).save({
source: input.provider,
name: input.name,
email: input.email,
email: trimmedEmail,
sourceUserId: input.sourceUserId,
password: input.password,
status: input.pendingConfirmation