Repository navigation
customer/add API должен поддерживать extra fields msCustomer #261
Description
Описание
После мержа #260 эндпойнт POST /api/v1/customer/add (метод ms3.customer.add() в storefront-JS) работает только для жёсткого whitelist полей first_name, last_name, email, phone. Любая попытка передать другое поле возвращает ошибку ms3_customer_err_field_not_allowed.
Это режет механизм расширения через Утилиты → Свои поля → msCustomer. Если магазин создал extra field (например, loyalty_card, birthday, referral_source), он не может быть обновлён через быстрый API — единственный официальный канал для одиночного поля.
Воспроизведение
- В админке: Утилиты → Свои поля → msCustomer → Создать поле
loyalty_card(textfield). - На фронте:
await ms3.customer.add('loyalty_card', '12345');
- Получаем 400 с сообщением «Это поле нельзя изменить через быстрый профиль».
Корень проблемы
В CustomerProfileController::updateField() (src/Controllers/Api/Web/CustomerProfileController.php):
$rules = $this->getProfileFieldRules();
if (!isset($rules[$key])) {
return $this->error($this->modx->lexicon('ms3_customer_err_field_not_allowed'));
}Метод getProfileFieldRules() возвращает фиксированный whitelist из 4 полей. Все остальное — отсекается.
Предлагаемое решение
Заменить whitelist на blacklist опасных полей + проверку существования поля в xPDO-карте msCustomer. Карта подмешивает extra fields через ms3->loadMap(), поэтому проверка по getFieldMeta(msCustomer::class) автоматически покрывает оба случая — штатные поля и extra fields.
Эскиз:
private const FORBIDDEN_FIELDS = [
'id', 'token', 'user_id', 'password',
'is_active', 'email_verified_at',
'createdon', 'updatedon',
];
public function updateField(array $data): array {
$key = trim((string)($data['key'] ?? ''));
$value = trim((string)($data['value'] ?? ''));
// 1. Запрет чувствительных полей
if (in_array($key, self::FORBIDDEN_FIELDS, true)) {
return $this->error($this->modx->lexicon('ms3_customer_err_field_not_allowed'));
}
// 2. Поле должно существовать в модели (вкл. extra fields)
$fieldMeta = $this->modx->getFieldMeta(msCustomer::class);
if (!isset($fieldMeta[$key])) {
return $this->error($this->modx->lexicon('ms3_customer_err_field_not_allowed'));
}
// 3. Жёсткая валидация для типовых полей, best-effort для остальных
$rules = $this->getProfileFieldRules();
if (isset($rules[$key])) {
$validation = (new Validator())->make([$key => $value], [$key => $rules[$key]]);
// ...
}
// 4. Email — уникальность + сброс верификации
if ($key === 'email') {
if (!$this->isEmailAvailable($customer, $value)) {
return $this->error($this->modx->lexicon('ms3_customer_err_email_exists'));
}
$this->resetEmailVerificationIfChanged($customer, $value);
}
$customer->set($key, $value);
// ...
}После этого:
ms3.customer.add('loyalty_card', '12345')— работает.ms3.customer.add('user_id', 999)— блокируется (в FORBIDDEN_FIELDS).ms3.customer.add('totally_made_up_field', 'x')— блокируется (нет в xPDO-карте).ms3.customer.add('email', 'new@example.com')— работает с полной валидацией (уникальность, сброс верификации).
Open questions для имплементации
- Валидация типов extra fields. Сейчас в
updateField()нет валидации для не-whitelist полей. Можно ли подтянуть type info из определения extra field (type=textfield/numberfield/checkbox/datefield) и валидировать соответственно? Или достаточно best-efforttrim((string)$value)+$customer->set()? - FORBIDDEN_FIELDS — какие ещё стоит добавить? Нужно ли запрещать поля, которыми оперируют другие сервисы (
OrderUserResolver,CustomerEmailController)? - Аналогичный подход для
msOrder? ВOrderFieldManager::add()есть похожая логика валидации полей заказа — там тоже жёсткий whitelist или поддержка extra fields?
Связанное
- Web API: отсутствуют маршруты customer/add и customer/changeAddress (CustomerAPI → 404) #241 (исходный баг — отсутствующие маршруты CustomerAPI), закрыт fix(web): missing customer API routes (#241) #260 (мержен в beta).
- Mechanism extra fields:
Утилиты → Свои поля, документировано вDocs/components/minishop3/interface/utilities/extra-fields.md.
Activity
fix(web): customer/add allows msCustomer extra fields (#261)
Merge pull request #268 from modx-pro/fix/gh-261-customer-add-extra-f…