Example #1
0
class Game(db.Model):
    __tablename__ = 'games'

    id = db.Column(db.Integer, primary_key=True)

    created_at = db.Column(db.TIMESTAMP, server_default=func.now())
    updated_at = db.Column(db.TIMESTAMP,
                           server_default=func.now(),
                           onupdate=func.current_timestamp())

    def __repr__(self):
        return '<Game %r>' % self.id
Example #2
0
class Message(db.Model):
    __tablename__ = 'messages'

    id = db.Column(db.Integer, primary_key=True)
    channel = db.relationship('Channel', back_populates='messages')
    channel_id = db.Column(db.Integer, db.ForeignKey('channels.id'), nullable=False)
    listener = db.relationship('Listener', back_populates='messages')
    listener_id = db.Column(db.Integer, db.ForeignKey('listeners.id'))
    content = db.Column(db.Text, nullable=False)
    encrypted_content = db.Column(db.Text, nullable=False)
    sender = db.Column(db.String, nullable=False)
    intercepted_at = db.Column(db.TIMESTAMP)
    created_at = db.Column(db.TIMESTAMP, server_default=func.now())
    updated_at = db.Column(db.TIMESTAMP, server_default=func.now(),onupdate=func.current_timestamp())

    def __repr__(self):
        return '<Message %r>' % self.id

    def create(content, channel_id, sender):
        message = Message(channel_id=channel_id,content=content,sender=sender, encrypted_content= Message.encrypt(content, 0))
        db.session.add(message)
        try:
            db.session.commit()
        except IntegrityError as e:
            print(str(e))
            raise ResourceMissing("Could not find channel {channel_id}, message was not delivered".format(channel_id=channel_id), 404)

        if message.channel.has_listeners():
            # Assuming there is only one listener
            message.listener = message.channel.listeners[0]
            message.intercepted_at = datetime.now()
            message.encrypted_content = Message.encrypt(content, message.listener.decrypt_level())
            db.session.commit()

        return message

    def serialize(self):
        # Return the encrypted messages to red team, not for blue team use
        return {
            'id': self.id,
            'channel_id': self.channel_id,
            'intercepted_at': self.intercepted_at,
            'created_at': self.created_at,
            'sender': self.sender,
            'content': self.encrypted_content
        }

    def encrypt(content, decrypt_level):
        length = len(content)
        decrypted_chars = []
        for _ in range(math.ceil(length * (1-decrypt_level))):
            char_index = random.randint(0, length)
            if char_index not in decrypted_chars:
                decrypted_chars.append(char_index)

        return "".join([('*' if index in decrypted_chars else char) for index, char in enumerate(content)])
Example #3
0
class Listener(db.Model):
    __tablename__ = 'listeners'

    id = db.Column(db.Integer, primary_key=True)
    channel = db.relationship('Channel', back_populates='listeners')
    channel_id = db.Column(db.Integer, db.ForeignKey('channels.id'))
    messages = db.relationship('Message', back_populates='listener', lazy=True)
    created_at = db.Column(db.TIMESTAMP, server_default=func.now())
    updated_at = db.Column(db.TIMESTAMP,
                           server_default=func.now(),
                           onupdate=func.current_timestamp())

    def __repr__(self):
        return '<Listener %r>' % self.id

    def find(instance_id):
        # Find instance by id
        return Listener.query.filter(Listener.id == instance_id).first()

    def create():
        new_listener = Listener()
        db.session.add(new_listener)
        db.session.commit()
        return True

    def listen_to(self, channel_id):
        channel = Channel.query.filter(Channel.id == channel_id).first()

        if channel:
            self.channel = channel
            db.session.commit()
            return True
        else:
            raise ResourceMissing("No channel found with id %r" % channel_id,
                                  404)

    def serialize_messages(self):
        return [message.serialize() for message in self.messages]

    def decrypt_level(self):
        intercepts = len(self.messages)
        if intercepts >= 10:
            return 1
        elif intercepts == 0:
            return 0
        else:
            return intercepts / 10.0
Example #4
0
class Channel(db.Model):
    __tablename__ = 'channels'

    id = db.Column(db.Integer, primary_key=True)
    messages = db.relationship('Message', back_populates='channel', lazy=True)
    listeners = db.relationship('Listener', back_populates='channel', lazy=True)
    created_at =db.Column(db.TIMESTAMP, server_default=func.now())
    updated_at =db.Column(db.TIMESTAMP, server_default=func.now(),onupdate=func.current_timestamp())

    def __repr__(self):
        return '<Channel %r>' % self.name

    def create():
        new_channel = Channel()
        db.session.add(new_channel)
        db.session.commit()
        return True

    def has_listeners(self):
        return len(self.listeners) > 0
