Exemplo n.º 1
0
class Service(db.Model):
    id = db.Column(INTEGER(unsigned=True), primary_key=True)
    secret = db.Column(db.VARCHAR(32), nullable=False)
    encryption_key = db.Column(db.VARCHAR(512), nullable=False)
    public = db.Column(db.VARCHAR(40), nullable=False)
    name = db.Column(db.VARCHAR(255), nullable=False)
    icon = db.Column(db.TEXT, nullable=False, default='')
    timestamp_created = db.Column(db.TIMESTAMP, default=datetime.utcnow)

    def __init__(self, name, icon='', encrypted=False):
        self.secret = hashlib.sha1(urandom(100)).hexdigest()[:32]
        if encrypted:
            self.encryption_key = hashlib.sha1(urandom(100)).hexdigest()[:32]
        else:
            self.encryption_key = ""
        self.name = name
        self.icon = icon
        pub = list(hashlib.new('ripemd160', self.secret).hexdigest())[:40]
        sep = [4, 11, 24, 30]
        for s in sep:
            pub[s] = '-'
        self.public = ''.join(pub)

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

    def cleanup(self):
        threshold = self.subscribed().order_by(
            Subscription.last_read.asc()).first().last_read

        # Nothing to do
        if not threshold:
            return

        messages = Message.query \
            .filter_by(service=self) \
            .filter(threshold > Message.id) \
            .all()

        map(db.session.delete, messages)

    def subscribed(self):
        return Subscription.query.filter_by(service=self)

    def as_dict(self, secret=False):
        data = {
            "public": self.public,
            "name": self.name,
            "created": int(self.timestamp_created.strftime("%s")),
            "icon": self.icon,
            "encrypted": True if self.encryption_key else False,
        }

        if secret:
            data["secret"] = self.secret
            data["encryption_key"] = self.encryption_key

        return data
Exemplo n.º 2
0
class Service(db.Model):
    id = db.Column(Integer, primary_key=True)
    secret = db.Column(db.VARCHAR(32), nullable=False)
    public = db.Column(db.VARCHAR(40), nullable=False)
    name = db.Column(db.Unicode(length=255), nullable=False)
    icon = db.Column(db.TEXT, nullable=False, default='')
    timestamp_created = db.Column(db.TIMESTAMP, default=datetime.utcnow)

    def __init__(self, name, icon=''):
        self.secret = hashlib.sha1(urandom(100)).hexdigest()[:32]
        self.name = name
        self.icon = icon
        pub = list(
            hashlib.new('ripemd160',
                        self.secret.encode("UTF-8")).hexdigest())[:40]
        sep = [4, 11, 24, 30]
        for s in sep:
            pub[s] = '-'
        self.public = ''.join(pub)

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

    def cleanup(self):
        threshold = self.subscribed().order_by(
            Subscription.last_read.asc()).first().last_read

        # Nothing to do
        if not threshold:
            return

        messages = Message.query \
            .filter_by(service=self) \
            .filter(threshold > Message.id) \
            .all()

        map(db.session.delete, messages)

    def subscribed(self):
        return Subscription.query.filter_by(service=self)

    def as_dict(self, secret=False):
        data = {
            "public":
            self.public,
            "name":
            self.name,
            "created":
            int((self.timestamp_created -
                 datetime.utcfromtimestamp(0)).total_seconds()),
            "icon":
            self.icon,
        }
        if secret:
            data["secret"] = self.secret
        return data
Exemplo n.º 3
0
class Subscription(db.Model):
    id = db.Column(INTEGER(unsigned=True), primary_key=True)
    device = db.Column(db.VARCHAR(40), nullable=False)
    service_id = db.Column(INTEGER(unsigned=True), db.ForeignKey('service.id'), nullable=False)
    service = db.relationship('Service', backref=db.backref('subscription', lazy='dynamic'))
    last_read = db.Column(INTEGER(unsigned=True), db.ForeignKey('message.id'), default=0)
    timestamp_created = db.Column(db.TIMESTAMP, default=datetime.utcnow)
    timestamp_checked = db.Column(db.TIMESTAMP)

    def __init__(self, device, service):
        last_message = Message.query.order_by(Message.id.desc()).first()

        self.device = device
        self.service = service
        self.timestamp_checked = datetime.utcnow()
        self.last_read = last_message.id if last_message else 0

    def __repr__(self):
        return '<Subscription {}>'.format(self.id)

    def messages(self):
        return Message.query \
            .filter_by(service_id=self.service_id) \
            .filter(Message.id > self.last_read)

    def as_dict(self):
        data = {
            "uuid": self.device,
            "service": self.service.as_dict(),
            "timestamp": int((self.timestamp_created - datetime.utcfromtimestamp(0)).total_seconds()),
            "timestamp_checked": int((self.timestamp_checked - datetime.utcfromtimestamp(0)).total_seconds())
        }
        return data
