diff --git a/CHANGELOG.md b/CHANGELOG.md index 308e8933b..7614f3cf5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,7 @@ This file documents all notable changes made to ITFlow. ### Upgrading -Update from Maintenance > Update — Update ITFlow hands the job to cron, which updates the files and applies this release's eight database changes (3.5.4 to 3.6.1) in the same pass. Nothing else is required. Everyone is signed out once after the update, agents and client portal contacts alike - see Security. The new Payment Provider Fees and Text Messages jobs in Maintenance > Cron are set up by themselves, and so are Manager Check-in and Managed Instances on an install whose config.php turns managed mode on (see New Features & Updates). +Update from Maintenance > Update — Update ITFlow hands the job to cron, which updates the files and applies this release's nine database changes (3.5.4 to 3.6.2) in the same pass. Nothing else is required. Everyone is signed out once after the update, agents and client portal contacts alike - see Security. The new Payment Provider Fees and Text Messages jobs in Maintenance > Cron are set up by themselves, and so are Manager Check-in and Managed Instances on an install whose config.php turns managed mode on (see New Features & Updates). ### Security @@ -36,6 +36,7 @@ Update from Maintenance > Update — Update ITFlow hands the job to cron, which - Managed mode: one ITFlow can now manage others - a client's, a reseller's or your own hosted ones. It's off until config.php turns it on, each side on its own: `$config_enable_managed_instances = true;` on the ITFlow that does the managing adds Admin > Managed Instances, and `$config_enable_managed_by = true;` on each one it manages adds Admin > Managed By. An install with neither line sees nothing of it - no menu, pages, cron jobs or sign-in. Then add one in Admin > Managed Instances, and paste the code it gives you into the other ITFlow's Admin > Managed By. From then on that ITFlow checks in every minute, and you see how each one is doing: its version and whether an update is waiting (a security one stands out), whether cron is running, its last backup, the errors it logged today, and its agents against its seat limit - and you're notified when one stops checking in. From the manager you can update an instance, or let it update itself a set number of days after a release comes out and straight away for a security release; set how many agents it can have and its white-label key; make it read-only, where its people can still sign in, look and export, or suspend it, with a message of your own; and sign in to it as support in a new tab, for two hours, with no password or seat of its own and every sign-in in its audit log. What the manager sets is locked on the instance, which says so - everything else stays the instance's own, and its admins can disconnect it unless its config.php keeps it managed (`$config_manager_required = true`, for a provider hosting it, which turns Managed By on as well). Instances only ever call the manager, so they can sit behind a firewall, and they send how they're doing - never client data. - Export Data: the documentation PDF can go out as a secure link, like a login, document or file. Share a link next to Download PDF - or Share the IT documentation on a client's Shared Links - makes the PDF from the parts you tick and gives you a link that works for as long and as many times as you set, with a passphrase or an emailed code first if you like, and tells you when it's downloaded. The PDF is made when the link is, so later changes aren't in it, and it's kept encrypted until the link stops working - then it's deleted. With passwords and 2FA secrets in it, the PDF is locked with a password of its own too, as a download is, and the page the link opens says so. - Maintenance > Update is easier to follow. It opens with where your install stands - up to date, an update available, an update running, or the database still to finish - and the one button for it, now Update ITFlow instead of Queue Update. Below it is what's new: the release notes for the versions between yours and the latest, read from the changelog each time ITFlow checks for updates, with the developer notes folded away and the commits behind them a click further. Before you update it lists what to do first, and says whether any of ITFlow's own files have been changed on your install, which updating would put back. Once you click Update ITFlow, the page shows the update running, refreshes itself until it's done, and then says when ITFlow was updated, or what stopped it. Alongside are this install's version, branch, database, when it last checked and updated, whether cron is running, and the command to run the same update from a shell, with the folder and user filled in for your server. +- Cron: a new install starts with cron switched on, so adding the cron job is the only step - in the crontab, or as a cron job that runs every minute in a hosting control panel such as Jabali, HestiaCP or cPanel - and jobs start as soon as it runs. Before, cron also had to be turned on in Maintenance > Cron, and an install that missed that step ran nothing without saying why. Get started's cron step is now just the cron job, with Turn cron on shown only if someone has switched it off. An install updated to this release keeps the setting it has. ### Bug Fixes @@ -49,6 +50,7 @@ Update from Maintenance > Update — Update ITFlow hands the job to cron, which ### Developer Updates +- Database 3.6.2 changes `settings.config_enable_cron`'s default to `1` and nothing else - no install's setting is changed, as switching it on would start late fees, overdue reminders and autopay retries on an install that has them stopped. `setup/seed_data.php` sets it too, so both setup paths start with cron on. CONTRIBUTING's master switch section says why it is on by default. - Text messaging is `functions/sms.php`. Database 3.6.0 adds `sms_providers` (the service, its SID and secret, the number in E.164 digits, the key in its inbound address), `sms_messages` (every text both ways - `sms_message_direction` `out`/`in`, `sms_message_status` queued/sending/sent/failed/blocked/cancelled going out and ticket/unmatched/code/spam/keyword/dismissed coming in) and `sms_numbers` (a number's name, `sms_number_opted_out_at`, `sms_number_blocked_at`), and `settings.config_ticket_sms_parse`, `config_ticket_sms_unknown_senders` and `config_ticket_sms_acknowledge`, read where they're used by `smsTicketSettings()`. - Sending: `smsQueue($e164, $text, $meta)` splits at `SMS_TEXT_LIMIT` and refuses a number that replied STOP (a `blocked` row) unless `force` - only the STOP answer itself. `smsSendQueued()` claims a row before sending, so a request and the new Text Messages job (`cron/sms_queue.php`, `smsQueueRun()`, every minute) can't both send it; a 401 fails at once, a timeout, 403/429 or 5xx is tried again up to `SMS_MAX_ATTEMPTS`. The job keeps under Skyetel's 300 texts in five minutes and a second apart, and `smsTidy()` wipes codes after `SMS_CODE_KEEP_HOURS`, deletes spam and dismissed texts after `SMS_SPAM_KEEP_DAYS` and the rest after `SMS_KEEP_DAYS`. Providers are `smsProviderKinds()` - another service is an entry there with its own send function and `api/sms/.php`. - Receiving: `api/sms/skyetel.php?key=` (the key compared with `hash_equals`, else 404) hands `{to, from, text, media}` to `smsInbound()`, in this order: a repeat within two minutes is dropped; STOP/START/HELP (`smsKeyword()`) are answered; a blocked number is Spam; a number with a text on an open ticket in `SMS_CONVERSATION_DAYS` replies on it (`smsConversationTicket()`, `smsTicketReply()`); a contact's mobile or phone (`smsContactsFor()`, matched on the digits with `REGEXP_REPLACE`) opens a ticket (`smsTicketOpen()`, source `Text`); then `smsVerificationCode()`, `smsLooksLikeSpam()`, and Unmatched with one in-app notification an hour per number. `smsSaveMedia()` fetches media over https only, from public addresses only, `SMS_MEDIA_MAX_BYTES` each, as `TICKET_ATTACHMENT_EXTENSIONS`. Texts and HTML go into queries through `smsSql()` (mysqli_real_escape_string) - `escapeSql()` strips anything that looks like a tag. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 3ddfece87..e7880d73e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -114,7 +114,7 @@ Be precise about what it does, because it is easy to oversell. It is **not** a g That last part is the reason it is not redundant with `cron_job_enabled`. Turning the switch off and back on returns you to exactly the configuration you had. Sweeping all seven rows off and back on does not: `backup` ships `'enabled' => 0`, so the sweep quietly turns on nightly backups nobody asked for, along with anything else that was deliberately disabled. -It defaults to `0`. That is a weaker guard than it looks — an install with no crontab entry runs nothing whatever the switch says, so the entry is the real gate — but it does mean adding the crontab line to a half-configured install is not enough on its own to start emailing. Both setup paths name the step on the way out. +It defaults to `1`. An install with no crontab entry runs nothing whatever the switch says, so the entry is the real gate, and a new install has nothing to email or charge until someone adds it. Shipping it off only added a second step that could be missed in silence. Database 3.6.2 changed the column's default and nothing else: an install that already has the switch off keeps it off, because turning it on would start late fees, overdue reminders and autopay retries it has stopped. Don't write a migration that flips the value itself. ## Backups diff --git a/admin/database_updates/3.6.2.php b/admin/database_updates/3.6.2.php new file mode 100644 index 000000000..5c29ca4f5 --- /dev/null +++ b/admin/database_updates/3.6.2.php @@ -0,0 +1,17 @@ +" data-gs-cron-heard="">
-
Add one line to the crontab
-
For the user that owns the ITFlow files - crontab -e as them. The install script adds it for you.
+
Add the cron job
+
One line, for the user that owns the ITFlow files - crontab -e as them. On a hosting control panel such as Jabali, HestiaCP or cPanel, add it as a cron job that runs every minute. The install script adds it for you.
@@ -34,21 +35,19 @@ $gs_cron_command = gettingStartedCronCommand();
-
  • - -
    -
    Turn cron on
    -
    It ships off, so a copy of ITFlow never emails clients or charges cards by surprise. Every job stops itself while it is off.
    - -
    On. Each job's schedule is in Maintenance > Cron.
    - + +
  • + +
    +
    Turn cron back on
    +
    Someone switched it off in Maintenance > Cron, and every job stops itself while it is off.
    - -
    -
  • + + +
    Nothing is emailed or backed up until cron runs - the other steps can be done meanwhile.
    diff --git a/db.sql b/db.sql index a0361ed50..c85a18701 100644 --- a/db.sql +++ b/db.sql @@ -3213,7 +3213,7 @@ CREATE TABLE `settings` ( `config_ticket_ai_triage` tinyint(1) NOT NULL DEFAULT 0, `config_ticket_default_billable` tinyint(1) NOT NULL DEFAULT 0, `config_ticket_timer_autostart` tinyint(1) NOT NULL DEFAULT 0, - `config_enable_cron` tinyint(1) NOT NULL DEFAULT 0, + `config_enable_cron` tinyint(1) NOT NULL DEFAULT 1, `config_recurring_auto_send_invoice` tinyint(1) NOT NULL DEFAULT 1, `config_enable_alert_domain_expire` tinyint(1) NOT NULL DEFAULT 1, `config_send_invoice_reminders` tinyint(1) NOT NULL DEFAULT 1, diff --git a/scripts/setup_cli.php b/scripts/setup_cli.php index 9372d6de7..b79bc8973 100644 --- a/scripts/setup_cli.php +++ b/scripts/setup_cli.php @@ -422,10 +422,9 @@ if ($backup_key !== '') { echo "\nBackup key - keep a copy somewhere safe, away from this server; a backup can't be restored without it:\n\n"; echo " $backup_key\n"; } -echo "\nNext, before ITFlow can send mail, parse tickets or bill anyone:\n\n"; -echo " 1. Add this single entry to the crontab of the user that owns the ITFlow files:\n\n"; +echo "\nNext, before ITFlow can send mail, parse tickets or bill anyone, add this single entry\n"; +echo "to the crontab of the user that owns the ITFlow files:\n\n"; echo " * * * * * php $itflow_path/cron/cron.php >/dev/null\n\n"; -echo " 2. Turn cron on in Maintenance > Cron. It ships off, and every job stops\n"; -echo " itself until it is enabled. Per-job schedules live on the same page.\n\n"; +echo "Jobs start as soon as it runs. Their schedules are in Maintenance > Cron.\n\n"; exit(0); diff --git a/setup/seed_data.php b/setup/seed_data.php index e019e8f5b..b0df0da05 100644 --- a/setup/seed_data.php +++ b/setup/seed_data.php @@ -23,7 +23,7 @@ defined('FROM_SETUP') || die("Direct file access is not allowed"); function seedDefaultData($mysqli) { $latest_database_version = LATEST_DATABASE_VERSION; - mysqli_query($mysqli,"INSERT INTO settings SET company_id = 1, config_current_database_version = '$latest_database_version', config_invoice_prefix = 'INV-', config_invoice_next_number = 1, config_recurring_invoice_prefix = 'REC-', config_quote_prefix = 'QUO-', config_quote_next_number = 1, config_default_net_terms = 30, config_ticket_next_number = 1, config_ticket_prefix = 'TCK-'"); + mysqli_query($mysqli,"INSERT INTO settings SET company_id = 1, config_enable_cron = 1, config_current_database_version = '$latest_database_version', config_invoice_prefix = 'INV-', config_invoice_next_number = 1, config_recurring_invoice_prefix = 'REC-', config_quote_prefix = 'QUO-', config_quote_next_number = 1, config_default_net_terms = 30, config_ticket_next_number = 1, config_ticket_prefix = 'TCK-'"); // Create Categories // Expense Categories Examples diff --git a/setup/steps/telemetry.php b/setup/steps/telemetry.php index a5d5f4293..76507a788 100644 --- a/setup/steps/telemetry.php +++ b/setup/steps/telemetry.php @@ -82,7 +82,7 @@ if ($localization_done) {
  • Cron - ITFlow needs one crontab entry, for the user that owns its files. The install script adds it for you; by hand, it is: /dev/null", 'Crontab entry') ?> - It ships off - Get started's first step turns it on. + On a hosting control panel such as Jabali, HestiaCP or cPanel, add it as a cron job that runs every minute. Jobs start as soon as it runs.
  • Email, backups, billing and support - the mailbox ITFlow sends from, a nightly backup, your rate and tax, and response times.
  • Your team and starter content - the people who work with you, and templates to start from.