예제 #1
0
def _lwm2m_protocol(data):
    """ handle lwm2m protocol publish """

    try:
        load_payload = json.loads(data['payload'])
    except Exception:
        raise FormInvalid(field='payload')
    # build emqx lwm2m protocol require payload
    handled_payload = _validate_lwm2m_topic(data['topic'])
    if data['topic'] == '/19/1/0':
        handled_payload['msgType'] = 'write'
        handled_payload['value'] = load_payload
    else:
        msg_type = load_payload.get('msgType')
        if msg_type == 'read':
            # {'msgType': 'read', 'path': xx}
            handled_payload['msgType'] = 'read'
        elif msg_type == 'write' and load_payload.get('value'):
            # {'msgType': 'write', 'path': xx, 'value': xx, 'type': xx}
            handled_payload['msgType'] = 'write'
            handled_payload['value'] = load_payload['value']
        elif msg_type == 'execute':
            # {'msgType': 'execute', 'path': xx, 'args'}
            handled_payload['msgType'] = 'execute'
            if load_payload.get('args'):
                handled_payload['args'] = load_payload['args']
        else:
            raise FormInvalid(field='payload')
    data['payload'] = json.dumps(handled_payload)
    return data
예제 #2
0
 def device_name_is_exist(self, value):
     device_type = self.get_origin_obj('deviceType')
     if device_type and device_type != value:
         # deviceType not support update
         raise FormInvalid(field='deviceType')
     product_type = self.get_request_data('productType')
     if device_type != product_type:
         raise FormInvalid(field='deviceType')
예제 #3
0
 def email_is_exist(self, value):
     try:
         split_email = value.split('@')[0]
         if split_email in current_app.config.get('RESERVED'):
             raise FormInvalid(field='email')
     except Exception:
         raise FormInvalid(field='email')
     if db.session.query(User.email).filter_by(email=value).first():
         raise DataExisted(field='email')
예제 #4
0
파일: schemas.py 프로젝트: imfht/flaskapp1
    def validate_webhook(self, data):
        url = data.get('url')
        token = data.get('token')
        if not all([url, token]):
            return
        timestamp = int(time.time())
        nonce = generate_uuid(size=10)
        hash_str = f"{token}{timestamp}{nonce}".encode('utf-8')
        signature = hashlib.sha1(hash_str).hexdigest()

        validate_status = True
        params = dict(signature=signature, timestamp=timestamp, nonce=nonce)
        with SyncHttp() as sync_http:
            response = sync_http.get(url=url, params=params)
        if response.responseCode != 200:
            validate_status = False
        try:
            response_dict = json.loads(response.responseContent)
            if response_dict.get('nonce') != params.get('nonce'):
                validate_status = False
        except Exception as e:
            logger.error(f"Webhook {e}", exc_info=True)
            validate_status = False
        if not validate_status:
            raise FormInvalid(field='Webhook url')
예제 #5
0
파일: auth.py 프로젝트: imfht/flaskapp1
def signup_normal_user(normal_user=None):
    tenant_dict = TenantSchema.validate_request()
    tenant_type = tenant_dict.get('tenantType')
    tenant_uid = random_tenant_uid(tenant_type)
    tenant_dict['contactEmail'] = normal_user['email']
    tenant_dict['tenantID'] = tenant_uid

    phone = normal_user.get('phone') or tenant_dict.get('contactPhone')
    tenant_dict['contactPhone'] = phone
    normal_user['phone'] = phone

    new_tenant = Tenant()
    for key, value in tenant_dict.items():
        if hasattr(new_tenant, key):
            setattr(new_tenant, key, value)
    db.session.add(new_tenant)
    db.session.flush()

    # Role
    if tenant_type == 1:
        normal_user['roleIntID'] = 3
    elif tenant_type == 2:
        normal_user['roleIntID'] = 2
    else:
        raise FormInvalid(field='tenantType')
    normal_user['tenantID'] = tenant_uid
    return normal_user
