Beispiel #1
0
class Mail(BaseModel):
    __tablename__ = 'mail'
    subject = db.Column(db.Text, nullable=False)
    content = db.Column(db.Text, nullable=False)
    sender_id = db.Column(db.Integer,
                          db.ForeignKey('users.id'),
                          nullable=False)
    receiver_id = db.Column(db.Integer,
                            db.ForeignKey('users.id'),
                            nullable=False)
    read = db.Column(db.Integer, nullable=False, default=0)

    def serialize(self):
        return {
            'id': self.id,
            'created': self.created_as_string,
            'subject': self.subject,
            'content': self.content,
            'read': self.read,
            'sender': self.sender.serialize(),
            'receiver': self.receiver.serialize(),
        }

    def __repr__(self):
        return "<Mail '{}'>".format(self.id)
Beispiel #2
0
class Membership(BaseModel):
    __tablename__ = 'memberships'
    user_id = db.Column(db.Integer, db.ForeignKey('users.id'))
    room_id = db.Column(db.Integer, db.ForeignKey('rooms.id'))
    level = db.Column(db.Integer, nullable=False, default=1)
    user = db.relationship("User",
                           backref=db.backref('memberships',
                                              lazy='dynamic',
                                              cascade="all, delete-orphan"))
    room = db.relationship("Room",
                           backref=db.backref('memberships',
                                              lazy='dynamic',
                                              cascade="all, delete-orphan"))
    __table_args__ = (db.UniqueConstraint('user_id',
                                          'room_id',
                                          name='membership_id'), )

    def serialize(self, include_results=False):
        return {
            'id': self.id,
            'created': self.created_as_string,
            'level': self.level,
        }

    def __repr__(self):
        return "<Membership '{}'>".format(self.id)
Beispiel #3
0
class Message(BaseModel):
    __tablename__ = 'messages'
    comment = db.Column(db.Text, nullable=False)
    user_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False)
    room_id = db.Column(db.Integer, db.ForeignKey('rooms.id'), nullable=False)

    def serialize(self):
        return {
            'id': self.id,
            'created': self.created_as_string,
            'comment': self.comment,
            'author': {
                'id': self.author.id,
                'name': self.author.name,
                'username': self.author.username,
                'avatar': self.author.avatar_or_default,
            },
            'room': {
                'id': self.room.id,
                'name': self.room.name,
            },
        }

    def __repr__(self):
        return "<Message '{}'>".format(self.id)
Beispiel #4
0
class Bug(BaseModel):
    __tablename__ = 'bugs'
    title = db.Column(db.String(255), nullable=False)
    vuln_id = db.Column(db.Integer, nullable=False, default=0)
    severity = db.Column(db.Integer, nullable=False, default=0)
    description = db.Column(db.Text, nullable=False)
    impact = db.Column(db.Text, nullable=False)
    status = db.Column(db.Integer, nullable=False, default=0)
    submitter_id = db.Column(db.Integer,
                             db.ForeignKey('users.id'),
                             nullable=False)
    reviewer_id = db.Column(db.Integer,
                            db.ForeignKey('users.id'),
                            nullable=False)

    @property
    def vulnerability_as_string(self):
        return VULNERABILITIES[self.vuln_id][0]

    @property
    def severity_as_string(self):
        return SEVERITY[self.severity]

    @property
    def status_as_string(self):
        return BUG_STATUSES[self.status]

    @property
    def bounty(self):
        return VULNERABILITIES[self.vuln_id][1] * self.severity

    @staticmethod
    def is_unique(signature):
        for bug in Bug.query.all():
            s = ' '.join((bug.title, bug.description, bug.impact))
            js = get_jaccard_sim(signature, s)
            if js > 0.5:
                return False
        return True

    @property
    def is_validated(self):
        # includes any validation result
        # rejected, confirmed, and fixed
        if self.status > 0:
            return True
        return False

    @property
    def is_accepted(self):
        # includes confirmed and fixed
        if self.status > 1:
            return True
        return False

    def __repr__(self):
        return "<Bug '{}'>".format(self.title)
