Files
kontextwerk/api/hooks/customer/put_update.js
2025-10-02 08:54:03 +02:00

251 lines
10 KiB
JavaScript

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 }
})()