diff --git a/.isort.cfg b/.isort.cfg new file mode 100644 index 0000000..83fb0de --- /dev/null +++ b/.isort.cfg @@ -0,0 +1,8 @@ +[settings] +multi_line_output = 3 +include_trailing_comma = True +force_grid_wrap = 0 +use_parentheses = True +ensure_newline_before_comments = True +line_length = 88 + diff --git a/admin/src/admin/lib/admin.py b/admin/src/admin/lib/admin.py index d04f5a1..0cc8f60 100644 --- a/admin/src/admin/lib/admin.py +++ b/admin/src/admin/lib/admin.py @@ -32,7 +32,14 @@ import secrets from .events import Events from .exceptions import UserExists, UserNotFound -from .helpers import count_repeated, rand_password, kpath2gids, kpath2kpaths, get_kid_from_kpath, get_group_with_childs +from .helpers import ( + count_repeated, + get_group_with_childs, + get_kid_from_kpath, + kpath2gids, + kpath2kpaths, + rand_password, +) MANAGER = os.environ["CUSTOM_ROLE_MANAGER"] TEACHER = os.environ["CUSTOM_ROLE_TEACHER"] @@ -579,8 +586,9 @@ class Admin: + ") uploaded user: " + u["username"] ) - user_groups = [g.strip() for g in u["groups"].split(",") if g !=""] - if not len(user_groups): user_groups = ["/"+u["role"].strip()] + user_groups = [g.strip() for g in u["groups"].split(",") if g != ""] + if not len(user_groups): + user_groups = ["/" + u["role"].strip()] pathslist = [] for group in user_groups: pathpart = "" @@ -604,7 +612,8 @@ class Admin: u["quota"] = "none" if u["role"] == "admin": u["quota"] = "none" - if u["quota"].lower() in ["false","unlimited"]: u["quota"] = "none" + if u["quota"].lower() in ["false", "unlimited"]: + u["quota"] = "none" users.append( { @@ -735,7 +744,7 @@ class Admin: log.warning("All syncs finished. Resyncing from apps...") self.resync_data() - def add_keycloak_groups(self,groups): + def add_keycloak_groups(self, groups): total = len(groups) i = 0 ev = Events( @@ -804,7 +813,7 @@ class Admin: ) self.keycloak.assign_realm_roles(uid, u["roles"][0]) gid = self.keycloak.get_group_by_path("/" + u["roles"][0])["id"] - self.keycloak.group_user_add(uid,gid) + self.keycloak.group_user_add(uid, gid) # Add user to groups for group in u["groups"]: for g in kpath2kpaths(group): @@ -821,12 +830,12 @@ class Admin: u["groups"].append(u["roles"][0]) self.resync_data() - def add_moodle_groups(self,groups): + def add_moodle_groups(self, groups): ### Create all groups. Skip / in system groups total = len(groups) log.warning(groups) ev = Events("Syncing groups from external to moodle", total=len(groups)) - i=1 + i = 1 for g in groups: moodle_groups = kpath2gids(g) for mg in moodle_groups: @@ -844,8 +853,7 @@ class Admin: log.warning( " MOODLE GROUPS: Group " + mg + " probably already exists" ) - i=i+1 - + i = i + 1 def sync_to_moodle_external(self): # works from the internal (keycloak) ### Process all groups from the users keycloak_groups key @@ -910,12 +918,12 @@ class Admin: ids = [c["id"] for c in cohorts] self.moodle.delete_cohorts(ids) - def add_nextcloud_groups(self,groups): + def add_nextcloud_groups(self, groups): ### Create all groups. Skip / in system groups total = len(groups) log.warning(groups) ev = Events("Syncing groups from external to nextcloud", total=len(groups)) - i=1 + i = 1 for g in groups: nextcloud_groups = kpath2gids(g) for ng in nextcloud_groups: @@ -933,7 +941,7 @@ class Admin: log.warning( " NEXTCLOUD GROUPS: Group " + ng + " probably already exists" ) - i=i+1 + i = i + 1 def sync_to_nextcloud_external(self): groups = [] @@ -967,7 +975,11 @@ class Admin: u["first"] + " " + u["last"], ) except ProviderItemExists: - log.warning(" NEXTCLOUD USERS: User " + u["username"] + " already exists. Skipping...") + log.warning( + " NEXTCLOUD USERS: User " + + u["username"] + + " already exists. Skipping..." + ) continue except: log.error(traceback.format_exc()) @@ -995,7 +1007,9 @@ class Admin: self.moodle.add_system_cohort(pathpart) except: # print(traceback.format_exc()) - log.warning("MOODLE: Group " + pathpart + " probably already exists.") + log.warning( + "MOODLE: Group " + pathpart + " probably already exists." + ) ### Get all existing moodle cohorts cohorts = self.moodle.get_cohorts() @@ -1093,7 +1107,9 @@ class Admin: subpath = subpath + "/" + parts[i] self.nextcloud.add_group(subpath) except: - log.warning("NEXTCLOUD GROUPS: "+subpath+" probably already exists") + log.warning( + "NEXTCLOUD GROUPS: " + subpath + " probably already exists" + ) i = i + 1 ev = Events( @@ -1629,7 +1645,9 @@ class Admin: ) ev.increment({"name": "Added to nextcloud", "data": []}) except ProviderItemExists: - log.warning(" NEXTCLOUD USERS: User " + username + " already exists. Skipping...") + log.warning( + " NEXTCLOUD USERS: User " + username + " already exists. Skipping..." + ) except: log.error(traceback.format_exc()) @@ -1819,9 +1837,13 @@ class Admin: except Exception as e: print(e) ev.update_text("Error deleting group. Not found in keycloak!") - log.error(' KEYCLOAK GROUPS: Could not delete group '+str(group_id)+' as it does not exist!') + log.error( + " KEYCLOAK GROUPS: Could not delete group " + + str(group_id) + + " as it does not exist!" + ) - #{'id': '966ad67c-499a-4f56-bd1d-283691cde0e7', 'name': 'asdgfewfwe', 'path': '/asdgfewfwe', 'attributes': {}, 'realmRoles': [], 'clientRoles': {}, 'subGroups': [], 'access': {'view': True, 'manage': True, 'manageMembership': True}} + # {'id': '966ad67c-499a-4f56-bd1d-283691cde0e7', 'name': 'asdgfewfwe', 'path': '/asdgfewfwe', 'attributes': {}, 'realmRoles': [], 'clientRoles': {}, 'subGroups': [], 'access': {'view': True, 'manage': True, 'manageMembership': True}} subgroups = get_group_with_childs(keycloak_group) @@ -1833,12 +1855,12 @@ class Admin: cohorts = self.moodle.get_cohorts() for sg in subgroups: - sg_gid=kpath2gid(sg) + sg_gid = kpath2gid(sg) cohort = [c["id"] for c in cohorts if c["name"] == sg_gid] - ev.update_text("Deleting from moodle cohort "+sg_gid) + ev.update_text("Deleting from moodle cohort " + sg_gid) self.moodle.delete_cohorts(cohort) - ev.update_text("Deleting from nextcloud group "+sg_gid) + ev.update_text("Deleting from nextcloud group " + sg_gid) self.nextcloud.delete_group(sg_gid) def delete_group_by_path(self, path): diff --git a/admin/src/admin/lib/dashboard.py b/admin/src/admin/lib/dashboard.py index 60db587..cb5699d 100644 --- a/admin/src/admin/lib/dashboard.py +++ b/admin/src/admin/lib/dashboard.py @@ -1,16 +1,14 @@ import logging as log +import os +import shutil import traceback +from io import BytesIO from pprint import pprint -import os, shutil - import requests - -from schema import And, Optional, Schema, SchemaError, Use import yaml - -from io import BytesIO from PIL import Image +from schema import And, Optional, Schema, SchemaError, Use from admin import app diff --git a/admin/src/admin/lib/helpers.py b/admin/src/admin/lib/helpers.py index 256f71c..47d588e 100644 --- a/admin/src/admin/lib/helpers.py +++ b/admin/src/admin/lib/helpers.py @@ -3,6 +3,7 @@ import string from collections import Counter from pprint import pprint + def get_recursive_groups(l_groups, l): for d_group in l_groups: data = {} @@ -14,8 +15,9 @@ def get_recursive_groups(l_groups, l): l.append(data) return l + def get_group_with_childs(keycloak_group): - return [ g["path"] for g in get_recursive_groups([keycloak_group],[])] + return [g["path"] for g in get_recursive_groups([keycloak_group], [])] def system_username(username): @@ -25,19 +27,29 @@ def system_username(username): else False ) + def system_group(groupname): return True if groupname in ["admin", "manager", "teacher", "student"] else False + def get_group_from_group_id(group_id, groups): return next((d for d in groups if d.get("id") == group_id), None) + def get_kid_from_kpath(kpath, groups): ids = [g["id"] for g in groups if g["path"] == kpath] - if not len(ids) or len(ids) > 1: return False + if not len(ids) or len(ids) > 1: + return False return ids[0] + def get_gid_from_kgroup_id(kgroup_id, groups): - return [g["path"].replace("/", ".")[1:] if len(g["path"].split("/")) else g["path"][1:] for g in groups if g["id"] == kgroup_id][0] + return [ + g["path"].replace("/", ".")[1:] if len(g["path"].split("/")) else g["path"][1:] + for g in groups + if g["id"] == kgroup_id + ][0] + def get_gids_from_kgroup_ids(kgroup_ids, groups): return [get_gid_from_kgroup_id(kgroup_id, groups) for kgroup_id in kgroup_ids] @@ -49,19 +61,22 @@ def kpath2gid(path): return path.replace("/", ".")[1:] return path.replace("/", ".") + def kpath2gids(path): - path=kpath2gid(path) + path = kpath2gid(path) l = [] for i in range(len(path.split("."))): l.append(".".join(path.split(".")[: i + 1])) return l + def kpath2kpaths(path): l = [] for i in range(len(path.split("/"))): l.append("/".join(path.split("/")[: i + 1])) return l[1:] + def gid2kpath(gid): return "/" + gid.replace(".", "/") diff --git a/admin/src/admin/lib/keycloak_client.py b/admin/src/admin/lib/keycloak_client.py index 4481a36..6aa3ba9 100644 --- a/admin/src/admin/lib/keycloak_client.py +++ b/admin/src/admin/lib/keycloak_client.py @@ -11,12 +11,12 @@ from pprint import pprint import yaml from jinja2 import Environment, FileSystemLoader from keycloak import KeycloakAdmin -from .helpers import kpath2kpaths, get_recursive_groups + +from .helpers import get_recursive_groups, kpath2kpaths +from .postgres import Postgres # from admin import app -from .postgres import Postgres - class KeycloakClient: """https://www.keycloak.org/docs-api/13.0/rest-api/index.html @@ -265,7 +265,7 @@ class KeycloakClient: ## RETURNS ALL GROUPS in root list self.connect() groups = self.keycloak_admin.get_groups() - return get_recursive_groups(groups,[]) + return get_recursive_groups(groups, []) def get_group_by_id(self, group_id): self.connect() @@ -293,17 +293,17 @@ class KeycloakClient: def add_group_tree(self, path): paths = kpath2kpaths(path) - parent="/" + parent = "/" for path in paths: try: - parent_path=None if parent=="/" else parent + parent_path = None if parent == "/" else parent # print("parent: "+str(parent_path)+" path: "+path.split("/")[-1]) self.add_group(path.split("/")[-1], parent_path, skip_exists=True) - parent=path + parent = path except: # print(traceback.format_exc()) log.warning("KEYCLOAK: Group :" + path + " already exists.") - parent=path + parent = path def add_user_with_groups_and_role( self, username, first, last, email, password, role, groups diff --git a/admin/src/admin/views/ApiViews.py b/admin/src/admin/views/ApiViews.py index a01c421..1fdc6dd 100644 --- a/admin/src/admin/views/ApiViews.py +++ b/admin/src/admin/views/ApiViews.py @@ -26,12 +26,12 @@ threads = {"external": None} from keycloak.exceptions import KeycloakGetError +from ..lib.dashboard import Dashboard from ..lib.exceptions import UserExists, UserNotFound -from ..lib.dashboard import Dashboard - dashboard = Dashboard() + @app.route("/sysadmin/api/resync") @app.route("/api/resync") @login_required @@ -510,13 +510,18 @@ def dashboard_put(item): {"Content-Type": "application/json"}, ) + @app.route("/api/legal/", methods=["GET", "POST"]) # @login_required def legal_put(item): if request.method == "GET": if item == "legal": lang = request.args.get("lang") - return json.dumps({ "html": "Legal
This works! in lang: "+lang}), 200, {'Content-Type': 'application/json'} + return ( + json.dumps({"html": "Legal
This works! in lang: " + lang}), + 200, + {"Content-Type": "application/json"}, + ) # if item == "privacy": # return json.dumps({ "html": "Privacy policy
This works!"}), 200, {'Content-Type': 'application/json'} if request.method == "POST": @@ -528,7 +533,7 @@ def legal_put(item): lang = data["lang"] except: log.error(traceback.format_exc()) - return json.dumps(data), 200, {'Content-Type': 'application/json'} + return json.dumps(data), 200, {"Content-Type": "application/json"} # if item == "privacy": # data = None # try: diff --git a/admin/src/admin/views/WebViews.py b/admin/src/admin/views/WebViews.py index 37c62f7..8af0365 100644 --- a/admin/src/admin/views/WebViews.py +++ b/admin/src/admin/views/WebViews.py @@ -10,6 +10,7 @@ import traceback from pprint import pprint from uuid import uuid4 +import requests from flask import ( Response, jsonify, @@ -26,8 +27,6 @@ from admin import app from ..lib.avatars import Avatars from .decorators import is_admin -import requests - avatars = Avatars() """ OIDC TESTS """ @@ -93,6 +92,7 @@ def dashboard(provider=False): "pages/dashboard.html", title="Customization", nav="Customization", data=data ) + @app.route("/legal") @login_required def legal(): diff --git a/admin/src/nextcloud_saml_onlycerts.py b/admin/src/nextcloud_saml_onlycerts.py index e5c80ed..652c62d 100644 --- a/admin/src/nextcloud_saml_onlycerts.py +++ b/admin/src/nextcloud_saml_onlycerts.py @@ -12,7 +12,6 @@ from datetime import datetime, timedelta import psycopg2 import yaml - from admin.lib.keycloak_client import KeycloakClient from admin.lib.postgres import Postgres diff --git a/admin/src/saml_scripts/keycloak_config.py b/admin/src/saml_scripts/keycloak_config.py index 0ba6484..1b3cfb9 100644 --- a/admin/src/saml_scripts/keycloak_config.py +++ b/admin/src/saml_scripts/keycloak_config.py @@ -1,9 +1,10 @@ #!/usr/bin/env python # coding=utf-8 import json -from lib.keycloak_client import KeycloakClient import logging as log +from lib.keycloak_client import KeycloakClient + class KeycloakConfig: def __init__(self): diff --git a/admin/src/saml_scripts/lib/keycloak_client.py b/admin/src/saml_scripts/lib/keycloak_client.py index 571dc6e..2b7cae9 100644 --- a/admin/src/saml_scripts/lib/keycloak_client.py +++ b/admin/src/saml_scripts/lib/keycloak_client.py @@ -12,10 +12,10 @@ import yaml from jinja2 import Environment, FileSystemLoader from keycloak import KeycloakAdmin -# from admin import app - from .postgres import Postgres +# from admin import app + class KeycloakClient: """https://www.keycloak.org/docs-api/13.0/rest-api/index.html diff --git a/admin/src/saml_scripts/moodle_saml.py b/admin/src/saml_scripts/moodle_saml.py index b6112c4..ce8960a 100644 --- a/admin/src/saml_scripts/moodle_saml.py +++ b/admin/src/saml_scripts/moodle_saml.py @@ -12,7 +12,6 @@ from datetime import datetime, timedelta import psycopg2 import yaml - from lib.keycloak_client import KeycloakClient from lib.postgres import Postgres diff --git a/admin/src/saml_scripts/nextcloud_saml.py b/admin/src/saml_scripts/nextcloud_saml.py index c5837d9..44a3e6a 100644 --- a/admin/src/saml_scripts/nextcloud_saml.py +++ b/admin/src/saml_scripts/nextcloud_saml.py @@ -12,7 +12,6 @@ from datetime import datetime, timedelta import psycopg2 import yaml - from lib.keycloak_client import KeycloakClient from lib.postgres import Postgres diff --git a/admin/src/saml_scripts/wordpress_saml.py b/admin/src/saml_scripts/wordpress_saml.py index 1a1c452..eb2ceec 100644 --- a/admin/src/saml_scripts/wordpress_saml.py +++ b/admin/src/saml_scripts/wordpress_saml.py @@ -12,7 +12,6 @@ from datetime import datetime, timedelta import psycopg2 import yaml - from lib.keycloak_client import KeycloakClient from lib.mysql import Mysql diff --git a/admin/src/scripts/avatars.py b/admin/src/scripts/avatars.py index 0d210f9..5a791b6 100644 --- a/admin/src/scripts/avatars.py +++ b/admin/src/scripts/avatars.py @@ -12,7 +12,6 @@ from keycloak import KeycloakAdmin from minio import Minio from minio.commonconfig import REPLACE, CopySource from minio.deleteobjects import DeleteObject - from postgres import Postgres diff --git a/admin/src/scripts/reset_pwds.py b/admin/src/scripts/reset_pwds.py index 04664ba..75dc36a 100644 --- a/admin/src/scripts/reset_pwds.py +++ b/admin/src/scripts/reset_pwds.py @@ -11,7 +11,6 @@ import diceware import yaml from jinja2 import Environment, FileSystemLoader from keycloak import KeycloakAdmin - from postgres import Postgres options = diceware.handle_options(None) diff --git a/admin/src/scripts/temporary_no.py b/admin/src/scripts/temporary_no.py index b851037..f90e87f 100644 --- a/admin/src/scripts/temporary_no.py +++ b/admin/src/scripts/temporary_no.py @@ -10,7 +10,6 @@ from pprint import pprint import yaml from jinja2 import Environment, FileSystemLoader from keycloak import KeycloakAdmin - from postgres import Postgres diff --git a/admin/src/scripts/temporary_no.py.mod b/admin/src/scripts/temporary_no.py.mod index e2fe662..a6c605d 100644 --- a/admin/src/scripts/temporary_no.py.mod +++ b/admin/src/scripts/temporary_no.py.mod @@ -10,7 +10,6 @@ from pprint import pprint import yaml from jinja2 import Environment, FileSystemLoader from keycloak import KeycloakAdmin - from postgres import Postgres diff --git a/admin/src/wordpress_saml_onlycerts.py b/admin/src/wordpress_saml_onlycerts.py index e7a8e66..4644cf4 100644 --- a/admin/src/wordpress_saml_onlycerts.py +++ b/admin/src/wordpress_saml_onlycerts.py @@ -12,7 +12,6 @@ from datetime import datetime, timedelta import psycopg2 import yaml - from admin.lib.keycloak_client import KeycloakClient from admin.lib.mysql import Mysql diff --git a/docker/api/src/api/__init__.py b/docker/api/src/api/__init__.py index 1f6d631..272236f 100644 --- a/docker/api/src/api/__init__.py +++ b/docker/api/src/api/__init__.py @@ -50,4 +50,4 @@ def send_templates(path): """ Import all views """ -from .views import AvatarsViews, MenuViews, InternalViews +from .views import AvatarsViews, InternalViews, MenuViews diff --git a/docker/api/src/api/lib/avatars.py b/docker/api/src/api/lib/avatars.py index b0e2d9d..a06a0f6 100644 --- a/docker/api/src/api/lib/avatars.py +++ b/docker/api/src/api/lib/avatars.py @@ -9,9 +9,8 @@ import traceback from datetime import datetime, timedelta import yaml -from keycloak import KeycloakAdmin - from api import app as application +from keycloak import KeycloakAdmin class Avatars: diff --git a/docker/api/src/api/lib/menu.py b/docker/api/src/api/lib/menu.py index be5012b..4db35bc 100644 --- a/docker/api/src/api/lib/menu.py +++ b/docker/api/src/api/lib/menu.py @@ -12,9 +12,8 @@ import traceback from datetime import datetime, timedelta import yaml -from jinja2 import Environment, FileSystemLoader - from api import app as application +from jinja2 import Environment, FileSystemLoader def write_css(): @@ -81,7 +80,9 @@ class Menu: "https://api." + application.config["DOMAIN"] + custom["background_login"] ) custom["logo"] = "https://api." + application.config["DOMAIN"] + custom["logo"] - custom["product_logo"] = "https://api." + application.config["DOMAIN"] + custom["product_logo"] + custom["product_logo"] = ( + "https://api." + application.config["DOMAIN"] + custom["product_logo"] + ) menudict = {**custom, **{"apps_internal": apps_internal, **user_menu_dict}} menudict["user"] = {} diff --git a/docker/api/src/api/views/AvatarsViews.py b/docker/api/src/api/views/AvatarsViews.py index 9815754..56e1654 100644 --- a/docker/api/src/api/views/AvatarsViews.py +++ b/docker/api/src/api/views/AvatarsViews.py @@ -8,6 +8,7 @@ import time import traceback from uuid import uuid4 +from api import app from flask import ( Response, jsonify, @@ -18,8 +19,6 @@ from flask import ( url_for, ) -from api import app - from ..lib.avatars import Avatars avatars = Avatars() diff --git a/docker/api/src/api/views/InternalViews.py b/docker/api/src/api/views/InternalViews.py index f153311..6a2ad46 100644 --- a/docker/api/src/api/views/InternalViews.py +++ b/docker/api/src/api/views/InternalViews.py @@ -2,11 +2,11 @@ import os +from api import app from flask import Response, jsonify, redirect, render_template, request, url_for from .decorators import is_internal -from api import app @app.route("/restart", methods=["GET"]) @is_internal diff --git a/docker/api/src/api/views/MenuViews.py b/docker/api/src/api/views/MenuViews.py index 9393cc0..2ba9a7f 100644 --- a/docker/api/src/api/views/MenuViews.py +++ b/docker/api/src/api/views/MenuViews.py @@ -8,9 +8,8 @@ import time import traceback from uuid import uuid4 -from flask import Response, jsonify, redirect, render_template, request, url_for - from api import app +from flask import Response, jsonify, redirect, render_template, request, url_for from ..lib.menu import Menu @@ -36,6 +35,7 @@ def api_v2_header(format, application=False): if application == "wordpress": return render_template("header_wordpress.html") + # @app.route('/user_menu/', methods=['GET']) # @app.route('/user_menu//', methods=['GET']) # def api_v2_user_menu(format,application=False): diff --git a/docker/api/src/api/views/decorators.py b/docker/api/src/api/views/decorators.py index d9017d0..7d053c1 100644 --- a/docker/api/src/api/views/decorators.py +++ b/docker/api/src/api/views/decorators.py @@ -6,6 +6,7 @@ from functools import wraps from flask import redirect, request, url_for + def is_internal(fn): @wraps(fn) def decorated_view(*args, **kwargs): diff --git a/docker/api/src/start.py b/docker/api/src/start.py index 342f90e..84a7489 100644 --- a/docker/api/src/start.py +++ b/docker/api/src/start.py @@ -4,9 +4,8 @@ from eventlet import monkey_patch monkey_patch() -from flask_socketio import SocketIO - from api import app +from flask_socketio import SocketIO socketio = SocketIO(app) diff --git a/docker/keycloak-client/kcli.py b/docker/keycloak-client/kcli.py index bc55826..5c9d799 100644 --- a/docker/keycloak-client/kcli.py +++ b/docker/keycloak-client/kcli.py @@ -1,4 +1,5 @@ -import json, sys +import json +import sys from pprint import pprint from keycloak import KeycloakAdmin