Example #1
0
def _transfer_to_user_amendement_on_import(request: Request, lecture: Lecture,
                                           amendement: Amendement, item: dict,
                                           team: Team) -> None:
    email = User.normalize_email(item["affectation_email"])

    if not User.email_is_well_formed(email):
        logger.warning("Invalid email address %r", email)
        return

    user, created = get_one_or_create(User, email=email)
    if created:
        affectation_name = User.normalize_name(item["affectation_name"])
        user.name = affectation_name if affectation_name != "" else email
        user.teams.append(team)

    user_table, _ = get_one_or_create(UserTable, user=user, lecture=lecture)
    if amendement.location.user_table is user_table:
        return

    old = amendement.table_name_with_email
    new = str(user)

    amendement.location.user_table = user_table
    amendement.location.shared_table = None

    AmendementTransfere.create(amendement=amendement,
                               old_value=old,
                               new_value=new,
                               request=request)
Example #2
0
def fetch_amendements_for_dossier(
    dossier_ref: DossierRef,
    chambre: Optional[str],
    num: Optional[int],
    settings: Dict[str, Any],
) -> None:
    dossier, _ = get_one_or_create(
        Dossier,
        an_id=dossier_ref.uid,
        create_kwargs=dict(titre=dossier_ref.titre, slug=dossier_ref.slug),
    )
    for lecture_ref in dossier_ref.lectures:
        texte_ref = lecture_ref.texte
        if chambre is not None and texte_ref.chambre.name.lower() != chambre:
            continue
        if num is not None and texte_ref.numero != num:
            continue
        texte, _ = get_one_or_create(
            Texte,
            type_=texte_ref.type_,
            chambre=texte_ref.chambre,
            legislature=texte_ref.legislature,
            session=texte_ref.session,
            numero=texte_ref.numero,
            date_depot=texte_ref.date_depot,
        )
        lecture = Lecture.create(
            phase=lecture_ref.phase,
            dossier=dossier,
            texte=texte,
            partie=lecture_ref.partie,
            organe=lecture_ref.organe,
            titre=lecture_ref.titre,
        )
        fetch_amendements_for_lecture(lecture, settings)
Example #3
0
    def post(self) -> Any:
        email = self.request.params.get("email")
        if not email:
            self.request.session["missing_email"] = True
            return HTTPFound(location=self.request.route_url("user_login"))

        email = User.normalize_email(email)
        if not User.validate_email(email):
            self.request.session["incorrect_email"] = True
            return HTTPFound(location=self.request.route_url("user_login"))

        user, created = get_one_or_create(User, email=email)

        # Automatically add user without a team to the authenticated team
        if not user.teams and self.request.team is not None:
            user.teams.append(self.request.team)

        if created:
            DBSession.flush()  # so that the DB assigns a value to user.pk

        # Prevent from impersonating an existing member of another team
        if self.request.team and self.request.team not in user.teams:
            self.request.session["already_in_use"] = True
            return HTTPFound(location=self.request.route_url("user_login"))

        user.last_login_at = datetime.utcnow()

        next_url = self.next_url
        if not user.name:
            next_url = self.request.route_url("welcome", _query={"source": next_url})

        headers = remember(self.request, user.pk)

        return HTTPFound(location=next_url, headers=headers)
Example #4
0
 def _find_or_create_users(self, emails: List[str]) -> Tuple[List[User], List[User]]:
     new_users = []
     existing_users = []
     for email in emails:
         user, created = get_one_or_create(User, email=email)
         if created:
             new_users.append(user)
         else:
             existing_users.append(user)
     return new_users, existing_users
Example #5
0
 def _get_article(self, lecture: Lecture) -> Article:
     article: Article
     created: bool
     article, created = get_one_or_create(
         Article,
         lecture=lecture,
         type=self.subdiv.type_,
         num=self.subdiv.num,
         mult=self.subdiv.mult,
         pos=self.subdiv.pos,
     )
     return article
