This chapter is about the data storage concept used in AsTeRICS Grid, meaning where and how user configuration and application data is stored.
- Introduction
- Abstraction layers
- One database per user
- Authentication layer
- Inspecting locally saved data
Since AsTeRICS Grid is designed to work offline, all configuration and user data have to be accessible without internet connection. There are the following possibilities for providing a data storage for an offline web-application:
- Any external locally running storage service, e.g. any locally running database like MySQL or MariaDB. This possibility has the downside that users would have to install additional Software in order to use AsTeRICS Grid.
- LocalStorage, a browser internal storage which is capable to store key-value pairs of string values. However the amount of data is limited to about 5-10MB in many browsers which is often too little to store all grids in AsTeRICS Grid.
- IndexedDB, a browser internal storage for big amounts of structured data
AsTeRICS Grid uses LocalStorage for temporary data which should not synchronized with the cloud (e.g. hashed encryption password) and IndexedDB for the majority of configuration like e.g. data of stored grids. For online users all data that is stored in IndexedDB is synchronized with the cloud, for offline users (see Users) data is only stored locally on the device.
For accessing IndexedDB in a more comfortable manner and making synchronization with a remote CouchDB possible, the Javascript library PouchDB is used.
All Javascript modules regarding storage of data in AsTeRICS Grid can be found in the folder src/js/service/data. Figure 1 shows the relevant files and their relationships:
Figure 1: Concept of data storage layers
These are the responsibilities and functions of the different modules:
- dataService.js: provides access to data objects on an application based abstraction level; implements methods that make it possible to get and save the objects described in chapter Data model, e.g.
GridData
objects. - databaseService.js: implements CRUD methods for generic data model objects, methods for switching databases (users) and initializes databases with default data. This layer also does encryption and decryption of data using
convertServiceDb.js
. This level of abstraction is still quite independent of PouchDB or IndexedDB and theoretically could also use a different backend. - pouchDbService.js: performs queries and actions on a PouchDB instance actually accessing the IndexedDB or CouchDB databases. It also caches queries for performance optimizations and broadcasts events if updates from the remote database are recognized.
- pouchDBAdapter.js: manages which actual database should be used, a local PouchDB instance or a remote CouchDB. Also sets up synchronization between both.
- undoService.js: is used by
grid.js
in order to pass updates on grids todataService.js
while keeping track of changes and providing an undo and redo functionality - convertServiceDb.js: provides methods in order to convert objects used in the application to (encrypted) objects that should be saved to database and vice versa. If an object with an outdated data model version passes these methods, additional filter functions are inserted in order to upgrade the data model.
- encryptionService.js: provides methods for AES encryption and decryption and hasing of data objects and strings using the sjcl library
- localStorageService.js: accesses the browser internal LocalStorage for saving data like the last active user or hashed user passwords - in general data which should not be synchronized to cloud or aren't suitable for a user's database.
AsTeRICS Grid implements the idea of one database per user. For each user a new database is created. Offline users have an own IndexedDB database within the browser and online users have both a local IndexedDB database and an online CouchDB database which are kept in sync by replication features of the PouchDB library. Advantages of this approach are:
- access rights are easy to manage, each user can access their own database and nothing else
- it's easy to delete all data of a user, just delete their database
- replication and synchronizing is simple, the whole user database can be replicated on the local device
The one-database-per-user approach needs a layer for managing user accounts and the corresponding CouchDB user databases (only for online users). For AsTeRICS Grid the framework superlogin is used. It provides an API in order to register and login users and creates the corresponding CouchDB databases in the background. However the original superlogin project seems to be no longer maintained and therefore AsTeRICS Grid uses a more up-to-date fork of it.
The file superlogin/start.js starts superlogin and contains it's configuration (= server side). The file loginService.js is the client-side counterpart which uses the library superlogin-client in order to connect to and make use of the superlogin server.
In order to start superlogin a CouchDB instance must be running on the same machine and the correct CouchDB parameters have to be inserted in start.js:43. Then use npm run start-superlogin-dev
or npm run start-superlogin-prod
in order to start superlogin in development or production mode.
For examining the locally saved data of AsTeRICS Grid do the following (e.g. in Firefox or Chrome browser):
- open developer tools (
Ctrl + Shift + I
orright click -> Inspect
) - go to
Application
(Chrome) orWeb-Storage
(Firefox) - open
LocalStorage
orIndexedDB
to inspect the data saved in these storages