예제 #6
0
 def validate_uplink_system(self, data):
     uplink_system = data.get('upLinkSystem')
     if uplink_system == 1:
         data['parentDevice'], data['gateway'] = None, None
     elif uplink_system == 2 and isinstance(data.get('parentDevice'), int):
         parent_device = data['parentDevice']
         end_device_id = EndDevice.query \
             .filter_tenant(tenant_uid=g.tenant_uid) \
             .filter(EndDevice.id == parent_device) \
             .with_entities(EndDevice.id).first()
         if not end_device_id:
             raise DataNotFound(field='parentDevice')
         data['parentDevice'], data['gateway'] = end_device_id, None
     elif uplink_system == 3 and isinstance(data.get('gateway'), int):
         gateway = data['gateway']
         gateway_id = Gateway.query \
             .filter_tenant(tenant_uid=g.tenant_uid) \
             .filter(Gateway.id == gateway) \
             .with_entities(Gateway.id).first()
         if not gateway_id:
             raise DataNotFound(field='gateway')
         data['parentDevice'], data['gateway'] = None, gateway_id
     else:
         raise FormInvalid(field='upLinkSystem')
     return data
예제 #7
0
def _validate_lwm2m_topic(topic: str) -> dict:
    handled_payload = {'path': topic}
    if topic == '/19/1/0':
        handled_payload['type'] = 'Opaque'
    else:
        product_item_info = [i for i in topic.split('/') if i.isdigit()]
        if len(product_item_info) != 3:
            raise FormInvalid(field='topic')
        # item_id/xx/object_id/ or item_id/xx/object_id/xxx
        object_id, item_id = product_item_info[0], product_item_info[2]
        lwm2m_item = Lwm2mItem.query \
            .filter(Lwm2mItem.objectID == object_id, Lwm2mItem.itemID == item_id) \
            .with_entities(Lwm2mItem.objectItem, Lwm2mItem.itemType).first()
        if not lwm2m_item:
            raise FormInvalid(field='topic')
        handled_payload['type'] = lwm2m_item.itemType
    return handled_payload
예제 #8
0
파일: schemas.py 프로젝트: imfht/flaskapp1
 def product_load(self, data):
     product_type = data.get('productType')
     if not product_type:
         data['productType'] = 1
     gateway_protocol = data.get('gatewayProtocol')
     if data['productType'] == 2 and not gateway_protocol:
         raise FormInvalid(field='gatewayProtocol')
     if data['productType'] == 1 and gateway_protocol:
         data['gatewayProtocol'] = None
     return data
예제 #9
0
파일: schemas.py 프로젝트: imfht/flaskapp1
 def stream_id_is_exist(self, value):
     if self._validate_obj('streamID', value):
         return
     if not re.match(r"^[a-zA-Z]\w{3,}$", value):
         raise FormInvalid(field='streamID')
     product_uid = self.get_request_data('productID')
     stream_name = db.session.query(DataStream.streamID) \
         .filter(DataStream.productID == product_uid,
                 DataStream.streamID == value).first()
     if stream_name:
         raise DataExisted(field='streamID')
예제 #10
0
파일: schemas.py 프로젝트: imfht/flaskapp1
 def validate_timer_format(data):
     timer_type = data.get('timerType')
     interval_time = data.get('intervalTime')
     crontab_time = data.get('crontabTime')
     if timer_type == 1 and crontab_time and not interval_time:
         date_now = arrow.now(tz=current_app.config['TIMEZONE']).shift(
             minutes=+2)
         try:
             crontab_time = arrow.get(crontab_time)
         except ParserError:
             raise FormInvalid(field='crontabTime')
         if crontab_time < date_now:
             FormInvalid(field='crontabTime')
     elif timer_type == 2 and interval_time and not crontab_time:
         check_status = check_interval_time(interval_time)
         if not check_status:
             raise FormInvalid(field='intervalTime')
     else:
         raise FormInvalid(field='timerType')
     return data