Example #6
0
    def _create_or_update_amendement(
        self,
        lecture: Lecture,
        article: Optional[Article],
        parent: Optional[Amendement],
        amend: OrderedDict,
        position: Optional[int],
        id_discussion_commune: Optional[int],
        id_identique: Optional[int],
    ) -> Tuple[Amendement, bool]:
        amendement, created = get_one_or_create(
            Amendement,
            create_kwargs={
                "article": article,
                "parent": parent
            },
            lecture=lecture,
            num=int(amend["numero"]),
        )

        raw_auteur = amend.get("auteur")
        if not raw_auteur:
            logger.warning("Unknown auteur for amendement %s", amend["numero"])
            matricule, groupe, auteur = "", "", ""
        else:
            matricule = raw_auteur["tribunId"]
            groupe = get_groupe(raw_auteur, amendement.num)
            auteur = get_auteur(raw_auteur)

        modified = False
        modified |= self.update_rectif(amendement, get_rectif(amend))
        modified |= self.update_corps(
            amendement, unjustify(get_str_or_none(amend, "dispositif") or ""))
        modified |= self.update_expose(
            amendement,
            unjustify(get_str_or_none(amend, "exposeSommaire") or ""))
        modified |= self.update_sort(amendement, get_sort(amend))
        modified |= self.update_attributes(
            amendement,
            article=article,
            parent=parent,
            position=position,
            id_discussion_commune=id_discussion_commune,
            id_identique=id_identique,
            matricule=matricule,
            groupe=groupe,
            auteur=auteur,
        )

        DBSession.flush()  # make sure foreign keys are updated

        return amendement, created
Example #7
0
def _get_article(lecture: Lecture, division: dict) -> Article:
    subdiv = parse_division(division)
    article: Article
    created: bool
    article, created = get_one_or_create(
        Article,
        lecture=lecture,
        type=subdiv.type_,
        num=subdiv.num,
        mult=subdiv.mult,
        pos=subdiv.pos,
    )
    return article
Example #8
0
def find_or_create_articles(lecture: Lecture, article_data: dict) -> List[Article]:
    nums_mults = get_article_nums_mults(article_data)
    return [
        get_one_or_create(
            Article,
            lecture=lecture,
            type=article_data["type"],
            num=num,
            mult=mult,
            pos="",
        )[0]
        for num, mult in nums_mults
    ]
Example #9
0
def _get_parent(lecture: Lecture, article: Article,
                amend: OrderedDict) -> Optional[Amendement]:
    parent_num, parent_rectif = Amendement.parse_num(get_parent_raw_num(amend))
    parent: Optional[Amendement]
    if parent_num:
        parent, created = get_one_or_create(
            Amendement,
            create_kwargs={
                "article": article,
                "rectif": parent_rectif
            },
            lecture=lecture,
            num=parent_num,
        )
    else:
        parent = None
    return parent
Example #10
0
File: auth.py Project: betagouv/zam
    def get(self) -> Any:

        if self.ip_limiter.exceeded(self.request.remote_addr):
            return HTTPTooManyRequests()

        if self.request.unauthenticated_userid:
            return HTTPFound(location=self.next_url)

        token = self.request.params.get("token")
        auth = repository.get_auth_token_data(token)
        if auth is None:
            self.log_failed_login_attempt(token)
            self.request.session.flash(
                Message(
                    cls="error",
                    text="Le lien est invalide ou a expiré. Merci de renouveler votre demande.",  # noqa
                )
            )
            raise HTTPFound(location=self.request.route_url("login"))

        # Delete token from repository after it's been used successfully
        repository.delete_auth_token(token)

        email = auth["email"]
        user, created = get_one_or_create(User, email=email)

        if created:
            DBSession.flush()  # so that the DB assigns a value to user.pk

        self.log_successful_login_attempt(email)

        user.last_login_at = datetime.utcnow()

        next_url = self.next_url
        if not user.name:
            next_url = self.request.route_url("welcome", _query={"source": next_url})

        # Compute response headers for the session cookie
        headers = remember(self.request, user.pk)

        app_name = self.request.registry.settings["zam.app_name"]
        self.request.session.flash(
            Message(cls="success", text=f"Bienvenue dans {app_name} !")
        )

        return HTTPFound(location=next_url, headers=headers)
