コード例 #1
0
ファイル: user.py プロジェクト: Res260/flaggr
class User(UserMixin, DB.Model):
    """
    User model

    A user of the application (event participant or admin). A user is only represented by its username and
    authenticates on the platform with its email and password.
    """

    __tablename__ = 'Users'

    id = DB.Column(DB.Integer, primary_key=True)
    """The unique ID of the user. Should be generated by the database. Used as primary key."""
    email = DB.Column(DB.String(255), index=True)
    """The user's email. Unique. Max 255 characters."""
    username = DB.Column(DB.String(64), index=True)
    """The user's display name. Unique. Max 64 characters."""
    password_hash = DB.Column(DB.String(128))
    """
    The hash of the user's password. Should always be set with the 'set_password' method. Max
    128 characters.
    """

    teams = association_proxy('teamInfo', 'team')

    def set_password(self, password: str):
        """Hash and set the user's password"""
        self.password_hash = generate_password_hash(password)

    def check_password(self, password: str) -> bool:
        """Check whether or not this is the user's password"""
        return check_password_hash(self.password_hash, password)

    def get_team(self) -> Optional[Team]:
        """
        :return: The team of the user, or none if the user has no team.
        """
        participant = self.get_participant()
        return None if not participant else participant.get_team()

    def get_participant(self) -> Optional[Participant]:
        """
        :return: The participant associated with the user, or none if the user has no participant.
        """
        return Participant.query.filter_by(user_id=self.id).first()

    def get_administrator(self) -> Optional[Administrator]:
        """
        :return: The administrator associated with the user, or none if the user has no administrator.
        """
        return Administrator.query.filter_by(user_id=self.id).first()

    def __repr__(self):
        return '<User id:{} email:{} username:{}>'.format(
            self.id, self.email, self.username)

    def __eq__(self, other):
        return self.id == other.id and \
               self.email == other.email and \
               self.username == other.username and \
               self.password_hash == other.password_hash
コード例 #2
0
class Category(DB.Model):
    """
    Category model

    A category groups challenges together under a common theme (programming, web, etc).
    A category is associated to a single event and should have a unique name within that event
    (events A and B can both have a category C, but event A cannot have two categories C).
    """

    __tablename__ = 'Categories'

    id = DB.Column(DB.Integer, primary_key=True)
    """The unique ID of the category. Should be generated by the database. Used as primary key."""
    event_id = DB.Column(DB.Integer, ForeignKey('Events.id'), nullable=True)
    """The ID of the event the category belongs to. Used as foreign key."""
    name = DB.Column(DB.String(64), index=True)
    """The name of the category. Max 64 characters."""

    __table_args__ = (UniqueConstraint('event_id',
                                       'name',
                                       name='categories_event_name_uc'), )

    challenges = relationship('Challenge', lazy='noload')

    def __repr__(self):
        return '<Category id:{} event_id:{} name:{}>'.format(
            self.id, self.event_id, self.name)

    def __eq__(self, other):
        return self.id == other.id and \
            self.name == other.name and \
            self.event_id == other.event_id
コード例 #3
0
ファイル: event.py プロジェクト: Res260/flaggr
class Event(DB.Model):
    """
    Event model

    The core of the application. An event's only defining characteristic is its name, which must be
    unique (i.e. 'CS Games 2019', 'United CTF 2019', etc). The rest is all handled by relations with
    the application's other models.
    """

    __tablename__ = 'Events'

    id = DB.Column(DB.Integer, primary_key=True)
    """The unique ID of the event. Should be generated by the database. Used as primary key."""
    name = DB.Column(DB.String(64), index=True, unique=True)
    """The name of the event. Max 64 characters."""
    front_page = DB.Column(DB.Text())
    """The front page content of the event. Markdown text that will be parsed by frontend."""
    teams = DB.Column(DB.Boolean)
    """Whether participants have to register as teams or individually."""
    url = DB.Column(DB.String(255), default="")
    """The URL of the event."""
    flag_format = DB.Column(DB.String(64), default="")
    """The flag format used by most challenges."""
    is_open = DB.Column(DB.Boolean, default=False)
    """Whether flag submission is open or not."""
    is_visible = DB.Column(DB.Boolean, default=False)
    """Whether the event is currently visible or not."""

    event_administrators = relationship('EventAdministrator',
                                        back_populates='event')
    administrators = association_proxy('event_administrators', 'administrator')

    def __repr__(self):
        return '<Event id:{} name:{} teams: {}>'.format(
            self.id, self.name, self.teams)

    def __eq__(self, other):
        return self.id == other.id and \
               self.name == other.name and \
               self.front_page == other.front_page and \
               self.teams == other.teams and \
               self.url == other.url and \
               self.flag_format == other.flag_format and \
               self.is_open == other.is_open and \
               self.is_visible == other.is_visible