class Friendship(db.Model):
    """A simple table of one-to-one friendships."""
    __tablename__ = 'friendships'
    __table_args__ = (UniqueConstraint('sender_id', 'receiver_id'), )

    VALID = 0
    REQUEST = 1
    PENDING = 2

    id = db.Column(db.Integer, primary_key=True)
    sender_id = db.Column(db.Integer,
                          db.ForeignKey('users.id'),
                          nullable=False)
    receiver_id = db.Column(db.Integer,
                            db.ForeignKey('users.id'),
                            nullable=False)
    sender = db.relationship('User',
                             uselist=False,
                             foreign_keys='Friendship.sender_id')
    receiver = db.relationship('User',
                               uselist=False,
                               foreign_keys='Friendship.receiver_id')
    valid = db.Column(db.Boolean, nullable=False, default=False)

    @staticmethod
    def create(sender, receiver):
        """Create an invalid friendship entry."""
        assert not Friendship.get(sender, receiver)
        friendship = Friendship(sender=sender, receiver=receiver, valid=False)
        db.session.add(friendship)
        return friendship

    @staticmethod
    def get(first, second):
        """Get the existing friendship entry, regardless of validity."""
        return Friendship.query.filter(
            or_(
                and_(Friendship.sender == first,
                     Friendship.receiver == second),
                and_(Friendship.sender == second,
                     Friendship.receiver == first))).first()

    @staticmethod
    def get_all(user):
        """Get all of a user's friendships."""
        return Friendship.query.filter(
            or_(Friendship.sender == user, Friendship.receiver == user)).all()

    def set_valid(self, valid):
        """Change the validity of a friendship."""
        self.valid = valid

    def __repr__(self):
        return '<friendship sender={} receiver={} valid={}>'.format(
            self.sender.email, self.receiver.email, self.valid)
Beispiel #6
0
class Note(BaseModel):
    __tablename__ = 'notes'
    name = db.Column(db.String(255), nullable=False)
    content = db.Column(db.Text)
    user_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False)

    def serialize(self):
        return {
            'id': self.id,
            'name': self.name,
            'content': self.content,
            'created': self.created_as_string,
            'modified': self.modified_as_string,
        }

    def __repr__(self):
        return "<Note '{}'>".format(self.name)
Beispiel #7
0
class Scan(BaseModel):
    __tablename__ = 'scans'
    id = db.Column(db.String(36), primary_key=True)
    command = db.Column(db.String(255), nullable=False)
    results = db.Column(db.Text)
    complete = db.Column(db.Boolean, default=False, nullable=False)
    user_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False)

    def serialize(self, include_results=False):
        return {
            'id': self.id,
            'created': self.created_as_string,
            'modified': self.modified_as_string,
            'command': self.command,
            'complete': self.complete,
        }

    def __repr__(self):
        return "<Scan '{}'>".format(self.name)
