Skip to content
Snippets Groups Projects
Commit f7cfdba4 authored by Tom Teichler's avatar Tom Teichler :beers:
Browse files

Merge branch '158-documentation-needed-for-first-release' into 'master'

Documentation for beta release (Documentation for first release part 1)

See merge request !333
parents 26bef1a9 d470157e
No related branches found
No related tags found
1 merge request!333Documentation for beta release (Documentation for first release part 1)
Pipeline #12652 canceled
Showing
with 563 additions and 59 deletions
......@@ -390,17 +390,16 @@ class ExtensibleForm(ModelForm, metaclass=_ExtensibleFormMetaclass):
This mixin adds functionality which allows
- apps to add layout nodes to the layout used by django-material
Add layout nodes
================
:Add layout nodes:
```
from material import Fieldset
.. code-block:: python
from material import Fieldset
from aleksis.core.forms import ExampleForm
from aleksis.core.forms import ExampleForm
node = Fieldset("field_name")
ExampleForm.add_node_to_layout(node)
```
node = Fieldset("field_name")
ExampleForm.add_node_to_layout(node)
"""
......
......@@ -32,6 +32,8 @@ internationalisation = Section("internationalisation", verbose_name=_("Internati
@site_preferences_registry.register
class SiteTitle(StringPreference):
"""Title of the AlekSIS instance, e.g. schools display name."""
section = general
name = "title"
default = "AlekSIS"
......@@ -41,6 +43,8 @@ class SiteTitle(StringPreference):
@site_preferences_registry.register
class SiteDescription(StringPreference):
"""Site description, e.g. a slogan."""
section = general
name = "description"
default = "The Free School Information System"
......@@ -50,6 +54,8 @@ class SiteDescription(StringPreference):
@site_preferences_registry.register
class ColourPrimary(StringPreference):
"""Primary colour in AlekSIS frontend."""
section = theme
name = "primary"
default = "#0d5eaf"
......@@ -60,6 +66,8 @@ class ColourPrimary(StringPreference):
@site_preferences_registry.register
class ColourSecondary(StringPreference):
"""Secondary colour in AlekSIS frontend."""
section = theme
name = "secondary"
default = "#0d5eaf"
......@@ -70,6 +78,8 @@ class ColourSecondary(StringPreference):
@site_preferences_registry.register
class Logo(FilePreference):
"""Logo of your AlekSIS instance."""
section = theme
field_class = ImageField
name = "logo"
......@@ -78,6 +88,8 @@ class Logo(FilePreference):
@site_preferences_registry.register
class Favicon(FilePreference):
"""Favicon of your AlekSIS instance."""
section = theme
field_class = ImageField
name = "favicon"
......@@ -86,6 +98,8 @@ class Favicon(FilePreference):
@site_preferences_registry.register
class PWAIcon(FilePreference):
"""PWA-Icon of your AlekSIS instance."""
section = theme
field_class = ImageField
name = "pwa_icon"
......@@ -94,6 +108,8 @@ class PWAIcon(FilePreference):
@site_preferences_registry.register
class MailOutName(StringPreference):
"""Mail out name of your AlekSIS instance."""
section = mail
name = "name"
default = "AlekSIS"
......@@ -103,6 +119,8 @@ class MailOutName(StringPreference):
@site_preferences_registry.register
class MailOut(StringPreference):
"""Mail out address of your AlekSIS instance."""
section = mail
name = "address"
default = settings.DEFAULT_FROM_EMAIL
......@@ -113,6 +131,8 @@ class MailOut(StringPreference):
@site_preferences_registry.register
class PrivacyURL(StringPreference):
"""Link to privacy policy of your AlekSIS instance."""
section = footer
name = "privacy_url"
default = ""
......@@ -123,6 +143,8 @@ class PrivacyURL(StringPreference):
@site_preferences_registry.register
class ImprintURL(StringPreference):
"""Link to imprint of your AlekSIS instance."""
section = footer
name = "imprint_url"
default = ""
......@@ -133,6 +155,8 @@ class ImprintURL(StringPreference):
@person_preferences_registry.register
class AdressingNameFormat(ChoicePreference):
"""User preference for adressing name format."""
section = notification
name = "addressing_name_format"
default = "first_last"
......@@ -146,6 +170,8 @@ class AdressingNameFormat(ChoicePreference):
@person_preferences_registry.register
class NotificationChannels(ChoicePreference):
"""User preference for notification channels."""
# FIXME should be a MultipleChoicePreference
section = notification
name = "channels"
......@@ -157,6 +183,8 @@ class NotificationChannels(ChoicePreference):
@site_preferences_registry.register
class PrimaryGroupPattern(StringPreference):
"""Regular expression to match primary group."""
section = account
name = "primary_group_pattern"
default = ""
......@@ -166,6 +194,8 @@ class PrimaryGroupPattern(StringPreference):
@site_preferences_registry.register
class PrimaryGroupField(ChoicePreference):
"""Field on person to match primary group against."""
section = account
name = "primary_group_field"
default = "name"
......@@ -196,6 +226,8 @@ class AutoLinkPerson(BooleanPreference):
@site_preferences_registry.register
class SchoolName(StringPreference):
"""Display name of the school."""
section = school
name = "name"
default = ""
......@@ -205,6 +237,8 @@ class SchoolName(StringPreference):
@site_preferences_registry.register
class SchoolNameOfficial(StringPreference):
"""Official name of the school, e.g. as given by supervisory authority."""
section = school
name = "name_official"
default = ""
......@@ -212,6 +246,20 @@ class SchoolNameOfficial(StringPreference):
verbose_name = _("Official name of the school, e.g. as given by supervisory authority")
@site_preferences_registry.register
class AuthenticationBackends(MultipleChoicePreference):
"""Authentication backends of your AlekSIS instance."""
section = auth
name = "backends"
default = None
verbose_name = _("Enabled custom authentication backends")
field_attribute = {"initial": []}
def get_choices(self):
return [(b, b) for b in settings.CUSTOM_AUTHENTICATION_BACKENDS]
@site_preferences_registry.register
class AllowPasswordChange(BooleanPreference):
section = auth
......@@ -230,6 +278,8 @@ class SignupEnabled(BooleanPreference):
@site_preferences_registry.register
class AvailableLanguages(MultipleChoicePreference):
"""Available languages of your AlekSIS instance."""
section = internationalisation
name = "languages"
default = [code[0] for code in settings.LANGUAGES]
......
......@@ -9,7 +9,11 @@ register = template.Library()
def add_class_to_el(value: str, arg: str) -> str:
"""Add a CSS class to every occurence of an element type.
Example: {{ mymodel.myhtmlfield|add_class_to_el:"ul,browser-default"
:Example:
.. code-block::
{{ mymodel.myhtmlfield|add_class_to_el:"ul,browser-default" }}
"""
el, cls = arg.split(",")
soup = BeautifulSoup(value, "html.parser")
......
Install AlekSIS
===============
From PyPI
---------
In this section we will install AlekSIS with `uWSGI` and `nGINX` on Debian
bullseye.
Filesystem locations
~~~~~~~~~~~~~~~~~~~~
AlekSIS will need and use the following paths:
* `/etc/aleksis` for configuration files
* `/var/lib/aleksis/media` for file storage (Django media)
* `/var/backups/aleksis` for backups of database and media files
* `/usr/local/share/aleksis/static` for static files
* `/usr/local/share/aleksis/node_modules` for frontend dependencies
You can change any of the paths as you like.
Prerequisites
~~~~~~~~~~~~~
For an installation on a dedicated server, the following prerequisites are needed:
* Debian 11
* PostgreSQL
* Redis
* uWSGI
* nginx
* Python 3.9
* Some system dependencies to build Python modules and manage frontend files
* The aforementioned paths
Install system packages
~~~~~~~~~~~~~~~~~~~~~~~
Install some packages from the Debian package system.
.. code-block:: shell
apt install uwsgi \
uwsgi-plugin-python3 \
nginx-full \
python3 \
python3-dev \
libldap2-dev \
libsasl2-dev \
yarnpkg \
python3-virtualenv \
chromium \
redis-server \
postgresql
Create PostgreSQL user and database
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Generate a secure password for the database, then create the user and database.
.. code-block:: shell
sudo -u postgres createuser -D -P -R -S aleksis
sudo -u postgres createdb -E UTF-8 -O aleksis -T template0 -l C.UTF-8 aleksis
When asked, use the password generated above.
Create the directories for storage
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. code-block:: shell
mkdir -p /etc/aleksis \
/usr/share/aleksis/{static,node_modules} \
/var/lib/aleksis/media \
/var/backups/aleksis
chown -R www-data:www-data /var/lib/aleksis
Create AlekSIS configuration file
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
AlekSIS is configured in files in `/etc/aleksis`. Create a basic configuration file
for the environment defined above by opening `/etc/aleksis/aleksis.toml` with your
favourite text editor and adding the following configuration.
.. code-block:: toml
static = { root = "/usr/local/share/aleksis/static", url = "/static/" }
media = { root = "/var/lib/aleksis/media", url = "/media/" }
node_modules = { root = "/usr/local/share/aleksis/node_modules" }
secret_key = "SomeRandomValue"
[http]
allowed_hosts = ["aleksis.example.com"]
[database]
host = "localhost"
name = "aleksis"
username = "aleksis"
password = "password_generated_above"
[backup]
location = "/var/backups/aleksis"
[auth.superuser]
username = "admin"
password = "admin"
email = "root@localhost"
Install AlekSIS itself
~~~~~~~~~~~~~~~~~~~~~~
To install AlekSIS now, and run all post-install tasks, run the following commands.
They will pull the AlekSIS standard distribution from `PyPI`_ and install it to the
system-wide `dist-packages` of Python. Afterwards, it will download frontend dependencies
from `yarnpkg`, collect static files, and migrate the database to the final schema.
.. code-block:: shell
pip3 install aleksis
aleksis-admin yarn install
aleksis-admin collectstatic
aleksis-admin migrate
aleksis-admin createinitialrevisions
Configure uWSGI
~~~~~~~~~~~~~~~
uWSGI is an application server that will manage the server processes and requests.
It will also run the Celery broker and scheduler for you.
Configure a uWSGI app by opening `/etc/uwsgi/apps-available/aleksis.ini` in an
editor and inserting:
.. code-block:: toml
[uwsgi]
vhost = true
plugins = python3
master = true
enable-threads = true
processes = 20
wsgi-file = /usr/local/lib/python3/dist-packages/aleksis/core/wsgi.py
chdir = /var/lib/aleksis
lazy = true
lazy-apps = true
attach-daemon = celery -A aleksis.core worker --concurrency=4
attach-daemon = celery -A aleksis.core beat
Afterwards, enable the app using:
.. code-block:: shell
ln -s /etc/uwsgi/apps-available/aleksis.ini /etc/uwsgi/apps-enabled/aleksis.ini
service uwsgi restart
Configure the nginx webserver
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
First, you should get a TLS certificate, e.g. by using `Let's Encrypt`_.
Then, create a virtual host in nginx, by editing `/etc/nginx/sites-available/aleksis.example.com`.
.. code-block:: nginx
server {
listen 80;
listen [::]:80;
server_name aleksis.example.com;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
ssl_certificate /etc/letsencrypt/certs/aleksis.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/certs/aleksis.example.com/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/certs/aleksis.example.com/chain.pem;
server_name aleksis.example.com;
access_log /var/log/nginx/access.log;
location /static {
alias /usr/local/share/aleksis/static;
}
location / {
uwsgi_pass aleksis;
include uwsgi_params;
proxy_redirect off;
proxy_pass_header Authorization;
}
}
Enable the virtual host:
.. code-block:: shell
ln -s /etc/nginx/sites-available/aleksis.example.com /etc/nginx/sites-enabled/aleksis.example.com
service nginx restart
Finalisation
~~~~~~~~~~~~
Your AlekSIS installation should now be reachable and you can login with the administration
account configured above.
With Docker
-----------
AlekSIS can also be installed using Docker, either only AlekSIS itself, or the
full stack, including Redis, using docker-compose
Full stack using docker-compose
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
First, install Docker and docker-compose on your system. Also install git
to get the docker-compose file and image definition.
.. code-block:: shell
apt install docker.io docker-compose git
Now, clone the distribution repository, which contains the docker-compose
file.
.. code-block:: shell
git clone https://edugit.org/AlekSIS/official/AlekSIS
You should review the file `docker-compose.yaml` for any environment variables
you want to change.
Finally, bring the stack up using:
.. code-block:: shell
docker-compose up -d
AlekSIS will be reachable on port 80 if you forgot to configure the environment.
You are responsible for adding a reverse proxy like nginx providing TLS, etc.
.. _Dynaconf: https://dynaconf.readthedocs.io/en/latest/
.. _Let's Encrypt: https://certbot.eff.org/instructions
.. _PyPI: https://pypi.org
......@@ -5,24 +5,24 @@ AlekSIS can authenticate users against an LDAP directory (like OpenLDAP or
Active Directory). The AlekSIS core can only authenticate and synchronise
authenticated users to AlekSIS’ database. There are apps that help with
tasks like mass-importing accounts and linking accounts to persons in
the BiscuIY system (see below).
the AlekSIS system (see below).
Installing packages for LDAP support
------------------------------------
Installing the necessary librairies for LDAP support unfortunately is not
very straightforward under all circumstances.
very straightforward under all circumstances. On Debian, install these packages::
TBA.
sudo apt install python3-ldap libldap2-dev libssl-dev libsasl2-dev python3-dev
Configuration of LDAP support
-----------------------------
Configuration is done under the `default.ldap` section in AlekSIS’
Configuration is done under the ``default.ldap`` section in AlekSIS’
configuration file. For example, add something like the following to your
configuration (normally in `/etc/aleksis`; you can either append to an
configuration (normally in ``/etc/aleksis``; you can either append to an
existing file or add a new one)::
[ldap]
......@@ -32,3 +32,9 @@ existing file or add a new one)::
[ldap.users]
search = { base = "ou=people,dc=myschool,dc=edu", filter = "(uid=%(user)s)" }
map = { first_name = "givenName", last_name = "sn", email = "mail" }
[ldap.groups]
search = { base = "ou=groups,dc=myschool,dc=edu" }
type = "groupOfNames"
# Users in group "admins" are superusers
flags = { is_superuser = "cn=admins,ou=groups,dc=myschool,dc=edu" }
Installing AlekSIS with PostgreSQL backend
==========================================
PostgreSQL is the only supported database backend for AlekSIS. If you are
installing AlekSIS manually, you need to properly set it up.
Install the PostgreSQL server
-----------------------------
On Debian, install the postgresql server package with::
sudo apt install postgresql
Create a database and user
--------------------------
On Debian, you can use the following commands to create the database and a
user who owns it::
sudo -u postgres createuser -D -P -R -S aleksis
sudo -u postgres createdb -E UTF-8 -O aleksis -T template0 -l C.UTF-8 aleksis
When asked for the database user password, choose a secure, preferrably
random, password. You can generate one using the pwgen utility if you like::
pwgen 16 1
Configure AlekSIS to use PostgreSQL
-----------------------------------
Fill in the configuration under `/etc/aleksis/aleksis.toml` (or a file with any other name in this directory)::
[database]
host = "localhost"
name = "aleksis"
username = "aleksis"
password = "Y0urV3ryR4nd0mP4ssw0rd"
Don't forget to run the migrations, like described in the basic setup guide.
Configuration options
=====================
AlekSIS provides lots of options to configure your instance.
Configuration file
------------------
All settings which are required for running an AlekSIS instance are stored in your configuration file ``/etc/aleksis/aleksis.toml``.
Example configuration file::
# General config for static, media and secret key, required
static = { root = "/srv/www/aleksis/data/static", url = "/static/" }
media = { root = "/srv/www/aleksis/data/media", url = "/media/" }
secret_key = "Xoc8eiwah3neehid2Xi3oomoh4laem"
# Admin contat, optional
[contact]
admins = [["AlekSIS - Admins", "root@example.com"]]
from = 'aleksis@example.com'
# Allowed hosts, required
[http]
allowed_hosts = ["localhost"]
# Database for whole AlekSIS data, required
[database]
host = "localhost"
name = "aleksis"
username = "aleksis"
password = "aleksis"
# Maintenance mode and debug, optional
[maintenance]
debug = true
# Two factor authentication with yubikey enabled, optional
[2fa]
enabled = true
yubikey = { enabled = true }
# Authentication via LDAP, optional
[ldap]
uri = "ldaps://ldap.myschool.edu"
bind = { dn = "cn=reader,dc=myschool,dc=edu", password = "secret" }
map = { first_name = "givenName", last_name = "sn", email = "mail" }
[ldap.users]
search = { base = "ou=people,dc=myschool,dc=edu", filter = "(uid=%(user)s)" }
[ldap.groups]
search = { base = "ou=groups,dc=myschool,dc=edu" }
type = "groupOfNames"
# Users in group "admins" are superusers
flags = { is_superuser = "cn=admins,ou=groups,dc=myschool,dc=edu" }
# Search index, optional
[search]
backend = "whoosh"
index = "/srv/www/aleksis/data/whoosh_index"
Configuration in frontend
-------------------------
Everything that must not be configured before the AlekSIS instance fully starts can be configured in frontend, such as site title and logo.
You can find the configuration options in your AlekSIS instance under ``Admin → Configuration``.
......@@ -31,7 +31,7 @@ author = "AlekSIS team"
# The short X.Y version
version = "2.0"
# The full version, including alpha/beta/rc tags
release = "2.0a1"
release = "2.0b0"
# -- General configuration ---------------------------------------------------
......@@ -84,7 +84,7 @@ pygments_style = None
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
#
html_theme = "alabaster"
html_theme = "sphinx_materialdesign_theme"
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
......
Materialize templates
======================
AlekSIS frontend uses the `MaterializeCSS`_ framework and the `django-material`_ library.
Internationalization
--------------------
Load the ``i18n`` template tag and start translating strings in templates with
the following template tags::
{% blocktrans %}String{% endblocktrans %}
{% trans "String" %}
``{% blocktrans %}`` is mostly used for multiple words or multiline, while ``{%
trans %}`` is used for single words.
Title and headlines
-------------------
To add a main headline or browser title to your template, you can add the
following blocks to your template::
{% block browser_title %}Title{% endblock %}
{% block page_title %}Headline{% endblock %}
To fully remove page or browser title, use these template tags::
{% block no_browser_title %}{% endblock %}
{% block no_page_title %}{% endblock %}
Forms in templates
------------------
The django MaterializeCSS integrations provides support for forms in
template.
You just have to load the ``material_form`` templatetag in the ``{% load %}``
block.
The following snippet generates the form::
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
{% form form=edit_person_form %}{% endform %}
{% include "core/partials/save_button.html" %}
</form>
``edit_person_form`` is the variable name of the form in your ``context``.
``{% include "core/partials/save_button.html" %}`` includes a template snippet
from AlekSIS core. You can modify the buttons icon and translatable caption
like this::
{% trans "Edit" as caption %}
{% include "core/partials/save_button.html" with caption=caption, icon="person" %}
In your ``forms.py`` you can configure the layout of the fields like in the EditPersonForm::
class EditPersonForm(ExtensibleForm):
"""Form to edit an existing person object in the frontend."""
layout = Layout(
Fieldset(
_("Base data"),
"short_name",
Row("user", "primary_group"),
"is_active",
Row("first_name", "additional_name", "last_name"),
),
Fieldset(_("Address"), Row("street", "housenumber"), Row("postal_code", "place")),
Fieldset(_("Contact data"), "email", Row("phone_number", "mobile_number")),
Fieldset(
_("Advanced personal data"), Row("sex", "date_of_birth"), Row("photo"), "guardians",
),
)
Tables in templates
-------------------
To display tables generated by ``django-tables2`` in your template, you have to load the ``render_table`` template tag from ``django_tables2``::
{% load render_table from django_tables2 %}
After you've loaded the template tag, you can simply generate the table like this::
{% render_table persons_table %}
``persons_table`` is the variable name of the table in your ``context``.
.. _MaterializeCSS: https://materializecss.com/
.. _django-material: https://pypi.org/project/django-material/
Extensible models
=================
In AlekSIS you can use ``ExtensibleModels`` to add model fields to other
apps models.
If you want to make your apps models extensible, use the ``ExtensibleModel``
class as parent class of your models.
.. automodule:: aleksis.core.mixins
:members:
Merging of app settings
=======================
AlekSIS provides features to merge app settings into main ``settings.py``.
Currently mergable settings
---------------------------
* INSTALLED_APPS
* DATABASES
* YARN_INSTALLED_APPS
* ANY_JS
If you want to add another database for your AlekSIS app, you have to add
the following into your ``settings.py``::
DATABASES = {
"database": {
"ENGINE": "django.db.backends.postgresql",
"NAME": "database",
"USER": "database",
"PASSWORD": "Y0urV3ryR4nd0mP4ssw0rd",
"HOST": "127.0.0.1",
"PORT": 5432,
}
If you install new apps and want to configure these, or need some other settings you can easily add
settings to your ``settings.py``. Only settings that does not exist in the
main ``settings.py`` will be respected.
......@@ -3,8 +3,8 @@
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
Welcome to AlekSIS documentation!
==================================
Welcome to AlekSIS-Core's documentation!
========================================
.. toctree::
:maxdepth: 2
......
Checks
======
.. automodule:: aleksis.core.checks
:members:
Managers
========
.. automodule:: aleksis.core.managers
:members:
Mixins
======
.. automodule:: aleksis.core.mixins
:members:
File moved
Core preference registries
==========================
.. automodule:: aleksis.core.registries
:members:
Search indexes
==============
.. automodule:: aleksis.core.search_indexes
:members:
Core tables
===========
.. automodule:: aleksis.core.tables
:members:
Core Celery tasks
=================
.. automodule:: aleksis.core.tasks
:members:
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment