Commit Graph

152 Commits

Author SHA1 Message Date
796e1b3072 feat: rewrite db.php from PDO to MySQLi
PDO extension was not available on CloudLinux/alt-php84 server.
MySQLi is available, so rewrote entire database layer to use it.

Added helper functions (_dbRun, _dbFetchAll, _dbFetchOne, etc.)
that handle named parameter conversion and type binding automatically.
All public db*() function signatures remain identical.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 16:04:14 +02:00
438a9b5070 temp: phpcheck to verify PDO after Plesk change
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 15:57:35 +02:00
a75ba19fe5 cleanup: remove phpcheck.php diagnostic script
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 15:28:01 +02:00
1a18da2430 temp: add phpcheck.php to diagnose PDO availability
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 15:26:51 +02:00
b15efa1758 cleanup: remove setup_config.php after use
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 15:25:37 +02:00
42571e46f3 temp: add setup_config.php to create db_config.php on server
Will be removed immediately after use.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 15:24:20 +02:00
2b8e053e52 debug: add error display to migrate.php to see what fails
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 15:23:35 +02:00
e540ec0448 fix: split initDatabase() into separate exec() calls per table
MySQL/PDO doesn't support multiple CREATE TABLE statements in a single
exec() call. Split into an array of individual statements with a loop.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 15:15:55 +02:00
13e0d1255f JSON → MySQL migraatio: tietokantapohjainen datatallennus
Lisätty:
- db.php: PDO-tietokantakerros (kaikki CRUD-funktiot)
- migrate.php: JSON → MySQL migraatioskripti
- db_config.php lisätty .gitignore:en (sisältää tunnukset)

Muutettu:
- api.php: kaikki JSON load/save → db*() funktiot
- session.cookie_samesite: Strict → Lax (captcha-fix alias-domaineilla)
- Poistettu kaikki JSON-tiedosto I/O (paitsi tiedostoupload + logot)