Beispiel #8
0
class Game(db.Model):
    """
    The game model.

    columns
    ~~~~~
    | name | max_points | max_players | status | random | previous_round |
    |------|------------|-------------|--------|--------|----------------|
    | str  | int        | int         | enum   | bool   | pickle         |

    relationships
    ~~~~~
    host      : user    -> game
    black_card: card    -> game
    judge     : player  -> game
    players   : player <-  game
    used_cards: card   <-> game
    """

    __tablename__ = 'games'

    ONGOING = 0
    PENDING = 1
    ENDED = 2

    id = db.Column(db.Integer, primary_key=True)
    host_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False)
    name = db.Column(db.String(80), nullable=False)
    max_points = db.Column(db.Integer, nullable=False)
    max_players = db.Column(db.Integer, nullable=False)
    status = db.Column(db.Integer, nullable=False)
    random = db.Column(db.Boolean, nullable=False)
    black_card_id = db.Column(db.Integer, db.ForeignKey('cards.id'))
    black_card = db.relationship('Card')
    judge_id = db.Column(db.Integer, db.ForeignKey('players.id'))
    judge = db.relationship('Player',
                            foreign_keys='Game.judge_id',
                            post_update=True)
    players = db.relationship('Player',
                              backref='game',
                              foreign_keys='Player.game_id')
    previous_round = db.Column(db.PickleType)
    used_cards = db.relationship('Card', uselist=True)
    end_time = db.Column(db.DateTime, nullable=True)

    @staticmethod
    def create(host, name, max_points, max_players, random):
        """Create an uninitialized (pending) match."""
        game = Game(host_id=host.id,
                    name=name,
                    max_points=max_points,
                    max_players=max_players,
                    random=random,
                    status=Game.PENDING,
                    previous_round={},
                    used_cards=[])
        db.session.add(game)
        return game

    @staticmethod
    def get(id):
        """Get a game by id."""
        return Game.query.get(id)

    @staticmethod
    def find_random(user):
        """
        Finds a valid optimal random game
        for the user. This is very inefficient
        and there is a better way to do this.

        TODO: optimize this
        """

        games = Game.query.filter(
            Game.random == True,  # this is not a mistake
            Game.status == Game.PENDING,
            ~Game.players.any(Player.user_id == user.id)).all()

        try:
            game = max(games,
                       key=lambda g: len(
                           [p for p in g.players
                            if p.status == Player.JOINED]))
        except ValueError:
            game = None

        return game

    @staticmethod
    def find_n_random(n, user):
        """Finds the top n optimal random games. TODO: optimize THE SHIT OUT OF THIS"""
        games = Game.query.filter(
            Game.random == True,  # this is not a mistake
            Game.status == Game.PENDING,
            ~Game.players.any(Player.user_id == user.id)).all()

        try:
            games = sorted(
                games,
                key=lambda g: len(
                    [p for p in g.players if p.status == Player.JOINED]))
        except ValueError:
            games = []

        return games if len(games) < n else games[:n]

    def start(self):
        """Begins the game."""
        self.status = self.ONGOING
        [
            player.delete() for player in self.players
            if player.status != Player.JOINED
        ]
        self.players = [
            player for player in self.players if player.status == Player.JOINED
        ]
        self.new_round(None)

    def end(self):
        """Ends the game."""
        for player in self.players:
            if player.user.num_random > 0:
                player.user.num_random -= 1

        self.status = Game.ENDED
        self.end_time = datetime.now()

    def new_round(self, winner):
        """
        Starts a new round.

        - Store previous round as Pickled dictionary
        - Fill every player's hand
        - Discard and play a new black card
        - Find a new judge and increment
          his judge count
        """

        if winner:
            self.previous_round = {
                'judge': {
                    'name': self.judge.user.name,
                    'email': self.judge.user.email
                },
                'winner': {
                    'name': winner.user.name,
                    'email': winner.user.email
                },
                'black_card': {
                    'id': self.black_card.id,
                    'text': self.black_card.text,
                    'answers': self.black_card.answers
                },
                'table': [{
                    'name':
                    player.user.name,
                    'email':
                    player.user.email,
                    'picture':
                    player.user.picture,
                    'cards': [{
                        'id': card.id,
                        'text': card.text
                    } for card in player.get_played()]
                } for player in self.players
                          if player.hand and player != self.judge]
            }

        self.winner = None

        if any(player.score == self.max_points for player in self.players):
            self.end()
            return

        white_cards = Card.get_all(black=False)

        # fill every player's hand and remove their played card
        for player in self.players:
            player.played = []

            while len(player.hand) < 10:
                white_card = choice(white_cards)

                while white_card in set(self.used_cards):
                    white_card = choice(white_cards)

                player.hand.append(white_card)
                self.used_cards.append(white_card)

        # play a new black card and choose a new judge
        black_cards = Card.get_all(black=True)
        self.black_card = choice(black_cards)

        while self.black_card in set(self.used_cards):
            self.black_card = choice(black_cards)

        self.used_cards.append(self.black_card)

        self.judge = min(self.players, key=lambda player: player.judged)
        self.judge.played = [self.black_card.id]
        self.judge.judged += 1

    def invite_all(self, players):
        """Invites a list of players to this game."""
        self.players += players

    def invite(self, player):
        """Invites a single player to this game."""
        self.players.append(player)

    def get_description(self):
        """Returns the description of the game."""
        if self.status == Game.ONGOING:
            players = sorted(self.players, key=lambda p: p.user.name)
            names = [player.user.name.split(' ')[0] for player in players]
            count = len(names)

            return '{}, {}, and {} others...'.format(names[0], names[1],
                                                     count - 2)

        elif self.status == Game.PENDING:
            joined = [
                player for player in self.players
                if player.status == Player.JOINED
            ]
            names = [player.user.name.split(' ')[0] for player in joined]
            count = len(names)

            if count == 1:
                return 'This game is hosted by {}!'.format(names[0])
            elif count == 2:
                return '{} and {} have joined this game!'.format(
                    names[0], names[1])
            elif count == 3:
                return '{}, {}, and {} have joined this game!'.format(
                    names[0], names[1], names[2])

            return '{}, {}, and {} others have joined this game!'.format(
                names[0], names[1], count - 2)

        elif self.status == Game.ENDED:
            winner = max(self.players, key=lambda p: p.score)
            name = winner.user.name.split(' ')[0]

            return '{} won the game with {} points!'.format(name, winner.score)

        return 'Something went horribly wrong...'

    def __repr__(self):
        return '<game id={} players={}>'.format(
            self.id, [player.user.id for player in self.players])
Beispiel #9
0
# coding: utf-8
from common import login_manager, db, ModelBase, ma
from itsdangerous import TimedJSONWebSignatureSerializer as Serializer
from itsdangerous.exc import SignatureExpired, BadSignature
from flask import current_app
from flask_restful import fields
from flask_security import RoleMixin, UserMixin, SQLAlchemyUserDatastore
from flask_security.utils import hash_password, verify_password

roles_users = db.Table(
    "users_roles",
    db.Column("user_id", db.Integer, db.ForeignKey("user.id")),
    db.Column("role_id", db.Integer(), db.ForeignKey("role.id")),
)


