Also abbreaviated as swis-api
or swapi
, is an in-memory database experimental project. It suits like a huge structured database with very low latency. The project is written in Go (1.20).
|
|
history
It all started in circa 2009 with a project called Šakal (‘shah-kahl’; abbreaviation of two authors’ names), a simple draft for a content management system (CMS) written in PHP language, with a very simple CSS layout. Years later, the project was renamed to sakalWeb
as it had been powering up some of the other projects (as their engines) at a time.
versioning
Below listing some of the projects’ names and concurrently used sakalWeb
versions.
sakalWeb version | project’s name(s) |
---|---|
0.5.6 | Kasanet Module, KasaServerSchool |
2.0.*–2.5.* | Rosolcity, diary, sys.rouring.net |
4.0.* | kyrspa-web |
4.23 | hellnut project |
4.7.* | litter nanoblogger |
4.9.* | old sakalWeb IS portal |
5.3.* | current swapi instance |
implementation
The backend itself is written in Go v1.20. A single binary executable is then exported from a staging docker image to a clean alpine image, resulting in docker image size being about 20 MB (alpine image itself is about 5.5 MB in size). Single built binary is about 11 MB (x86_64 arch).
The system is build on Gin-Gonic framework, making it both fast, and highly reliable from the beginning. As far as the system model is concerned, the system is modular — core engine is just gin and its middlewares with other modules exposing their routes, controllers and models to the core. The core then links each route via gin.RouterGroup
to the main HTTP server handler.
As the name suggets, CRUD (Create, Read, Update, Delete) model is implemented for each module making it truly RESTful (mostly).
data storage
Data are virtually stored in data structures and models’ vars (arrays of structures) — in the runtime memory. After (re)start, the system is flushed clean, making it mandatory for data to be imported afterwards… At the moment, we do keep data backups as JSON files, being available to import using
API calls.
The largest import we have fullfilled so far took swapi
about 1.5 ms (miliseconds) to load! (The file had about 40 kB in size, carrying more than 350 lines of JSON objects.)
development
For our development, we use swapi
instances being spined off locally, allowing one to access modules and their routes immediately. As SCM we use GitHub with an automatic (on-push) CI/CD pipelines being run/executed in our own infrastructure using Github Actions Runners.
modules
The IS has its core in handling all routes, and the middleware such as Gin logger, panic recovery, and custom auth middleware (more below).
alvax
alvax is our internal Telegram bot for savla.dev folks to entertain. This module serves alvax’s command list for it to fetch, decode and serve itself.
auth
This module has no routes, but it serves as custom middleware in terms of AAA (at least the first A’s as in Authentication and Authorization). Every request goes through this middleware, being checked for X-Auth-Token
header contents. If empty, HTTP 401 Unauthorized code and message are returned. The same comes when the token is invalid, or the user is not activated. Only when one enters a valid token, middleware pushes the app context to the next service.
For further database access, explicit list (ACL) of modules has to be set for each user. Default methods GET
and OPTIONS
are enabled by default on every module. Methods PUT
, PUSH
, UPDATE
can be used with power
Role. Roles serve as the other layer of authorization. Only admin
roles can use DELETE
method over such module.
example
User wants to list/read/get contents of the depots
loaded module. One has to fulfill all the listed items:
- a record (account) in
users
module - activated account
- valid SHA256 token
- ACL with such module name assigned
- no special Role is required for this HTTP method
business
Business module stores all information about customers (business-to-business!) in terms of name, VAT ID, addresses and contact. These are usualy used when generating invoices for example.
depot
Depot(s) module is meant to be “an interface” for storing storage inforamtion like Item name, description and location. This idea comes from the old swis. One can see the information when looking for a particular item (like old notebook), just to find out that that object is not in his area at the time (they left it elsewhere).
dish
This module serves socket lists to savla-dish instances. Ususally, a dish can request “its sockets” by dialing
|
|
API call, Only unmuted and matching sockets are then exported and returned as JSON list to dish to load the stream.
docs
This module is a shadow one, because it does not really serves anything directly, it just acts like “a storage” for swagger exported documentation files. Swagger UI then acts like a frontend for those data — files are linked to container and read-only’d.
finance
Financial accounts module stores all internal account info, bank codes etc. It however does not store any explicit bank card details and so on. Moreover, financial records could be included, so some sort of remote Bank API is to be implemented and used to sync the records themselves.
groups
As the name suggests, this module is to be used to moderate groups within the organization.
infra
This module stores information about infrastructure as a whole. It includes models for domains, network, and nodes logic. One is being able to link them together and to construct a diagram out of given JSON.
Fig. 1: Grafana panel with a simple infrastructure overview using Diagram panel.
news
News module have two so-called submodules: news sources and the actual news, in form of a model to link with RSS feed stream input. The first submodule gives the information of one’s news sources — what one wants to fetch, which RSS sources to use. The second one allows one to execute an RSS fetching mechanism allowing swapi to parse and return given news as JSON.
sources example output
|
|
|
|
news (RSS) feed (parsed on other fronted)
Example of parsed swapi
JSON output (CZ news, screenshot):
Fig. 2: News module formatted output example.
projects
Project(s) module is to serve list(s) of local projects being worked on in such organization. It includes project’s name, its repository, URL, status of publishment, project leader and so on.
swife
swife
stands for sakalWeb IS frontend(s). This module stores raw page data as base64 strings, to fetch them by forntend engines, and to easily edit them on the backend. Note that this is only a temporary module.
users
The main module of them all — user management system, unified interface for adding, fetching, editing and deleting user records. It also stores user’s access tokens needed to be allowed into swapi
. When there are no users loaded, the root token (generated at start/or loaded from the local environment at start — required) has to be used for initial setups, and for data imports (restores).
clients
As swapi
acts like a JSON API, any frontend app can be built above the data base backend. For this purposes, we use a simple desktop-ready frontend built on SB Admin 2 and Django framework (called swjango
); and a very simple mobile-ready PWA called swAPP. Both applications run on the internal network only, hence the VPN connection is a must there.
- bbs-go (simple telnet BBS experiment in Go)
- savla-gw (API gateway experiment in Go)
- swapp (mobile-webapp-first UI, PWA in Go)
- swife-xp (XP.css powered fronted in Vue and Node.js)
- swjango (desktop webapp, Django)