Compare commits
2 Commits
f59913910f
...
d204756cfe
| Author | SHA1 | Date | |
|---|---|---|---|
| d204756cfe | |||
| a34ca51223 |
283
Claude.md
283
Claude.md
@@ -1,283 +0,0 @@
|
||||
# Tinker Tickets - Project Documentation for AI Assistants
|
||||
|
||||
## Project Status (January 2026)
|
||||
|
||||
**Current Phase**: All core features implemented. System is production-ready.
|
||||
|
||||
**Completed Features**:
|
||||
- Activity Timeline, Ticket Assignment, Status Transitions with Workflows
|
||||
- Ticket Templates, Bulk Actions (Admin Only)
|
||||
- File Attachments, Ticket Dependencies, @Mentions in Comments
|
||||
- Recurring Tickets, Custom Fields, Advanced Search with Saved Filters
|
||||
- Export to CSV/JSON, API Key Management
|
||||
- Ticket Visibility Levels (public/internal/confidential)
|
||||
- Collapsible Sidebar, Kanban Card View, Inline Ticket Preview
|
||||
- Mobile Responsive Design, Ticket Linking in Comments
|
||||
- Admin Pages (Templates, Workflow, Recurring, Custom Fields, User Activity, Audit Log, API Keys)
|
||||
- Comment Edit/Delete (owner or admin can modify their comments)
|
||||
- Markdown Tables Support, Auto-linking URLs in Comments
|
||||
|
||||
**Security Features** (January 2026):
|
||||
- CSP with nonce-based script execution (no unsafe-inline)
|
||||
- IP-based rate limiting (prevents session bypass attacks)
|
||||
- Visibility checks on attachment downloads
|
||||
- Unique ticket ID generation with collision prevention
|
||||
- Internal visibility requires groups validation
|
||||
|
||||
## Design Decisions
|
||||
|
||||
**Not Planned / Out of Scope**:
|
||||
- Email integration - Discord webhooks are the notification method for this system
|
||||
- SLA management - Not required for internal infrastructure use
|
||||
- Time tracking - Out of scope for current requirements
|
||||
- OAuth2/External identity providers - Authelia is the only approved SSO method
|
||||
- GraphQL API - REST API is sufficient for current needs
|
||||
|
||||
**Wiki Documentation**: https://wiki.lotusguild.org/en/Services/service-tinker-tickets
|
||||
|
||||
## Project Overview
|
||||
|
||||
Tinker Tickets is a feature-rich, self-hosted ticket management system built for managing data center infrastructure issues. It features SSO integration with Authelia/LLDAP, workflow management, Discord notifications, and a retro terminal-style web interface.
|
||||
|
||||
**Tech Stack:**
|
||||
- Backend: PHP 7.4+ with MySQLi
|
||||
- Frontend: Vanilla JavaScript, CSS3
|
||||
- Database: MariaDB on separate LXC (10.10.10.50)
|
||||
- Web Server: nginx with PHP-FPM on production (10.10.10.45)
|
||||
- Authentication: Authelia SSO with LLDAP backend
|
||||
|
||||
**Production Environment:**
|
||||
- **Primary URL**: https://t.lotusguild.org
|
||||
- **Web Server**: nginx at 10.10.10.45 (`/var/www/html/tinkertickets`)
|
||||
- **Database**: MariaDB at 10.10.10.50 (`ticketing_system` database)
|
||||
- **Authentication**: Authelia provides SSO via headers
|
||||
- **Dev Environment**: `/root/code/tinker_tickets` (not production)
|
||||
|
||||
## Architecture
|
||||
|
||||
### MVC Pattern
|
||||
```
|
||||
Controllers → Models → Database
|
||||
↓
|
||||
Views
|
||||
```
|
||||
|
||||
### Project Structure
|
||||
```
|
||||
/tinker_tickets/
|
||||
├── api/ # API endpoints
|
||||
│ ├── add_comment.php # POST: Add comment
|
||||
│ ├── assign_ticket.php # POST: Assign ticket to user
|
||||
│ ├── bulk_operation.php # POST: Bulk operations - admin only
|
||||
│ ├── check_duplicates.php # GET: Check for duplicate tickets
|
||||
│ ├── delete_attachment.php # POST/DELETE: Delete attachment
|
||||
│ ├── delete_comment.php # POST: Delete comment (owner/admin)
|
||||
│ ├── download_attachment.php # GET: Download attachment (with visibility check)
|
||||
│ ├── export_tickets.php # GET: Export tickets to CSV/JSON
|
||||
│ ├── generate_api_key.php # POST: Generate API key (admin)
|
||||
│ ├── get_template.php # GET: Fetch ticket template
|
||||
│ ├── get_users.php # GET: Get user list
|
||||
│ ├── manage_recurring.php # CRUD: Recurring tickets (admin)
|
||||
│ ├── manage_templates.php # CRUD: Templates (admin)
|
||||
│ ├── manage_workflows.php # CRUD: Workflow rules (admin)
|
||||
│ ├── revoke_api_key.php # POST: Revoke API key (admin)
|
||||
│ ├── ticket_dependencies.php # GET/POST/DELETE: Ticket dependencies
|
||||
│ ├── update_comment.php # POST: Update comment (owner/admin)
|
||||
│ ├── update_ticket.php # POST: Update ticket (workflow validation)
|
||||
│ └── upload_attachment.php # GET/POST: List or upload attachments
|
||||
├── assets/
|
||||
│ ├── css/
|
||||
│ │ ├── dashboard.css # Dashboard + terminal styling
|
||||
│ │ └── ticket.css # Ticket view styling
|
||||
│ ├── js/
|
||||
│ │ ├── advanced-search.js # Advanced search modal
|
||||
│ │ ├── ascii-banner.js # ASCII art banner
|
||||
│ │ ├── dashboard.js # Dashboard + bulk actions + kanban + sidebar
|
||||
│ │ ├── keyboard-shortcuts.js # Keyboard shortcuts
|
||||
│ │ ├── markdown.js # Markdown rendering + ticket linking
|
||||
│ │ ├── settings.js # User preferences
|
||||
│ │ ├── ticket.js # Ticket + comments + visibility
|
||||
│ │ └── toast.js # Toast notifications
|
||||
│ └── images/
|
||||
│ └── favicon.png
|
||||
├── config/
|
||||
│ └── config.php # Config + .env loading
|
||||
├── controllers/
|
||||
│ ├── DashboardController.php # Dashboard with stats + filters
|
||||
│ └── TicketController.php # Ticket CRUD + timeline + visibility
|
||||
├── cron/
|
||||
│ └── create_recurring_tickets.php # Process recurring ticket schedules
|
||||
├── helpers/
|
||||
│ └── ResponseHelper.php # Standardized JSON responses
|
||||
├── middleware/
|
||||
│ ├── AuthMiddleware.php # Authelia SSO integration
|
||||
│ ├── CsrfMiddleware.php # CSRF protection
|
||||
│ ├── RateLimitMiddleware.php # Session + IP-based rate limiting
|
||||
│ └── SecurityHeadersMiddleware.php # CSP with nonces, security headers
|
||||
├── models/
|
||||
│ ├── ApiKeyModel.php # API key generation/validation
|
||||
│ ├── AuditLogModel.php # Audit logging + timeline
|
||||
│ ├── BulkOperationsModel.php # Bulk operations tracking
|
||||
│ ├── CommentModel.php # Comment data access
|
||||
│ ├── CustomFieldModel.php # Custom field definitions/values
|
||||
│ ├── DependencyModel.php # Ticket dependencies
|
||||
│ ├── RecurringTicketModel.php # Recurring ticket schedules
|
||||
│ ├── StatsModel.php # Dashboard statistics
|
||||
│ ├── TemplateModel.php # Ticket templates
|
||||
│ ├── TicketModel.php # Ticket CRUD + assignment + visibility
|
||||
│ ├── UserModel.php # User management + groups
|
||||
│ ├── UserPreferencesModel.php # User preferences
|
||||
│ └── WorkflowModel.php # Status transition workflows
|
||||
├── scripts/
|
||||
│ ├── cleanup_orphan_uploads.php # Clean orphaned uploads
|
||||
│ └── create_dependencies_table.php # Create ticket_dependencies table
|
||||
├── uploads/ # File attachment storage
|
||||
├── views/
|
||||
│ ├── admin/
|
||||
│ │ ├── ApiKeysView.php # API key management
|
||||
│ │ ├── AuditLogView.php # Audit log browser
|
||||
│ │ ├── CustomFieldsView.php # Custom field management
|
||||
│ │ ├── RecurringTicketsView.php # Recurring ticket management
|
||||
│ │ ├── TemplatesView.php # Template management
|
||||
│ │ ├── UserActivityView.php # User activity report
|
||||
│ │ └── WorkflowDesignerView.php # Workflow transition designer
|
||||
│ ├── CreateTicketView.php # Ticket creation with visibility
|
||||
│ ├── DashboardView.php # Dashboard with kanban + sidebar
|
||||
│ └── TicketView.php # Ticket view with visibility editing
|
||||
├── .env # Environment variables (GITIGNORED)
|
||||
├── Claude.md # This file
|
||||
├── README.md # User documentation
|
||||
└── index.php # Main router
|
||||
```
|
||||
|
||||
## Admin Pages
|
||||
|
||||
All admin pages are accessible via the **Admin dropdown** in the dashboard header (for admin users only).
|
||||
|
||||
| Route | Description |
|
||||
|-------|-------------|
|
||||
| `/admin/templates` | Create and edit ticket templates |
|
||||
| `/admin/workflow` | Visual workflow transition designer |
|
||||
| `/admin/recurring-tickets` | Manage recurring ticket schedules |
|
||||
| `/admin/custom-fields` | Define custom fields per category |
|
||||
| `/admin/user-activity` | View per-user activity statistics |
|
||||
| `/admin/audit-log` | Browse all audit log entries |
|
||||
| `/admin/api-keys` | Generate and manage API keys |
|
||||
|
||||
## Database Schema
|
||||
|
||||
**Database**: `ticketing_system` at 10.10.10.50
|
||||
**User**: `tinkertickets`
|
||||
|
||||
### Core Tables
|
||||
|
||||
| Table | Description |
|
||||
|-------|-------------|
|
||||
| `tickets` | Core ticket data with assignment, visibility, and tracking |
|
||||
| `ticket_comments` | Markdown-supported comments with user_id reference |
|
||||
| `ticket_attachments` | File attachment metadata |
|
||||
| `ticket_dependencies` | Ticket relationships (blocks, blocked_by, relates_to, duplicates) |
|
||||
| `users` | User accounts synced from LLDAP (includes groups) |
|
||||
| `user_preferences` | User settings and preferences |
|
||||
| `audit_log` | Complete audit trail with indexed queries |
|
||||
| `status_transitions` | Workflow configuration |
|
||||
| `ticket_templates` | Reusable ticket templates |
|
||||
| `recurring_tickets` | Scheduled ticket definitions |
|
||||
| `custom_field_definitions` | Custom field schemas per category |
|
||||
| `custom_field_values` | Custom field data per ticket |
|
||||
| `saved_filters` | User-saved dashboard filters |
|
||||
| `bulk_operations` | Bulk operation tracking |
|
||||
| `api_keys` | API key storage with hashed keys |
|
||||
|
||||
### tickets Table Key Columns
|
||||
|
||||
| Column | Type | Description |
|
||||
|--------|------|-------------|
|
||||
| `ticket_id` | varchar(9) | Unique 9-digit identifier |
|
||||
| `visibility` | enum | 'public', 'internal', 'confidential' |
|
||||
| `visibility_groups` | varchar(500) | Comma-separated group names (for internal) |
|
||||
| `created_by` | int | Foreign key to users |
|
||||
| `assigned_to` | int | Foreign key to users (nullable) |
|
||||
| `updated_by` | int | Foreign key to users |
|
||||
| `priority` | int | 1-5 (1=Critical, 5=Minimal) |
|
||||
| `status` | varchar(20) | Open, Pending, In Progress, Closed |
|
||||
|
||||
### Indexed Columns (for performance)
|
||||
|
||||
- `tickets`: ticket_id (unique), status, priority, created_at, created_by, assigned_to, visibility
|
||||
- `audit_log`: user_id, action_type, entity_type, created_at
|
||||
|
||||
## Dashboard Features
|
||||
|
||||
- **View Toggle**: Switch between Table view and Kanban card view
|
||||
- **Collapsible Sidebar**: Click arrow to collapse/expand filter sidebar
|
||||
- **Stats Widgets**: Clickable cards for quick filtering
|
||||
- **Inline Ticket Preview**: Hover over ticket IDs for 300ms to see preview popup
|
||||
- **Sortable Columns**: Click headers to sort
|
||||
- **Advanced Search**: Date ranges, priority ranges, user filters
|
||||
- **Saved Filters**: Save and load custom filter combinations
|
||||
- **Bulk Actions** (admin): Select multiple tickets for bulk operations
|
||||
- **Export**: Export selected tickets to CSV or JSON
|
||||
|
||||
## Ticket Visibility Levels
|
||||
|
||||
- **Public**: All authenticated users can view
|
||||
- **Internal**: Only users in specified groups can view (groups required)
|
||||
- **Confidential**: Only creator, assignee, and admins can view
|
||||
|
||||
**Important**: Internal visibility requires at least one group to be specified. Attempting to create/update a ticket with internal visibility but no groups will fail validation.
|
||||
|
||||
## Important Notes for AI Assistants
|
||||
|
||||
1. **Session format**: `$_SESSION['user']['user_id']` (not `$_SESSION['user_id']`)
|
||||
2. **API auth**: Check `$_SESSION['user']['user_id']` exists
|
||||
3. **Admin check**: `$_SESSION['user']['is_admin'] ?? false`
|
||||
4. **Config path**: `config/config.php` (not `config/db.php`)
|
||||
5. **Comments table**: `ticket_comments` (not `comments`)
|
||||
6. **CSRF**: Required for POST/DELETE requests via `X-CSRF-Token` header
|
||||
7. **Cache busting**: Use `?v=YYYYMMDD` query params on JS/CSS files
|
||||
8. **Ticket linking**: Use `#123456789` in markdown-enabled comments
|
||||
9. **User groups**: Stored in `users.groups` as comma-separated values
|
||||
10. **API routing**: All API endpoints must be added to `index.php` router
|
||||
11. **Session in APIs**: RateLimitMiddleware starts session; don't call session_start() again
|
||||
12. **Database collation**: Use `utf8mb4_general_ci` (not unicode_ci) for new tables
|
||||
13. **Discord webhook URLs**: Set `APP_DOMAIN` in `.env` for correct ticket URLs in Discord notifications
|
||||
13. **Ticket ID extraction**: Use `getTicketIdFromUrl()` helper in JS files
|
||||
14. **CSP Nonces**: All inline scripts require `nonce="<?php echo $nonce; ?>"` attribute
|
||||
15. **Visibility validation**: Internal visibility requires groups; code validates this
|
||||
16. **Rate limiting**: Both session-based AND IP-based limits are enforced
|
||||
|
||||
## File Reference Quick Guide
|
||||
|
||||
| File | Purpose |
|
||||
|------|---------|
|
||||
| `index.php` | Main router for all routes |
|
||||
| `api/update_ticket.php` | Ticket updates with workflow + visibility |
|
||||
| `api/download_attachment.php` | File downloads with visibility check |
|
||||
| `api/bulk_operation.php` | Bulk operations with visibility filtering |
|
||||
| `models/TicketModel.php` | Ticket CRUD, visibility filtering, collision-safe ID generation |
|
||||
| `models/ApiKeyModel.php` | API key generation and validation |
|
||||
| `middleware/SecurityHeadersMiddleware.php` | CSP headers with nonce generation |
|
||||
| `middleware/RateLimitMiddleware.php` | Session + IP-based rate limiting |
|
||||
| `assets/js/dashboard.js` | Dashboard UI, kanban, sidebar, bulk actions |
|
||||
| `assets/js/ticket.js` | Ticket UI, visibility editing |
|
||||
| `assets/js/markdown.js` | Markdown parsing + ticket linking (XSS-safe) |
|
||||
| `assets/css/dashboard.css` | Terminal styling, kanban, sidebar |
|
||||
|
||||
## Security Implementations
|
||||
|
||||
| Feature | Implementation |
|
||||
|---------|---------------|
|
||||
| SQL Injection | All queries use prepared statements with parameter binding |
|
||||
| XSS Prevention | HTML escaped in markdown parser, CSP with nonces |
|
||||
| CSRF Protection | Token-based with constant-time comparison |
|
||||
| Session Security | Fixation prevention, secure cookies, timeout |
|
||||
| Rate Limiting | Session-based + IP-based (file storage) |
|
||||
| File Security | Path traversal prevention, MIME validation |
|
||||
| Visibility | Enforced on views, downloads, and bulk operations |
|
||||
|
||||
## Repository
|
||||
|
||||
- **Gitea**: https://code.lotusguild.org/LotusGuild/tinker_tickets
|
||||
- **Production**: https://t.lotusguild.org
|
||||
- **Wiki**: https://wiki.lotusguild.org/en/Services/service-tinker-tickets
|
||||
304
README.md
304
README.md
@@ -3,6 +3,22 @@
|
||||
A feature-rich PHP-based ticketing system designed for tracking and managing data center infrastructure issues with enterprise-grade workflow management and a retro terminal aesthetic.
|
||||
|
||||
**Documentation**: [Wiki](https://wiki.lotusguild.org/en/Services/service-tinker-tickets)
|
||||
**Design System**: [web_template](https://code.lotusguild.org/LotusGuild/web_template) — shared CSS, JS, and layout patterns for all LotusGuild apps
|
||||
|
||||
## Styling & Layout
|
||||
|
||||
Tinker Tickets uses the **LotusGuild Terminal Design System**. For all styling, component, and layout documentation see:
|
||||
|
||||
- [`web_template/README.md`](https://code.lotusguild.org/LotusGuild/web_template/src/branch/main/README.md) — full component reference, CSS variables, JS API
|
||||
- [`web_template/base.css`](https://code.lotusguild.org/LotusGuild/web_template/src/branch/main/base.css) — unified CSS (`.lt-*` classes)
|
||||
- [`web_template/base.js`](https://code.lotusguild.org/LotusGuild/web_template/src/branch/main/base.js) — `window.lt` utilities (toast, modal, CSRF, fetch helpers)
|
||||
- [`web_template/php/layout.php`](https://code.lotusguild.org/LotusGuild/web_template/src/branch/main/php/layout.php) — PHP base layout template
|
||||
|
||||
**Key conventions:**
|
||||
- All `.lt-*` CSS classes come from `base.css` — do not duplicate them in `assets/css/`
|
||||
- All `lt.*` JS utilities come from `base.js` — use `lt.toast`, `lt.modal`, `lt.api`, etc.
|
||||
- CSP nonces: every `<script>` tag needs `nonce="<?php echo $nonce; ?>"`
|
||||
- CSRF: inject `window.CSRF_TOKEN` via the nonce-protected inline script block; `lt.api.*` adds the header automatically
|
||||
|
||||
## Design Decisions
|
||||
|
||||
@@ -17,7 +33,7 @@ The following features are intentionally **not planned** for this system:
|
||||
### Dashboard & Ticket Management
|
||||
- **View Modes**: Toggle between Table view and Kanban card view
|
||||
- **Collapsible Sidebar**: Click the arrow to collapse/expand the filter sidebar
|
||||
- **Inline Ticket Preview**: Hover over ticket IDs for a quick preview popup
|
||||
- **Inline Ticket Preview**: Hover over ticket IDs for a quick preview popup (300ms delay)
|
||||
- **Stats Widgets**: Clickable cards for quick filtering (Open, Critical, Unassigned, Today's tickets)
|
||||
- **Full-Text Search**: Search across tickets, descriptions, and metadata
|
||||
- **Advanced Search**: Date ranges, priority ranges, user filters with saved filter support
|
||||
@@ -30,7 +46,7 @@ The following features are intentionally **not planned** for this system:
|
||||
|
||||
### Ticket Visibility Levels
|
||||
- **Public**: All authenticated users can view the ticket
|
||||
- **Internal**: Only users in specified groups can view the ticket
|
||||
- **Internal**: Only users in specified groups can view the ticket (at least one group required)
|
||||
- **Confidential**: Only the creator, assignee, and admins can view the ticket
|
||||
|
||||
### Workflow Management
|
||||
@@ -102,7 +118,7 @@ Access all admin pages via the **Admin dropdown** in the dashboard header.
|
||||
### Notifications
|
||||
- **Discord Integration**: Webhook notifications for ticket creation and updates
|
||||
- **Rich Embeds**: Color-coded priority indicators and ticket links
|
||||
- **Dynamic URLs**: Ticket links adapt to the server hostname
|
||||
- **Dynamic URLs**: Ticket links adapt to the server hostname (set `APP_DOMAIN` in `.env`)
|
||||
|
||||
### Keyboard Shortcuts
|
||||
| Shortcut | Action |
|
||||
@@ -129,6 +145,7 @@ Access all admin pages via the **Admin dropdown** in the dashboard header.
|
||||
- **Language**: PHP 7.4+
|
||||
- **Database**: MariaDB/MySQL
|
||||
- **Architecture**: MVC pattern with models, views, controllers
|
||||
- **Authentication**: Authelia SSO with LLDAP backend
|
||||
|
||||
### Frontend
|
||||
- **HTML5/CSS3**: Semantic markup with retro terminal styling
|
||||
@@ -138,6 +155,7 @@ Access all admin pages via the **Admin dropdown** in the dashboard header.
|
||||
- **Mobile Responsive**: Touch-friendly controls, responsive layouts
|
||||
|
||||
### Database Tables
|
||||
|
||||
| Table | Purpose |
|
||||
|-------|---------|
|
||||
| `tickets` | Core ticket data with visibility |
|
||||
@@ -153,9 +171,29 @@ Access all admin pages via the **Admin dropdown** in the dashboard header.
|
||||
| `custom_field_definitions` | Custom field schemas |
|
||||
| `custom_field_values` | Custom field data |
|
||||
| `saved_filters` | Saved filter combinations |
|
||||
| `api_keys` | API key storage |
|
||||
| `bulk_operations` | Bulk operation tracking |
|
||||
| `api_keys` | API key storage with hashed keys |
|
||||
|
||||
#### `tickets` Table Key Columns
|
||||
|
||||
| Column | Type | Description |
|
||||
|--------|------|-------------|
|
||||
| `ticket_id` | varchar(9) | Unique 9-digit identifier |
|
||||
| `visibility` | enum | `public`, `internal`, `confidential` |
|
||||
| `visibility_groups` | varchar(500) | Comma-separated group names (for internal) |
|
||||
| `created_by` | int | Foreign key to users |
|
||||
| `assigned_to` | int | Foreign key to users (nullable) |
|
||||
| `updated_by` | int | Foreign key to users |
|
||||
| `priority` | int | 1–5 (1=Critical, 5=Minimal) |
|
||||
| `status` | varchar(20) | Open, Pending, In Progress, Closed |
|
||||
|
||||
#### Indexed Columns (performance)
|
||||
|
||||
- `tickets`: `ticket_id` (unique), `status`, `priority`, `created_at`, `created_by`, `assigned_to`, `visibility`
|
||||
- `audit_log`: `user_id`, `action_type`, `entity_type`, `created_at`
|
||||
|
||||
### API Endpoints
|
||||
|
||||
| Endpoint | Method | Description |
|
||||
|----------|--------|-------------|
|
||||
| `/api/update_ticket.php` | POST | Update ticket with workflow validation |
|
||||
@@ -169,75 +207,101 @@ Access all admin pages via the **Admin dropdown** in the dashboard header.
|
||||
| `/api/export_tickets.php` | GET | Export tickets to CSV/JSON |
|
||||
| `/api/generate_api_key.php` | POST | Generate API key (admin) |
|
||||
| `/api/revoke_api_key.php` | POST | Revoke API key (admin) |
|
||||
|
||||
## Setup & Configuration
|
||||
|
||||
### 1. Environment Configuration
|
||||
|
||||
Copy the example file and edit with your values:
|
||||
```bash
|
||||
cp .env.example .env
|
||||
nano .env
|
||||
```
|
||||
|
||||
Required environment variables:
|
||||
```env
|
||||
DB_HOST=10.10.10.50
|
||||
DB_USER=tinkertickets
|
||||
DB_PASS=your_password
|
||||
DB_NAME=ticketing_system
|
||||
DISCORD_WEBHOOK_URL=https://discord.com/api/webhooks/...
|
||||
APP_DOMAIN=t.lotusguild.org
|
||||
TIMEZONE=America/New_York
|
||||
```
|
||||
|
||||
**Note**: `APP_DOMAIN` is required for Discord webhook ticket links to work correctly. Without it, links will default to localhost.
|
||||
|
||||
### 2. Cron Jobs
|
||||
|
||||
Add to crontab for recurring tickets:
|
||||
```bash
|
||||
# Run every hour to create scheduled recurring tickets
|
||||
0 * * * * php /var/www/html/tinkertickets/cron/create_recurring_tickets.php
|
||||
```
|
||||
|
||||
### 3. File Uploads
|
||||
|
||||
Ensure the `uploads/` directory exists and is writable:
|
||||
```bash
|
||||
mkdir -p /var/www/html/tinkertickets/uploads
|
||||
chown www-data:www-data /var/www/html/tinkertickets/uploads
|
||||
chmod 755 /var/www/html/tinkertickets/uploads
|
||||
```
|
||||
|
||||
### 4. Authelia Integration
|
||||
|
||||
Tinker Tickets uses Authelia for SSO. User information is passed via headers:
|
||||
- `Remote-User`: Username
|
||||
- `Remote-Name`: Display name
|
||||
- `Remote-Email`: Email address
|
||||
- `Remote-Groups`: User groups (comma-separated)
|
||||
|
||||
Admin users must be in the `admin` group in LLDAP.
|
||||
| `/api/delete_comment.php` | POST | Delete comment (owner/admin) |
|
||||
| `/api/update_comment.php` | POST | Update comment (owner/admin) |
|
||||
| `/api/delete_attachment.php` | POST/DELETE | Delete attachment |
|
||||
| `/api/download_attachment.php` | GET | Download attachment (visibility checked) |
|
||||
| `/api/check_duplicates.php` | GET | Check for duplicate tickets |
|
||||
| `/api/manage_recurring.php` | CRUD | Recurring tickets (admin) |
|
||||
| `/api/manage_templates.php` | CRUD | Templates (admin) |
|
||||
| `/api/manage_workflows.php` | CRUD | Workflow rules (admin) |
|
||||
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
tinker_tickets/
|
||||
├── api/ # API endpoints
|
||||
├── assets/ # Static assets (CSS, JS)
|
||||
├── config/ # Configuration
|
||||
├── controllers/ # MVC Controllers
|
||||
├── cron/ # Scheduled task scripts
|
||||
├── helpers/ # Utility classes
|
||||
├── middleware/ # Request middleware
|
||||
├── models/ # Data models
|
||||
├── scripts/ # Maintenance scripts
|
||||
├── uploads/ # File upload storage
|
||||
├── views/ # View templates
|
||||
│ └── admin/ # Admin panel views
|
||||
├── index.php # Main router
|
||||
└── .env # Environment configuration
|
||||
├── api/
|
||||
│ ├── add_comment.php # POST: Add comment
|
||||
│ ├── assign_ticket.php # POST: Assign ticket to user
|
||||
│ ├── bulk_operation.php # POST: Bulk operations (admin only)
|
||||
│ ├── check_duplicates.php # GET: Check for duplicate tickets
|
||||
│ ├── delete_attachment.php # POST/DELETE: Delete attachment
|
||||
│ ├── delete_comment.php # POST: Delete comment (owner/admin)
|
||||
│ ├── download_attachment.php # GET: Download with visibility check
|
||||
│ ├── export_tickets.php # GET: Export tickets to CSV/JSON
|
||||
│ ├── generate_api_key.php # POST: Generate API key (admin)
|
||||
│ ├── get_template.php # GET: Fetch ticket template
|
||||
│ ├── get_users.php # GET: Get user list
|
||||
│ ├── manage_recurring.php # CRUD: Recurring tickets (admin)
|
||||
│ ├── manage_templates.php # CRUD: Templates (admin)
|
||||
│ ├── manage_workflows.php # CRUD: Workflow rules (admin)
|
||||
│ ├── revoke_api_key.php # POST: Revoke API key (admin)
|
||||
│ ├── ticket_dependencies.php # GET/POST/DELETE: Ticket dependencies
|
||||
│ ├── update_comment.php # POST: Update comment (owner/admin)
|
||||
│ ├── update_ticket.php # POST: Update ticket (workflow validation)
|
||||
│ └── upload_attachment.php # GET/POST: List or upload attachments
|
||||
├── assets/
|
||||
│ ├── css/
|
||||
│ │ ├── dashboard.css # Dashboard + terminal styling
|
||||
│ │ └── ticket.css # Ticket view styling
|
||||
│ ├── js/
|
||||
│ │ ├── advanced-search.js # Advanced search modal
|
||||
│ │ ├── ascii-banner.js # ASCII art banner
|
||||
│ │ ├── dashboard.js # Dashboard + bulk actions + kanban + sidebar
|
||||
│ │ ├── keyboard-shortcuts.js # Keyboard shortcuts
|
||||
│ │ ├── markdown.js # Markdown rendering + ticket linking (XSS-safe)
|
||||
│ │ ├── settings.js # User preferences
|
||||
│ │ ├── ticket.js # Ticket + comments + visibility
|
||||
│ │ └── toast.js # Toast notifications
|
||||
│ └── images/
|
||||
│ └── favicon.png
|
||||
├── config/
|
||||
│ └── config.php # Config + .env loading
|
||||
├── controllers/
|
||||
│ ├── DashboardController.php # Dashboard with stats + filters
|
||||
│ └── TicketController.php # Ticket CRUD + timeline + visibility
|
||||
├── cron/
|
||||
│ └── create_recurring_tickets.php # Process recurring ticket schedules
|
||||
├── helpers/
|
||||
│ └── ResponseHelper.php # Standardized JSON responses
|
||||
├── middleware/
|
||||
│ ├── AuthMiddleware.php # Authelia SSO integration
|
||||
│ ├── CsrfMiddleware.php # CSRF protection
|
||||
│ ├── RateLimitMiddleware.php # Session + IP-based rate limiting
|
||||
│ └── SecurityHeadersMiddleware.php # CSP with nonces, security headers
|
||||
├── models/
|
||||
│ ├── ApiKeyModel.php # API key generation/validation
|
||||
│ ├── AuditLogModel.php # Audit logging + timeline
|
||||
│ ├── BulkOperationsModel.php # Bulk operations tracking
|
||||
│ ├── CommentModel.php # Comment data access
|
||||
│ ├── CustomFieldModel.php # Custom field definitions/values
|
||||
│ ├── DependencyModel.php # Ticket dependencies
|
||||
│ ├── RecurringTicketModel.php # Recurring ticket schedules
|
||||
│ ├── StatsModel.php # Dashboard statistics
|
||||
│ ├── TemplateModel.php # Ticket templates
|
||||
│ ├── TicketModel.php # Ticket CRUD + visibility + collision-safe IDs
|
||||
│ ├── UserModel.php # User management + groups
|
||||
│ ├── UserPreferencesModel.php # User preferences
|
||||
│ └── WorkflowModel.php # Status transition workflows
|
||||
├── scripts/
|
||||
│ ├── cleanup_orphan_uploads.php # Clean orphaned uploads
|
||||
│ └── create_dependencies_table.php # Create ticket_dependencies table
|
||||
├── uploads/ # File attachment storage
|
||||
├── views/
|
||||
│ ├── admin/
|
||||
│ │ ├── ApiKeysView.php # API key management
|
||||
│ │ ├── AuditLogView.php # Audit log browser
|
||||
│ │ ├── CustomFieldsView.php # Custom field management
|
||||
│ │ ├── RecurringTicketsView.php # Recurring ticket management
|
||||
│ │ ├── TemplatesView.php # Template management
|
||||
│ │ ├── UserActivityView.php # User activity report
|
||||
│ │ └── WorkflowDesignerView.php # Workflow transition designer
|
||||
│ ├── CreateTicketView.php # Ticket creation with visibility
|
||||
│ ├── DashboardView.php # Dashboard with kanban + sidebar
|
||||
│ └── TicketView.php # Ticket view with visibility editing
|
||||
├── .env # Environment variables (GITIGNORED)
|
||||
├── README.md # This file
|
||||
└── index.php # Main router
|
||||
```
|
||||
|
||||
## Workflow States
|
||||
@@ -252,6 +316,110 @@ Open → Pending → In Progress → Closed
|
||||
All states can transition to Closed (with comment).
|
||||
Closed tickets can be reopened to Open or In Progress.
|
||||
|
||||
## Setup & Configuration
|
||||
|
||||
### 1. Environment Configuration
|
||||
|
||||
Copy the example file and edit with your values:
|
||||
```bash
|
||||
cp .env.example .env
|
||||
nano .env
|
||||
```
|
||||
|
||||
Required environment variables:
|
||||
```env
|
||||
DB_HOST=your_db_host
|
||||
DB_USER=your_db_user
|
||||
DB_PASS=your_password
|
||||
DB_NAME=ticketing_system
|
||||
DISCORD_WEBHOOK_URL=https://discord.com/api/webhooks/...
|
||||
APP_DOMAIN=your.domain.example
|
||||
TIMEZONE=America/New_York
|
||||
```
|
||||
|
||||
**Note**: `APP_DOMAIN` is required for Discord webhook ticket links to work correctly. Without it, links will default to localhost.
|
||||
|
||||
### 2. Cron Jobs
|
||||
|
||||
Add to crontab for recurring tickets:
|
||||
```bash
|
||||
# Run every hour to create scheduled recurring tickets
|
||||
0 * * * * php /path/to/tinkertickets/cron/create_recurring_tickets.php
|
||||
```
|
||||
|
||||
### 3. File Uploads
|
||||
|
||||
Ensure the `uploads/` directory exists and is writable:
|
||||
```bash
|
||||
mkdir -p /path/to/tinkertickets/uploads
|
||||
chown www-data:www-data /path/to/tinkertickets/uploads
|
||||
chmod 755 /path/to/tinkertickets/uploads
|
||||
```
|
||||
|
||||
### 4. Authelia Integration
|
||||
|
||||
Tinker Tickets uses Authelia for SSO. User information is passed via headers:
|
||||
- `Remote-User`: Username
|
||||
- `Remote-Name`: Display name
|
||||
- `Remote-Email`: Email address
|
||||
- `Remote-Groups`: User groups (comma-separated)
|
||||
|
||||
Admin users must be in the `admin` group in LLDAP.
|
||||
|
||||
## Developer Notes
|
||||
|
||||
Key conventions and gotchas for working with this codebase:
|
||||
|
||||
1. **Session format**: `$_SESSION['user']['user_id']` (not `$_SESSION['user_id']`)
|
||||
2. **API auth check**: Verify `$_SESSION['user']['user_id']` exists
|
||||
3. **Admin check**: `$_SESSION['user']['is_admin'] ?? false`
|
||||
4. **Config path**: `config/config.php` (not `config/db.php`)
|
||||
5. **Comments table**: `ticket_comments` (not `comments`)
|
||||
6. **CSRF**: Required for all POST/DELETE requests via `X-CSRF-Token` header
|
||||
7. **Cache busting**: Use `?v=YYYYMMDD` query params on JS/CSS files
|
||||
8. **Ticket linking**: Use `#123456789` in markdown-enabled comments
|
||||
9. **User groups**: Stored in `users.groups` as comma-separated values
|
||||
10. **API routing**: All API endpoints must be registered in `index.php` router
|
||||
11. **Session in APIs**: `RateLimitMiddleware` starts the session — do not call `session_start()` again
|
||||
12. **Database collation**: Use `utf8mb4_general_ci` (not `unicode_ci`) for new tables
|
||||
13. **Discord URLs**: Set `APP_DOMAIN` in `.env` for correct ticket URLs in Discord notifications
|
||||
14. **Ticket ID extraction**: Use `getTicketIdFromUrl()` helper in JS files
|
||||
15. **CSP nonces**: All inline `<script>` tags require `nonce="<?php echo $nonce; ?>"`
|
||||
16. **Visibility validation**: Internal visibility requires at least one group — validated server-side
|
||||
17. **Rate limiting**: Both session-based AND IP-based limits are enforced
|
||||
|
||||
## File Reference
|
||||
|
||||
| File | Purpose |
|
||||
|------|---------|
|
||||
| `index.php` | Main router for all routes |
|
||||
| `config/config.php` | Config loader + .env parsing |
|
||||
| `api/update_ticket.php` | Ticket updates with workflow + visibility validation |
|
||||
| `api/download_attachment.php` | File downloads with visibility check |
|
||||
| `api/bulk_operation.php` | Bulk operations with visibility filtering |
|
||||
| `models/TicketModel.php` | Ticket CRUD, visibility filtering, collision-safe ID generation |
|
||||
| `models/ApiKeyModel.php` | API key generation and validation |
|
||||
| `middleware/AuthMiddleware.php` | Authelia header parsing + session setup |
|
||||
| `middleware/CsrfMiddleware.php` | CSRF token generation and validation |
|
||||
| `middleware/SecurityHeadersMiddleware.php` | CSP headers with per-request nonce generation |
|
||||
| `middleware/RateLimitMiddleware.php` | Session + IP-based rate limiting |
|
||||
| `assets/js/dashboard.js` | Dashboard UI, kanban, sidebar, bulk actions |
|
||||
| `assets/js/ticket.js` | Ticket UI, visibility editing |
|
||||
| `assets/js/markdown.js` | Markdown parsing + ticket linking (XSS-safe) |
|
||||
| `assets/css/dashboard.css` | Terminal styling, kanban, sidebar |
|
||||
|
||||
## Security Implementations
|
||||
|
||||
| Feature | Implementation |
|
||||
|---------|---------------|
|
||||
| SQL Injection | All queries use prepared statements with parameter binding |
|
||||
| XSS Prevention | HTML escaped in markdown parser; CSP with per-request nonces |
|
||||
| CSRF Protection | Token-based with constant-time comparison (`hash_equals`) |
|
||||
| Session Security | Fixation prevention, secure cookies, session timeout |
|
||||
| Rate Limiting | Session-based + IP-based (file storage) |
|
||||
| File Security | Path traversal prevention, MIME type validation |
|
||||
| Visibility | Enforced on ticket views, downloads, and bulk operations |
|
||||
|
||||
## License
|
||||
|
||||
Internal use only - LotusGuild Infrastructure
|
||||
|
||||
@@ -2566,7 +2566,8 @@ input[type="checkbox"]:checked {
|
||||
.filter-group label {
|
||||
display: block;
|
||||
margin: 0.4rem 0;
|
||||
color: var(--terminal-green);
|
||||
color: var(--terminal-amber);
|
||||
text-shadow: var(--glow-amber);
|
||||
cursor: pointer;
|
||||
font-size: 0.85rem;
|
||||
font-family: var(--font-mono);
|
||||
|
||||
Reference in New Issue
Block a user