class Role(db.Model, RoleMixin, ModelBase):

    __tablename__ = "role"

    name = db.Column(db.String(80), unique=True)
    description = db.Column(db.String(80))


class User(db.Model, UserMixin, ModelBase):

    __tablename__ = "user"

    name = db.Column(db.String(255), unique=True, nullable=False)
    email = db.Column(db.String(255), unique=True, nullable=False)
    password_hash = db.Column(db.String(255), nullable=False)
class Player(db.Model):
    """
    Player model containing
    functions which encapsulate
    gameplay state changes.

    columns
    ~~~~~
    | status | score | judged | seen | played |
    |--------|-------|--------|------|--------|
    | enum   | int   | int    | bool | pickle |

    relationships
    ~~~~~
    user  : user   <-  player
    game  : game   <-  player
    hand  : player  -  card
    """

    __tablename__ = 'players'

    PENDING  = 0
    JOINED   = 1
    REJECTED = 2

    id      = db.Column(db.Integer, primary_key=True)
    user_id = db.Column(db.Integer, db.ForeignKey('users.id', name='user_to_player'), nullable=False)
    game_id = db.Column(db.Integer, db.ForeignKey('games.id', name='game_to_player'), nullable=False)
    status  = db.Column(db.Integer, nullable=False)
    score   = db.Column(db.Integer, nullable=False)
    judged  = db.Column(db.Integer, nullable=False)
    seen    = db.Column(db.Boolean, nullable=False, default=False)
    played  = db.Column(db.PickleType, nullable=True)
    hand    = db.relationship('Card', secondary=hands)

    @staticmethod
    def create(user, game):
        """Creates a single uninitialized player."""
        player = Player(
            user=user, game=game, status=Player.PENDING, score=0, judged=0
        )
        db.session.add(player)
        return player

    @staticmethod
    def create_all(users, game):
        """Creates many players for a given game."""
        players = [
            Player(
                user=user, game=game, status=Player.PENDING, score=0, judged=0
            )
            for user in users
        ]
        db.session.add_all(players)
        return players

    @staticmethod
    def get(user, game):
        """Returns the player associated with a specific user and game."""
        return Player.query.filter_by(user=user, game=game).first()

    def delete(self):
        """Deletes a player. Typically used when declining to join a game."""
        db.session.delete(self)

    def get_played(self):
        """
        Store the player's played cards as a list of
        card ids. This is necessary for efficiently
        enforcing played order. The nested loop below
        is still faster than making one query for each card.
        """

        if not self.played:
            return []

        cards  = Card.query.filter(
            or_(Card.id == card_id for card_id in self.played)
        ).all()
        played = []

        for card_id in self.played:
            card = next(
                (c for c in cards if c.id == card_id),
                None
            )
            played.append(card)

        return played

    def play_cards(self, cards):
        assert not self.played
        self.played = [card.id for card in cards]
        [self.hand.remove(card) for card in cards]

    def set_status_joined(self):
        """Change player status to JOINED."""
        self.status = Player.JOINED

    def set_status_denied(self):
        """Change player status to DENIED."""
        self.status = Player.DENIED

    def add_points(self, n):
        """Add n points to the player's score."""
        self.score += n

    def __repr__(self):
        return '<player email={} game={} status={}>'.format(
            self.user.email, self.game.id, self.status
        )
    models.player
    ~~~~~
    Player model and assoc
    tables, which represent
    a user's state inside a game.
"""

from sqlalchemy import or_

from common import db
from models import Card

hands = db.Table(
    'hands',
    db.Model.metadata,
    db.Column('player', db.Integer, db.ForeignKey('players.id')),
    db.Column('card', db.Integer, db.ForeignKey('cards.id'))
)


class Player(db.Model):
    """
    Player model containing
    functions which encapsulate
    gameplay state changes.

    columns
    ~~~~~
    | status | score | judged | seen | played |
    |--------|-------|--------|------|--------|
    | enum   | int   | int    | bool | pickle |
Beispiel #12
0
from common import db, app, migrate
from exceptions import DBException

# Volunteer - Classroom: One to many
volunteer_classroom = db.Table(
    'volunteer_classroom',
    db.Column('volunteer_id',
              db.Integer,
              db.ForeignKey('volunteer.id'),
              primary_key=True),
    db.Column('classroom_id',
              db.Integer,
              db.ForeignKey('classroom.id'),
              primary_key=True))

# Student - Classroom: One to many
student_classroom = db.Table(
    'student_classroom',
    db.Column('student_id',
              db.Integer,
              db.ForeignKey('student.id'),
              primary_key=True),
    db.Column('classroom_id',
              db.Integer,
              db.ForeignKey('classroom.id'),
              primary_key=True))


class Volunteer(db.Model):
    __tablename__ = 'volunteer'