When Evotor sends a new /user/create for an existing userId, the new
password should replace the old one so /user/verify stays in sync.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Evotor sends userId but not necessarily a matching phone/email.
Now tries evotor_user_id first, then falls back to email/phone.
Also removed the requirement for username/phone when userId is present.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
When a connection row exists for the user but with a different/null
evotor_user_id, the lookup by evotor_user_id alone missed it and tried
to INSERT, hitting the unique constraint on user_id. Now looks up by
either evotor_user_id or user_id, and always syncs both fields on update.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Accept phone as an alternative to username for user lookup
- On first auth when user has no password set, save the provided
password and activate the account (same logic as /user/create)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
When Evotor sends a password in the payload, hash and store it
immediately and set the user to active — skipping the invite flow.
Without a password, behaviour is unchanged (pending status + invite email).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
userId is nested inside body.data, and event types are
ApplicationInstalled / ApplicationUninstalled (not install/uninstall).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Evotor sends user fields (email, phone_number, first_name, last_name)
at the top level of the webhook body, not inside customField. Now we
check both locations with top-level taking precedence. Also store the
full body in evotor_meta instead of just the customField subset.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add POST /user/install endpoint handling Evotor app install/uninstall
events: uninstall suspends the user and marks connection offline;
reinstall reactivates a suspended account
- Exclude admin and system role users from refresh_catalog,
refresh_vk_catalog, and mirror_to_vk periodic tasks by joining users
table and filtering role = 'user'
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Remove /register route and nav links (users created via Evotor webhook)
- Fix evotor_webhooks.py: use phone=None instead of phone="" to avoid unique constraint
- Add admin "view as user" feature: POST /admin/users/{id}/view-as sets viewed_user_id
in session; POST /admin/view-as/stop clears it
- catalog, vk_catalog, sync, connections GET routes use get_viewed_user() so admins
see another user's data while browsing
- Orange banner shown at top when admin is viewing as another user
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>