Example #11
0
 def post(self) -> Response:
     titre: str = self.request.POST.get("titre")
     table, created = get_one_or_create(SharedTable,
                                        titre=titre,
                                        lecture=self.lecture)
     if created:
         SharedTableCreee.create(lecture=self.lecture,
                                 titre=titre,
                                 request=self.request)
         self.request.session.flash(
             Message(cls="success",
                     text=f"Boîte « {table.titre} » créée avec succès."))
     else:
         self.request.session.flash(
             Message(cls="warning",
                     text=f"La boîte « {table.titre} » existe déjà…"))
     return HTTPFound(location=self.request.resource_url(
         self.context.lecture_resource, "options", anchor="shared-tables"))
Example #12
0
def _transfer_to_box_amendement_on_import(request: Request, lecture: Lecture,
                                          amendement: Amendement,
                                          item: dict) -> None:
    shared_table, created = get_one_or_create(SharedTable,
                                              titre=item["affectation_box"],
                                              lecture=lecture)

    if amendement.location.shared_table is shared_table:
        return

    old = amendement.table_name_with_email
    new = shared_table.titre

    amendement.location.shared_table = shared_table
    amendement.location.user_table = None

    AmendementTransfere.create(amendement=amendement,
                               old_value=old,
                               new_value=new,
                               request=request)
Example #13
0
def transfer_amendement(
    request: Request, lecture: Lecture, amendement: Amendement, item: dict
) -> None:
    email = User.normalize_email(item["affectation_email"])

    if not User.validate_email(email):
        logging.warning("Invalid email address %r", email)
        return

    user, created = get_one_or_create(User, email=email)
    if created:
        affectation_name = User.normalize_name(item["affectation_name"])
        user.name = affectation_name if affectation_name != "" else email
        if lecture.owned_by_team:
            user.teams.append(lecture.owned_by_team)

    target_table = user.table_for(lecture)
    old = str(amendement.user_table.user) if amendement.user_table else ""
    new = str(target_table.user) if target_table else ""
    if amendement.user_table is target_table:
        return
    amendement.user_table = target_table
    AmendementTransfere.create(request, amendement, old, new)
Example #14
0
def update_lecture_articles(lecture: Lecture, all_article_data: List[dict]) -> bool:
    changed = False
    for index, article_data in enumerate(all_article_data):
        if article_data["type"] in {"texte", "section", "dots"}:
            continue
        elif article_data["type"] == "annexe":
            articles = [
                get_one_or_create(
                    Article,
                    lecture=lecture,
                    type=article_data["type"],
                    num=str(index),  # To avoid override in case of many annexes.
                )[0]
            ]
        else:
            if "titre" not in article_data:
                continue
            articles = find_or_create_articles(lecture, article_data)
        for article in articles:
            changed |= update_article_contents(article, article_data)
            changed |= set_default_article_title(
                article, article_data, partial(get_section_title, all_article_data)
            )
    return changed
