Source code for privacyidea.models.event

# SPDX-FileCopyrightText: (C) 2025 NetKnights GmbH <https://netknights.it>
# SPDX-FileCopyrightText: (C) 2025 Paul Lettich <paul.lettich@netknights.it>
#
# SPDX-License-Identifier: AGPL-3.0-or-later
#
# This code is free software; you can redistribute it and/or
# modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
# as published by the Free Software Foundation; either
# version 3 of the License, or any later version.
#
# This code is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU AFFERO GENERAL PUBLIC LICENSE for more details.
#
# You should have received a copy of the GNU Affero General Public
# License along with this program.  If not, see <http://www.gnu.org/licenses/>.

from sqlalchemy import (
    Sequence,
    Unicode,
    Integer,
    Boolean,
    ForeignKey,
    UniqueConstraint,
)
from sqlalchemy.orm import Mapped, mapped_column, relationship

from privacyidea.lib.utils import convert_column_to_unicode
from privacyidea.models import db
from privacyidea.models.utils import MethodsMixin


[docs] class EventHandler(MethodsMixin, db.Model): """ This model holds the list of defined events and actions of this eventhandler. A handler module can be bound to an event with the corresponding condition and action. """ __tablename__ = 'eventhandler' id: Mapped[int] = mapped_column(Integer, Sequence("eventhandler_seq"), primary_key=True, nullable=False) # in fact the name is a description name: Mapped[str | None] = mapped_column(Unicode(64), unique=False, nullable=True) active: Mapped[bool | None] = mapped_column(Boolean, default=True) ordering: Mapped[int] = mapped_column(Integer, nullable=False, default=0) position: Mapped[str | None] = mapped_column(Unicode(10), default="post") # This is the name of the event in the code event: Mapped[str] = mapped_column(Unicode(255), nullable=False) # This is the identifier of an event handler module handlermodule: Mapped[str] = mapped_column(Unicode(255), nullable=False) condition: Mapped[str | None] = mapped_column(Unicode(1024), default="") action: Mapped[str | None] = mapped_column(Unicode(1024), default="") # Relationships with cascade to automatically delete child records options = relationship('EventHandlerOption', lazy='dynamic', backref='eventhandler', cascade="all, delete-orphan") conditions = relationship('EventHandlerCondition', lazy='dynamic', backref='eventhandler', cascade="all, delete-orphan") def __init__(self, name, event, handlermodule, action, condition="", ordering=0, options=None, id=None, conditions=None, active=True, position="post"): self.name = name self.ordering = ordering self.event = event self.handlermodule = handlermodule self.condition = condition self.action = action self.active = active self.position = position if id == "": id = None self.id = id
[docs] def get(self): """ Return the serialized eventhandler object including the options :return: complete dict :rytpe: dict """ d = {"active": self.active, "name": self.name, "handlermodule": self.handlermodule, "id": self.id, "ordering": self.ordering, "position": self.position or "post", "action": self.action, "condition": self.condition} event_list = [x.strip() for x in self.event.split(",")] d["event"] = event_list option_dict = {} # Fetching all options from the relationship for option in self.options: option_dict[option.Key] = option.Value d["options"] = option_dict condition_dict = {} # Fetching all conditions from the relationship for cond in self.conditions: condition_dict[cond.Key] = cond.Value d["conditions"] = condition_dict return d
[docs] class EventHandlerCondition(db.Model): """ Each EventHandler entry can have additional conditions according to the handler module """ __tablename__ = "eventhandlercondition" id: Mapped[int] = mapped_column(Integer, Sequence("eventhandlercond_seq"), primary_key=True) eventhandler_id: Mapped[int | None] = mapped_column(Integer, ForeignKey('eventhandler.id')) Key: Mapped[str] = mapped_column(Unicode(255), nullable=False) Value: Mapped[str | None] = mapped_column(Unicode(2000), default='') comparator: Mapped[str | None] = mapped_column(Unicode(255), default='equal') __table_args__ = (UniqueConstraint('eventhandler_id', 'Key', name='ehcix_1'),) def __init__(self, eventhandler_id, Key, Value, comparator="equal"): self.eventhandler_id = eventhandler_id self.Key = Key self.Value = convert_column_to_unicode(Value) self.comparator = comparator
[docs] class EventHandlerOption(db.Model): """ Each EventHandler entry can have additional options according to the handler module. """ __tablename__ = 'eventhandleroption' id: Mapped[int] = mapped_column(Integer, Sequence("eventhandleropt_seq"), primary_key=True) eventhandler_id: Mapped[int | None] = mapped_column(Integer, ForeignKey('eventhandler.id')) Key: Mapped[str] = mapped_column(Unicode(255), nullable=False) Value: Mapped[str | None] = mapped_column(Unicode(2000), default='') Type: Mapped[str | None] = mapped_column(Unicode(2000), default='') Description: Mapped[str | None] = mapped_column(Unicode(2000), default='') __table_args__ = (UniqueConstraint('eventhandler_id', 'Key', name='ehoix_1'),) def __init__(self, eventhandler_id, Key, Value, Type="", Description=""): self.eventhandler_id = eventhandler_id self.Key = Key self.Value = convert_column_to_unicode(Value) self.Type = Type self.Description = Description