Package: aether.sdk
Aether Django SDK LibraryThis library contains the most common features used by the different Aether django modules.Table of contentsRequirementsInstallationDistributionTestsUsageQuick startEnvironment variablesManagement commandsRequirementsThis library requiresPython 3.6and above.Python libraries:djangoAs web framework. (Above 2.2)django-cors-headersfor handling the server headers required for Cross-Origin Resource Sharing (CORS).django-debug-toolbarA configurable set of panels that display various debug information about the current request/response.django_postgrespool2Postgres Connection Pooling for Django, powered by SQLAlchemy.django-prometheusTo monitor the application with Prometheus.io.django-silkA live profiling and inspection tool for the Django framework.django-uwsgiDjango related examples/tricks/modules for uWSGI.djangorestframeworkA powerful and flexible toolkit for building Web APIs. (Above 3.8)drf-dynamic-fieldsDynamically select only a subset of fields per DRF resource,
either using a whitelist or a blacklist.markdownThis is a Python implementation of John Gruber's Markdown.psycopg2-binaryPython-PostgreSQL Database Adapter.pygmentsA syntax highlighting package written in Python.python-json-loggerA python library adding a json log formatter.requestsHTTP for Humans.uwsgiThe Python Web Server Gateway Interface.Extra dependencies (based on settings):cachedjango-cacheopsA slick ORM cache with automatic granular event-driven invalidation.django-redisFull featured redis cache backend for Django.schedulerdjango-rqA simple app that provides django integration for RQ (Redis Queue).redisThe Python interface to the Redis key-value store.rqSimple, lightweight, library for creating background jobs, and processing them.rq-schedulerSmall package that adds job scheduling capabilities to RQ.serversentry-sdkPython client for Sentry.storagedjango-minio-storageA django storage driver for minio.django-storagesA collection of custom storage backends for Django.
Enabled forboto3andgoogle-cloud-storage.django-cleanupAutomatically deletes old file for FileField and ImageField.
It also deletes files on models instance deletion.testcoverageA tool for measuring code coverage of Python programs.flake8Tool For Style Guide Enforcement.flake8-quotesFlake8 extension for checking quotes in python.tblibTraceback serialization library.webpackdjango-webpack-loaderTransparently use webpack with django.Return to TOCInstallation# standalonepip3installaether.sdk# with extra dependenciespip3installaether.sdk[scheduler,server,storage,test,webpack]Return to TOCDistributionHow to create the package distributionExecute the following command:python3setup.pybdist_wheelor./scripts/build.shReturn to TOCTestsHow to test the libraryFirst install dependencies (execute it only once):./scripts/install.shAfter that execute the following command:source./venv/bin/activate
./scripts/test.shThe filescripts/test.inicontains the environment variables used in the tests.Return to TOCUsageQuick startAdd this snippet in thesettings.pyfile to have the build the django application
settings based on the environment variables.# if it's an aether modulefromaether.sdk.conf.settings_aetherimport*# noqa# if it's an external aether productfromaether.sdk.conf.settingsimport*# noqa# continue with the application specific settings# and re-import the settings variables you need to reuse# from aether.sdk.conf.settings[_aether] import WHATEVER YOU NEED TO...Add this snippet in theurls.pyfile to generate defaulturlpatternsbased on the application settings.fromaether.sdk.conf.urlsimportgenerate_urlpatternsurlpatterns=generate_urlpatterns(token=[True|False],app=[# include here the application/module specific URLs])Default URLs included:The health endpoints:the/healthURL. Always responds with200status and an empty content.
Usesaether.sdk.health.views.healthview.the/check-dbURL. Responds with500status if the database is not available.
Usesaether.sdk.health.views.check_dbview.the/check-appURL. Responds with current application version and more.
Usesaether.sdk.health.views.check_appview.the/adminsection URLs (ADMIN_URLsetting).the/admin/~prometheus/metricsURL. Displays the raw monitoring data.the/admin/~uwsgi/URL. If uWSGI is running displays the server uWSGI settings.the/admin/~purge-cacheURL. Purges django cache.
Available if django cache is enabled.the/admin/~realmsURL. Returns the list of realms with linked data.
TheDEFAULT_REALMis always included even if it has no linked data.
If MULTITENANCY is not enabled returns the fake realmsettings.NO_MULTITENANCY_REALM.the/accountsURLs (AUTH_URLsetting), checks if the REST Framework ones,
using the templates indicated inLOGIN_TEMPLATEandLOGGED_OUT_TEMPLATEsettings, or the Keycloak ones.Based on the arguments:token: indicates if the application should be able to create and return
user tokens via POST request and activates the URL.
The URL endpoint is indicated in theTOKEN_URLsetting.
Defaults to/token.
Usesaether.sdk.auth.views.auth_tokenview.If the current user is not an admin user then creates and returns the authorization
token for himself, otherwise creates a token for theusernamecontained
in the request payload.Based on the application settings:IfDEBUGis enabled:thedebug toolbarURLs.IfPROFILING_ENABLEDis set:the/admin/~silk/URL. Displays the profiling data.IfEXTERNAL_APPSis set and valid:the/check-app/{name}URL. Checks if the external application is reachable
with the URL and token indicated in the settings.
Usesaether.sdk.health.views.check_externalview.
For/check-app/app-namechecks if an external application serverAPP_NAMEis reachable with the provided environment variablesAPP_NAME_URLandAPP_NAME_TOKEN.Possible responses:500-Always Look on the Bright Side of Life!!!✘200-Brought to you by eHealth Africa - good tech for hard places✔the/check-tokensURL. Redirects to the user tokens page if any of the
external applications is not reachable with the URL indicated in the settings
and the linked current user token.
Usesaether.sdk.health.views.healthview and theaether.sdk.auth.apptoken.decorators.app_token_requireddecorator.the/check-user-tokensURL (CHECK_TOKEN_URLsetting). Displays the external
application tokens for the current user.
Usesaether.sdk.auth.apptoken.views.user_app_token_viewview and
the templateeha/tokens.html.IfAPP_URLsetting is different than/, then the URL pattern for all
endpoints is like:/{app-url}/{endpoint}.IfGATEWAY_ENABLEDisTrue:The application endpoints are also reachable with a prefixed regular expresion
that includes the realm value and the the gateway id for this application.The URL pattern is like:/{app-url}/{current-realm}/{gateway-id}/{endpoint}.The authorization and admin endpoints never depend on any realm so the URLs
use always the public realm.Something like:/{app-url}/{public-realm}/{gateway-id}/accountsand/{app-url}/{public-realm}/{gateway-id}/admin.Return to TOCEnvironment variablesThe following environment variables are used to build the application django settings.
Take a look at thedjango settings.Take a look ataether/sdk/conf.settings.pyfile to check the list of all
the expected environment variables.App specificAPP_LINK:https://www.ehealthafrica.org. The link that appears in the DRF web pages.APP_NAME:eha. The application name displayed in the web pages.APP_NAME_HTML: The HTML expression for the application name.
Defaults to the application name.APP_MODULE: The django module that refers to this application to be included
in theINSTALLED_APPSlist.APP_FAVICON:eha/images/eHA-icon.svg. The application favicon.APP_LOGO:eha/images/eHA-icon.svg. The application logo.APP_URL:/. The application URL in the server.
If host ishttp://my-serverand the application URL is/my-module,
the application enpoints will be accessible athttp://my-server/my-module/{endpoint}.Return to TOCGenericDEBUG: Enables debug mode. Isfalseif unset or set to empty string,
anything else is consideredtrue.TESTING: Indicates if the application executes under test conditions.
Isfalseif unset or set to empty string, anything else is consideredtrue.LOGGING_FORMATTER:json. The application messages format.
Possible values:verboseorjson.LOGGING_LEVEL:info. Logging level for application messages.https://docs.python.org/3/library/logging.html#levelsSENTRY_DSN: Sentry DSN (error reporting tool).https://docs.sentry.ioPRETTIFIED_CUTOFF:10000. Indicates the maximum length of a prettified JSON value.
See:aether.sdk.utils.json_prettified(value, indent=2)method.DjangoDJANGO_SECRET_KEY: Django secret key for this installation (mandatory).https://docs.djangoproject.com/en/3.2/ref/settings/#std:setting-SECRET_KEYLANGUAGE_CODE:en-us. Language code for this installation.https://docs.djangoproject.com/en/3.2/ref/settings/#language-codeTIME_ZONE:UTC. Time zone for this installation.https://docs.djangoproject.com/en/3.2/ref/settings/#std:setting-TIME_ZONESTATIC_URL:/static/. Provides a base URL for the static assets to be served from.STATIC_ROOT:/var/www/static/. Provides the local folder for the static assets to be served from.Django Rest Framework (DRF)PAGE_SIZE:10. Default page size for the REST API.MAX_PAGE_SIZE:5000. Maximum page size for the REST API.HTML_SELECT_CUTOFF:100. Options size for the REST API Form select fields.DatabaseMore information inhttps://docs.djangoproject.com/en/3.2/ref/settings/#databasesPGHOST: Postgres host name (mandatory).PGPORT: Postgres port (mandatory).DB_NAME: Postgres database name (mandatory).PGUSER: Postgres user (mandatory).PGPASSWORD: Postgres user password (mandatory).DB_CONN_MAX_AGE: The lifetime of a database connection, in seconds.
Defaults to0. Value0means non persistent connections butNonemeans persistent.ENABLE_CONNECTION_POOL: Used to indicate if a connection pooler is enabled.
Isfalseif unset or set to empty string, anything else is consideredtrue.
The expected pooler ispgbouncerthat might run
as an external service.DB_POOL_INTERNAL: Used to indicate that an internal connection pooler is used.
Isfalseif unset or set to empty string, anything else is consideredtrue.SQLAlchemylibrary is used to handle internally the connections.
Optional environment variables:DB_POOL_INITIAL_SIZE:20, the initial number of open connections.DB_POOL_MAX_OVERFLOW:80, the number of connections that can be created.DB_POOL_RECYCLE_SECONDS:3600(1 hour), the maximum age, in seconds,
for a connection before discarding it.DB_POOL_USE_LIFO: Used to indicate that an internal connection pooler uses LIFO.
Isfalseif unset or set to empty string, anything else is consideredtrue.Using FIFO vs. LIFOEndpointsADMIN_URL:admin. Admin section endpoint.AUTH_URL:accounts. Authorization endpoints (login and logout URLs)LOGIN_URL,/{AUTH_URL}/login. Login URL.TOKEN_URL:token. Get authorization token endpoint.CHECK_TOKEN_URL:check-user-tokens. Check authorization tokens endpoint.TemplatesLOGIN_TEMPLATE:eha/login.html. Template used in the login page.LOGGED_OUT_TEMPLATE:eha/logged_out.html. Template used in the logged out page.DRF_API_RENDERER_TEMPLATE:eha/api.html. Template used in the DRF browsable
API renderer page.DRF_ADMIN_RENDERER_TEMPLATE:eha/admin.html. Template used in the DRF API
admin renderer page.KEYCLOAK_TEMPLATE:eha/login_realm.html. Template used in the login step
to get the realm and redirect to keycloak login page.KEYCLOAK_BEHIND_TEMPLATE:eha/login_keycloak.html. Template used in the
login page when keycloak is enabled behind the scenes.ProfilingPROFILING_ENABLED: Used to indicate if the profiling tool (Silk) is enabled.
Isfalseif unset or set to empty string, anything else is consideredtrue.SILKY_PYTHON_PROFILER. Used to indicate if uses Python's built-in cProfile profiler.
Isfalseif unset or set to empty string, anything else is consideredtrue.SILKY_PYTHON_PROFILER_BINARY. Used to indicate if generates a binary.proffile.
Isfalseif unset or set to empty string, anything else is consideredtrue.SILKY_PYTHON_PROFILER_RESULT_PATH:/tmp/. Local directory where the*.proffiles are stored.SILKY_META. To see what effect Silk is having on the request/response time.
Isfalseif unset or set to empty string, anything else is consideredtrue.SILKY_MAX_REQUEST_BODY_SIZE:-1. Silk saves the request body if its size (in bytes)
is less than the indicated value. Any value less than0means no limit.SILKY_MAX_RESPONSE_BODY_SIZE:-1. Silk saves the response body if its size (in bytes)
is less than the indicated value. Any value less than0means no limit.SILKY_INTERCEPT_PERCENT:100. Indicates the percentage of requests that are recorded.SILKY_MAX_RECORDED_REQUESTS:10000. The number of request/responses stored.SILKY_MAX_RECORDED_REQUESTS_CHECK_PERCENT:10.The/admin/~silk/URL displays the profiling data (accessible to admin users only).See more inhttps://github.com/jazzband/django-silkReturn to TOCFile Storage SystemSTORAGE_REQUIRED: Used to indicate if the file storage system is required.
Isfalseif unset or set to empty string, anything else is consideredtrue.DJANGO_STORAGE_BACKEND: Used to specify aDefault file storage system.
Available options:minio,s3,gcs.COLLECT_STATIC_FILES_ON_STORAGE: Used to indicate if static files should be collected on the specified cloud-based storage service (minio,s3orgcs)
Isfalseif unset or set to empty string, anything else is consideredtrue.CDN_URL: Used to indicate the public cdn base url to access webpack static files.More information inhttps://django-storages.readthedocs.io/en/latest/index.htmlMinio (DJANGO_STORAGE_BACKEND=minio)BUCKET_NAME: Name of the bucket that will act as MEDIA folder (mandatory).STATIC_BUCKET_NAME: Name of the bucket to collect static files (mandatoryifCOLLECT_STATIC_FILES_ON_STORAGEis set totrue)MINIO_STORAGE_ACCESS_KEY: Minio Access Key.MINIO_STORAGE_SECRET_KEY: Minio Secret Access Key.MINIO_STORAGE_ENDPOINT: Minio server URL endpoint (without scheme).MINIO_STORAGE_USE_HTTPS: Whether to use TLS or not. Determines the scheme.MINIO_STORAGE_AUTO_CREATE_MEDIA_BUCKET: Whether to create the bucket if it does not already exist.MINIO_STORAGE_MEDIA_USE_PRESIGNED: Determines if the media file URLs should be pre-signed.See more inhttps://django-minio-storage.readthedocs.io/en/latest/usageS3 (DJANGO_STORAGE_BACKEND=s3)BUCKET_NAME: Name of the bucket to use on s3 (mandatory). Must be unique on s3.STATIC_BUCKET_NAME: Name of the bucket to collect static files (mandatoryifCOLLECT_STATIC_FILES_ON_STORAGEis set totrue)AWS_ACCESS_KEY_ID: AWS Access Key to your s3 account.AWS_SECRET_ACCESS_KEY: AWS Secret Access Key to your s3 account.Google Cloud Storage (DJANGO_STORAGE_BACKEND=gcs)BUCKET_NAME: Name of the bucket to use on gcs (mandatory).
Create bucket usingGoogle Cloud Consoleand set appropriate permissions.STATIC_BUCKET_NAME: Name of the bucket to collect static files (mandatoryifCOLLECT_STATIC_FILES_ON_STORAGEis set totrue)GS_ACCESS_KEY_ID: Google Cloud Access Key.GS_SECRET_ACCESS_KEY: Google Cloud Secret Access Key.How to create Access Keys on Google Cloud StorageReturn to TOCSchedulerSCHEDULER_REQUIRED: Used to indicate if the RQ platform is required.
Isfalseif unset or set to empty string, anything else is consideredtrue.REDIS_HOST: The redis host name (mandatory).REDIS_PORT: The redis port (mandatory).REDIS_DB: The redis database. Defaults to0.REDIS_PASSWORD: The redis password.Return to TOCCacheDJANGO_USE_CACHE: Used to indicate if the cache is enabled.
Isfalseif unset or set to empty string, anything else is consideredtrue.DJANGO_CACHE_TIMEOUT: Cache timeout in seconds. Defaults to300(5 minutes).REDIS_HOST: The redis host name (mandatory).REDIS_PORT: The redis port (mandatory).REDIS_PASSWORD: The redis password.REDIS_DB_CACHEOPS: The django ORM Redis database. Defaults to1.REDIS_DJANGO_CACHE: Used to indicated if the django cache is handled by Redis.
Isfalseif unset or set to empty string, anything else is consideredtrue.REDIS_DB_DJANGO: The django platform Redis database. Defaults to2.REDIS_SESSION_CACHE: Used to indicated if the django session cache is handled by Redis.
Isfalseif unset or set to empty string, anything else is consideredtrue.REDIS_DB_SESSION: The django session Redis database. Defaults to3.See more indjango-cacheopsReturn to TOCSecurityDJANGO_ALLOWED_HOSTS:*. SetALLOWED_HOSTSDjango setting.https://docs.djangoproject.com/en/3.2/ref/settings/#allowed-hostsCSRF_COOKIE_DOMAIN:.ehealthafrica.org. SetCSRF_COOKIE_DOMAINDjango setting.https://docs.djangoproject.com/en/3.2/ref/settings/#csrf-cookie-domainCSRF_TRUSTED_ORIGINS. SetCSRF_TRUSTED_ORIGINSDjango setting.https://docs.djangoproject.com/en/3.2/ref/settings/#csrf-trusted-originsDJANGO_USE_X_FORWARDED_HOST:False. SetUSE_X_FORWARDED_HOSTDjango setting.https://docs.djangoproject.com/en/3.2/ref/settings/#use-x-forwarded-hostDJANGO_USE_X_FORWARDED_PORT:False. SetUSE_X_FORWARDED_PORTDjango setting.https://docs.djangoproject.com/en/3.2/ref/settings/#use-x-forwarded-portDJANGO_HTTP_X_FORWARDED_PROTO:False. If present setsSECURE_PROXY_SSL_HEADERDjango setting to('HTTP_X_FORWARDED_PROTO', 'https').https://docs.djangoproject.com/en/3.2/ref/settings/#std:setting-SECURE_PROXY_SSL_HEADERReturn to TOCWebpackWEBPACK_REQUIRED: Used to indicate if the assets are served via webpack.
Isfalseif unset or set to empty string, anything else is consideredtrue.WEBPACK_STATS_FILE:{STATIC_ROOT}webpack-stats.json, indicates the file path
that webpack uses to serve the different assets.Return to TOCUsers & AuthenticationStandardThe standard options are to log in via token authentication, via basic authentication
or via the standard django authentication.Return to TOCKeycloak ServerSet theKEYCLOAK_SERVER_URLandKEYCLOAK_CLIENT_IDenvironment variables if
you want to use Keycloak as authentication server.KEYCLOAK_CLIENT_ID(defaults toeha) is the public client that allows
the aether module to authenticate using the Keycloak REST API.
This client id must be added to all the realms used by the aether module.
TheKEYCLOAK_SERVER_URLmust include all the path until the realm is indicated,
usually until/auth/realms.There are two ways of setting up keycloak:a) In this case the authentication process happens in the server side without
any further user interaction.# .env fileKEYCLOAK_SERVER_URL=http://my-keycloak-server/auth/realmsKEYCLOAK_BEHIND_SCENES=trueb) In this case the user is redirected to the keycloak server to finish the
sign in step.# .env fileKEYCLOAK_SERVER_URL=http://my-keycloak-server/auth/realmsKEYCLOAK_BEHIND_SCENES=Read more inKeycloak.Note: Multi-tenancy is automatically enabled if the authentication server
is keycloak.Return to TOCGateway AuthenticationSetGATEWAY_SERVICE_IDto enable gateway authentication with keycloak.
This means that the authentication is handled by a third party system
(likeKong) that includes in each request the JSON Web
Token (JWT) in theGATEWAY_HEADER_TOKENheader (defaults toX-Oauth-Token).
TheGATEWAY_SERVICE_IDindicates the gateway service.In this case the application URLs can be reached in several ways:Trying to access the health endpoint/health:http://my-server/healthusing the internal URLhttp://my-gateway-server/my-realm/my-module/healthusing the gateway URL
(beingmy-moduletheGATEWAY_SERVICE_IDvalue)For those endpoints that don't depend on the realm and must also be available
"unprotected" we need one more environment variable:GATEWAY_PUBLIC_REALM:-This represents the fake realm that is not protected
by the gateway server. In this case the authentication is handled by the other
available options, i.e., basic, token...The authorization and admin endpoints never depend on any realm so the final URLs
use always the public realm.http://my-gateway-server/-/my-module/accounts/http://my-gateway-server/-/my-module/admin/Return to TOCMulti-tenancyThe technical implementation is explained inMulti-tenancy README.
Follow the instructions to enable multi-tenancy option in your application.MULTITENANCY, Enables or disables the feature, isfalseif unset or set
to empty string, anything else is consideredtrue.DEFAULT_REALM,ehaThe default realm for artefacts created
while multi-tenancy was not enabled.REALM_COOKIE,eha-realmThe name of the cookie that keeps the current
tenant id in the request headers.Return to TOCExternal applicationsEXTERNAL_APPS: comma separated list with the external apps that the
current instance must be able to connect to and interact with.
For each value there should be the correspondent environment variables:<<EXTERNAL_APP>>_URL: External application server URL (mandatory).<<EXTERNAL_APP>>_TOKEN: External application authorization token (mandatory).<<EXTERNAL_APP>>_URL_TEST: External application server URL used in tests.
Defaults to the external application server URL.<<EXTERNAL_APP>>_TOKEN_TEST: External application authorization token used in tests.
Defaults to the external application authorization token.If theEXTERNAL_APPSequals toapp-1,mod-ule-2,pro-d-uct-3the expected and
mandatory environment variables are:APP_1_URL,APP_1_TOKENMOD_ULE_2_URL,MOD_ULE_2_TOKENPRO_D_UCT_3_URL,PRO_D_UCT_3_TOKENIf the Gateway authentication is enabled instead of using the given token the
application will use the providedGATEWAY_HEADER_TOKENvalue to communicate
with the external application when possible.Return to TOCManagement commandsTo check if an URL is reachable via command line# arguments:#      -u | --url        required#      -t | --token      optional./manage.pycheck_url-u=http://my-server/url/to/checkTo create "admin" users via command line# arguments:#      -u | --username   optional (defaults to "admin")#      -p | --password   required#      -e | --email      optional#      -t | --token      optional./manage.pysetup_admin-u=admin-p=password-t=auth_tokenTo create "standard" users via command line# arguments:#      -u | --username   required#      -p | --password   required#      -e | --realm      optional (required if MULTITENANCY enabled)#      -t | --token      optional./manage.pycreate_user-u=user-p=password-t=auth_tokenTo publish webpack assets to CDN via command line# arguments:#      -u | --cdn-url       required#      -w | --webpack-dir   required#      -s | --storage-path  optional./manage.pycdn_publish\-u=http://cdn-server/path/to/assets\-w=path/to/assets/bundles\-s=static/content/by/webpack/Return to TOC