Mobile app
CoreInto has its own app for Android and iOS. Staff sign in with their admin username and have the whole admin area in the app: every menu, list, report, utility, "add" form and settings page, as far as their role allows. Clients have the whole client area: services, domains, invoices and quotes, the store and cart, tickets, account details, contacts, users, payment methods and security. The app is a native app built for your brand from the CoreInto app template, not a copy of the website in a frame: CoreInto describes each page (its headings, tables, forms, buttons, pop-ups and tabs) and the app draws it with the phone's own controls. It reads and writes the same database through the same code as the website, so a change in the app shows on the website at once, and the other way round.
This chapter covers the CoreInto side: the settings, the phones that are signed in, push notices, and the connection the app uses. The app itself and how to build and publish it are described in the app template's own guide.
Settings > Mobile App#
Settings > System > Mobile App (/admin/settings/mobile, permission "Mobile app settings and signed-in phones", settings.mobile).
| Setting | Meaning |
|---|---|
| The app can be used | Turns the app's connection on. Off: the app says it is not available |
| App name | The name under the icon and at the top of the app (empty: the website name) |
| Package name | The app's identity in Google Play and the App Store, such as com.example.app. It cannot change once the app is published |
| Main colour, Second colour | The app's colours |
| Staff can sign in to the app | Shows the staff sign-in. Turning it off signs every staff phone out |
| New clients can open an account in the app | Only while sign-ups are allowed on the website too |
| Google Play address, App Store address | Links to the published app, shown in the website's footer |
| Firebase service account key | For push notices (below) |
Phones and the app file (/admin/settings/mobile/devices) lists every signed-in phone: who it belongs to, its name and app version, whether it takes notices, when it signed in and when it was last seen. You can sign a phone out, or send it a test notice. The page also lists the last 30 notices sent and has Download the app file (coreinto-app.json): the name, colours, logo and the address of this CoreInto that the app is built with. The file holds no passwords or keys.
Signing in#
Clients sign in with their email address and password. Staff sign in with their username and password. If two-step sign-in is on for the person, the app asks for the code. The same limits as the website apply: failed sign-ins lock the person and the address for a while, and banned addresses are refused.
When the sign-in succeeds, the phone gets two tokens. The access token lasts an hour. The refresh token lasts 60 days and is replaced each time it is used, so the app stays signed in while it is used at least every two months. Only a hash of each token is kept in the database. A phone is signed out:
- when the person signs out in the app, or removes the phone under their phones in the app;
- when staff sign it out under Phones and the app file;
- when the person's password changes (anywhere: the website, the admin area, a reset link), or their account is disabled;
- when a refresh token is used a second time, which means it was copied;
- for staff, when staff sign-in in the app is turned off.
A client who works in more than one account chooses the account in the app, as on the website. What a user may see and do follows the permissions the account owner gave them; staff see what their role allows.
Every page in the app#
The app's main menu is the website's: for staff the admin area's menus (Clients, Orders, Billing, Support, Reports, Utilities, Website, Add-ons) with Settings and the things waiting (pending orders, tickets, overdue invoices); for clients the client area's menus and the account menu. A page's own menu (for example a client's pages in the admin area, or the account menu of the client area) is under the list icon at the top right. Lists show each row as a card; tapping a row opens it. Forms work as on the website, including file uploads, pop-ups ("Add payment", "Change status") and tabs, and the website's own messages ("Saved.") and checks apply. Exports and PDFs (invoices, reports, CSV files) are saved on the phone.
Each page runs on the server exactly as it does in a browser, with the same permission checks, so pages added in later versions of CoreInto appear in the app without a new app. A few things stay on the website: paying (below), signing in as a client from the admin area, and the parts of pages that work only with the website's scripts (such as dragging dashboard widgets). The website's block editor has its own screen in the app (Website editor in the menu).
The app works with a web session of its own for each phone. Its key is worked out on the server from the encryption key and the phone, so it is never sent to the phone or stored; it ends when the phone signs out. "Check the address of sessions" does not end it when the phone's internet address changes (phones change address often); the phone's tokens are what keeps it signed in. Cookies the pages set (the cart, a chosen currency) are kept by the app and sent back, as a browser does. Files up to 15 MB can be downloaded in the app and up to 25 MB sent with a form.
Paying and the website#
Payments always happen on the payment provider's own pages, so the app opens the invoice on the website in the browser, already signed in. The link the app uses works once and only for two minutes, and only for pages of the client area, the cart and the store. The app opens other website pages, such as a service's control panel login, the same way.
Push notices#
Push notices go through Firebase Cloud Messaging with your own Firebase project:
- Create a project at console.firebase.google.com and add the Android app (and the iOS app) with your package name.
- Download
google-services.json(Android) andGoogleService-Info.plist(iOS). They go into the app build. - In Project settings, Service accounts, press Generate new private key. Paste the whole JSON file into Firebase service account key and save. It is stored encrypted.
Notices follow the emails CoreInto already sends. When an email goes to a client (a new invoice, a payment, a ticket reply, a suspension, a domain renewal notice), the phones of that account's users also get a notice, even if the client turned that kind of email off. Each phone chooses which kinds it wants: invoices and payments, support tickets, services, domains, news and other messages. Emails about signing in, such as password resets, are never pushed.
Staff phones get a notice for new orders, new tickets and ticket replies, payments, new clients, cancellation requests and failed module actions, when their role may see that kind. Ticket notices go to the same staff as the ticket emails: the staff member the ticket is assigned to, else the department's staff, and staff watching the ticket. Each staff phone chooses the kinds it wants too.
Notices are sent by the cron job (the "jobs" task, every minute), so pages never wait for Firebase. A phone Firebase no longer knows (the app was removed) stops getting notices. Notices older than 30 days are removed from the log.
The app's connection (for developers)#
The app talks to CoreInto at /api/app/v1/ACTION (or /api/index.php?app=1&action=ACTION where short addresses are not used). Signed-in calls send Authorization: Bearer <access token>. Parameters are sent as JSON; actions that change something use POST. Every answer is JSON: {"result":"success", ...}, or {"result":"error","message":"...","code":"..."} with a matching HTTP status. Form errors also carry fields (field name and what is wrong with it). The code tells the app what to do:
| code | Meaning |
|---|---|
| token_expired | Refresh the tokens with auth.refresh and try again |
| signed_out | Show the sign-in screen |
| wrong_password, wrong_code | Show the message; the person tries again |
| choose_account | The user has several accounts: ask which one (accounts.list, accounts.switch) |
| no_permission | The account owner did not allow this |
| two_step_setup, password_change | The person must finish this on the website first |
| fields | The form has errors (see fields) |
| Action | Who | What it does |
|---|---|---|
| app.config | anyone | Name, colours, logo, what the app may offer, the sign-up fields and countries |
| auth.login | anyone | kind (client or staff), email or username, password, device (name, platform, app_version, language). Answers with tokens, or with two_step and a ticket |
| auth.code | anyone | ticket and code: the two-step code (or a recovery code) |
| auth.refresh | anyone | refresh: answers with new tokens |
| auth.register | anyone | A new client account: the profile fields, password, tos, marketing, custom fields as cf_ID |
| auth.password_reset | anyone | email: sends the reset link (same answer whether the address is known or not) |
| auth.logout, me | signed in | Sign out; who is signed in |
| device.update, device.list, device.remove | signed in | push_token, push_off (kinds not wanted), name, language; the person's phones; sign one out |
| store.groups, store.product | anyone | Product groups with plans and prices; one product with terms, options and add-ons |
| store.quote | anyone | items (products and domains), promo, country: lines, tax, totals, errors and payment methods |
| domains.check | anyone | name: whether it can be registered here, with prices |
| site.pages, site.page | anyone | The website's pages as blocks the app draws, with plans and prices filled in |
| news.list, news.get, kb.list, kb.get | anyone | Announcements and the knowledgebase |
| accounts.list, accounts.switch | client | The user's accounts; work in another |
| client.dashboard | client | Counts and short lists of services, domains, invoices and tickets |
| services.list, services.get | client | Services with options, add-ons and licences |
| domains.list, domains.get | client | Domains |
| invoices.list, invoices.get, invoices.pay | client | Invoices with lines, taxes and payments; a link to pay on the website |
| tickets.list, tickets.get, tickets.open, tickets.reply, tickets.close, tickets.departments, tickets.attachment | client | Tickets; files go as base64 (files: [{"name":"...","data":"..."}]) |
| account.get, account.update | client | The account's details |
| store.order | client | Places the order (items, promo, gateway, tos, notes); answers with a link to pay when there is something to pay |
| portal.link | client | path: a one-time link that opens a client area page signed in |
| page | signed in | Any page of the admin area (staff) or the client area (clients): route, method (GET or POST), fields (name and value pairs in page order), files (field, name, data in base64), cookies (as the last answer gave them), menu (true: also the main menus). Answers with screen (title, nodes, sheets, menu, nav), file (name, type, data), open (an address for the browser) or sign_out, and with route, status and cookies |
| staff.dashboard | staff | Pending orders, tickets waiting for staff, unpaid and overdue invoices, clients, and income (each only when the role allows it) |
| staff.orders.list, staff.orders.get, staff.orders.accept, staff.orders.cancel | staff | Orders; accept (with welcome emails and set-up on servers) or cancel (fraud: true marks it as fraud) |
| staff.clients.list, staff.clients.get | staff | Search clients; one client with services, domains, invoices and tickets |
| staff.services.get, staff.services.command | staff | A service; create, suspend, unsuspend, terminate or change package on its server |
| staff.domains.get | staff | A domain |
| staff.invoices.list, staff.invoices.get, staff.invoices.add_payment | staff | Invoices; record a payment (amount, gateway, transaction_id) |
| staff.tickets.list, staff.tickets.get, staff.tickets.reply, staff.tickets.update | staff | Tickets of the staff member's departments; reply (or a private note), change status, priority, department or who handles it |
| website.pages, website.page, website.save, website.publish, website.upload | staff | The website: pages and posts with the kinds of block and their fields, save the working copy (publish: true to put it on the site), publish or take off, upload an image |
Each staff action needs the same permission as the matching admin page: for example orders.manage to accept orders, invoices.manage to record payments, services.module for server commands, website for the website. HTML blocks are shown and changed only for staff with the website settings permission; for others they arrive as {"type":"html","locked":true,"index":N} and are kept as they were when the page is saved.
Amounts come as {"value": "1500.00", "text": "Rs 1,500"}; times as ISO 8601 in UTC, dates as YYYY-MM-DD.
Something missing? Ask in the community or open a ticket.