Hyödyt:
- Git deploy ei enää ylikirjoita dataa
- Tiedostolukot ja transaktiot → ei korruptiota
- Parempi suorituskyky isoilla tietomäärillä

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 15:00:38 +02:00
c714f39bc5 Päivitä admin-salasana admin123 + kaikki tuotantodata
FTP:llä haettu data vanhalta intra.cuitunet.fi:
- 3 käyttäjää, admin-salasana resetoitu admin123
- 4 yritystä brändäyskentillä
- 35 CuituNet-asiakasta

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 14:31:46 +02:00
eed1ac5639 Migroi kaikki data vanhalta intra.cuitunet.fi -palvelimelta
FTP:llä haettu:
- 4 yritystä (CuituNet, Web1, Empor, Woima Services)
- 35 CuituNet-asiakasta + 1 liidi
- 1 Web1-asiakas
- 3 käyttäjää (admin, Jukka, ville)
- Brändäyskentät lisätty companies.json:iin

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 14:26:11 +02:00
52bf1bd300 Päivitä CuituNetin data vanhalta palvelimelta (intra.cuitunet.fi)
Haettu API:n kautta: 2 asiakasta, 1 liidi.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 14:24:44 +02:00
78af39b252 Lisää CuituNetin asiakasdata gittiin
Asiakkaat, liidit, tiketit, asetukset, arkisto ja changelog.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 14:19:59 +02:00
712e9a1222 Lisää data-tiedostot gittiin + dynaaminen SITE_URL
- companies.json, users.json, config.json gitin seurantaan
- SITE_URL dynaaminen HTTP_HOST:in mukaan
- MAIL_FROM vaihdettu noreply@noxus.fi
- CuituNet Intra → Noxus Intra sähköposteissa

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 14:18:23 +02:00
daec42600a Korjaa deploy_data.php - pakota datan ylikirjoitus
initUsers() luo oletusadminin ennen deploy-skriptiä,
joten tiedostot eivät ole tyhjiä. Nyt ylikirjoitetaan aina.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 14:16:23 +02:00
edefd05ec6 Lisää deploy_data.php - alustaa data tuotantoon
Väliaikainen skripti joka luo companies.json, users.json, config.json
tuotantopalvelimelle. Poistettava käytön jälkeen.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 14:14:07 +02:00
095dc90b6f White-label multi-domain tuki (Noxus Intra)
- CSS-muuttujat: kaikki kovakoodatut #0f3460/#16213e korvattu var(--primary-color)/var(--primary-dark)
- Uudet API-endpointit: branding (julkinen, domain-pohjainen), company_logo, company_logo_upload
- Domain-pohjainen brändäys: HTTP_HOST → yrityksen domains-arrayn matchaus
- Login: domain asettaa oletusyrityksen sessioon
- check_auth: palauttaa branding-objektin (primary_color, subtitle, logo_url)
- company_create/update: käsittelee domains, primary_color, subtitle, logo_file
- Dynaaminen login-sivu, header ja footer (logo, nimi, alaotsikko, värit)
- JS: loadBranding(), applyBranding(), yritysvaihdon brändäyspäivitys
- Admin-paneeli: brändäysasetukset (logo-upload, väri, alaotsikko, domainit)
- Git-repo siirretty intra.noxus.fi:hin

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 13:44:49 +02:00
918a5ff120 Lisää sähköpostiallekirjoitus per käyttäjä per postilaatikko
- Allekirjoitukset tallennetaan users.json:iin (signatures-objekti, avaimena mailbox_id)
- Käyttäjälomakkeessa dynaamiset textareat jokaiselle postilaatikolle
- Allekirjoitus liitetään automaattisesti sähköpostivastauksiin (ticket_reply)
- Esikatselu näkyy tikettivastauslomakkeen alla
- Muistiinpanoihin (ticket_note) ei lisätä allekirjoitusta
- Uusi all_mailboxes endpoint palauttaa kaikki käyttäjän postilaatikot
- check_auth ja login palauttavat nyt myös user_id ja signatures

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 13:09:30 +02:00
11e1103eb4 Siirrä yritysvalitsin header-yläpalkkiin nappien joukkoon
Dropdown siirretty header-left → header-right, kompaktimpi nappikoko
headerissa, flex-wrap tukee kapeampia näyttöjä.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 11:46:49 +02:00
44e401f4d3 Make API key and CORS settings per-company
- saatavuus endpoint finds company by API key, searches only that company
- config/config_update/generate_api_key now use company config
- API tab shows active company name
- Each company has own api_key and cors_origins in their config.json

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 11:39:35 +02:00
92d52f34ad Add ticket sorting by status priority, updated, or created date
Default sort: status priority (käsittelyssä → uusi → odottaa → suljettu)
then by updated date within same status.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 11:37:31 +02:00
64ff8eaa91 Fix company access: sync session from users.json on every check_auth
- check_auth always reads fresh company permissions from users.json
- user_update updates session immediately when editing own permissions
- Prevents stale session showing tickets from companies user lost access to

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 11:34:18 +02:00
9973485cb4 Remove temp diag endpoints, improve auto-recovery for companies.json
- Remove temporary data_diag/data_read/data_write endpoints
- Auto-recovery now scans existing company directories if companies.json
  is empty or missing (handles git deploy wiping the file)
- Auto-creates config.json for any company dir missing it

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 11:33:21 +02:00
443e8fcfc3 TEMP: Fix diag endpoint auth for production recovery
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 11:28:51 +02:00
6b7bdcd17d TEMP: Add data diagnostics endpoints for production recovery
Will be removed after data is restored.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 11:28:04 +02:00
ab03eb7e61 Fix data loss: remove data files from git, add gitignore, auto-recover
- Remove data/companies.json and data/companies/cuitunet/config.json from git
  (tracked data files get overwritten on every deploy, causing data loss)