예제 #11
0
파일: schemas.py 프로젝트: imfht/flaskapp1
    def validate_point_uid(self, value):
        if not value or self._validate_obj('dataPointID', value):
            return

        if not re.match(r"^[0-9A-Za-z_\-]*$", value):
            raise FormInvalid(field='dataPointID')
        product_uid = self.get_request_data('productID')
        data_point_uid = db.session.query(DataPoint.dataPointID) \
            .filter(DataPoint.productID == product_uid,
                    DataPoint.dataPointID == value).first()
        if data_point_uid:
            raise DataExisted(field='dataPointID')
예제 #12
0
파일: auth.py 프로젝트: imfht/flaskapp1
def signup_invite_user(token):
    jwt = JWT(current_app.config['SECRET_KEY'])
    try:
        data = jwt.loads(token)
    except Exception:
        raise FormInvalid(field='token')

    if not data.get('invitation_id'):
        raise FormInvalid(field='invitation')
    invitation = Invitation.query \
        .join(Tenant, Tenant.tenantID == Invitation.tenantID) \
        .filter(Invitation.id == data.get('invitation_id'),
                Invitation.inviteStatus == 0, Tenant.enable == 1) \
        .first()
    if not invitation:
        raise DataNotFound(field='invitation')
    invitation.inviteStatus = 1
    invite_user = {
        'roleIntID': invitation.roleIntID,
        'tenantID': invitation.tenantID
    }
    return invite_user
예제 #13
0
파일: schemas.py 프로젝트: imfht/flaskapp1
 def handle_load_data(self, data):
     product_uid: str = data.get('productID')
     if not isinstance(product_uid, str):
         raise FormInvalid(field='productID')
     product = Product.query. \
         filter_tenant(tenant_uid=g.tenant_uid) \
         .filter(Product.productID == product_uid).first()
     if not product:
         raise DataNotFound(field='productID')
     data['productID'] = product.productID
     data['cloudProtocol'] = product.cloudProtocol
     data = handle_extend_type_attr(data)
     return data
예제 #14
0
파일: devices.py 프로젝트: imfht/flaskapp1
def device_query_object() -> Tuple[BaseQueryT, BaseModelT]:
    device_type = request.args.get('deviceType', type=int)
    if request.method in ('PUT', 'POST'):
        request_dict = request.get_json() or {}
        device_type = request_dict.get('deviceType')
        if device_type not in [1, 2]:
            raise FormInvalid(field='deviceType')
    if device_type == 1:
        query, model = EndDevice.query, EndDevice
    elif device_type == 2:
        query, model = Gateway.query, Gateway
    else:
        query, model = Device.query, Device
    return query, model
예제 #15
0
 def handle_origin_data(self, data):
     product_uid = data.get('productID')
     if not isinstance(product_uid, str):
         raise FormInvalid(field='productID')
     product = Product.query \
         .filter_tenant(tenant_uid=g.tenant_uid) \
         .filter(Product.productID == product_uid).first()
     if not product:
         raise DataNotFound(field='productID')
     data['productType'] = product.productType
     data['productID'] = product.productID
     data['cloudProtocol'] = product.cloudProtocol
     data['gatewayProtocol'] = product.gatewayProtocol
     return data
예제 #16
0
def device_publish():
    request_dict = PublishSchema.validate_request()
    # # create publish logs
    request_dict['taskID'] = generate_uuid()
    request_dict['publishStatus'] = 1
    request_dict['payload'] = json.loads(request_dict['payload'])
    client_publish_log = PublishLog()
    created_publish_log = client_publish_log.create(request_dict)
    # get publish json of protocol
    publish_json_func = PROTOCOL_PUBLISH_JSON_FUNC.get(request_dict['protocol'])
    if not publish_json_func:
        raise FormInvalid(field='cloudProtocol')
    publish_json = publish_json_func(request_dict)
    record = _emqx_client_publish(publish_json, created_publish_log)
    return jsonify(record)