Exemplo n.º 4
0
class Gcm(db.Model):
    id = db.Column(INTEGER(unsigned=True), primary_key=True)
    uuid = db.Column(db.VARCHAR(40), nullable=False)
    gcmid = db.Column(db.TEXT, nullable=False)
    timestamp_created = db.Column(db.TIMESTAMP, default=datetime.utcnow)

    def __init__(self, device, gcmid):
        self.uuid = device
        self.gcmid = gcmid

    def __repr__(self):
        return '<Gcm {}>'.format(self.uuid)

    def as_dict(self):
        data = {
            "uuid": self.service.as_dict(),
            "gcm_registration_id": self.gcmId,
            "timestamp": int(self.timestamp_created.strftime('%s')),
        }
        return data

    @staticmethod
    def send_message(message):
        """

        :type message: Message
        """
        subscriptions = Subscription.query.filter_by(
            service=message.service).all()
        if len(subscriptions) == 0:
            return 0
        gcm_devices = Gcm.query.filter(
            Gcm.uuid.in_([l.device for l in subscriptions])).all()

        if len(gcm_devices) > 0:
            data = dict(message=message.as_dict(), encrypted=False)
            Gcm.gcm_send([r.gcmid for r in gcm_devices], data)

        if len(gcm_devices) > 0:
            uuids = [g.uuid for g in gcm_devices]
            gcm_subscriptions = Subscription.query.filter_by(
                service=message.service).filter(
                    Subscription.device.in_(uuids)).all()
            last_message = Message.query.order_by(Message.id.desc()).first()
            for l in gcm_subscriptions:
                l.timestamp_checked = datetime.utcnow()
                l.last_read = last_message.id if last_message else 0
            db.session.commit()
        return len(gcm_devices)

    @staticmethod
    def gcm_send(ids, data):
        url = 'https://android.googleapis.com/gcm/send'
        headers = dict(Authorization='key={}'.format(google_api_key))
        data = dict(registration_ids=ids, data=data)

        if current_app.config['TESTING'] is True:
            current_app.config['TESTING_GCM'].append(data)
        else:
            requests.post(url, json=data, headers=headers)
Exemplo n.º 5
0
class Subscription(db.Model):
    id = db.Column(INTEGER(unsigned=True), primary_key=True)
    device = db.Column(db.VARCHAR(40), nullable=False)
    service_id = db.Column(INTEGER(unsigned=True),
                           db.ForeignKey('service.id'),
                           nullable=False)
    service = db.relationship('Service',
                              backref=db.backref('subscription',
                                                 lazy='dynamic'))
    timestamp_created = db.Column(db.TIMESTAMP, default=datetime.utcnow)
    timestamp_checked = db.Column(db.TIMESTAMP)

    def __init__(self, device, service):
        self.device = device
        self.service = service
        self.timestamp_checked = datetime.utcnow() - timedelta(minutes=30)

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

    def messages(self):
        return Message.query \
            .filter_by(service_id=self.service_id) \
            .filter(Message.timestamp_created > self.timestamp_checked)

    def as_dict(self):
        data = {
            "uuid": self.device,
            "service": self.service.as_dict(),
            "timestamp": int(self.timestamp_created.strftime('%s')),
            "timestamp_checked": int(self.timestamp_checked.strftime('%s'))
        }
        return data
Exemplo n.º 6
0
class Gcm(db.Model):
    id = db.Column(INTEGER(unsigned=True), primary_key=True)
    uuid = db.Column(db.VARCHAR(40), nullable=False)
    gcmid = db.Column(db.TEXT, nullable=False)
    pubkey = db.Column(db.TEXT, default=None)
    timestamp_created = db.Column(db.TIMESTAMP, default=datetime.utcnow)

    def __init__(self, device, gcmid, pubkey=None):
        self.uuid = device
        self.gcmid = gcmid
        self.pubkey = pubkey

    def __repr__(self):
        return '<Gcm %r>' % self.uuid

    def as_dict(self):
        data = {
            "uuid": self.service.as_dict(),
            "gcm_registration_id": self.gcmId,
            "timestamp": int(self.timestamp_created.strftime('%s')),
        }
        return data

    @staticmethod
    def send_message(message):
        """

        :type message: Message
        """
        subscriptions = Subscription.query.filter_by(service=message.service).all()
        if len(subscriptions) == 0:
            return 0
        gcm_filter = Gcm.query.filter(Gcm.uuid.in_([l.device for l in subscriptions])).all()

        devices_plain = [r.gcmid for r in gcm_filter if r.pubkey is None]
        devices_crypto = [r for r in gcm_filter if r.pubkey is not None]

        if len(devices_plain) > 0:
            data = {"message": dumps(message.as_dict()), "encrypted": True}
            Gcm.gcm_send(devices_plain, data)
        for device in devices_crypto:
            pubkey = rsa.PublicKey.load_pkcs1(b64decode(device.pubkey), 'DER')
            message_enc = rsa.encrypt(dumps(message.as_dict()), pubkey)

            data = {"message": message_enc, "encrypted": True}
            Gcm.gcm_send([device.gcmid], data)

        if len(gcm_filter) > 0:
            uuids = [g.uuid for g in gcm_filter]
            gcm_subscriptions = Subscription.query.filter_by(service=message.service).filter(Subscription.device.in_(uuids)).all()
            for l in gcm_subscriptions:
                l.timestamp_checked = datetime.utcnow()
            db.session.commit()
        return len(gcm_filter)

    @staticmethod
    def gcm_send(ids, data):
        data = dumps({
            "registration_ids": ids,
            "data": data,
        })
        headers = {
            'Authorization': 'key=%s' % google_api_key,
            'Content-Type': 'application/json',
        }
        req = urllib2.Request('https://android.googleapis.com/gcm/send', data, headers)
        urllib2.urlopen(req).read()
