5b57289a50
qr_apply_owner_scope() used where('id_owner', X) + orWhere('id_owner', NULL,
'IS'). Any caller that had already added its own where('id', $id) before
calling it (qrcode_image.php, bulk_action.php's download path) ended up
with "WHERE id = ? AND id_owner = ? OR id_owner IS NULL" - AND binds
tighter than OR in SQL, so this was actually "(id = ? AND id_owner = ?) OR
(id_owner IS NULL)", which silently detaches the id filter and returns an
arbitrary null-owner row instead (or nothing, if that row's file is
missing) whenever the intended row didn't have a null owner. This is what
broke qr code thumbnails/downloads on qr.ensembia.com for scoped (non-super)
accounts, old and newly-created codes alike - reproduced and confirmed
fixed with a local before/after query dump, then with a live HTTP request
scenario (two accounts, two codes, one null-owner).
Fixed by building the scope as a single parenthesized raw condition
instead of two separate where() calls, so it can't be split apart by
whatever the caller already added to the query.
Also this session, per user feedback on the OSS rebrand review:
- Format moved back next to Filename in both qr-creation forms (was
separated from it when Filename got grouped with Owner last session).
- README/About now mention the temporary admin/admin demo account instead
of the not-yet-built self-registration flow.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Fo3DiRRpmz2DXjD7Uzhc8u
71 lines
3.0 KiB
Markdown
71 lines
3.0 KiB
Markdown
<p align="center"><img src="src/dist/img/brand/logo.svg" alt="QRForge" width="320"></p>
|
|
|
|
<p align="center"><strong>Self-hosted, open-source QR code generator.</strong></p>
|
|
|
|
**QRForge** creates and manages static and dynamic QR codes from a clean,
|
|
responsive control panel. It's a security-hardened, actively maintained fork
|
|
of the original [PHP Dynamic Qr code](https://github.com/giandonatoinverso/PHP-Dynamic-Qr-code)
|
|
project by Giandonato Inverso, built on [AdminLTE](https://adminlte.io/).
|
|
|
|
- **Try it free:** [qr.ensembia.com](https://qr.ensembia.com) - fully functional OSS test
|
|
instance. Self-service signup isn't live yet, so log in with the temporary shared demo
|
|
account `admin` / `admin` in the meantime.
|
|
- **Commercial VIP edition** (self-service create-rights, logo-embedded QR codes):
|
|
[www.qrforge.eu](https://www.qrforge.eu).
|
|
- **Self-host it yourself:** this repository, MIT-licensed.
|
|
|
|
# Features
|
|
|
|
- Dynamic QR codes with a database-backed URL shortener
|
|
- Create, edit, delete, enable/disable the redirect
|
|
- Download any time, bulk download/delete
|
|
- Batch-generate from a CSV file
|
|
- 16 static QR code types: Text, Email, Phone, SMS, WhatsApp, Skype, Location,
|
|
vCard, Event/calendar, Bookmark, WiFi (incl. WPA3), PayPal, Bitcoin, 2FA,
|
|
App Link (Android intent / universal links), Bluetooth
|
|
- QR code styling: 6 export formats, foreground/background color, 4 precision
|
|
levels, 10 sizes, optional label text below the code (custom font + size),
|
|
optional icon shown above the code, save/load your own style presets
|
|
- Address search (OpenStreetMap Nominatim) for Location QR codes
|
|
- Built-in QR scanner (camera or image upload, decodes entirely client-side)
|
|
- Installable as a PWA
|
|
- Role-based access: `super` (full access + user management), `admin`
|
|
(scoped to their own codes and sub-users), `user` (read-only, with
|
|
optional per-account create rights and view toggles set by an admin)
|
|
- Dashboard with QR/scan statistics and a 7-day activity chart
|
|
- CSRF protection, login rate limiting, session hardening, audit log
|
|
- Docker Compose setup, both a dev image and a production Nginx + PHP-FPM image
|
|
|
|
# What is included
|
|
|
|
- PHP 8.4 application source
|
|
- Database schema + migrations
|
|
- Docker Compose files (dev and production)
|
|
- CSS/JS assets
|
|
|
|
# Setup with Docker Compose
|
|
|
|
1. Clone this repository.
|
|
2. Copy `.env.example` to `.env` and set a real `DATABASE_PASSWORD` /
|
|
`MYSQL_ROOT_PASSWORD`.
|
|
3. Start the stack:
|
|
```bash
|
|
docker compose up -d --build
|
|
```
|
|
4. Open `http://localhost` and log in with `superadmin` / `superadmin`. You'll
|
|
be required to set a new password on first login.
|
|
|
|
For a production deployment behind a reverse proxy, use
|
|
`docker-compose.prod.yml` (Nginx + PHP-FPM) instead of the dev stack.
|
|
|
|
# Credits
|
|
|
|
- Originally forked from [PHP Dynamic Qr code](https://github.com/giandonatoinverso/PHP-Dynamic-Qr-code)
|
|
by Giandonato Inverso.
|
|
- QR code rendering powered by [chillerlan/php-qrcode](https://github.com/chillerlan/php-qrcode).
|
|
- Admin panel UI built on [AdminLTE](https://adminlte.io/).
|
|
|
|
# License
|
|
|
|
MIT - see [LICENSE](LICENSE).
|