PresenceEngine is a lightweight, framework-free PHP application that tracks user presence across multiple sections of an organization in real time.
It provides administrators with a live dashboard showing:
- Who is currently online
- When users logged in
- Which section they belong to
- Historical presence activity
All activity is persisted to a MySQL database for historical reporting.
The system is built on a custom MVC architecture using PDO for database access and Workerman for WebSocket communication, delivering sub-second updates without page refreshes.
- Role-based access control (Admin / User)
- Live presence dashboard with real-time WebSocket updates
- User management: create accounts, enable/disable accounts, and assign sections
- Automatic login and logout timestamp tracking
- IP address logging per session
- Full historical audit log of presence events
- CSRF protection on all state-changing forms
- Secure session handling with
HttpOnlyandSameSite=Strict - Password hashing with bcrypt
- Minimal, responsive dark UI built with vanilla CSS and JavaScript
- No frontend framework dependencies
| Layer | Technology |
|---|---|
| Backend | PHP 8.1+ (Custom MVC, no framework) |
| Database | MySQL 5.7+ / MariaDB 10.3+ |
| DB Access | PDO with prepared statements |
| WebSocket | Workerman 4.x |
| Frontend | Vanilla JavaScript, Inter font |
| Authentication | Session-based with CSRF tokens |
| Configuration | vlucas/phpdotenv |
-
PHP 8.1 or higher
-
PHP extensions:
pdopdo_mysqlzip
-
MySQL 5.7+ or MariaDB 10.3+
-
Composer
-
Apache or Nginx
-
A terminal capable of running long-lived processes for the WebSocket server
-
PHP built-in server can be used for development
git clone https://github.com/fouad-salehi/PresenceEngine.git
cd PresenceEnginecomposer installCopy the example environment file:
cp .env.example .envEdit .env:
APP_NAME=PresenceEngine
APP_ENV=production
APP_DEBUG=false
APP_URL=http://localhost
DB_HOST=127.0.0.1
DB_PORT=3306
DB_NAME=presence_engine
DB_USER=root
DB_PASS=your_password
DB_CHARSET=utf8mb4
WS_HOST=0.0.0.0
WS_PORT=8080
SESSION_LIFETIME=7200mysql -u root -p < database/migrations/001_create_tables.sqlGenerate a bcrypt password hash:
php -r "echo password_hash('your-secure-password', PASSWORD_DEFAULT);"Insert the admin user into the database:
INSERT INTO users (
username,
email,
password_hash,
section,
role
) VALUES (
'admin',
'admin@example.com',
'$2y$10$...your_generated_hash...',
NULL,
'admin'
);Open a dedicated terminal window. This process must remain running.
php ws-server.php startPoint your web server's document root to the public/ directory.
For Apache, the included .htaccess handles URL rewriting.
For development, you can use PHP's built-in server:
php -S localhost:8000 -t publicOpen:
http://localhost:8000
Log in using the admin credentials created in step 5.
PresenceEngine/
├── app/
│ ├── Controllers/
│ │ ├── AuthController.php
│ │ ├── AdminController.php
│ │ └── UserController.php
│ │
│ ├── Models/
│ │ ├── User.php
│ │ └── PresenceLog.php
│ │
│ ├── Views/
│ │ ├── layouts/
│ │ ├── auth/
│ │ ├── admin/
│ │ ├── user/
│ │ └── errors/
│ │
│ ├── Core/
│ │ ├── Router.php
│ │ ├── Database.php
│ │ ├── Model.php
│ │ ├── Controller.php
│ │ ├── Session.php
│ │ ├── Config.php
│ │ └── View.php
│ │
│ └── Middleware/
│ ├── AuthMiddleware.php
│ ├── AdminMiddleware.php
│ └── GuestMiddleware.php
│
├── public/
│ ├── index.php
│ └── .htaccess
│
├── database/
│ └── migrations/
│ └── 001_create_tables.sql
│
├── storage/
│ └── logs/
│
├── ws-server.php
├── composer.json
└── .env.example
| Column | Type | Description |
|---|---|---|
id |
INT UNSIGNED |
Primary key |
username |
VARCHAR(50) |
Unique login name |
email |
VARCHAR(100) |
Unique email address |
password_hash |
VARCHAR(255) |
Bcrypt password hash |
section |
VARCHAR(50) |
Section assignment (NULL for admins) |
role |
ENUM |
admin or user |
is_active |
TINYINT(1) |
Account enabled flag |
created_at |
TIMESTAMP |
Creation timestamp |
updated_at |
TIMESTAMP |
Last update timestamp |
| Column | Type | Description |
|---|---|---|
id |
BIGINT UNSIGNED |
Primary key |
user_id |
INT UNSIGNED |
Foreign key to users |
section |
VARCHAR(50) |
Section at login time |
login_time |
DATETIME |
Login timestamp |
logout_time |
DATETIME |
Logout timestamp (NULL if online) |
is_online |
TINYINT(1) |
Current presence flag |
ip_address |
VARCHAR(45) |
Client IP address (IPv4 or IPv6) |
created_at |
TIMESTAMP |
Record creation timestamp |
PresenceEngine implements several security measures:
- Passwords hashed with bcrypt via
password_hash() - All SQL queries use PDO prepared statements
- CSRF tokens required on all POST requests
- Session cookies configured with
HttpOnlyandSameSite=Strict - Role-based middleware guards protected routes
- Output escaping with
htmlspecialchars() - Deactivated accounts are rejected during authentication
- Log in with an admin account.
- Access the dashboard at
/adminto view live presence. - Navigate to
/admin/usersto manage accounts. - Use
/admin/historyto review historical activity. - Create new users at
/admin/users/create.
- Log in with a standard account.
- View personal status at
/me. - The session is automatically logged on login and logout.
- Set
APP_DEBUG=falsein production. - Use HTTPS in production environments.
- The WebSocket server must run as a persistent process.
- On Windows, use a process manager such as NSSM to run the WebSocket server as a service.
- On Linux, use systemd or Supervisor.
- Audio notification on user login
- Section-based filtering in live dashboard
- CSV export of historical logs
- Idle timeout for inactive sessions
- Rate limiting on authentication endpoint
- Docker Compose configuration
- Automated test suite
This project is licensed under the MIT License. See the LICENSE file for details.
- Workerman for the WebSocket server
- vlucas/phpdotenv for environment configuration
- Inter typeface





