Core Architecture
SOGo6-server is a RESTful API using the Flask framework.
SOGo 6 web application code is under the package app
Start
-
app/run.py: init and check SOGo state, set the index endpoint, has the main function to create the Flask app
-
app/init.py: creates the Flask app, sets the swagger, sets global before_request and after_request.
-
app/service.py: contains the global cache object (and any future global service)
Core
The goal of SOGo 6 is to be modular to easily get new features or services. As such, the code is mainly separated between 4 categories:
-
API: defines the endpoints, the request or response schema.
-
Manager: requests external services (database, dovecot, ldap…)
-
Module: Uses the manager to read or write data. Contains the main logic of any operation
-
Interface: Link between API and Module; Calls the right module, formats the answer and status code for the API. Also catches exceptions.
Rules
-
An API can only import one Interface
-
One API implies one dedicated Interface
-
Interface must return ready-to-use response (meaning data + http status code)
-
Interface can only import the modules it needs, can be one or several.
-
ONLY Interface catches RequestException.
-
Interface uses method create_api_base_response to format response (app/utils/api/ApiBaseResponse.py)
-
Module dynamically imports the proper managers. It can import one or several managers if needed (ex: ldap and sql if two kinds of user sources)
-
Manager does not import anything except utils/config. Manager must do its best to catch external library exceptions and either raise SOGo exception or let the module/interface decide what to do
Structure
-
app/api: The files of kind API, they can only import from interface, utils and config.
-
app/auth: The files to handle authentication, token, session in cache and set the class User.
-
app/config: The files to define SOGo 6 configuration, both parameters and database structure. Also contains the methods for initialization.
-
app/interface: The files of kind Interface, they can only import modules, utils and config
-
app/manager: The files of kind Manager, they can only import utils and config
-
app/module: The files of kind Module, they can only import manager, utils and config
-
app/utils: The files that define methods, classes and constants used everywhere. Can never import something from app.
API
APIs are defined in path app/api/<version>/
SOGo 6 has two distinct APIs: one for the webmail called "user" and one for the admin UI "admin".
Admin API only has endpoints defined within app/api/<version>/admin/ All the others folders are for the user API.
Each API file must start by setting the blueprint for this api
from flask_smorest import Blueprint
blp = Blueprint("<name>", __name__, url_prefix="<url>")
-
<name> will be shown in the Swagger to regroup same endpoints together under
user#Mail Folder -
<url_prefix> is the url after /api/user/v1/<url_prefix>
Next step is to add a before_request to instantiate the interface
@blp.before_request
def init_mail_config() -> None:
"""
Initialize the mail interface and any other required configuration for the request.
Provide user_conf as either a single dict or a list of dicts (accounts).
Here we provide a list: index 0 = primary, index 1 = secondary.
"""
logger_api.debug("Calling before_request for ApiMailFolder")
process: ProcessSetting = g.process_settings
user_domain_settings: dict = g.user_domain_settings
user: User = g.user
interface_api = InterfaceApiMailFolder(
process_setting=process,
user_domain_settings=user_domain_settings,
user=user
)
g.inter = interface_api