예제 #17
0
def update_tenant(tenant_id):
    if g.role_id != 1:
        raise DataNotFound(field='url')

    tenant = Tenant.filter(Tenant.id == tenant_id).first_or_404()
    request_dict = request.get_json()
    if not request_dict:
        raise APIException()
    enable = request_dict.get('enable')
    if enable not in [0, 1]:
        raise FormInvalid(field='enable')

    update_dict = {'enable': enable}
    updated_tenant = tenant.update(update_dict)
    record = updated_tenant.to_dict()
    return jsonify(record)
예제 #18
0
 def handle_user_auth_type(self, data):
     if 'user_id' not in g:
         data['userAuthType'] = 1
     groups_uid = self.get_request_data(key='groups')
     auth_type = data.get('userAuthType')
     if auth_type not in (1, 2):
         raise FormInvalid(field='userAuthType')
     if auth_type == 2 and groups_uid:
         groups = Group.query \
             .filter_tenant(tenant_uid=g.tenant_uid) \
             .filter(Group.groupID.in_(set(groups_uid))).all()
         if len(groups_uid) != len(groups):
             raise DataNotFound(field='groups')
         data['groups'] = groups
     else:
         data.pop('groups', None)
     return data
예제 #19
0
 def handle_data(self, data):
     device_uid = data.get('deviceID')
     if not isinstance(device_uid, str):
         raise FormInvalid(field='deviceID')
     client_info = db.session \
         .query(Device.id.label('deviceIntID'), Device.productID, Device.tenantID,
                DictCode.codeValue.label('cloudProtocol'),
                func.lower(DictCode.enLabel).label('protocol')) \
         .join(Product, Product.productID == Device.productID) \
         .join(DictCode, DictCode.codeValue == Product.cloudProtocol) \
         .filter(Device.deviceID == device_uid, Device.tenantID == g.tenant_uid,
                 DictCode.code == 'cloudProtocol').to_dict()
     data.update(client_info)
     data['prefixTopic'] = (
         f"/{data['protocol']}/{data['tenantID']}"
         f"/{data['productID']}/{data['deviceID']}/"
     )
     return data
예제 #20
0
 def handle_validated_data(self, data):
     data = self.handle_put_request(data)
     groups_uid: List[str] = data.get('groups')
     if groups_uid:
         groups = Group.query \
             .filter_tenant(tenant_uid=g.tenant_uid) \
             .filter(Group.groupID.in_(set(groups_uid))) \
             .many(expect_result=len(groups_uid))
         data['groups'] = groups
     if data['authType'] == 2:
         certs_id: List[int] = data.get('certs')
         if not certs_id:
             raise FormInvalid(field='certs')
         certs = Cert.query \
             .filter_tenant(tenant_uid=g.tenant_uid) \
             .filter(Cert.id.in_(set(certs_id))) \
             .many(expect_result=len(certs_id))
         data['certs'] = certs
     return data
예제 #21
0
def create_rule():
    request_dict = RuleSchema.validate_request()
    rule = Rule()
    new_rule = rule.create(request_dict, commit=False)

    action_ids = request.get_json().get('actions')
    if not isinstance(action_ids, list):
        raise FormInvalid(field='actions')
    actions = Action.query \
        .filter(Action.id.in_(action_ids)) \
        .many()
    for action in actions:
        new_rule.actions.append(action)

    rule_json = get_rule_json(new_rule)
    url = f"{current_app.config.get('STREAM_RULE_URL')}/"
    stream_rule_http('post', url=url, json=rule_json)
    db.session.commit()
    record = new_rule.to_dict()
    return jsonify(record), 201