Example #5
0
class Player(db.Model):
    __tablename__ = 'players'

    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String, nullable=False, unique=True)
    agents = db.relationship('Agent', back_populates='player')
    description = db.Column(db.Text)
    api_key = db.Column(db.String)
    ip_address = db.Column(db.String)
    created_at = db.Column(db.TIMESTAMP, server_default=func.now())
    updated_at = db.Column(db.TIMESTAMP, server_default=func.now(),onupdate=func.current_timestamp())

    def __repr__(self):
        return '<Player %r>' % self.id

    def create(name, description):
        new_player = Player(name=name, description=description)
        db.session.add(new_player)
        new_player.generate_api_key()
        db.session.commit()
        return new_player

    def find_or_assign(ip_address):
        player = Player.query.filter(Player.ip_address == ip_address).first()
        if player:
            return player
        else:
            players = Player.query.filter(Player.ip_address == None).all()
            if len(players) == 0:
                raise FullGame("Sorry this game is already full", 423)
            player = random.choice(players)
            player.ip_address = ip_address
            db.session.commit()
            return player


    def current_user(api_key):
        return Player.query.filter(Player.api_key == api_key).first()

    def generate_api_key(self):
        self.api_key = '%030x' % random.randrange(16**30)

    def serialize_agents(self,requestor):
        if (requestor == 'Alpha' or requestor == 'Charlie') and self.name == 'Alpha':
            return [agent.serialize(requestor) for agent in self.agents if requestor == 'Alpha' or (not agent.in_safehouse() and requestor == 'Charlie')]
        elif (requestor == 'Charlie' or requestor == 'Bravo') and self.name == 'Charlie':
            return [agent.serialize(requestor) for agent in self.agents]
        else:
            raise Unauthenticated("You are not permitted to access this resource!", 401)
Example #6
0
class Safehouse(db.Model):
    __tablename__ = 'safehouses'

    id = db.Column(db.Integer, primary_key=True)
    agents = db.relationship('Agent', back_populates='safehouse')
    packages = db.relationship('Package', back_populates='safehouse')
    x = db.Column(db.Integer, nullable=False, index=True)
    y = db.Column(db.Integer, nullable=False, index=True)
    dropoff = db.Column(db.Boolean, server_default='t', nullable=False)
    created_at = db.Column(db.TIMESTAMP, server_default=func.now())
    updated_at = db.Column(db.TIMESTAMP,
                           server_default=func.now(),
                           onupdate=func.current_timestamp())

    def __repr__(self):
        return '<Safehouse %r>' % self.id

    def find(instance_id):
        # Find instance by id
        return Safehouse.query.filter(Safehouse.id == instance_id).first()

    def create(position, dropoff):
        new_safehouse = Safehouse(dropoff=dropoff,
                                  x=position[0],
                                  y=position[1])
        db.session.add(new_safehouse)
        db.session.commit()
        return new_safehouse

    def all():
        return Safehouse.query.all()

    def has_packages(self):
        return len(self.packages) > 0

    def serialize(self):
        return {
            'id': self.id,
            'x': self.x,
            'y': self.y,
            'dropoff': self.dropoff,
            'packages': len(self.packages)
        }
Example #7
0
class Package(db.Model):
    __tablename__ = 'packages'

    id = db.Column(db.Integer, primary_key=True)
    agent = db.relationship('Agent', back_populates='packages')
    agent_id = db.Column(db.Integer, db.ForeignKey('agents.id'), index=True)
    safehouse = db.relationship('Safehouse', back_populates='packages')
    safehouse_id = db.Column(db.Integer,
                             db.ForeignKey('safehouses.id'),
                             index=True)
    x = db.Column(db.Integer, nullable=False, index=True)
    y = db.Column(db.Integer, nullable=False, index=True)
    created_at = db.Column(db.TIMESTAMP, server_default=func.now())
    updated_at = db.Column(db.TIMESTAMP,
                           server_default=func.now(),
                           onupdate=func.current_timestamp())

    def __repr__(self):
        return '<Package %r>' % self.id

    def find(instance_id):
        # Find instance by id
        return Package.query.filter(Package.id == instance_id).first()

    def all():
        return Package.query.all()

    def create(position):
        new_package = Package(x=position[0], y=position[1])
        db.session.add(new_package)
        db.session.commit()
        return new_package

    def in_safehouse(self):
        return not self.safehouse_id == None

    def pickup(self, agent):
        self.agent = agent
        db.session.commit()

    def drop(self):
        self.agent_id = None
        db.session.commit()

    def enter_safehouse(self, safehouse):
        self.safehouse = safehouse
        self.agent_id = None
        db.session.commit()

    def move(self, x, y):
        if x == self.x and y == self.y:
            # We are already here, don't waste db cycle
            return
        self.x = x
        self.y = y
        db.session.commit()

    def serialize(self):
        return {
            'id': self.id,
            'x': self.x,
            'y': self.y,
            'agent_id': self.agent_id,
            'in_safehouse': self.in_safehouse()
        }