コード例 #4
0
ファイル: challenge.py プロジェクト: Res260/flaggr
class Challenge(DB.Model):
    """
    Challenge model

    A challenge an event participant has to solve. A challenge is always associated with a
    category and is composed of a (relatively) short name, an arbitrarily long description (which
    might include nothing at all, or a very complex, multi-chapter backstory, and a number of points
    to be awarded upon challenge completion.

    A challenge may also be hidden from event participants if it is for example in a draft stage or
    simply not yet released.
    """

    __tablename__ = 'Challenges'

    id = DB.Column(DB.Integer, primary_key=True)
    """The unique ID of the challenge. Should be generated by the database. Used as primary key."""
    category_id = DB.Column(DB.Integer,
                            ForeignKey('Categories.id'),
                            nullable=True)
    """The ID of the category the challenge belongs to. Used as foreign key."""
    name = DB.Column(DB.String(255), index=True)
    """The name of the challenge. Max 255 characters."""
    description = DB.Column(DB.Text())
    """The description of the event. Can be arbitrarily long."""
    points = DB.Column(DB.Integer)
    """The number of points the challenge is worth."""
    hidden = DB.Column(DB.Boolean)
    """Whether or not the challenge should be visible by the event participants."""

    flags = relationship('Flag', lazy='joined')

    category = relationship('Category', lazy='joined')

    category = relationship('Category', lazy='select')

    submissions = relationship('Submission', lazy='noload')

    solves = relationship(
        'Submission',
        primaryjoin="and_(Challenge.id==Submission.challenge_id,"
        "     Submission.is_correct == True)")

    is_solved: bool

    def __repr__(self):
        return '<Challenge id:{} category_id:{} name:{} description:{} points:{}>'\
            .format(self.id, self.category_id, self.name, self.description, self.points)

    def __eq__(self, other):
        return self.id == other.id and \
               self.category_id == other.category_id and \
               self.name == other.name and \
               self.description == other.description and \
               self.points == other.points and \
               self.hidden == other.hidden
コード例 #5
0
class Role(DB.Model):
    """
    Role model

    A role defines the actions that an administrator is or is not allowed to perform for a given
    event. For example, an administrator needs the role "challenge designer" to be allowed to create
    challenges.
    """

    __tablename__ = 'Roles'

    id = DB.Column(DB.Integer, primary_key=True)
    """The unique ID of the role. Should be generated by the database. Used as primary key."""
    label = DB.Column(DB.String(64), unique=True)
    """The label of the role"""
    def __repr__(self):
        return '<Role id:{} label:{}'.format(self.id, self.label)
コード例 #6
0
ファイル: submission.py プロジェクト: Res260/flaggr
class Submission(DB.Model):
    """
    Submission model

    A submission is an attempt from an event participant to solve a challenge.
    """

    __tablename__ = 'Submissions'

    id = DB.Column(DB.Integer, primary_key=True)
    """The unique ID of the submission. Should be generated by the database. Used as primary key."""
    team_id = DB.Column(DB.Integer, ForeignKey('Teams.id'), nullable=True)
    """The ID of the team who made the submission. Used as foreign key."""
    challenge_id = DB.Column(DB.Integer, ForeignKey('Challenges.id'), nullable=True)
    """The ID of the challenge that this submission attempted to solve. Used as foreign key."""
    input = DB.Column(DB.String(64))
    """The solution that was submitted."""
    is_correct = DB.Column(DB.Boolean)
    """Whether or not the submission is correct."""
    time = DB.Column(DB.DateTime, server_default=func.now())
    """The date and time of the submission."""

    team = relationship(Team, back_populates='submissions')
    """The team that did the submission"""
    challenge = relationship(Challenge, lazy='noload')
    """The challenge that the submission belongs to"""

    def __repr__(self):
        return '<Submission id:{} team_id:{} challenge_id:{} input:{} is_correct:{}>'\
            .format(self.id, self.team_id, self.challenge_id, self.input, self.is_correct)

    def __eq__(self, other):
        return self.id == other.id and \
            self.team_id == other.team_id and \
            self.challenge_id == other.challenge_id and \
            self.input == other.input and \
            self.is_correct == other.is_correct and \
            self.time == other.time
コード例 #7
0
ファイル: team.py プロジェクト: Res260/flaggr
class Team(DB.Model):
    """
    Team model

    A team is a grouping of participants who compete together. A team must always have at least one
    member.
    """
    __tablename__ = 'Teams'
    __table_args__ = (UniqueConstraint('event_id',
                                       'name',
                                       name='team_event_name_uc'), )

    id = DB.Column(DB.Integer, primary_key=True)
    """The unique ID of the team. Should be generated by the database. Used as primary key."""
    event_id = DB.Column(DB.Integer, ForeignKey('Events.id'), nullable=True)
    """The ID of the event the team is registered to. Used as foreign key."""
    name = DB.Column(DB.String(64), index=True)
    """The name of the team. Two teams competing in the same event cannot have the same name."""

    members = relationship('TeamMember', lazy="joined", back_populates="team")
    submissions = relationship('Submission',
                               lazy="joined",
                               back_populates="team")
    requests = relationship('TeamRequest', lazy='joined')
    event = relationship(Event, lazy='noload')

    def __repr__(self):
        return '<Team id:{} event_id:{} name:{}>'.format(
            self.id, self.event_id, self.name)

    def __eq__(self, other):
        return self.id == other.id and \
               self.event_id == other.event_id and \
               self.name == other.name

    def __hash__(self):
        return hash(self.__dict__.values())