diff --git a/app/api/partitions.py b/app/api/partitions.py index bc534cf7..c3aa736d 100644 --- a/app/api/partitions.py +++ b/app/api/partitions.py @@ -9,9 +9,8 @@ """ from flask import abort, jsonify, request +from app import db from app.api import bp - -from app.api.errors import error_response from app.api.auth import token_auth, token_permission_required from app.models import FormSemestre, FormSemestreInscription, Identite from app.models import GroupDescr, Partition @@ -90,6 +89,8 @@ def etud_in_group(group_id: int): @bp.route("/group//etudiants/query", methods=["GET"]) +@token_auth.login_required +@token_permission_required(Permission.APIView) def etud_in_group_query(group_id: int): """Etudiants du groupe, filtrés par état""" etat = request.get("etat", "") @@ -104,3 +105,83 @@ def etud_in_group_query(group_id: int): ) return jsonify([etud.to_dict_short() for etud in query]) + + +@bp.route("/group//set_etudiant/", methods=["POST"]) +@token_auth.login_required +@token_permission_required(Permission.APIEditGroups) +def set_etud_group(etudid: int, group_id: int): + """Affecte l'étudiant au groupe indiqué""" + etud = Identite.query.get_or_404(etudid) + group = GroupDescr.query.get_or_404(group_id) + if etud.id not in {e.id for e in group.partition.formsemestre.etuds}: + abort(404, "etud non inscrit au formsemestre du groupe") + groups = ( + GroupDescr.query.filter_by(partition_id=group.partition.id) + .join(group_membership) + .filter_by(etudid=etudid) + ) + ok = False + for group in groups: + if group.id == group_id: + ok = True + else: + group.etuds.remove(etud) + if not ok: + group.etuds.append(etud) + db.session.commit() + return jsonify({"group_id": group_id, "etudid": etudid}) + + +@bp.route("/partition//group/create", methods=["POST"]) +@token_auth.login_required +@token_permission_required(Permission.APIEditGroups) +def group_create(partition_id: int): + """Création d'un groupe dans une partition + + The request content type should be "application/json": + { + "group_name" : nom_du_groupe, + } + """ + partition: Partition = Partition.query.get_or_404(partition_id) + data = request.get_json(force=True) # may raise 400 Bad Request + group_name = data.get("group_name") + if group_name is None: + abort(404, "missing group name or invalid data format") + if not GroupDescr.check_name(partition, group_name): + abort(404, "invalid group_name") + group_name = group_name.strip() + + group = GroupDescr(group_name=group_name, partition_id=partition_id) + db.session.add(group) + db.session.commit() + return jsonify(group.to_dict(with_partition=True)) + + +@bp.route("/group//delete", methods=["POST"]) +@token_auth.login_required +@token_permission_required(Permission.APIEditGroups) +def group_delete(group_id: int): + """Delete group""" + group = GroupDescr.query.get_or_404(group_id) + db.session.delete(group) + db.session.commit() + return jsonify({"OK": 1}) + + +@bp.route("/group//edit", methods=["POST"]) +@token_auth.login_required +@token_permission_required(Permission.APIEditGroups) +def group_edit(group_id: int): + """Edit a group""" + group: GroupDescr = GroupDescr.query.get_or_404(group_id) + data = request.get_json(force=True) # may raise 400 Bad Request + group_name = data.get("group_name") + if group_name is not None: + if not GroupDescr.check_name(group.partition, group_name, existing=True): + abort(404, "invalid group_name") + group.group_name = group_name.strip() + db.session.add(group) + db.session.commit() + return jsonify(group.to_dict(with_partition=True)) diff --git a/app/models/groups.py b/app/models/groups.py index 4eca1ca7..dc3ac510 100644 --- a/app/models/groups.py +++ b/app/models/groups.py @@ -104,6 +104,21 @@ class GroupDescr(db.Model): d["partition"] = self.partition.to_dict(with_groups=False) return d + @classmethod + def check_name( + cls, partition: "Partition", group_name: str, existing=False + ) -> bool: + """check if a group named 'group_name' can be created in the given partition. + If existing is True, allow a group_name already existing in the partition. + """ + if not isinstance(group_name, str): + return False + if not len(group_name.strip()) > 0: + return False + if (not existing) and (group_name in [g.group_name for g in partition.groups]): + return False + return True + group_membership = db.Table( "group_membership", diff --git a/app/scodoc/sco_permissions.py b/app/scodoc/sco_permissions.py index fd04e510..2a68b1a4 100644 --- a/app/scodoc/sco_permissions.py +++ b/app/scodoc/sco_permissions.py @@ -51,7 +51,7 @@ _SCO_PERMISSIONS = ( # 27 à 39 ... réservé pour "entreprises" # Api scodoc9 (1 << 40, "APIView", "API: Lecture"), - (1 << 41, "APIEtudChangeGroups", "API: Modifier les groupes"), + (1 << 41, "APIEditGroups", "API: Modifier les groupes"), (1 << 42, "APIEditAllNotes", "API: Modifier toutes les notes"), (1 << 43, "APIAbsChange", "API: Saisir des absences"), )