Example #8
0
class Agent(db.Model):
    __tablename__ = 'agents'

    id = db.Column(db.Integer, primary_key=True)
    player = db.relationship('Player', back_populates='agents')
    player_id = db.Column(db.Integer,
                          db.ForeignKey('players.id'),
                          nullable=False,
                          index=True)
    safehouse = db.relationship('Safehouse', back_populates='agents')
    safehouse_id = db.Column(db.Integer,
                             db.ForeignKey('safehouses.id'),
                             index=True)
    packages = db.relationship('Package', back_populates='agent')
    x = db.Column(db.Integer, nullable=False, index=True)
    y = db.Column(db.Integer, nullable=False, index=True)
    alive = db.Column(db.Boolean, server_default='t', nullable=False)
    created_at = db.Column(db.TIMESTAMP, server_default=func.now())
    updated_at = db.Column(db.TIMESTAMP,
                           server_default=func.now(),
                           onupdate=func.current_timestamp())

    def __repr__(self):
        return '<Agent %r>' % self.id

    def find(instance_id):
        # Find instance by id
        return Agent.query.filter(Agent.id == instance_id).first()

    def create(player, position):
        new_agent = Agent(player_id=player.id, x=position[0], y=position[1])
        db.session.add(new_agent)
        db.session.commit()
        return new_agent

    def has_packages(self):
        return len(self.packages) > 0

    def in_safehouse(self):
        return not self.safehouse_id == None

    def kill(self):
        self.alive = False
        [package.drop() for package in self.packages]
        db.session.commit()

    def legal_moves(self):
        moves = [(self.x + 1, self.y), (self.x - 1, self.y),
                 (self.x, self.y + 1), (self.x, self.y - 1)]
        return [
            move for move in moves if move[0] > -1 and move[0] < 100
            and move[1] > -1 and move[1] < 100
        ]

    def serialize(self, requestor):
        if requestor == 'Alpha' and self.player.name == 'Alpha':
            return {
                'id': self.id,
                'x': self.x,
                'y': self.y,
                'safehouse': self.in_safehouse(),
                'packages': len(self.packages)
            }
        elif requestor == 'Charlie' and (self.player.name == 'Alpha'
                                         or self.player.name == 'Charlie'):
            return {'id': self.id, 'x': self.x, 'y': self.y}
        elif requestor == 'Bravo' and (self.player.name == 'Charlie'):
            return {'id': self.id, 'x': self.x, 'y': self.y}

    def leave_safehouse(self):
        self.safehouse_id = None
        db.session.commit()

    def enter_safehouse(self, safehouse):
        self.safehouse = safehouse
        db.session.commit()

    def move(self, x, y):
        if not self.alive:
            raise IsDead("Agent {agent_id} is dead".format(agent_id=self.id),
                         404)
        if (x, y) not in self.legal_moves():
            raise IllegalMove(
                "Agent {agent_id} can't move to {x},{y}, only to [{legal_moves}]"
                .format(agent_id=self.id,
                        x=x,
                        y=y,
                        legal_moves=",".join(
                            [str(move) for move in self.legal_moves()])), 404)
        self.x = x
        self.y = y
        db.session.commit()
        self.resolve_move()

    def resolve_move(self):

        if self.safehouse_id != None and self.player.name != "Charlie":
            self.leave_safehouse()

        # Quite a few things need to happen and we need to get the priority right
        #First is there any agents already here?
        other_agents = Agent.query.filter(Agent.x == self.x
                                          and Agent.y == self.y
                                          and Agent.id != self.id
                                          and Agent.alive == True).all()

        for agent in other_agents:
            if agent.player.name == "Charlie" and (self.player.name == "Bravo"
                                                   or self.player.name
                                                   == "Alpha"):
                self.kill()
                raise IsDead(
                    "Agent {agent_id} is dead".format(agent_id=self.id), 404)
            elif self.player.name == "Charlie" and not agent.in_safehouse(
            ) and (agent.player.name == "Bravo"
                   or agent.player.name == "Alpha"):
                agent.kill()

        if self.player.name == "Charlie":
            # Charlie does not care about packages or safehouses
            return True

        packages = Package.query.filter(
            Package.x == self.x and Package.y == self.y
            and Package.agent_id == None
            and Package.safehouse_id == None).all()
        [package.pickup(self) for package in packages]
        [package.move(self.x, self.y) for package in self.packages]

        safehouse = Safehouse.query.filter(Safehouse.x == self.x
                                           and Safehouse.y == self.y).first()

        if safehouse:
            self.enter_safehouse(safehouse)
            if safehouse.dropoff:
                [
                    package.enter_safehouse(safehouse)
                    for package in self.packages
                ]

        return True