User Provisioning
User provisioning allows administrators to create WordPress user accounts directly from person records, establishing a bidirectional link between the person and the WP user.
Overview
Section titled “Overview”When an administrator or the self-service activation flow creates a user account for a person:
- A WordPress user is created with the Rondo User role
- The person record is linked to the WP user (and vice versa)
- The member’s KNVB ID is stored on the WP user
- Roles from current functions and committee memberships are applied immediately through
CapabilitySync::sync_user_by_person_id() - A configurable welcome email can be sent with login instructions
This uses the same role mappings and date/status checks as later synchronization. Members of a committee mapped to a custom role (for example Jubilarissen) can use that access on their first sign-in; expired, future, and inactive memberships do not grant it.
Account names
Section titled “Account names”Accounts normally use first.last as their login and the personal name as their display name.
For sponsor contacts without a personal name, provisioning uses the canonical company_name
field: for example, van Dal Assurantien becomes login van-dal-assurantien and display name
van Dal Assurantien. Personal name fields remain empty.
The generated login must also produce a non-empty WordPress nicename. If neither the personal
name nor the company name can do so (for example, names containing only punctuation), the login
falls back to gebruiker-{person_id}. Logins are limited to 60 characters, including any numeric
suffix needed for uniqueness. These rules apply to administrator provisioning and self-service
activation; existing accounts keep their names.
Person-User Linking
Section titled “Person-User Linking”Provisioning creates a bidirectional link between person records and WordPress users:
| Storage | Meta Key | Value |
|---|---|---|
| Person post meta | _rondo_wp_user_id | WordPress user ID |
| WP user meta | rondo_linked_person_id | Person post ID |
| WP user meta | _rondo_knvb_id | KNVB member ID |
| WP user meta | rondo_contact_email | The member’s real email address |
This linking enables:
- Showing the linked user account on person detail pages (AccountCard component)
- Showing the linked person name in the WordPress users list
- Cross-referencing between member data and user accounts
If the forward link (_rondo_wp_user_id) is missing but the reverse link survives, provision()
adopts the existing account rather than creating a duplicate.
Shared household mailboxes
Section titled “Shared household mailboxes”Families share one email address, but WordPress enforces a unique user_email. So:
- The first member provisioned on an address keeps it as their
user_email. - Later members get an undeliverable placeholder,
person-{id}@members.rondo.invalid. (.invalidis reserved by RFC 2606 and can never resolve.) - Every provisioned user gets
rondo_contact_email— the address mail must actually go to.
WordPress core does not know about the meta — retrieve_password() addresses the reset link
straight to user_email. ContactEmailRouter therefore hooks the wp_mail filter and rewrites any
synthetic recipient to the member’s real address, dropping it when none is known. Fail closed: a
mail that cannot reach the right person must not reach the wrong one. Without this, every household
member after the first would have an unrecoverable account.
is_synthetic_email() tests for the placeholder domain.
Members who use Magic Login may not know the random password created during provisioning. The
profile therefore offers an authenticated POST /rondo/v1/user/password-reset action. It calls
WordPress core’s retrieve_password() for the current user’s exact username and only confirms that
the message was requested; the password can be changed only with the expiring key received by
email. The existing ContactEmailRouter ensures this also reaches later members of a household.
Rondo removes WordPress’s wp_password_change_notification callback from after_password_reset,
so completing a password reset does not notify the site administrator. User password-reset links,
household email routing and user-facing password-change confirmations remain enabled.
Signing in
Section titled “Signing in”Members never see the username Rondo generated for them, and the second member of a household
cannot sign in with the family address — it belongs to the first claimant’s account. LoginResolver
therefore accepts two extra identifiers and rewrites them to the real user_login:
| Identifier | Source | Resolves when |
|---|---|---|
| Username | user_login | Always (core) |
user_email | Always (core) | |
| KNVB-ID | _rondo_knvb_id | Exactly one user matches |
| Contact address | rondo_contact_email | Exactly one user matches |
A shared family address matches several members, so it is ambiguous and the resolver refuses to guess — picking one would be impersonation. Those members sign in with their KNVB-ID.
Who can be provisioned
Section titled “Who can be provisioned”GET /rondo/v1/users/provisionable requires that the person is published, has no account yet, has a
valid email_1 or email_2, and passes ActivationService::is_person_activatable(). Active people,
current parents, and active sponsor contacts are eligible; other former members are not.
It deliberately does not require a knvb-id. The parents who carry the ouderplicht are not
Sportlink members and have none — requiring it hid 269 of them from the picker.
REST Endpoints
Section titled “REST Endpoints”Provision a User
Section titled “Provision a User”POST /rondo/v1/people/{person_id}/provision
Creates a WordPress user account for the specified person and links them.
Permission: Admin only
Response:
{ "success": true, "user_id": 42, "person_id": 789, "welcome_email_sent": true}Provisioning Settings
Section titled “Provisioning Settings”GET /rondo/v1/provisioning/settings
Returns current provisioning settings including the welcome email template.
Permission: Admin only
Response:
{ "welcome_email_subject": "Welkom bij Rondo", "welcome_email_body": "Beste {{naam}},\n\nJe account is aangemaakt...", "auto_send_welcome_email": true}POST /rondo/v1/provisioning/settings
Update provisioning settings.
Permission: Admin only
Body:
{ "welcome_email_subject": "Welkom bij Rondo", "welcome_email_body": "Beste {{naam}},\n\nJe account is aangemaakt...", "auto_send_welcome_email": true}API Response Fields
Section titled “API Response Fields”Person Response
Section titled “Person Response”When retrieving a person via the REST API, provisioning-related fields are included:
| Field | Type | Description |
|---|---|---|
linked_user_id | int|null | WordPress user ID linked to this person |
welcome_email_sent_at | string|null | ISO timestamp of when the welcome email was sent |
linked_user_switch_url | string | Nonce-secured User Switching URL; only included for administrators who may switch to the linked account |
Users List
Section titled “Users List”The WordPress users list includes additional fields for linked persons:
| Field | Type | Description |
|---|---|---|
linked_person_id | int|null | Person post ID linked to this user |
linked_person_name | string|null | Display name of the linked person |
Welcome Email
Section titled “Welcome Email”The welcome email template is configurable under Settings > Beheer > E-mails > Account aanmaken (WelkomstmailTab component).
The stored template body is plain text with placeholders. Rondo\Users\UserProvisioning resolves those placeholders first and then renders the message inside the shared Rondo\Notifications\EmailTemplate HTML layout, including a primary CTA button for the password-set link.
Available template variables:
| Variable | Description |
|---|---|
{{naam}} | Person’s full name |
{{voornaam}} | Person’s first name |
{{email}} | Person’s email address |
{{site_url}} | URL of the Rondo Club site |
Administrators can also manually trigger or resend the welcome email from the AccountCard component on a person’s detail page.
UI Components
Section titled “UI Components”AccountCard
Section titled “AccountCard”The AccountCard component is displayed on person detail pages for administrators. It shows:
- Whether the person has a linked WordPress user account
- The linked user’s email and role
- Link to switch to the linked account when the User Switching plugin is active and permits it
- Button to provision a new account (if no linked user)
- Button to send/resend the welcome email
- Timestamp of when the welcome email was last sent
Implementation
Section titled “Implementation”Class: Rondo\Users\UserProvisioning
| Method | Description |
|---|---|
provision( $person_id ) | Create WP user and link to person |
send_welcome_email( $user_id ) | Send the welcome email to a provisioned user |
get_settings() | Get current provisioning settings |
update_settings( $settings ) | Update provisioning settings |
Related Documentation
Section titled “Related Documentation”- Access Control - Roles and permissions
- Multi-User System - User management overview
- People API - Person REST endpoints
- REST API - Full API reference