Skip to content

Commit

Permalink
Merge pull request #9 from endlessm/kolibri-0-16
Browse files Browse the repository at this point in the history
Add Kolibri 0.16.0b5
  • Loading branch information
dbnicholson authored Sep 8, 2023
2 parents bcca8af + e12b283 commit e3b870e
Show file tree
Hide file tree
Showing 10 changed files with 62 additions and 167 deletions.

This file was deleted.

6 changes: 3 additions & 3 deletions build-aux/flatpak/modules/python3-kolibri-pytz.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@
"name": "python3-pytz",
"buildsystem": "simple",
"build-commands": [
"pip3 install --exists-action=i --no-index --find-links=\"file://${PWD}\" pytz==2022.7.1 --upgrade --target=\"${KOLIBRI_MODULE_PATH}/dist/\""
"pip3 install --exists-action=i --no-index --find-links=\"file://${PWD}\" pytz==2023.3.post1 --upgrade --target=\"${KOLIBRI_MODULE_PATH}/dist/\""
],
"sources": [
{
"type": "file",
"url": "https://files.pythonhosted.org/packages/2e/09/fbd3c46dce130958ee8e0090f910f1fe39e502cc5ba0aadca1e8a2b932e5/pytz-2022.7.1-py2.py3-none-any.whl",
"sha256": "78f4f37d8198e0627c5f1143240bb0206b8691d8d7ac6d78fee88b78733f8c4a"
"url": "https://files.pythonhosted.org/packages/69/4f/7bf883f12ad496ecc9514cd9e267b29a68b3e9629661a2bbc24f80eff168/pytz-2023.3.post1.tar.gz",
"sha256": "7b4fddbeb94a1eba4b557da24f19fdf9db575192544270a9101d8509f9f43d7b"
}
]
}
5 changes: 2 additions & 3 deletions build-aux/flatpak/modules/python3-kolibri.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,13 @@
"buildsystem": "simple",
"build-commands": [
"pip3 install --exists-action=i --no-index --find-links=\"file://${PWD}\" --prefix=${FLATPAK_DEST} kolibri",
"patch -d ${KOLIBRI_MODULE_PATH} -p2 < 0001-Allow-superuser-to-be-null-in-device-provision-API.patch",
"patch -d ${KOLIBRI_MODULE_PATH}/dist/ifcfg -p3 < dist_ifcfg/0001-Remove-needless-ifcfg-warning.patch"
],
"sources": [
{
"type": "file",
"url": "https://files.pythonhosted.org/packages/10/7d/8bfa283b1f89c2e4c442da3aff8eea119403609f176a97157454851733a7/kolibri-0.15.12-py2.py3-none-any.whl",
"sha256": "66871d3780263c3f5b5562c9821e803952edc0da594036dfb532fa25f5917c04"
"url": "https://github.com/learningequality/kolibri/releases/download/v0.16.0-beta5/kolibri-0.16.0b5-py2.py3-none-any.whl",
"sha256": "3925b7a18b6684547fd50e1df7326ace318d9d81d1fa02317f1870e117eb515c"
},
{
"type": "dir",
Expand Down
4 changes: 2 additions & 2 deletions build-aux/flatpak/modules/python3-setproctitle.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
"sources": [
{
"type": "file",
"url": "https://files.pythonhosted.org/packages/78/9a/cf6bf4c472b59aef3f3c0184233eeea8938d3366bcdd93d525261b1b9e0a/setproctitle-1.2.3.tar.gz",
"sha256": "ecf28b1c07a799d76f4326e508157b71aeda07b84b90368ea451c0710dbd32c0"
"url": "https://files.pythonhosted.org/packages/b5/47/ac709629ddb9779fee29b7d10ae9580f60a4b37e49bce72360ddf9a79cdc/setproctitle-1.3.2.tar.gz",
"sha256": "b9fb97907c830d260fa0658ed58afd48a86b2b88aac521135c352ff7fd3477fd"
}
]
}
3 changes: 2 additions & 1 deletion build-aux/flatpak/org.endlessos.Key.Devel.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@
"--system-talk-name=org.endlessos.Key.Devel.Daemon",
"--env=KOLIBRI_HOME=~/.var/app/org.endlessos.Key.Devel/data/kolibri",
"--env=KOLIBRI_HTTP_PORT=0",
"--env=PYTHONPATH=/app/kolibri-plugins/lib/python"
"--env=PYTHONPATH=/app/kolibri-plugins/lib/python",
"--env=JSC_useDFGJIT=0"
],
"add-extensions" : {
"org.learningequality.Kolibri.Content" : {
Expand Down
8 changes: 6 additions & 2 deletions src/kolibri_app/globals.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,12 @@
config.PROFILE_ENV_PREFIX + "APP_DEVELOPER_EXTRAS"
)

APP_FORCE_AUTOMATIC_LOGIN = os.environ.get(
config.PROFILE_ENV_PREFIX + "APP_FORCE_AUTOMATIC_LOGIN"
APP_DISABLE_AUTOMATIC_LOGIN = os.environ.get(
config.PROFILE_ENV_PREFIX + "APP_DISABLE_AUTOMATIC_LOGIN"
)

APP_DISABLE_AUTOMATIC_PROVISION = os.environ.get(
config.PROFILE_ENV_PREFIX + "APP_DISABLE_AUTOMATIC_PROVISION"
)

XDG_CURRENT_DESKTOP = os.environ.get("XDG_CURRENT_DESKTOP")
Expand Down
1 change: 0 additions & 1 deletion src/kolibri_daemon/kolibri_http_process.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,6 @@ def run(self):
self.__kolibri_bus = KolibriProcessBus(
port=OPTIONS["Deployment"]["HTTP_PORT"],
zip_port=OPTIONS["Deployment"]["ZIP_CONTENT_PORT"],
background=False,
)

kolibri_daemon_plugin = _KolibriDaemonPlugin(self.__kolibri_bus, self.context)
Expand Down
54 changes: 33 additions & 21 deletions src/kolibri_daemon/kolibri_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,14 @@
import json
import logging
import os
import platform
import shutil
import typing
from gettext import gettext as _
from pathlib import Path

from kolibri_app.config import KOLIBRI_HOME_TEMPLATE_DIR
from kolibri_app.globals import APP_DISABLE_AUTOMATIC_PROVISION
from kolibri_app.globals import KOLIBRI_HOME_PATH

from .content_extensions_manager import ContentExtensionsManager
Expand All @@ -26,6 +29,7 @@
"kolibri_app_desktop_xdg_plugin",
"kolibri_desktop_auth_plugin",
"kolibri_dynamic_collections_plugin",
"kolibri_explore_plugin",
"kolibri_zim_plugin",
]

Expand Down Expand Up @@ -56,10 +60,8 @@ def _init_kolibri_env():
# workload, we can use a smaller number of threads.
os.environ.setdefault("KOLIBRI_CHERRYPY_THREAD_POOL", "10")

# Automatically provision with $KOLIBRI_HOME/automatic_provision.json if it
# exists.
# TODO: Once kolibri-gnome supports automatic login for all cases, use an
# included automatic provision file by default.
# Automatically provision with $KOLIBRI_HOME/automatic_provision.json or a
# generated automatic_provision.json if applicable.
automatic_provision_path = _get_automatic_provision_path()
if automatic_provision_path:
os.environ.setdefault(
Expand All @@ -72,15 +74,13 @@ def _init_kolibri_env():

def _enable_kolibri_plugin(plugin_name: str, optional=False) -> bool:
from kolibri.plugins import config as plugins_config
from kolibri.plugins.registry import registered_plugins
from kolibri.plugins.utils import enable_plugin

if optional and not importlib.util.find_spec(plugin_name):
return False

if plugin_name not in plugins_config.ACTIVE_PLUGINS:
logger.info(f"Enabling plugin {plugin_name}")
registered_plugins.register_plugins([plugin_name])
enable_plugin(plugin_name)

return True
Expand All @@ -89,24 +89,36 @@ def _enable_kolibri_plugin(plugin_name: str, optional=False) -> bool:
def _get_automatic_provision_path() -> typing.Optional[Path]:
path = KOLIBRI_HOME_PATH.joinpath("automatic_provision.json")

if not path.is_file():
if path.is_file():
return path
elif not APP_DISABLE_AUTOMATIC_PROVISION:
# TODO: Only do this if Kolibri does not have a facility configured.
with path.open("w") as file:
json.dump(_get_automatic_provision_data(), file)
return path
else:
return None

with path.open("r") as in_file:
try:
data = json.load(in_file)
except json.JSONDecodeError as error:
logger.warning(
f"Error reading automatic provision data from '{path.as_posix()}': {error}"
)
return None

if not data.keys().isdisjoint(["facility", "superusername", "superuserpassword"]):
# If a file has an attribute unique to the old format, we will asume it
# is outdated.
return None

return path
def _get_automatic_provision_data():
facility_name = _("Kolibri on {host}").format(host=platform.node() or "localhost")
return {
"facility_name": facility_name,
"preset": "formal",
"facility_settings": {
"learner_can_login_with_no_password": False,
},
"device_settings": {
"language_id": None,
"landing_page": "learn",
"allow_guest_access": False,
"allow_other_browsers_to_connect": False,
},
"superuser": {
"username": None,
"password": None,
},
}


def _kolibri_update_from_home_template():
Expand Down
93 changes: 12 additions & 81 deletions src/kolibri_gnome/kolibri_context.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
from __future__ import annotations

import logging
import platform
import re
import typing
from gettext import gettext as _
from pathlib import Path
from urllib.parse import parse_qs
from urllib.parse import SplitResult
Expand Down Expand Up @@ -245,7 +243,6 @@ class _KolibriSetupHelper(GObject.GObject):

is_app_key_cookie_ready = GObject.Property(type=bool, default=False)
is_session_cookie_ready = GObject.Property(type=bool, default=False)
is_facility_ready = GObject.Property(type=bool, default=False)

is_setup_complete = GObject.Property(type=bool, default=False)

Expand All @@ -270,23 +267,19 @@ def __init__(
self.__kolibri_daemon.connect(
"notify::app-key-cookie", self.__kolibri_daemon_on_notify_app_key_cookie
)
self.__kolibri_daemon.connect(
"notify::is-started", self.__kolibri_daemon_on_notify_is_started
)

await_properties(
[
(self, "is-facility-ready"),
(self.__kolibri_daemon, "is-started"),
(self, "login-token"),
],
self.__on_await_facility_ready_and_login_token,
self.__on_await_kolibri_is_started_and_login_token,
)

map_properties(
[
(self, "is-app-key-cookie-ready"),
(self, "is-session-cookie-ready"),
(self, "is-facility-ready"),
],
self.__update_is_setup_complete,
)
Expand All @@ -311,90 +304,28 @@ def __kolibri_daemon_on_dbus_owner_changed(
else:
self.props.is_session_cookie_ready = True

def __kolibri_daemon_on_notify_is_started(
self, kolibri_daemon: KolibriDaemonManager, pspec: GObject.ParamSpec = None
def __kolibri_daemon_on_login_token_ready(
self, kolibri_daemon: KolibriDaemonManager, login_token: typing.Optional[str]
):
self.props.is_facility_ready = False

if not self.__kolibri_daemon.props.is_started:
return

if not self.__kolibri_daemon.do_automatic_login:
# No automatic login so we don't need a facility:
self.props.is_facility_ready = True
return

self.__kolibri_daemon.kolibri_api_get_async(
"/api/public/v1/facility/",
result_cb=self.__on_kolibri_api_facility_response,
)

def __on_kolibri_api_facility_response(self, data: typing.Any):
if isinstance(data, list) and data:
self.props.is_facility_ready = True
return

# There is no facility, so automatically provision the device:
self.__automatic_device_provision()

def __automatic_device_provision(self):
# TODO: In the future, this could be done in kolibri-daemon itself by
# using a simple automatic_provision.json file in the Kolibri home
# template. We need to do it here for now because we are only
# using this configuration with automatic login, which is only
# enabled in certain cases.
logger.info("Provisioning device…")
facility_name = _("Kolibri on {host}").format(
host=platform.node() or "localhost"
)
request_body_data = {
"facility": {
"name": facility_name,
"learner_can_login_with_no_password": False,
},
"preset": "formal",
"superuser": None,
"language_id": None,
"device_name": None,
"settings": {
"landing_page": "learn",
"allow_other_browsers_to_connect": False,
},
"allow_guest_access": False,
}
self.__kolibri_daemon.kolibri_api_post_async(
"/api/device/deviceprovision/",
result_cb=self.__on_kolibri_api_deviceprovision_response,
request_body=request_body_data,
)

def __on_kolibri_api_deviceprovision_response(self, data: dict):
logger.info("Device provisioned.")
self.props.is_facility_ready = True
self.props.login_token = login_token

def __on_await_facility_ready_and_login_token(
self, is_facility_ready: bool, login_token: str
def __on_await_kolibri_is_started_and_login_token(
self, is_started: bool, login_token: str
):
if self.props.is_session_cookie_ready:
return

login_url = self.__kolibri_daemon.get_absolute_url(
self.AUTOLOGIN_URL_TEMPLATE.format(token=login_token)
)

self.__login_webview.load_uri(login_url)

def __kolibri_daemon_on_login_token_ready(
self, kolibri_daemon: KolibriDaemonManager, login_token: typing.Optional[str]
):
self.props.login_token = login_token

if login_token is None:
# If we are unable to get a login token, pretend the session cookie
# is ready so the app will proceed as usual. This should only happen
# in an edge case where kolibri-daemon is running on the system bus
# but is unable to communicate with AccountsService.
self.props.is_session_cookie_ready = True
elif self.__kolibri_daemon.do_automatic_login:
login_url = self.__kolibri_daemon.get_absolute_url(
self.AUTOLOGIN_URL_TEMPLATE.format(token=login_token)
)
self.__login_webview.load_uri(login_url)

def __kolibri_daemon_on_notify_app_key_cookie(
self, kolibri_daemon: KolibriDaemonManager, pspec: GObject.ParamSpec = None
Expand Down
6 changes: 2 additions & 4 deletions src/kolibri_gnome/kolibri_daemon_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
from gi.repository import Soup
from kolibri_app.config import DAEMON_APPLICATION_ID
from kolibri_app.config import DAEMON_MAIN_OBJECT_PATH
from kolibri_app.globals import APP_FORCE_AUTOMATIC_LOGIN
from kolibri_app.globals import APP_DISABLE_AUTOMATIC_LOGIN

from .utils import GioInputStreamIO

Expand Down Expand Up @@ -50,9 +50,7 @@ def __init__(self):

g_bus_type = KolibriDaemonDBus.get_default_bus_type()

self.__do_automatic_login = (
g_bus_type == Gio.BusType.SYSTEM or APP_FORCE_AUTOMATIC_LOGIN
)
self.__do_automatic_login = not APP_DISABLE_AUTOMATIC_LOGIN

self.__dbus_proxy = KolibriDaemonDBus.MainProxy(
g_bus_type=g_bus_type,
Expand Down

0 comments on commit e3b870e

Please sign in to comment.