madbox-99 / laravel-user-team-sync
User and team synchronization between a subscriber hub and secondary Laravel apps
Installs: 32
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 0
Forks: 0
Open Issues: 0
pkg:composer/madbox-99/laravel-user-team-sync
Requires
- php: ^8.3
- laravel/framework: ^11.0 || ^12.0
Requires (Dev)
- laravel/pint: ^1.0
- orchestra/testbench: ^9.0 || ^10.0
- pestphp/pest: ^3.0 || ^4.0
README
Laravel package for synchronizing users and teams across multiple Laravel applications using a Publisher/Receiver pattern.
Requirements
- PHP 8.3+
- Laravel 11 or 12
Installation
composer require madbox-99/laravel-user-team-sync
Then run the install command:
php artisan user-team-sync:install
This will:
- Ask for your sync mode (publisher/receiver/both)
- Generate or accept an API key
- Update your
.envfile - Publish the config and migration files
- Optionally run migrations
Manual Installation
If you prefer to install manually:
php artisan vendor:publish --tag=user-team-sync-config php artisan vendor:publish --tag=user-team-sync-migrations php artisan migrate
Then add these to your .env:
USER_TEAM_SYNC_MODE=receiver USER_TEAM_SYNC_API_KEY=your-secret-key
Configuration
Modes
| Mode | Description |
|---|---|
publisher |
Sends sync events to other apps |
receiver |
Receives sync events from a publisher |
both |
Sends and receives |
Publisher Setup
Set mode to publisher. Receiver apps can be stored in the config file or in the database.
Option A: Config-based apps (default)
Define apps in config/user-team-sync.php:
'publisher' => [ 'app_source' => 'config', // default 'api_key' => env('USER_TEAM_SYNC_API_KEY'), 'apps' => [ 'crm' => [ 'url' => env('CRM_APP_URL'), 'api_key' => env('CRM_APP_API_KEY'), // optional, falls back to default 'active' => true, ], 'shop' => [ 'url' => env('SHOP_APP_URL'), 'api_key' => env('SHOP_APP_API_KEY'), 'active' => true, ], ], ],
Option B: Database-based apps (recommended)
Store apps in the sync_apps table for dynamic management:
USER_TEAM_SYNC_APP_SOURCE=database
The install command (php artisan user-team-sync:install) can set this up interactively, or you can manage apps manually:
use Madbox99\UserTeamSync\Models\SyncApp; // Add a new app SyncApp::create([ 'name' => 'crm', 'url' => 'https://crm.example.com', 'api_key' => 'secret-key', // stored encrypted 'is_active' => true, ]); // Deactivate an app SyncApp::where('name', 'crm')->update(['is_active' => false]);
API keys are stored using Laravel's
encryptedcast. Make sure yourAPP_KEYis set.
Receiver Setup
Set mode to receiver and configure the API key:
'receiver' => [ 'api_key' => env('USER_TEAM_SYNC_API_KEY'), 'route_prefix' => 'api', 'role_driver' => 'spatie', 'default_role' => 'subscriber', 'default_active' => false, ],
The receiver API key must match the publisher's key for that app.
Usage
Automatic Sync (Observer)
When auto_observe is enabled (default), the package automatically watches your User model for changes to configured fields (email, role by default) and syncs them to all active receiver apps.
// This automatically triggers sync to all receiver apps $user->update(['role' => 'admin']);
Manual Sync via Facade
use Madbox99\UserTeamSync\Facades\UserTeamSync; // Create a user on all receiver apps UserTeamSync::createUser( email: 'john@example.com', name: 'John Doe', password: 'plain-text-password', // hashed automatically before sending role: 'editor', ownerEmail: 'owner@example.com', ); // Sync user changes UserTeamSync::syncUser('john@example.com', [ 'new_email' => 'john.doe@example.com', 'role' => 'admin', ]); // Create a team on all receiver apps UserTeamSync::createTeam( teamName: 'Marketing', userEmail: 'john@example.com', slug: 'marketing', // optional, auto-generated from name ); // Toggle user active status on a specific app UserTeamSync::toggleUserActive( userEmail: 'john@example.com', isActive: true, appKey: 'crm', );
API Endpoints (Receiver)
All endpoints are protected by Bearer token authentication.
| Method | Endpoint | Description |
|---|---|---|
| POST | /api/create-user |
Create a new user |
| POST | /api/sync-user |
Update user fields |
| POST | /api/toggle-user-active |
Set active/inactive status |
| POST | /api/create-team |
Create a team |
| GET | /api/user-teams |
Get user's teams |
| POST | /api/sync-password |
Sync password hash |
Events
Listen to these events for custom logic:
| Event | When |
|---|---|
UserCreatedFromSync |
User created on receiver |
UserSynced |
User fields updated |
PasswordSynced |
Password synced to receiver |
UserActiveToggled |
Active status changed |
TeamCreatedFromSync |
Team created on receiver |
SyncFailed |
Any sync operation failed |
// In EventServiceProvider or listener use Madbox99\UserTeamSync\Events\UserCreatedFromSync; class HandleSyncedUser { public function handle(UserCreatedFromSync $event): void { // $event->user } }
Logging
All sync operations are logged to the sync_logs table. Configure in config/user-team-sync.php:
'logging' => [ 'enabled' => true, 'table' => 'sync_logs', 'retention_days' => 30, ],
Environment Variables
| Variable | Description | Default |
|---|---|---|
USER_TEAM_SYNC_MODE |
Sync mode | receiver |
USER_TEAM_SYNC_API_KEY |
API key for authentication | — |
USER_TEAM_SYNC_APP_SOURCE |
App storage: config or database |
config |
USER_TEAM_SYNC_USER_MODEL |
User model class | App\Models\User |
USER_TEAM_SYNC_TEAM_MODEL |
Team model class | App\Models\Team |
USER_TEAM_SYNC_QUEUE |
Queue name for jobs | default |
USER_TEAM_SYNC_QUEUE_CONNECTION |
Queue connection | null |
USER_TEAM_SYNC_TRIES |
Job retry attempts | 3 |
USER_TEAM_SYNC_BACKOFF |
Seconds between retries | 60 |
USER_TEAM_SYNC_TIMEOUT |
HTTP timeout in seconds | 10 |
Testing
vendor/bin/pest
License
MIT License. See LICENSE for details.