- Add data/companies/*/ and data/tickets.json to .gitignore
- Migration now auto-recovers companies.json and config.json if missing
  (handles case where git clean removes untracked data files)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 11:25:36 +02:00
9a17bc9cf5 Remove tags column from ticket list view
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 11:21:43 +02:00
f82f62877d Add cross-company ticket viewing and move Yritykset button to header
- tickets endpoint supports ?all=1 to fetch from all user's companies
- ticket_detail/reply/status/etc support ?company_id= for cross-company ops
- Support tab shows all companies' tickets with company badge on subject
- Yritykset button moved from tab bar to header (next to Käyttäjät)
- requireCompanyOrParam() helper for ticket endpoints

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 11:19:35 +02:00
7f89a29b94 Fix migration check: detect unmigrated data by checking data/customers.json
The previous check (directory existence) failed on production because
git pull created data/companies/ from committed config.json, causing
the migration to be skipped while customer data remained in data/ root.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 11:06:08 +02:00
c34b5a2c26 Add multi-tenant support with per-company data isolation
Implement full multi-company architecture:
- Per-company directory structure (data/companies/{id}/)
- Automatic migration from single-tenant to multi-tenant
- Company management admin tab (create, edit, delete companies)
- Per-company IMAP mailbox configuration (multiple mailboxes per company)
- User access control per company (companies array on users)
- Company switcher in header (shown when user has access to >1 company)
- Session-based company context with check_auth fallback for old sessions
- Ticket list shows mailbox name instead of sender
- IMAP settings moved from global config to company-specific config
- All data endpoints protected with requireCompany() guard

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 11:04:24 +02:00
562153e040 Add ticket tags system, tag filtering, and auto-close feature
- Fix tickets API endpoint: add type, customer_name, customer_id, tags fields
- Add tags array to ticket data structure with add/remove UI
- Add tag filter input to toolbar and tag column in ticket list
- Add ticket_tags API endpoint for updating tags
- Add set_tags and auto_close_days actions to auto-rules
- Auto-close check runs on ticket list load, closes expired tickets
- Add tag CSS styles with editable tag badges in detail view

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 10:32:09 +02:00
f918952c3f Add auto-refresh toggle and tab persistence via URL hash
- Auto-refresh checkbox with configurable interval (30s-5min)
- URL hash (#support, #customers etc.) persists active tab on refresh
- switchToTab() centralized function for tab switching
- Logo click uses same function

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 10:20:24 +02:00
7fcf0a3b31 Add auto-rules management, bulk actions for tickets
- Auto-rules JS: load, render, save, edit, delete, toggle rules
- Rules UI: Säännöt view with rule list and form
- Bulk actions: checkbox selection in ticket list
- Bulk close/delete endpoints (ticket_bulk_status, ticket_bulk_delete)
- Bulk toolbar with select all, close selected, delete selected

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 10:18:10 +02:00
ea7c3e0cf7 Add closed tickets checkbox, customer linking for tickets
- Closed tickets completely hidden from default view, separate
  "Suljetut" checkbox to toggle them with search capability
- Removed "Osoitettu" column, added "Asiakas" column to ticket list
- Customer dropdown in ticket detail view to link ticket to a customer
- ticket_customer API endpoint for linking tickets to customers
- ticket_type changelog label added

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 10:06:38 +02:00
91930c9420 Add ticket types, move Asiakaspalvelu tab first, hide closed tickets
- Asiakaspalvelu tab moved to first position in navigation
- Added ticket type field (Laskutus, Tekniikka, Vika, Muu) with
  type filter dropdown and type column in ticket list
- Type selector in ticket detail view with API endpoint
- Closed tickets hidden by default (selectable via "Kaikki tilat")
- Käsittelyssä rows highlighted with green background
- Type badges with color coding per category

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 10:01:29 +02:00
f0a7676451 Rewrite ImapClient to use raw sockets instead of php-imap extension
Production server doesn't have php-imap extension. Replaced the entire
ImapClient class to use stream_socket_client() with raw IMAP protocol
commands. Supports SSL/TLS, STARTTLS, MIME header decoding, body
extraction with encoding detection, and charset conversion.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 09:46:21 +02:00
42e3648e3d Add Asiakaspalvelu email ticketing system
IMAP client for fetching emails from asiakaspalvelu@cuitunet.fi,
Freshdesk-style ticket management with status tracking, message
threading, reply/note functionality, and IMAP settings in API tab.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 08:52:00 +02:00
cc3a6c465d Add logo click to return to customers view
Clicking the CuituNet Intra brand/logo in the header
navigates back to the Asiakkaat (customers) tab.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 03:00:54 +02:00
db8b64cd5b Move user management button to header
Users button now appears next to the logged-in user info
in the top right header instead of as a tab. Only visible
to admin users.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 02:59:30 +02:00
ddc96f4164 Rename Asetukset tab to API
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 02:52:09 +02:00
37ffd7e46b Restrict saatavuus API to return only true/false
Requires exact match of osoite + postinumero + kaupunki.
No longer exposes addresses, speeds, or any customer data.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 02:43:58 +02:00
b927cd2bf5 Fix missing mbstring: replace mb_strtolower with strtolower
Production server (PHP 8.4) doesn't have mbstring extension,
causing 500 error on saatavuus endpoint.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 02:39:04 +02:00
37e6f6b90e Add temporary error reporting to debug 500 on saatavuus endpoint
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 02:37:16 +02:00
b8b3fb422a Fix PHP 7 compatibility: replace str_contains with strpos
str_contains() requires PHP 8.0+, causing 500 error on production.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 02:32:31 +02:00
14707b9616 Add public availability API and settings panel
Public saatavuus endpoint with API key + CORS protection for
cuitunet.fi website integration. Admin settings tab for API key
management and testing. Includes standalone widget page.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 01:50:52 +02:00
8ba925d3dc Add leads (liidit) tab for tracking potential customers
- New Liidit tab with table, search, add/edit/delete
- Lead fields: company, contact, phone, email, address, city, status, notes
- Status workflow: Uusi → Kontaktoitu → Kiinnostunut → Odottaa toimitusta
- Color-coded status badges
- Detail view with notes display
- "Muuta asiakkaaksi" converts lead to customer with pre-filled data
- Lead CRUD endpoints in api.php with changelog logging
- leads.json added to .gitignore

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 01:35:04 +02:00
8a07689a1f Add security hardening, captcha login, and password reset via email
- .htaccess: HTTPS enforcement, security headers, block sensitive files
- data/.htaccess: deny all direct access to data directory
- Secure session settings (httponly, secure, strict mode, samesite)
- Rate limiting on login (10 attempts per 15 min per IP)
- Math captcha on login form (server-side validated)
- Password reset via email with token (1 hour expiry)
- Forgot password UI with reset link flow
- Email field added to user management
- Updated .gitignore for reset_tokens.json and login_attempts.json

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 01:00:19 +02:00
e4914e9edb Add user management, change log and customer archive
- Multi-user auth with username/password (replaces single password)
- Default admin account created automatically (admin/cuitunet2024)
- User CRUD with admin/user roles (only admin can manage users)
- All customer changes logged with timestamp, user and details
- Customer deletion now archives instead of permanently removing
- Archive view with restore and permanent delete options
- Tab navigation: Asiakkaat, Arkisto, Muutosloki, Käyttäjät
- Protect users.json, changelog.json and archive.json in .gitignore

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 00:41:40 +02:00
695d8c6545 Add multiple connections per customer, contract period, and layout redesign
- Refactor data model: each customer now has a liittymat array (auto-migration from old format)
- Add sopimuskausi (1/12/24/36 kk) and alkupvm fields per connection
- Form supports adding/removing multiple connection rows per company
- Add "use same as installation address" checkbox for billing address
- Move stat cards to compact sidebar on the right
- Place search bar above customer table

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 00:21:31 +02:00
c648c9311c Add file uploads and speed distribution chart
- File upload/download/delete per customer (max 20MB, stored in data/files/)
- Files section shown in customer detail modal
- Speed distribution chart replaces single "top speed" stat
- Bar chart shows all speeds with count, top speed bolded
- Customer delete also cleans up associated files
- data/files/ added to .gitignore

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 00:05:21 +02:00