diff --git a/aleksis/core/mixins.py b/aleksis/core/mixins.py index 564a4eed7b029c1b21fd7bd21a5bb02dd00af9f5..fa6c4fa29a67ec2904e42dba173ce72575c0e6ba 100644 --- a/aleksis/core/mixins.py +++ b/aleksis/core/mixins.py @@ -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) """ diff --git a/aleksis/core/preferences.py b/aleksis/core/preferences.py index d3639e805db623e0ea5cc55e1b0d0682b7d3749c..4e1bd8a40744e8374a3c3df041b2832da3f7275d 100644 --- a/aleksis/core/preferences.py +++ b/aleksis/core/preferences.py @@ -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] diff --git a/aleksis/core/templatetags/html_helpers.py b/aleksis/core/templatetags/html_helpers.py index 16238fcd00b0a88cb8eb8d6e25fb190ec432e1a5..5f78b1b195f9030cc97d96a0488c14845d450741 100644 --- a/aleksis/core/templatetags/html_helpers.py +++ b/aleksis/core/templatetags/html_helpers.py @@ -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") diff --git a/docs/admin/01_install.rst b/docs/admin/01_install.rst new file mode 100644 index 0000000000000000000000000000000000000000..8c8161fb56ff23ae4b29fd6e2420aa1d630703c6 --- /dev/null +++ b/docs/admin/01_install.rst @@ -0,0 +1,250 @@ +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 diff --git a/docs/admin/02_ldap.rst b/docs/admin/02_ldap.rst index 5ef33259b580fc68909c58f4b4a8b1fd507fcd4b..b8fbd657dedc3d3e7a6ef04a7fa36d9b7f1b66bf 100644 --- a/docs/admin/02_ldap.rst +++ b/docs/admin/02_ldap.rst @@ -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" } diff --git a/docs/admin/03_psql.rst b/docs/admin/03_psql.rst deleted file mode 100644 index 6d5ab57ae3b157ca906f3cfb7df1d3897efdfbd7..0000000000000000000000000000000000000000 --- a/docs/admin/03_psql.rst +++ /dev/null @@ -1,41 +0,0 @@ -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. diff --git a/docs/admin/05_configuration_options.rst b/docs/admin/05_configuration_options.rst new file mode 100644 index 0000000000000000000000000000000000000000..19321db371728406086e35e3a4d7dd1e6979f367 --- /dev/null +++ b/docs/admin/05_configuration_options.rst @@ -0,0 +1,68 @@ +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``. diff --git a/docs/conf.py b/docs/conf.py index 5817b0ad2b1195aeb704d7561fa57aec5a6d880a..136f619aebbbcefc457b9e1d316c6aa70b670e7a 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -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 diff --git a/docs/dev/04_materialize_templates.rst b/docs/dev/04_materialize_templates.rst new file mode 100644 index 0000000000000000000000000000000000000000..34d582166caa4688ad5e6b2e841d082a4dfd649c --- /dev/null +++ b/docs/dev/04_materialize_templates.rst @@ -0,0 +1,93 @@ +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/ diff --git a/docs/dev/05_extensible_models.rst b/docs/dev/05_extensible_models.rst new file mode 100644 index 0000000000000000000000000000000000000000..1e291b1a7d6c8d730020b755d891f5a2a19b99c5 --- /dev/null +++ b/docs/dev/05_extensible_models.rst @@ -0,0 +1,11 @@ +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: diff --git a/docs/dev/06_merging_app_settings.rst b/docs/dev/06_merging_app_settings.rst new file mode 100644 index 0000000000000000000000000000000000000000..5c8bc1f65cced9153946bf36fbd005740e5fabb7 --- /dev/null +++ b/docs/dev/06_merging_app_settings.rst @@ -0,0 +1,29 @@ +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. diff --git a/docs/index.rst b/docs/index.rst index 11863e5e9bd4590693add06b465a73ca3152e14c..aded3b28d2e41186b0f871d0064627bc807a7a29 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -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 diff --git a/docs/ref/core/01_checks.rst b/docs/ref/core/01_checks.rst new file mode 100644 index 0000000000000000000000000000000000000000..ef096f388bf270049197cf2ffe66e45956edb009 --- /dev/null +++ b/docs/ref/core/01_checks.rst @@ -0,0 +1,5 @@ +Checks +====== + +.. automodule:: aleksis.core.checks + :members: diff --git a/docs/ref/core/02_managers.rst b/docs/ref/core/02_managers.rst new file mode 100644 index 0000000000000000000000000000000000000000..23248579f12e5a5e62ce8dccdb1a129b30fe0598 --- /dev/null +++ b/docs/ref/core/02_managers.rst @@ -0,0 +1,5 @@ +Managers +======== + +.. automodule:: aleksis.core.managers + :members: diff --git a/docs/ref/core/03_mixins.rst b/docs/ref/core/03_mixins.rst new file mode 100644 index 0000000000000000000000000000000000000000..5933fb3e1791b70cacfcc97cd3b25e1b8344f2cb --- /dev/null +++ b/docs/ref/core/03_mixins.rst @@ -0,0 +1,5 @@ +Mixins +====== + +.. automodule:: aleksis.core.mixins + :members: diff --git a/docs/ref/core/01_models.rst b/docs/ref/core/04_models.rst similarity index 100% rename from docs/ref/core/01_models.rst rename to docs/ref/core/04_models.rst diff --git a/docs/ref/core/05_registries.rst b/docs/ref/core/05_registries.rst new file mode 100644 index 0000000000000000000000000000000000000000..97d2137617478b7bf8cf23e3c5751f596255aa6b --- /dev/null +++ b/docs/ref/core/05_registries.rst @@ -0,0 +1,5 @@ +Core preference registries +========================== + +.. automodule:: aleksis.core.registries + :members: diff --git a/docs/ref/core/06_search_indexes.rst b/docs/ref/core/06_search_indexes.rst new file mode 100644 index 0000000000000000000000000000000000000000..ba9944ace9a203d10b9e15a58177ce18a7cc83bb --- /dev/null +++ b/docs/ref/core/06_search_indexes.rst @@ -0,0 +1,5 @@ +Search indexes +============== + +.. automodule:: aleksis.core.search_indexes + :members: diff --git a/docs/ref/core/07_tables.rst b/docs/ref/core/07_tables.rst new file mode 100644 index 0000000000000000000000000000000000000000..ee4eeec7ac2db851bcd733588eeea271a0a95594 --- /dev/null +++ b/docs/ref/core/07_tables.rst @@ -0,0 +1,5 @@ +Core tables +=========== + +.. automodule:: aleksis.core.tables + :members: diff --git a/docs/ref/core/08_tasks.rst b/docs/ref/core/08_tasks.rst new file mode 100644 index 0000000000000000000000000000000000000000..76a3a430f924f41784d382a0b42a208799f18640 --- /dev/null +++ b/docs/ref/core/08_tasks.rst @@ -0,0 +1,5 @@ +Core Celery tasks +================= + +.. automodule:: aleksis.core.tasks + :members: diff --git a/docs/ref/core/09_utils.rst b/docs/ref/core/09_utils.rst new file mode 100644 index 0000000000000000000000000000000000000000..74f6f9311644bfd168abfbe0cc4a9db0121a1620 --- /dev/null +++ b/docs/ref/core/09_utils.rst @@ -0,0 +1,43 @@ +Core utillity functions +======================= + + +General helper functions in core +--------------------------------- + .. automodule:: aleksis.core.util.core_helpers + :members: + +Predicates for permission systemd +--------------------------------- +.. automodule:: aleksis.core.util.predicates + :members: + +Messages +-------- +.. automodule:: aleksis.core.util.messages + :members: + +General helper functions for models +----------------------------------- +.. automodule:: aleksis.core.util.model_helpers + :members: + +Helper functions for SASS +------------------------- +.. automodule:: aleksis.core.util.sass_helpers + :members: + +Utillity function for AlekSIS app container +------------------------------------------- +.. automodule:: aleksis.core.util.apps + :members: + +AlekSIS core middlewares +------------------------ +.. automodule:: aleksis.core.util.middlewares + :members: + +Search utillity +------------------------ +.. automodule:: aleksis.core.util.search + :members: diff --git a/docs/ref/core/10_views.rst b/docs/ref/core/10_views.rst new file mode 100644 index 0000000000000000000000000000000000000000..15c111f8b97bcfd330dd625cdc864b28b3fa2a44 --- /dev/null +++ b/docs/ref/core/10_views.rst @@ -0,0 +1,5 @@ +Core views +========== + +.. automodule:: aleksis.core.views + :members: diff --git a/docs/ref/core/11_filters.rst b/docs/ref/core/11_filters.rst new file mode 100644 index 0000000000000000000000000000000000000000..04a5aa623a3a339cfbc5884b742e5de14ef317d8 --- /dev/null +++ b/docs/ref/core/11_filters.rst @@ -0,0 +1,5 @@ +Core filters +============ + +.. automodule:: aleksis.core.filters + :members: diff --git a/docs/ref/core/12_template_tags.rst b/docs/ref/core/12_template_tags.rst new file mode 100644 index 0000000000000000000000000000000000000000..a4c79715f317fa925a8e2f4dfa7508f4e0d6040c --- /dev/null +++ b/docs/ref/core/12_template_tags.rst @@ -0,0 +1,22 @@ +Template tags +============= + +AlekSIS provides some templatetags to display data in templates. + +Dashboard +--------- + +.. automodule:: aleksis.core.templatetags.dashboard + :members: + +Data helpers +------------ + +.. automodule:: aleksis.core.templatetags.data_helpers + :members: + +HTML helpers +------------ + +.. automodule:: aleksis.core.templatetags.html_helpers + :members: diff --git a/poetry.lock b/poetry.lock index b850025a3fc6551080f7b4b9bec6c46d9ffaeaf3..b5989fdcb97c20819171489c37d17a2e8397ce44 100644 --- a/poetry.lock +++ b/poetry.lock @@ -8,7 +8,7 @@ python-versions = "*" [[package]] name = "aleksis-builddeps" -version = "3" +version = "4" description = "AlekSIS (School Information System) — Build/Dev dependencies for apps" category = "dev" optional = false @@ -27,7 +27,7 @@ flake8-docstrings = ">=1.5.0,<2.0.0" flake8-fixme = ">=1.1.1,<2.0.0" flake8-isort = ">=4.0.0,<5.0.0" flake8-mypy = ">=17.8.0,<18.0.0" -flake8-rst-docstrings = ">=0.1.0,<0.2.0" +flake8-rst-docstrings = ">=0.2.0,<0.3.0" freezegun = ">=1.1.0,<2.0.0" isort = ">=5.0.0,<6.0.0" pytest = ">=6.0,<7.0" @@ -39,6 +39,7 @@ safety = ">=1.8.5,<2.0.0" selenium = ">=3.141.0,<4.0.0" sphinx = ">=3.0,<4.0" sphinx-autodoc-typehints = ">=1.7,<2.0" +sphinx_materialdesign_theme = ">=0.1.11,<0.2.0" sphinxcontrib-django = ">=0.5.0,<0.6.0" [package.source] @@ -214,20 +215,20 @@ python-versions = "*" [[package]] name = "boto3" -version = "1.17.77" +version = "1.17.78" description = "The AWS SDK for Python" category = "main" optional = true python-versions = ">= 2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" [package.dependencies] -botocore = ">=1.20.77,<1.21.0" +botocore = ">=1.20.78,<1.21.0" jmespath = ">=0.7.1,<1.0.0" s3transfer = ">=0.4.0,<0.5.0" [[package]] name = "botocore" -version = "1.20.77" +version = "1.20.78" description = "Low-level, data-driven core of boto 3." category = "main" optional = true @@ -1123,7 +1124,7 @@ tablib = ["tablib"] [[package]] name = "django-templated-email" -version = "2.3.0" +version = "2.4.0" description = "A Django oriented templated / transaction email abstraction" category = "main" optional = false @@ -1131,7 +1132,6 @@ python-versions = "*" [package.dependencies] django-render-block = ">=0.5" -six = ">=1" [[package]] name = "django-timezone-field" @@ -1410,7 +1410,7 @@ flake8 = "*" [[package]] name = "flake8-rst-docstrings" -version = "0.1.2" +version = "0.2.3" description = "Python docstring reStructuredText (RST) validator" category = "dev" optional = false @@ -1418,7 +1418,6 @@ python-versions = ">=3.3" [package.dependencies] flake8 = ">=3.0.0" -pydocstyle = ">=3.0.0" pygments = "*" restructuredtext-lint = "*" @@ -2374,6 +2373,14 @@ Sphinx = ">=3.0" test = ["pytest (>=3.1.0)", "typing-extensions (>=3.5)", "sphobjinv (>=2.0)", "Sphinx (>=3.2.0)", "dataclasses"] type_comments = ["typed-ast (>=1.4.0)"] +[[package]] +name = "sphinx-materialdesign-theme" +version = "0.1.11" +description = "Sphinx Material Design Theme" +category = "dev" +optional = false +python-versions = "*" + [[package]] name = "sphinxcontrib-applehelp" version = "1.0.2" @@ -2671,7 +2678,7 @@ alabaster = [ {file = "alabaster-0.7.12.tar.gz", hash = "sha256:a661d72d58e6ea8a57f7a86e37d86716863ee5e92788398526d58b26a4e4dc02"}, ] aleksis-builddeps = [ - {file = "AlekSIS-Builddeps-3.tar.gz", hash = "sha256:04597e29a861e576d78adc068c9f1bf85450c81dc43cb1f7db0ed43e975b64a2"}, + {file = "AlekSIS-Builddeps-4.tar.gz", hash = "sha256:aaaa22965228b9b9b7de812e3e7fa9cbfdbf8635bb22d6f3a201dc0cc6d8d307"}, ] amqp = [ {file = "amqp-5.0.6-py3-none-any.whl", hash = "sha256:493a2ac6788ce270a2f6a765b017299f60c1998f5a8617908ee9be082f7300fb"}, @@ -2735,12 +2742,12 @@ bleach = [ {file = "boolean.py-3.8.tar.gz", hash = "sha256:cc24e20f985d60cd4a3a5a1c0956dd12611159d32a75081dabd0c9ab981acaa4"}, ] boto3 = [ - {file = "boto3-1.17.77-py2.py3-none-any.whl", hash = "sha256:b434170484348b870e3624069ca577d38e52ace0229d0619d8368454bb66ad3b"}, - {file = "boto3-1.17.77.tar.gz", hash = "sha256:02835bcad77a5fda1fc376a824323779301ddf88f04a0ac16044d980f350c4a3"}, + {file = "boto3-1.17.78-py2.py3-none-any.whl", hash = "sha256:1a87855123df1f18081a5fb8c1abde28d0096a03f6f3ebb06bcfb77cdffdae5e"}, + {file = "boto3-1.17.78.tar.gz", hash = "sha256:2a5caee63d45fbdcc85e710c7f4146112f5d10b22fd0176643d2f2914cce54df"}, ] botocore = [ - {file = "botocore-1.20.77-py2.py3-none-any.whl", hash = "sha256:466ab5eac5e5735d573e83e84194585cac4e804d2b91b7bbe0351bcaff10df32"}, - {file = "botocore-1.20.77.tar.gz", hash = "sha256:b2a71043378687dc891997669830e8b61eaea656981059dbd4898825659df639"}, + {file = "botocore-1.20.78-py2.py3-none-any.whl", hash = "sha256:37105b9434d73f9c4d4960ee54c8eb129120f4c6681eb16edf483f03c5e2326d"}, + {file = "botocore-1.20.78.tar.gz", hash = "sha256:e74775f9e64e975787d76390fc5ac5aba875d726bb9ece3b7bd900205b430389"}, ] bs4 = [ {file = "bs4-0.0.1.tar.gz", hash = "sha256:36ecea1fd7cc5c0c6e4a1ff075df26d50da647b75376626cc186e2212886dd3a"}, @@ -3128,7 +3135,7 @@ django-tables2 = [ {file = "django_tables2-2.4.0-py2.py3-none-any.whl", hash = "sha256:0f10ecef25708385a9d32d68d7c9478ca8dda31569410cb05a025be3f2c57593"}, ] django-templated-email = [ - {file = "django-templated-email-2.3.0.tar.gz", hash = "sha256:536c4e5ae099eabfb9aab36087d4d7799948c654e73da55a744213d086d5bb33"}, + {file = "django-templated-email-2.4.0.tar.gz", hash = "sha256:3bcd95cb806070b13c9919a72fec944b5ce319e30e8828a08180767bb1f84027"}, ] django-timezone-field = [ {file = "django-timezone-field-4.1.2.tar.gz", hash = "sha256:cffac62452d060e365938aa9c9f7b72d70d8b26b9c60243bce227b35abd1b9df"}, @@ -3213,8 +3220,8 @@ flake8-polyfill = [ {file = "flake8_polyfill-1.0.2-py2.py3-none-any.whl", hash = "sha256:12be6a34ee3ab795b19ca73505e7b55826d5f6ad7230d31b18e106400169b9e9"}, ] flake8-rst-docstrings = [ - {file = "flake8-rst-docstrings-0.1.2.tar.gz", hash = "sha256:7d34d2175a0cd92aba0872ade74268b2f2c12582c7267d4a0e6ef1c32a828ce3"}, - {file = "flake8_rst_docstrings-0.1.2-py3-none-any.whl", hash = "sha256:73b5db2fd9d4d7c7e6b7767931730c4570e5a89f34a1501b837afb3b6d31537a"}, + {file = "flake8-rst-docstrings-0.2.3.tar.gz", hash = "sha256:3045794e1c8467fba33aaea5c246b8369efc9c44ef8b0b20199bb6df7a4bd47b"}, + {file = "flake8_rst_docstrings-0.2.3-py3-none-any.whl", hash = "sha256:565bbb391d7e4d0042924102221e9857ad72929cdd305b26501736ec22c1451a"}, ] freezegun = [ {file = "freezegun-1.1.0-py2.py3-none-any.whl", hash = "sha256:2ae695f7eb96c62529f03a038461afe3c692db3465e215355e1bb4b0ab408712"}, @@ -3817,6 +3824,9 @@ sphinx-autodoc-typehints = [ {file = "sphinx-autodoc-typehints-1.12.0.tar.gz", hash = "sha256:193617d9dbe0847281b1399d369e74e34cd959c82e02c7efde077fca908a9f52"}, {file = "sphinx_autodoc_typehints-1.12.0-py3-none-any.whl", hash = "sha256:5e81776ec422dd168d688ab60f034fccfafbcd94329e9537712c93003bddc04a"}, ] +sphinx-materialdesign-theme = [ + {file = "sphinx_materialdesign_theme-0.1.11.tar.gz", hash = "sha256:6e9dae4c6e5ba23c0657a94c1cf65f64be9c8bc1594a6fb41815f7daa3326aa9"}, +] sphinxcontrib-applehelp = [ {file = "sphinxcontrib-applehelp-1.0.2.tar.gz", hash = "sha256:a072735ec80e7675e3f432fcae8610ecf509c5f1869d17e2eecff44389cdbc58"}, {file = "sphinxcontrib_applehelp-1.0.2-py2.py3-none-any.whl", hash = "sha256:806111e5e962be97c29ec4c1e7fe277bfd19e9652fb1a4392105b43e01af885a"},