refactor(webapp): remove email normalization (#8580)

* remove email normalization from webapp

* missing change

* fix error when email is not defined

* fix lint

* remove obsolete test

* remove obsolete tests

* fix password reset

---------

Co-authored-by: Wolfgang Huß <wolle.huss@pjannto.com>
This commit is contained in:
Ulf Gebhardt 2025-05-25 15:58:41 +02:00 committed by GitHub
parent 2b0d38fdff
commit ad4b6e0d79
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 16 additions and 53 deletions

View File

@ -15,6 +15,7 @@ import Resolver from './helpers/Resolver'
export default {
Query: {
VerifyNonce: async (_parent, args, context, _resolveInfo) => {
args.email = normalizeEmail(args.email)
const session = context.driver.session()
const readTxResultPromise = session.readTransaction(async (txc) => {
const result = await txc.run(
@ -38,7 +39,6 @@ export default {
AddEmailAddress: async (_parent, args, context, _resolveInfo) => {
let response
args.email = normalizeEmail(args.email)
try {
const { neode } = context
await new Validator(neode, neode.model('UnverifiedEmailAddress'), args)
@ -86,6 +86,7 @@ export default {
const {
user: { id: userId },
} = context
args.email = normalizeEmail(args.email)
const { nonce, email } = args
const session = context.driver.session()
const writeTxResultPromise = session.writeTransaction(async (txc) => {

View File

@ -2,7 +2,10 @@
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
/* eslint-disable @typescript-eslint/no-unsafe-return */
import normalizeEmail from './normalizeEmail'
export default async function alreadyExistingMail({ args, context }) {
args.email = normalizeEmail(args.email)
const session = context.driver.session()
try {
const existingEmailAddressTxPromise = session.writeTransaction(async (transaction) => {

View File

@ -10,15 +10,18 @@ import { v4 as uuid } from 'uuid'
import registrationConstants from '@constants/registrationBranded'
import createPasswordReset from './helpers/createPasswordReset'
import normalizeEmail from './helpers/normalizeEmail'
export default {
Mutation: {
requestPasswordReset: async (_parent, { email }, { driver }) => {
email = normalizeEmail(email)
// TODO: why this is generated differntly from 'backend/src/schema/resolvers/helpers/generateNonce.js'?
const nonce = uuid().substring(0, registrationConstants.NONCE_LENGTH)
return createPasswordReset({ driver, nonce, email })
},
resetPassword: async (_parent, { email, nonce, newPassword }, { driver }) => {
email = normalizeEmail(email)
const stillValid = new Date()
stillValid.setDate(stillValid.getDate() - 1)
const encryptedNewPassword = await bcrypt.hash(newPassword, 10)

View File

@ -13,6 +13,7 @@ import { getNeode } from '@db/neo4j'
import { Context } from '@src/server'
import { defaultTrophyBadge, defaultVerificationBadge } from './badges'
import normalizeEmail from './helpers/normalizeEmail'
import Resolver from './helpers/Resolver'
import { mergeImage, deleteImage } from './images/images'
import { createOrUpdateLocations } from './users/location'
@ -66,8 +67,8 @@ export default {
}
},
User: async (object, args, context, resolveInfo) => {
const { email } = args
if (email) {
if (args.email) {
args.email = normalizeEmail(args.email)
let session
try {
session = context.driver.session()

View File

@ -89,24 +89,6 @@ describe('Request', () => {
})
})
describe('capital letters in a gmail address', () => {
beforeEach(async () => {
wrapper = Wrapper()
wrapper.find('input#email').setValue('mAiL@gmail.com')
await wrapper.find('form').trigger('submit')
})
it('normalizes email to lower case letters', () => {
const expected = expect.objectContaining({
variables: {
email: 'mail@gmail.com',
locale: 'en',
},
})
expect(mocks.$apollo.mutate).toHaveBeenCalledWith(expected)
})
})
describe('backend throws an error', () => {
beforeEach(() => {
mocks.$apollo.mutate = jest.fn().mockRejectedValue({

View File

@ -45,7 +45,6 @@
<script>
import gql from 'graphql-tag'
import { SweetalertIcon } from 'vue-sweetalert-icons'
import normalizeEmail from '~/components/utils/NormalizeEmail'
export default {
components: {
@ -68,11 +67,8 @@ export default {
}
},
computed: {
email() {
return normalizeEmail(this.formData.email)
},
submitMessage() {
const { email } = this
const email = this.formData.email
return this.$t('components.password-reset.request.form.submitted', { email })
},
},
@ -90,7 +86,7 @@ export default {
}
`
try {
const { email } = this
const email = this.formData.email
await this.$apollo.mutate({ mutation, variables: { email, locale: this.$i18n.locale() } })
this.submitted = true

View File

@ -32,7 +32,6 @@
import gql from 'graphql-tag'
import metadata from '~/constants/metadata'
import { isEmail } from 'validator'
import normalizeEmail from '~/components/utils/NormalizeEmail'
import translateErrorMessage from '~/components/utils/TranslateErrorMessage'
export const SignupMutation = gql`
@ -94,9 +93,6 @@ export default {
},
methods: {
async sendValidation() {
if (this.formData.email && isEmail(this.formData.email)) {
this.formData.email = normalizeEmail(this.formData.email)
}
const { email } = this.formData
this.sliderData.setSliderValuesCallback(this.validInput, { collectedInputData: { email } })

View File

@ -1,11 +0,0 @@
import { normalizeEmail } from 'validator'
export default (email) =>
normalizeEmail(email, {
// gmail_remove_dots: false, default
gmail_remove_subaddress: false,
// gmail_convert_googlemaildotcom: true, default
outlookdotcom_remove_subaddress: false,
yahoo_remove_subaddress: false,
icloud_remove_subaddress: false,
})

View File

@ -114,12 +114,6 @@ describe('Users', () => {
expect(wrapper.vm.email).toEqual('email@example.org')
expect(wrapper.vm.filter).toBe(null)
})
it('email address is case-insensitive', async () => {
const wrapper = await searchAction(Wrapper(), { query: 'eMaiL@example.org' })
expect(wrapper.vm.email).toEqual('email@example.org')
expect(wrapper.vm.filter).toBe(null)
})
})
describe('query is just text', () => {

View File

@ -85,7 +85,6 @@
<script>
import { mapGetters } from 'vuex'
import { isEmail } from 'validator'
import normalizeEmail from '~/components/utils/NormalizeEmail'
import PaginationButtons from '~/components/_new/generic/PaginationButtons/PaginationButtons'
import { adminUserQuery } from '~/graphql/User'
import { FetchAllRoles, updateUserRole } from '~/graphql/admin/Roles'
@ -193,7 +192,7 @@ export default {
this.offset = 0
const { query } = formData
if (isEmail(query)) {
this.email = normalizeEmail(query)
this.email = query
this.filter = null
} else {
this.email = null

View File

@ -30,7 +30,6 @@
import { mapGetters } from 'vuex'
import { AddEmailAddressMutation } from '~/graphql/EmailAddress.js'
import { SweetalertIcon } from 'vue-sweetalert-icons'
import normalizeEmail from '~/components/utils/NormalizeEmail'
import scrollToContent from '../scroll-to-content.js'
export default {
@ -62,7 +61,7 @@ export default {
},
},
formSchema() {
const currentEmail = normalizeEmail(this.currentUser.email)
const currentEmail = this.currentUser.email
const sameEmailValidationError = this.$t('settings.email.validation.same-email')
return {
email: [
@ -70,7 +69,7 @@ export default {
{
validator(rule, value, callback, source, options) {
const errors = []
if (currentEmail === normalizeEmail(value)) {
if (currentEmail === value) {
errors.push(sameEmailValidationError)
}
return errors