const { updateCustomer, updateCustomerAddressById, deleteCustomerAddressById, addCustomerAddress, validateCredentials, getCustomerById, } = require("../lib/bigcommerceRestAPI") const { withAccount } = require("../lib/utils") const { getJwt } = require("../lib/utils") const emailRegex = /(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\.){3}(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9])|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])/ ;(function () { if (context.user.auth()) return let data = context.data const r = context.request() const customerId = r.param("id") const backendAuth = context.user.auth() let returnCustomer = undefined if (!backendAuth) { // require authorization header with jwt const token = getJwt(context) /** @type {JWTPwResetClaims} */ // @ts-ignore const pwResetClaims = token.claims /** @type {Customer} */ // @ts-ignore const customer = context.db.find("bigCommerceCustomer", { filter: { _id: pwResetClaims.tibiId }, })[0] if (!customer) { throw { status: 404, error: "customer not found", log: false, } } if (data.operation === "resetPassword") { if (pwResetClaims && pwResetClaims.tibiId && pwResetClaims.check) { // is password reset token since it has .check if (pwResetClaims.tibiId != customerId) throw { status: 403, error: "token not valid for this id", log: false, } if (pwResetClaims.check != customer.currentToken) throw { status: 403, error: "password reset token expired", log: false, } updateCustomer({ authentication: { force_password_reset: false, new_password: data.password, }, id: Number(customer.bigCommerceId), }) throw { status: 200, log: false, } } else { throw { status: 403, error: "invalid token", log: false, } } } withAccount((loginClaims) => { /** @type {BigCommerceCustomer} */ const customer = data.customer if (customer) customer.id = Number(loginClaims.bigCommerceId) if (data.operation === "updateCustomer") { customer.email = loginClaims.email const index = customer.form_fields.findIndex((f) => f.name === "username") const internalCustomer = context.db.find("bigCommerceCustomer", { filter: { email: customer.email }, })[0] if (index >= 0) customer.form_fields[index].value = internalCustomer.username const response = updateCustomer(customer) throw { status: 200, data: response, message: "customer updated", log: false, } } else if (data.operation == "updateInternalCustomer") { const customer = data.customer returnCustomer = customer } else if (data.operation === "updateCustomerAddress") { /** @type {BigCommerceAddress} */ const address = data.address address.customer_id = Number(loginClaims.bigCommerceId) const response = updateCustomerAddressById(address) throw { status: 200, message: "customer addresses updated", data: response, log: false, } } else if (data.operation === "deleteCustomerAddress") { deleteCustomerAddressById(Number(loginClaims.bigCommerceId), data.addressId) throw { status: 200, message: "customer address deleted", data: { success: true, }, log: false, } } else if (data.operation === "addCustomerAddress") { /** @type {BigCommerceAddress} */ const address = data.address address.customer_id = Number(loginClaims.bigCommerceId) delete address.id const response = addCustomerAddress(address) throw { status: 200, message: "customer addresses updated", data: response, log: false, } } else if (data.operation === "changePassword") { const res = validateCredentials(loginClaims.email, data.currentPassword) if (!res.is_valid) { throw { status: 403, error: "current password incorrect", log: false, } } const resPw = updateCustomer({ authentication: { force_password_reset: false, new_password: data.newPassword, }, id: Number(loginClaims.bigCommerceId), }) throw { status: 200, message: "password reset successful", log: false, } } else if (data.operation === "updateEmail") { const resValidation = validateCredentials(loginClaims.email, data.password) if (!resValidation.is_valid) { throw { status: 403, error: "password incorrect", log: false, } } if (!data.email) throw { status: 400, error: "email is required", log: false, } data.email = data.email.toLowerCase() const customers = context.db.find("bigCommerceCustomer", { filter: { email: data.email }, }) if (customers.length > 0) throw { status: 409, error: "email already in use", log: false, } if (emailRegex.test(data.email) === false) { throw { status: 400, error: "invalid email", log: false, } } const res = updateCustomer({ id: Number(loginClaims.bigCommerceId), email: data.email }) context.db.update("bigCommerceCustomer", loginClaims.tibiId, { email: data.email }) throw { status: 200, message: "customer updated", data: res, log: false, } } else if (data.operation === "updateUsername") { const resValidation = validateCredentials(loginClaims.email, data.password) if (!resValidation.is_valid) { throw { status: 403, error: "password incorrect", log: false, } } /**@type {string} */ let username = data.username if (!username) throw { status: 400, error: "username is required", log: false, } username = username.toLowerCase() const userWithUsername = context.db.find("bigCommerceCustomer", { filter: { username: username }, })[0] if (userWithUsername) throw { status: 409, message: "username already in use", } const internalCustomer = context.db.find("bigCommerceCustomer", { filter: { email: loginClaims.email }, })[0] internalCustomer.username = username if (internalCustomer) { context.db.update("bigCommerceCustomer", internalCustomer.id, internalCustomer) } //update bigcommerce customer too : get it and then update it with username swapped const bCCustomer = getCustomerById(loginClaims.bigCommerceId) if (!bCCustomer.form_fields) bCCustomer.form_fields = [] const usernameIndex = bCCustomer.form_fields.findIndex((f) => f.name === "username") if (usernameIndex >= 0) bCCustomer.form_fields[usernameIndex].value = username else bCCustomer.form_fields = [...bCCustomer.form_fields, { name: "username", value: username }] updateCustomer(bCCustomer) throw { status: 200, message: "customer updated", data: internalCustomer, log: false, } } }) } if (returnCustomer) { return { data: returnCustomer, } } throw { status: 401, error: "unauthorized", log: false } })()