Skip to content
Commits on Source (46)
......@@ -6,6 +6,23 @@ All notable changes to this project will be documented in this file.
The format is based on `Keep a Changelog`_,
and this project adheres to `Semantic Versioning`_.
`2.7.3`_ - 2022-02-03
---------------------
Fixed
~~~~~
* Migration added in 2.7.2 did not work in all scenarios
* [Dev] Field change tracking API for Person was broken in 2.7.2
* [OAuth] Automatic clean-up of expired OAuth tokens could fail
* Allow maskable icons for non-masked use
* Add missing documentation
Known issues
~~~~~~~~~~~~
* Maskable and non-masked icons *purpose) any cannot be separated
`2.7.2`_ - 2022-01-31
---------------------
......@@ -709,3 +726,4 @@ Fixed
.. _2.7: https://edugit.org/AlekSIS/Official/AlekSIS/-/tags/2.7
.. _2.7.1: https://edugit.org/AlekSIS/Official/AlekSIS/-/tags/2.7.1
.. _2.7.2: https://edugit.org/AlekSIS/Official/AlekSIS/-/tags/2.7.2
.. _2.7.3: https://edugit.org/AlekSIS/Official/AlekSIS/-/tags/2.7.3
......@@ -12,11 +12,7 @@ class Migration(migrations.Migration):
]
def _migrate_preference_models_to_unique(apps, schema_editor):
GroupPreferenceModel = apps.get_model("core", "GroupPreferenceModel")
PersonPreferenceModel = apps.get_model("core", "PersonPreferenceModel")
SitePreferenceModel = apps.get_model("core", "SitePreferenceModel")
from dynamic_preferences.models import BasePreferenceModel
from aleksis.core.models import GroupPreferenceModel, PersonPreferenceModel, SitePreferenceModel
models = [GroupPreferenceModel, PersonPreferenceModel, SitePreferenceModel]
......@@ -32,7 +28,7 @@ class Migration(migrations.Migration):
if len(objs) > 1:
found = False
for obj in objs:
if BasePreferenceModel.get_value(obj) == BasePreferenceModel.preference(obj).default or found:
if obj.value == obj.preference.default or found:
obj.delete()
else:
found = True
......
......@@ -316,7 +316,7 @@ class Person(ExtensibleModel):
def initials(self):
return f"{self.first_name[0]}{self.last_name[0]}".upper()
user_info_tracker = FieldTracker(fields=("first_name", "last_name", "email", "user"))
user_info_tracker = FieldTracker(fields=("first_name", "last_name", "email", "user_id"))
@property
def member_of_recursive(self) -> QuerySet:
......@@ -341,9 +341,9 @@ class Person(ExtensibleModel):
super().save(*args, **kwargs)
if self.pk is None or bool(changed):
if "user" in changed:
if "user_id" in changed:
# Clear groups of previous Django user
previous_user = changed["user"]
previous_user = changed["user_id"]
if previous_user is not None:
get_user_model().objects.get(pk=previous_user).groups.clear()
......@@ -355,7 +355,7 @@ class Person(ExtensibleModel):
self.user.email = self.email
self.user.save()
if "user" in changed:
if "user_id" in changed:
# Synchronise groups to Django groups
for group in self.member_of.union(self.owner_of.all()).all():
group.save(force=True)
......
......@@ -45,6 +45,6 @@ def backup_data() -> None:
@app.task(run_every=timedelta(days=1))
def clear_oauth_tokens():
"""Clear expired OAuth2 tokens."""
from oauth2_provider.models import clear_tokens # noqa
from oauth2_provider.models import clear_expired # noqa
return clear_tokens()
return clear_expired()
......@@ -175,7 +175,7 @@ class ManifestView(View):
{
"src": favicon_img.faviconImage.url,
"sizes": f"{favicon_img.size}x{favicon_img.size}",
"purpose": "maskable" if prefs["theme__pwa_icon_maskable"] else "any",
"purpose": "maskable any" if prefs["theme__pwa_icon_maskable"] else "any",
}
for favicon_img in pwa_imgs
]
......
......@@ -4,7 +4,7 @@ Concepts of the AlekSIS core
The AlekSIS core provides functionality and data models as a base for
all apps.
.. _sec:SchoolTerms:
.. _core-concept-schoolterm:
The concept of school terms
---------------------------
......@@ -32,7 +32,7 @@ of all school terms and buttons to create, edit or delete school terms.
Please be aware that there can be only one school term at time and each
school term needs a unique name.
.. _sec:Persons:
.. _core-concept-person:
The concept of persons
----------------------
......@@ -49,7 +49,7 @@ information like the following:
- Address details
- Photo
- Relation to guardians
- Primary group (e. g. a class or a tutor group, cf. [@sec:Groups])
- Primary group (e. g. a class or a tutor group, cf. :ref:`core-concept-group`)
Except for the name, all data points are optional, so you can decide on
your own (and based on your local data protection laws) which data should be
......@@ -74,7 +74,7 @@ The main method to manage persons is the view under
``People → Persons``. To add person to groups, you have to open the
respective group and set the person as a member or an owner.
.. _sec:Groups:
.. _core-concept-group:
The concept of groups
---------------------
......@@ -95,18 +95,20 @@ class or a course varies from school term to school term. In order to
archive historical data according to local laws, these groups have to be
separeted which is solved by linking them to a school term.
Manage group types
~~~~~~~~~~~~~~~~~~
You can manage your local group types by opening the menu entry
``People → Group types`` as an admin user.
Manage groups
~~~~~~~~~~~~~
Groups are managed on the page ``People → Groups``. There you can
search, view, create, change and delete groups.
.. _core-concept-grouptype:
Manage group types
~~~~~~~~~~~~~~~~~~
You can manage your local group types by opening the menu entry
``People → Group types`` as an admin user.
Import school terms, persons and groups from other data sources
---------------------------------------------------------------
......
......@@ -20,6 +20,8 @@ AlekSIS will need and use the following paths:
You can change any of the paths as you like.
.. _core-install-prerequisites:
Prerequisites
~~~~~~~~~~~~~
......@@ -123,6 +125,8 @@ from `yarnpkg`, collect static files, and migrate the database to the final sche
aleksis-admin migrate
aleksis-admin createinitialrevisions
.. _core-configure-uwsgi:
Configure uWSGI
~~~~~~~~~~~~~~~
......
.. _core-configuration-files:
Configuration files and format
==============================
......
Mail
====
AlekSIS needs to send mails e.g. for account confirmations, feedback or
error reports.
Configure mailing
-----------------
The mailserver can be configured via the configuration file
.. code-block:: toml
[mail.server]
host = "mail.example.com"
tls = False
ssl = True
port = 25
user = "mailuser"
password = "password"
Name and address for mails sent by AlekSIS can be configured in the
webinterface. To configure, visit `Admin → Configuration` and click on the
`Mail` tab.
Configure mail recipients
-------------------------
You can configure admin contacts in your configuration file, located at
``/etc/aleksis/``.
.. code-blocK:: toml
[contact]
admins = [["AlekSIS - Admins", "root@example.com"],["AlekSIS - Admins2", "root2@example.com"]]
from = 'aleksis@example.com'
.. _core-ldap:
Authenticating against LDAP
===========================
......
Registration and user invitations
=================================
In addition to central management of user accounts, AlekSIS allows self-registration
by users. Registration can be either fully open, or based on personal invitations.
In a system handling ciritcal data, access control should be as tight as possible.
However, there are scenarios where central account creation is not feasible, e.g.
for optional guardian accounts. In such a scenario, the invitation system allows
for processes like handing out invitation codes as a letter or through e-mail
campaigns.
Configuration
-------------
.. _core-registration:
Registration
~~~~~~~~~~~~
Registration can be enabled via the configuration interface in frontend.
In the ``Authentication`` tab, click the checkbox ``Enable signup`` to enable
signup for everyone. A menu item will be added for public registration.
.. warning::
Do not enable this feature unless you intend to run a public AlekSIS instance.
User invitations
~~~~~~~~~~~~~~~~
.. _core-user-invitations:
In the same location as public registration, the invitation system can be enabled.
* Authentication
* Enable invitations: Click to enable invitations.
* Length of invite code: Length of invitation code packets, defaults to 5.
* Size of packets: Configure how many packets are generated, defaults to 3.
By default, an invitation code looks like the following:
``abcde-abcde-abcde``.
A menu item will become available for users to enter their invitation code.
Usage
-----
Invite by email or code
~~~~~~~~~~~~~~~~~~~~~~~
To invite a new user , visit the invitation page located at ``People → Invite
person``
Here you are able to invite the user by email address or generate an
invitation code.
.. image:: ../_static/invitations.png
:width: 100%
:alt: Invitations page
This mechanism allows for registration of entirely new persons that do not
exist in the system, e.g. if perosnal details are not known in advance.
Invite existing person
~~~~~~~~~~~~~~~~~~~~~~
To invite an existing person, open the person in AlekSIS and click ``Invite
user``.
The invitation will be sent to the person's email address, and can only
be used by this person. Upon registration, the new account will automatically
be linked to the existing person.
.. image:: ../_static/invite_existing.png
:width: 100%
:alt: Invite existing person
.. note::
Before using this feature, make sure to read and understand
:ref:`core-concept-person`.
......@@ -34,5 +34,5 @@ provider and enter client id and secret from your application and choose
your site:
.. image:: ../_static/create_social_application.png
:width: 400
:width: 100%
:alt: Create social application
Background tasks
================
Operations that are expected to take a long time are run as background tasks.
For this, at least one `Celery`_ worker has to be running, e.g. by coupling it
with uWSGI as laid out in :ref:`core-configure-uwsgi`.
If a task is triggered from the AlekSIS frontend, for example by starting an import
job, a progress page is displayed, and the result of the job is waited for.
.. _core-periodic-tasks:
Periodic tasks
~~~~~~~~~~~~~~
Some tasks are also run on a schedule. For example, the backup job is run on
a regular basis.
All tasks in AlekSIS that are expected to run have a default schedule, which
is registered when migrating the database. Changing this default schedule
is currently only possible through the Django Admin backend, under
*Admin → Backend Admin*.
Under the *Periodic Tasks* app, you can define schedules and tasks. The names
of tasks you can add manually are documented in the respective sections
of the manual.