Exemplo n.º 7
0
class Apns(db.Model):
    id = db.Column(INTEGER(unsigned=True), primary_key=True)
    uuid = db.Column(db.VARCHAR(40), nullable=False)
    device_token = db.Column(db.TEXT, nullable=False)
    timestamp_created = db.Column(db.TIMESTAMP, default=datetime.utcnow)

    def __init__(self, uuid, token):
        self.uuid = uuid
        self.device_token = token

    def __repr__(self):
        return '<Apns {}>'.format(self.uuid)

    def as_dict(self):
        data = {
            "uuid":
            self.uuid,
            "device_token":
            self.device_token,
            "timestamp":
            int((self.timestamp_created -
                 datetime.utcfromtimestamp(0)).total_seconds()),
        }
        return data

    @staticmethod
    def send_message(message):
        """

        :type message: Message
        """
        subscriptions = Subscription.query.filter_by(
            service=message.service).all()
        if len(subscriptions) == 0:
            return 0
        apns_devices = Apns.query.filter(
            Apns.uuid.in_([l.device for l in subscriptions])).all()

        if len(apns_devices) > 0:
            Apns.apns_send([r.device_token for r in apns_devices],
                           message.as_dict())
            uuids = [g.uuid for g in apns_devices]
            apns_subscriptions = Subscription.query.filter_by(
                service=message.service).filter(
                    Subscription.device.in_(uuids)).all()
            last_message = Message.query.order_by(Message.id.desc()).first()
            for l in apns_subscriptions:
                l.timestamp_checked = datetime.utcnow()
                l.last_read = last_message.id if last_message else 0
            db.session.commit()
        return len(apns_devices)

    @staticmethod
    def apns_send(tokens, data):
        if current_app.config['TESTING'] is True:
            current_app.config['TESTING_APNS'].append(data)
            return
        payload = Payload(alert=data['service']['name'],
                          sound="default",
                          badge=1,
                          custom=data)
        notifications = [
            Notification(token=token, payload=payload) for token in tokens
        ]
        topic = 'me.elrod.iPushjet'
        client = APNsClient(apns_cert_path,
                            use_sandbox=True,
                            use_alternative_port=False)
        client.send_notification_batch(notifications, topic)
Exemplo n.º 8
0
class MQTT(db.Model):
    id = db.Column(Integer, primary_key=True)
    uuid = db.Column(db.VARCHAR(40), nullable=False)
    timestamp_created = db.Column(db.TIMESTAMP, default=datetime.utcnow)

    def __init__(self, device):
        self.uuid = device

    def __repr__(self):
        return '<MQTT {}>'.format(self.uuid)

    def as_dict(self):
        data = {
            "uuid":
            self.service.as_dict(),
            "timestamp":
            int((self.timestamp_created -
                 datetime.utcfromtimestamp(0)).total_seconds()),
        }
        return data

    @staticmethod
    def send_message(message):
        """

        :type message: Message to send to mqtt subscribers
        """
        subscriptions = Subscription.query.filter_by(
            service=message.service).all()
        if len(subscriptions) == 0:
            return 0
        mqtt_devices = MQTT.query.filter(
            MQTT.uuid.in_([l.device for l in subscriptions])).all()

        if len(mqtt_devices) > 0:
            data = dict(message=message.as_dict(), encrypted=False)
            MQTT.mqtt_send([r.uuid for r in mqtt_devices], data)

        if len(mqtt_devices) > 0:
            uuids = [g.uuid for g in mqtt_devices]
            mqtt_subscriptions = Subscription.query.filter_by(
                service=message.service).filter(
                    Subscription.device.in_(uuids)).all()
            last_message = Message.query.order_by(Message.id.desc()).first()
            for l in mqtt_subscriptions:
                l.timestamp_checked = datetime.utcnow()
                l.last_read = last_message.id if last_message else 0
            db.session.commit()
        return len(mqtt_devices)

    @staticmethod
    def mqtt_send(uuids, data):
        url = cfg.mqtt_broker_address
        if ":" in url:
            port = url.split(":")[1]
            url = url.split(":")[0]
        else:
            # default port
            port = 1883

        client = mqtt_api.Client()
        client.connect(url, port, 60)

        for uuid in uuids:
            client.publish(uuid, str(data))
        client.disconnect()