diff --git a/README.md b/README.md
index 9e79af1e0..b2955bb92 100644
--- a/README.md
+++ b/README.md
@@ -172,7 +172,7 @@ de votre installation ScoDoc 7 pour passer à ScoDoc 8 (*ne pas utiliser en prod
su scodoc # si besoin
cd /opt/scodoc
source venv/bin/activate
- flask sco-create-dept DEPT
+ flask create-dept DEPT
où `DEPT` est le nom du département (un acronyme en majuscule, comme "RT", "GEA", ...).
@@ -181,7 +181,7 @@ où `DEPT` est le nom du département (un acronyme en majuscule, comme "RT", "GE
su scodoc # si besoin
cd /opt/scodoc
source venv/bin/activate
- flask sco-delete-dept DEPT
+ flask delete-dept DEPT
## Lancement serveur (développement, sur VM Linux)
diff --git a/app/auth/models.py b/app/auth/models.py
index 758a836df..84b802d18 100644
--- a/app/auth/models.py
+++ b/app/auth/models.py
@@ -194,7 +194,7 @@ class User(UserMixin, db.Model):
return user
# Permissions management:
- def has_permission(self, perm, dept=False):
+ def has_permission(self, perm: int, dept=False):
"""Check if user has permission `perm` in given `dept`.
Similar to Zope ScoDoc7 `has_permission``
@@ -382,7 +382,7 @@ class UserRole(db.Model):
id = db.Column(db.Integer, primary_key=True)
user_id = db.Column(db.Integer, db.ForeignKey("user.id"))
role_id = db.Column(db.Integer, db.ForeignKey("role.id"))
- dept = db.Column(db.String(64))
+ dept = db.Column(db.String(64)) # dept acronym
user = db.relationship(
User, backref=db.backref("user_roles", cascade="all, delete-orphan")
)
diff --git a/app/auth/routes.py b/app/auth/routes.py
index 410c5f43d..b4b98a4ea 100644
--- a/app/auth/routes.py
+++ b/app/auth/routes.py
@@ -34,7 +34,7 @@ def login():
if form.validate_on_submit():
user = User.query.filter_by(user_name=form.user_name.data).first()
if user is None or not user.check_password(form.password.data):
- flash(_("Invalid user_name or password"))
+ flash(_("Invalid user name or password"))
return redirect(url_for("auth.login"))
login_user(user, remember=form.remember_me.data)
next_page = request.args.get("next")
diff --git a/app/scodoc/VERSION.py b/app/scodoc/VERSION.py
index bd1ed9d9e..4bbb79293 100644
--- a/app/scodoc/VERSION.py
+++ b/app/scodoc/VERSION.py
@@ -1,7 +1,7 @@
# -*- mode: python -*-
# -*- coding: utf-8 -*-
-SCOVERSION = "8.0.1"
+SCOVERSION = "8.1"
SCONAME = "ScoDoc"
diff --git a/app/scodoc/sco_abs.py b/app/scodoc/sco_abs.py
index 3d9cac178..567a1c403 100644
--- a/app/scodoc/sco_abs.py
+++ b/app/scodoc/sco_abs.py
@@ -37,7 +37,6 @@ import datetime
import calendar
import cgi
-from scodoc_manager import sco_mgr
from app.scodoc import notesdb as ndb
from app.scodoc.notes_log import log
from app.scodoc.scolog import logdb
diff --git a/app/scodoc/sco_find_etud.py b/app/scodoc/sco_find_etud.py
index 5847ba519..ba08ff8e3 100644
--- a/app/scodoc/sco_find_etud.py
+++ b/app/scodoc/sco_find_etud.py
@@ -31,8 +31,8 @@ import flask
from flask import url_for, g
from flask_login import current_user
-from scodoc_manager import sco_mgr
import app
+from app.models import Departement
import app.scodoc.sco_utils as scu
import app.scodoc.notesdb as ndb
from app.scodoc.gen_tables import GenTable
@@ -270,12 +270,12 @@ def search_etud_in_accessible_depts(expnom=None, code_nip=None):
"""
result = []
accessible_depts = []
- depts = sco_mgr.get_dept_ids()
+ depts = Departement.query.filter_by(visible=True).all()
for dept in depts:
- if current_user.has_permission(Permission.ScoView, dept=dept):
+ if current_user.has_permission(Permission.ScoView, dept=dept.acronym):
if expnom or code_nip:
- accessible_depts.append(dept)
- app.set_sco_dept(dept)
+ accessible_depts.append(dept.acronym)
+ app.set_sco_dept(dept.acronym)
etuds = search_etuds_infos(expnom=expnom, code_nip=code_nip)
else:
etuds = []
diff --git a/app/scodoc/sco_formsemestre.py b/app/scodoc/sco_formsemestre.py
index af6f77d26..f09a374f1 100644
--- a/app/scodoc/sco_formsemestre.py
+++ b/app/scodoc/sco_formsemestre.py
@@ -30,7 +30,8 @@
import time
from operator import itemgetter
-from scodoc_manager import sco_mgr
+import app
+from app.models import Departement
from app.scodoc import sco_codes_parcours
from app.scodoc import sco_cache
from app.scodoc import sco_formations
@@ -474,16 +475,23 @@ def sem_est_courant(context, sem):
return (debut <= now) and (now <= fin)
-def scodoc_get_all_unlocked_sems(context):
- """Liste de tous les semestres non verrouillés de tous les départements"""
- depts = sco_mgr.get_dept_ids()
+def scodoc_get_all_unlocked_sems():
+ """Liste de tous les semestres non verrouillés de _tous_ les départements
+ (utilisé pour rapports d'activités)
+ """
+ cur_dept = g.scodoc_dept
+ depts = Departement.query.filter_by(visible=True).all()
semdepts = []
- for dept in depts:
- semdepts += [
- (sem, dept.Scolarite.Notes)
- for sem in do_formsemestre_list(dept.Scolarite.Notes)
- if sem["etat"]
- ]
+ try:
+ for dept in depts:
+ app.set_sco_dept(dept.acronym)
+ semdepts += [
+ (sem, dept)
+ for sem in do_formsemestre_list(dept.Scolarite.Notes)
+ if sem["etat"]
+ ]
+ finally:
+ app.set_sco_dept(cur_dept)
return semdepts
diff --git a/app/scodoc/sco_lycee.py b/app/scodoc/sco_lycee.py
index 60e87dbdc..14713021c 100644
--- a/app/scodoc/sco_lycee.py
+++ b/app/scodoc/sco_lycee.py
@@ -33,6 +33,7 @@ from operator import itemgetter
from flask import url_for, g
+import app
import app.scodoc.sco_utils as scu
from app.scodoc import html_sco_header
from app.scodoc import sco_formsemestre
@@ -64,11 +65,18 @@ def formsemestre_table_etuds_lycees(
def scodoc_table_etuds_lycees(context, format="html", REQUEST=None):
- """Table avec _tous_ les étudiants des semestres non verrouillés de _tous_ les départements."""
- semdepts = sco_formsemestre.scodoc_get_all_unlocked_sems(context)
+ """Table avec _tous_ les étudiants des semestres non verrouillés
+ de _tous_ les départements.
+ """
+ cur_dept = g.scodoc_dept
+ semdepts = sco_formsemestre.scodoc_get_all_unlocked_sems()
etuds = []
- for (sem, deptcontext) in semdepts:
- etuds += sco_report.tsp_etud_list(deptcontext, sem["formsemestre_id"])[0]
+ try:
+ for (sem, dept) in semdepts:
+ app.set_sco_dept(dept.acronym)
+ etuds += sco_report.tsp_etud_list(context, sem["formsemestre_id"])[0]
+ finally:
+ app.set_sco_dept(cur_dept)
tab, etuds_by_lycee = _table_etuds_lycees(
context,
diff --git a/app/scodoc/sco_utils.py b/app/scodoc/sco_utils.py
index 963202da7..deb258bff 100644
--- a/app/scodoc/sco_utils.py
+++ b/app/scodoc/sco_utils.py
@@ -54,8 +54,6 @@ from PIL import Image as PILImage
from flask import g, url_for, request
-from scodoc_manager import sco_mgr
-
from config import Config
from app.scodoc.notes_log import log
diff --git a/app/templates/scodoc.html b/app/templates/scodoc.html
index 8325544f9..c5fe5c81a 100644
--- a/app/templates/scodoc.html
+++ b/app/templates/scodoc.html
@@ -11,11 +11,11 @@
{% endif %}
- {% for dept in dept_ids %}
+ {% for dept in depts %}
-
- Département
- {{dept}}
+ Département
+ {{dept.acronym}}
{% endfor %}
diff --git a/app/views/absences.py b/app/views/absences.py
index 0f5d0dcf4..ffde5f832 100644
--- a/app/views/absences.py
+++ b/app/views/absences.py
@@ -110,7 +110,7 @@ def sco_publish(route, function, permission, methods=["GET"]):
protected by permission and called following ScoDoc 7 Zope standards.
"""
return bp.route(route, methods=methods)(
- permission_required(permission)(scodoc7func(context)(scodoc(function)))
+ scodoc(permission_required(permission)(scodoc7func(context)(function)))
)
diff --git a/app/views/notes.py b/app/views/notes.py
index 5bca53260..3d41ea05e 100644
--- a/app/views/notes.py
+++ b/app/views/notes.py
@@ -43,7 +43,6 @@ from flask import current_app
from flask_login import current_user
from config import Config
-import scodoc_manager
from app.auth.models import User
@@ -145,7 +144,7 @@ def sco_publish(route, function, permission, methods=["GET"]):
protected by permission and called following ScoDoc 7 Zope standards.
"""
return bp.route(route, methods=methods)(
- permission_required(permission)(scodoc7func(context)(function))
+ scodoc(permission_required(permission)(scodoc7func(context)(function)))
)
diff --git a/app/views/scodoc.py b/app/views/scodoc.py
index 855a418f2..6b4ee01ca 100644
--- a/app/views/scodoc.py
+++ b/app/views/scodoc.py
@@ -35,23 +35,23 @@ from flask import render_template
from flask import request
from flask_login.utils import login_required
-from scodoc_manager import sco_mgr
-
-from app.views import scodoc_bp as bp
+from app.models import Departement
from app.scodoc import VERSION
from app.scodoc import sco_find_etud
from app.scodoc.sco_permissions import Permission
+from app.views import scodoc_bp as bp
@bp.route("/ScoDoc")
@bp.route("/ScoDoc/index")
-def index(): # XXX TODO A REECRIRE
- dept_ids = sco_mgr.get_dept_ids()
+def index():
+ "Page d'accueil: liste des départements"
+ depts = Departement.query.filter_by(visible=True).all()
return render_template(
"scodoc.html",
title=VERSION.SCONAME,
current_app=flask.current_app,
- dept_ids=dept_ids,
+ depts=depts,
Permission=Permission,
)
diff --git a/app/views/scolar.py b/app/views/scolar.py
index 82ecc27c9..dfd76c41f 100644
--- a/app/views/scolar.py
+++ b/app/views/scolar.py
@@ -46,7 +46,6 @@ from flask import current_app
from flask_login import current_user
from config import Config
-import scodoc_manager
from app.decorators import (
scodoc,
scodoc7func,
@@ -116,12 +115,12 @@ from app.scodoc import sco_etud
context = ScoDoc7Context("scolar")
-def sco_publish(route, function, permission, methods=("GET",)):
+def sco_publish(route, function, permission, methods=["GET"]):
"""Declare a route for a python function,
protected by permission and called following ScoDoc 7 Zope standards.
"""
return bp.route(route, methods=methods)(
- permission_required(permission)(scodoc7func(context)(scodoc(function)))
+ scodoc(permission_required(permission)(scodoc7func(context)(function)))
)
@@ -257,7 +256,6 @@ def showEtudLog(context, etudid, format="html", REQUEST=None):
# @bp.route("/")
@bp.route("/kimo")
@scodoc
-@scodoc
@permission_required(Permission.ScoView)
@scodoc7func(context)
def kimo(context, REQUEST=None, showcodes=0, showsemtable=0):
@@ -266,9 +264,8 @@ def kimo(context, REQUEST=None, showcodes=0, showsemtable=0):
return f"{time.time()} := {g.scodoc_dept}"
-# @bp.route("/")
-@bp.route("/index_html2")
-@scodoc
+@bp.route("/")
+@bp.route("/index_html")
@scodoc
@permission_required(Permission.ScoView)
@scodoc7func(context)
diff --git a/app/views/users.py b/app/views/users.py
index 17c68411a..9b876b2f1 100644
--- a/app/views/users.py
+++ b/app/views/users.py
@@ -42,11 +42,12 @@ from flask import g
from flask_login import current_user
from app import db
-
from app.auth.models import Permission
from app.auth.models import User
from app.auth.models import Role
from app.auth.models import UserRole
+from app.models import Departement
+
from app.decorators import (
scodoc,
scodoc7func,
@@ -63,8 +64,6 @@ from app.scodoc.sco_exceptions import AccessDenied, ScoValueError
from app.scodoc.sco_permissions_check import can_handle_passwd
from app.scodoc.TrivialFormulator import TrivialFormulator, tf_error_message
from app.views import users_bp as bp
-from scodoc_manager import sco_mgr
-from six.moves import range
context = ScoDoc7Context("users") # sco8
@@ -128,7 +127,7 @@ def create_user_form(context, REQUEST, user_name=None, edit=0):
# sinon, les départements dans lesquels l'utilisateur a le droit
if is_super_admin:
log("create_user_form called by %s (super admin)" % (current_user.user_name,))
- dept_ids = sco_mgr.get_dept_ids()
+ dept_ids = [d.acronym for d in Departement.query.all()]
else:
# Si on n'est pas SuperAdmin, liste les départements dans lesquels on a la
# permission ScoUsersAdmin
diff --git a/scodoc.py b/scodoc.py
index a0fe96daf..c1e7a60da 100755
--- a/scodoc.py
+++ b/scodoc.py
@@ -145,7 +145,7 @@ def user_password(username, password=None): # user-password
@app.cli.command()
@click.argument("dept")
-def sco_delete_dept(dept): # sco-delete-dept
+def delete_dept(dept): # delete-dept
"""Delete existing departement"""
click.confirm(
f"""Attention: Cela va effacer toutes les données du département {dept}
@@ -167,7 +167,7 @@ def sco_delete_dept(dept): # sco-delete-dept
@app.cli.command()
@click.argument("dept")
-def sco_create_dept(dept): # sco-create-dept
+def create_dept(dept): # create-dept
"Create new departement"
d = models.Departement(acronym=dept)
db.session.add(d)
diff --git a/scodoc_manager.py b/scodoc_manager.py
deleted file mode 100755
index 6c301b547..000000000
--- a/scodoc_manager.py
+++ /dev/null
@@ -1,115 +0,0 @@
-# -*- coding: UTF-8 -*
-
-"""
-Manage departments, databases.
-
-Each departement `X` has its own database, `SCOX`
-and a small configuration file `.../config/depts/X.cfg`
-containing the database URI
-Old ScoDoc7 installs config files contained `dbname=SCOX`
-which translates as
-"postgresql://@localhost:5432/"
- being given by `SCODOC7_SQL_USER` env variable.
-"""
-import os
-import re
-import glob
-import logging
-
-from flask import g
-
-from config import Config
-
-from app.scodoc.sco_exceptions import ScoConfigurationError
-
-
-class ScoDeptDescription(object):
- """Description d'un département
- .dept_id : eg "RT"
- .db_uri : dept database URI
- """
-
- def __init__(self, filename):
- """Read dept description from dept file"""
- if os.path.split(filename)[1][-4:] != ".cfg":
- raise ScoConfigurationError("Invalid dept config filename: %s" % filename)
- self.dept_id = os.path.split(filename)[1][:-4]
- if not self.dept_id:
- raise ScoConfigurationError("Invalid dept config filename: %s" % filename)
- try:
- db_uri = open(filename).read().strip()
- except:
- raise ScoConfigurationError("Department config file missing: %s" % filename)
- m = re.match(r"dbname=SCO([a-zA-Z0-9]+$)", db_uri)
- if m:
- # ScoDoc7 backward compat
- dept = m.group(1) # unused in ScoDoc7
- db_name = "SCO" + self.dept_id.upper()
- db_uri = "postgresql://%(db_user)s@localhost:%(db_port)s/%(db_name)s" % {
- "db_user": Config.SCODOC7_SQL_USER,
- "db_name": db_name,
- "db_port": Config.DEFAULT_SQL_PORT,
- }
- self.db_uri = db_uri
-
-
-class ScoDocManager(object):
- """Gestion de la liste des départements
- En ScoDoc8, c'est très simple: on intègre tous les départements pour
- lesquels un fichier de config est présent.
- """
-
- def __init__(self):
- _ = self.get_dept_descriptions()
-
- def get_dept_descriptions(self):
- filenames = glob.glob(Config.SCODOC_VAR_DIR + "/config/depts/*.cfg")
- descr_list = [ScoDeptDescription(f) for f in filenames]
- self._dept_descriptions = {d.dept_id: d for d in descr_list}
- return self._dept_descriptions
-
- def get_dept_db_uri(self, dept_id):
- "DB URI for this dept id"
- return self._dept_descriptions[dept_id].db_uri
-
- def get_dept_ids(self):
- "get (sorted) dept ids"
- return sorted(self.get_dept_descriptions().keys())
-
- def get_db_uri(self):
- """
- Returns DB URI for the "current" departement.
- Replaces ScoDoc7 GetDBConnexionString()
- """
- return self.get_dept_db_uri(g.scodoc_dept)
-
-
-sco_mgr = ScoDocManager()
-
-
-class FakeUsers(object):
- """Temporary for ScoDoc8 devs"""
-
- def __init__(self):
- logging.getLogger(__name__).info("Warning: creating a FakeUser instance !")
-
- def user_info(self, user_name="test8", REQUEST=None):
- return {
- "user_name": user_name,
- "nom": user_name,
- "prenom": "",
- "email": "",
- "dept": "",
- "nomprenom": user_name,
- "prenomnom": user_name,
- "prenom_fmt": "",
- "nom_fmt": user_name,
- "nomcomplet": user_name,
- "nomplogin": user_name,
- "passwd_temp": 0,
- "status": "",
- "date_expiration": None,
- }
-
- def get_user_list(self, dept=None, with_inactives=False):
- return [self.user_info()]
diff --git a/tests/unit/sco_fake_gen.py b/tests/unit/sco_fake_gen.py
index 130bae44e..9cf9276e4 100644
--- a/tests/unit/sco_fake_gen.py
+++ b/tests/unit/sco_fake_gen.py
@@ -15,7 +15,6 @@ import string
import typing
-import scodoc_manager
from config import Config
from app.auth.models import User
from app.models import NotesFormModalite