Example #15
0
def _make_amendement(
    node: etree.Element, uid_map: Dict[str, Amendement], lecture: Lecture
) -> Amendement:
    extract = partial(extract_from_node, node)

    subdiv = _parse_division(node)

    texte_uid = extract("identifiant", "saisine", "refTexteLegislatif")
    if texte_uid is None:
        raise ValueError("Missing refTexteLegislatif")

    is_gouvernemental = extract("signataires", "auteur", "typeAuteur") == "Gouvernement"

    if is_gouvernemental:
        auteur_name = "LE GOUVERNEMENT"
        groupe_name = None
        matricule = None
    else:
        auteur_uid = extract("signataires", "auteur", "acteurRef")
        if auteur_uid is None:
            raise ValueError("Missing auteur acteurRef")
        auteur_name = get_auteur_name(auteur_uid)
        matricule = auteur_uid

        groupe_uid = extract("signataires", "auteur", "groupePolitiqueRef")
        if groupe_uid is None:
            raise ValueError("Missing auteur groupePolitiqueRef")
        groupe_name = get_groupe_name(groupe_uid)

    check_same_lecture(
        lecture=lecture,
        session=extract("identifiant", "legislature"),
        partie=extract_partie(node),
        organe=extract("identifiant", "saisine", "organeExamen"),
        texte_uid=texte_uid,
    )

    article, created = get_one_or_create(
        Article,
        lecture=lecture,
        type=subdiv.type_,
        num=subdiv.num,
        mult=subdiv.mult,
        pos=subdiv.pos,
    )
    parent = get_parent(extract("amendementParent"), uid_map, lecture)
    amendement, created = get_one_or_create(
        Amendement,
        create_kwargs={"article": article, "parent": parent},
        lecture=lecture,
        num=to_int(extract("identifiant", "numero")),
    )
    if not created:
        amendement.article = article
        amendement.parent = parent
    amendement.alinea = to_int(extract("pointeurFragmentTexte", "alinea", "numero"))
    amendement.auteur = auteur_name
    amendement.matricule = matricule
    amendement.groupe = groupe_name
    amendement.date_depot = to_date(extract("dateDepot"))
    amendement.sort = get_sort(
        sort=extract("sort", "sortEnSeance"), etat=extract("etat")
    )
    amendement.corps = clean_html(extract("corps", "dispositif") or "")
    amendement.expose = clean_html(extract("corps", "exposeSommaire") or "")
    return cast(Amendement, amendement)
Example #16
0
    def post(self) -> Response:
        dossier_ref = self._get_dossier_ref()
        lecture_ref = self._get_lecture_ref(dossier_ref)

        chambre = lecture_ref.chambre.value
        titre = lecture_ref.titre
        organe = lecture_ref.organe
        partie = lecture_ref.partie

        session = lecture_ref.get_session()
        texte = lecture_ref.texte

        assert texte.date_depot is not None

        texte_model = get_one_or_create(
            TexteModel,
            uid=texte.uid,
            type_=texte.type_,
            chambre=Chambre.AN
            if lecture_ref.chambre.value == "an" else Chambre.SENAT,
            legislature=int(session) if chambre == "an" else None,
            session=int(session.split("-")[0]) if chambre == "senat" else None,
            numero=texte.numero,
            titre_long=texte.titre_long,
            titre_court=texte.titre_court,
            date_depot=texte.date_depot,
        )[0]

        dossier_model = get_one_or_create(DossierModel,
                                          uid=dossier_ref.uid,
                                          titre=dossier_ref.titre)[0]

        if LectureModel.exists(chambre, session, texte_model, partie, organe):
            self.request.session.flash(
                Message(cls="warning", text="Cette lecture existe déjà…"))
            return HTTPFound(location=self.request.resource_url(self.context))

        lecture_model: LectureModel = LectureModel.create(
            owned_by_team=self.request.team,
            chambre=chambre,
            session=session,
            texte=texte_model,
            partie=partie,
            titre=titre,
            organe=organe,
            dossier=dossier_model,
        )
        get_articles(lecture_model)
        LectureCreee.create(self.request, lecture=lecture_model)
        ArticlesRecuperes.create(request=None, lecture=lecture_model)
        # Call to fetch_* tasks below being asynchronous, we need to make
        # sure the lecture_model already exists once and for all in the database
        # for future access. Otherwise, it may create many instances and
        # thus many objects within the database.
        transaction.commit()
        fetch_amendements(lecture_model.pk)
        self.request.session.flash(
            Message(
                cls="success",
                text=
                ("Lecture créée avec succès, amendements en cours de récupération."
                 ),
            ))
        return HTTPFound(location=self.request.resource_url(
            self.context[lecture_model.url_key], "amendements"))