Mobile app connection
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, in…
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.
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.