예제 #22
0
 def validate_cloud_protocol(self, data):
     cloud_protocol = data.get('cloudProtocol')
     if cloud_protocol in [1, 2, 5, 6, 7]:
         # mqtt, coap, http, websocket, modbus
         data['loraData'], data['lwm2mData'] = None, None
     elif cloud_protocol == 3 and data.get('lwm2mData'):
         # lwm2m data
         data['loraData'] = None
         data['lwm2mData'] = Lwm2mDeviceSchema().load(
             data['lwm2mData']).data
         data['deviceID'] = data['lwm2mData']['IMEI']
     elif cloud_protocol == 4 and data.get('loraData'):
         # lora data
         data['lwm2mData'] = None
         data['loraData'] = LoRaDeviceSchema().load(data['loraData']).data
     else:
         error_fields = {3: 'lwm2mData', 4: 'loraData'}
         raise FormInvalid(
             field=error_fields.get(cloud_protocol, 'cloudProtocol'))
     return data
예제 #23
0
def get_rule_json(rule):
    rule_actions = []
    for action in rule.actions:
        if action.actionType == 1:
            alert_dict = AlertActionSchema().dump(action.config).data
            action_config = {
                'webhook': {
                    **alert_dict, 'url':
                    current_app.config.get('CURRENT_ALERT_URL'),
                    'ruleIntID':
                    rule.id
                }
            }
        elif action.actionType == 2:
            email_dict = EmailActionSchema().dump(action.config).data
            action_config = {'mail': email_dict}
        elif action.actionType == 3:
            webhook_dict = WebhookActionSchema().dump(action.config).data
            action_config = {'webhook': webhook_dict}
        elif action.actionType == 4:
            publish_dict = PublishActionSchema().dump(action.config).data
            publish_dict['taskID'] = generate_uuid()
            publish_json_func = PROTOCOL_PUBLISH_JSON_FUNC.get(
                publish_dict['protocol'])
            if not publish_json_func:
                raise FormInvalid(field='cloudProtocol')
            publish_json = publish_json_func(publish_dict)
            action_config = {'publish': {'json': json.dumps(publish_json)}}
        elif action.actionType == 5:
            mqtt_dict = MqttActionSchema().dump(action.config).data
            action_config = {'mqtt': mqtt_dict}
        else:
            continue
        rule_actions.append(action_config)
    rule_json = {
        'id': rule.id,
        'sql': rule.sql,
        'enabled': rule.enable == 1,
        'actions': rule_actions
    }
    return rule_json
예제 #24
0
    def device_uid_is_exist(self, data):
        device_uid = data.get('deviceID')
        username = data.get('deviceUsername')

        if self.get_origin_obj('deviceID'):
            return data
        if not device_uid or not username:
            device_uuid = generate_uuid(size=36)
            data['deviceID'] = device_uuid
            data['deviceUsername'] = device_uuid
            return data
        # unique within the tenant
        device_uid = db.session.query(Device.deviceID) \
            .filter(Device.deviceID == device_uid,
                    Device.tenantID == g.tenant_uid).first()
        if device_uid:
            raise DataExisted(field='deviceID')
        # unique within the platform
        device = db.session.query(Device.id) \
            .filter(Device.deviceID == device_uid,
                    Device.deviceUsername == username).first()
        if device:
            raise FormInvalid(field='deviceID')
        return data
예제 #25
0
 def company_is_exist(self, value):
     if value == '':
         raise FormInvalid(field='company')
     if Tenant.query.filter_by(company=value).first():
         raise DataExisted(field='company')
예제 #26
0
 def validate_username(self, value):
     if value in current_app.config.get('RESERVED'):
         raise FormInvalid(field='username')
예제 #27
0
 def is_empty_list(self, value):
     if not value:
         raise FormInvalid('permissions')
예제 #28
0
파일: schemas.py 프로젝트: imfht/flaskapp1
 def validate_topic(self, value):
     if not value or self._validate_obj('topic', value):
         return
     if not re.match(r"^[0-9A-Za-z_\-/]*$", value):
         raise FormInvalid(field='topic')
예제 #29
0
 def handle_error(self, exception, data):
     """ Log and raise our custom exception when (de)serialization fails. """
     raise FormInvalid(errors=exception.messages)