Beispiel #1
0
def trigger_action():
    device_name_bi = request.args.get("device_name_bi", None)
    name_bi = request.args.get("name_bi", None)
    additional_data = request.args.get("additional_data", None)
    user = User.get_using_jwt_token(request.headers.get("Authorization", ""))

    arg_check = check_missing_request_argument(
        (device_name_bi, DEVICE_NAME_BI_MISSING_ERROR_MSG),
        (additional_data, ADDITIONAL_DATA_MISSING_ERROR_MSG),
        (name_bi, ACTION_NAME_BI_MISSING_ERROR_MSG))
    if arg_check is not True:
        return arg_check

    dv = Device.get_by_name_bi(device_name_bi)
    if dv is None or not User.can_use_device(user, dv.id):
        return http_json_response(False, 400,
                                  **{"error": UNAUTHORIZED_USER_ERROR_MSG})

    topic = format_topic(user.mqtt_creds.username, dv.mqtt_creds.username)
    ac = Device.get_action_by_bi(dv.id, name_bi)
    if ac is None:
        return http_json_response(False, 400,
                                  **{"error": ACTION_BI_INVALID_ERROR_MSG})
    payload = create_payload(user.mqtt_creds.username, {
        "action": ac.name.decode("utf-8"),
        "additional_data": additional_data
    })
    client.publish(topic, payload)
    return http_json_response()
Beispiel #2
0
def create_device():
    device_type_id = request.form.get("type_id", None)
    correctness_hash = request.form.get("correctness_hash", None)
    name = request.form.get("name", None)
    name_bi = request.form.get("name_bi", None)
    password_hash = request.form.get("password", None)
    user = User.get_using_jwt_token(request.headers.get("Authorization", ""))
    arg_check = check_missing_request_argument(
        (device_type_id, DEVICE_TYPE_ID_MISSING_ERROR_MSG),
        (correctness_hash, CORRECTNESS_HASH_MISSING_ERROR_MSG),
        (name, DEVICE_NAME_MISSING_ERROR_MSG),
        (password_hash, DEVICE_PASSWORD_MISSING_ERROR_MSG),
        (name_bi, DEVICE_NAME_BI_MISSING_ERROR_MSG))
    if arg_check is not True:
        return arg_check
    dt = None
    try:
        if is_valid_uuid(device_type_id):
            dt = db.session.query(DeviceType).filter(
                DeviceType.type_id == device_type_id).first()
    finally:
        if dt is None:
            return http_json_response(
                False, 400, **{"error": DEVICE_TYPE_ID_INCORRECT_ERROR_MSG})

    if not user.is_registered_with_broker:
        return http_json_response(
            False, 400, **{"error": NOT_REGISTERED_WITH_BROKER_ERROR_MSG})
    if not validate_broker_password(password_hash):
        return http_json_response(
            False, 400, **{"error": INVALID_BROKER_PASSWORD_ERROR_MSG})
    ud = UserDevice()
    # noinspection PyArgumentList
    dv = Device(device_type_id=device_type_id,
                device_type=dt,
                owner=user,
                owner_id=user.id,
                correctness_hash=correctness_hash,
                name=name.encode(),
                name_bi=name_bi)
    ud.device = dv
    with db.session.no_autoflush:
        user.devices.append(ud)
    dv.create_mqtt_creds_for_device(password_hash, db.session)
    user.add_acls_for_device(dv.id)
    db.session.add(dv)
    db.session.commit()
    return http_json_response(**{'id': dv.id})
Beispiel #3
0
def test_can_use_device(app_and_ctx, access_token, access_token_two):
    app, ctx = app_and_ctx
    device_id = 23

    with app.app_context():
        user = User.get_by_id(1)
        assert not User.can_use_device(user, "non a number")
        assert not User.can_use_device(user, 45)
        assert User.can_use_device(user, device_id)

        user_2 = User.get_by_id(2)
        assert not User.can_use_device(user_2, device_id)
        ud = UserDevice()
        dv = Device.get_by_id(device_id)
        ud.device = dv
        with db.session.no_autoflush:
            ud.user = user_2
        db.session.add(ud)
        db.session.commit()
        assert User.can_use_device(user_2, device_id)

        ud = UserDevice.get_by_ids(device_id, user_2.id)  # Clean-up
        dv.users.remove(ud)
        db.session.add(dv)
        db.session.commit()
        assert not User.can_use_device(user_2, device_id)
Beispiel #4
0
def get_device_data():
    device_name_bi = request.args.get("device_name_bi", None)
    user = User.get_using_jwt_token(request.headers.get("Authorization", ""))

    arg_check = check_missing_request_argument(
        (device_name_bi, DEVICE_NAME_BI_MISSING_ERROR_MSG))
    if arg_check is not True:
        return arg_check

    device = Device.get_by_name_bi(device_name_bi)

    if device is None:
        return http_json_response(
            False, 400, **{"error": DEVICE_NAME_BI_INVALID_ERROR_MSG})

    if not User.can_use_device(user, device.id):
        return http_json_response(False, 400,
                                  **{"error": UNAUTHORIZED_USER_ERROR_MSG})

    result = []
    for row in device.data:
        r = row.as_dict()
        for k, v in r.items():
            if isinstance(v, bytes):
                r[k] = v.decode()
        result.append(r)

    return http_json_response(**{'device_data': result})
Beispiel #5
0
def set_device_action():
    device_id = request.form.get("device_id", None)
    correctness_hash = request.form.get("correctness_hash", None)
    name = request.form.get("name", None)
    name_bi = request.form.get("name_bi", None)
    user = User.get_using_jwt_token(request.headers.get("Authorization", ""))

    arg_check = check_missing_request_argument(
        (device_id, DEVICE_ID_MISSING_ERROR_MSG),
        (correctness_hash, CORRECTNESS_HASH_MISSING_ERROR_MSG),
        (name, ACTION_NAME_MISSING_ERROR_MSG),
        (name_bi, ACTION_NAME_BI_MISSING_ERROR_MSG))
    if arg_check is not True:
        return arg_check

    if not user.is_registered_with_broker:
        return http_json_response(
            False, 400, **{"error": NOT_REGISTERED_WITH_BROKER_ERROR_MSG})
    if not User.can_use_device(user, device_id):
        return http_json_response(False, 400,
                                  **{"error": UNAUTHORIZED_USER_ERROR_MSG})

    dv = Device.get_by_id(device_id)
    with db.session.no_autoflush:
        dv.add_action(name.encode(), name_bi, correctness_hash)
    db.session.add(dv)
    db.session.commit()

    return http_json_response()
Beispiel #6
0
def test_get_action_by_bi(app_and_ctx):
    app, ctx = app_and_ctx

    with app.app_context():
        ac = Device.get_action_by_bi(
            23,
            '86a638eab77f45b9e0e2fb384471e517664df67cec75c33d724efa8649be357e')
        assert ac.correctness_hash == '$2b$12$jOfamxBlpNv4BM0Ro3t9uOjLOxkA28J8/82vHAG7m9H.roDBlntPi'
Beispiel #7
0
def revoke_user():
    device_name_bi = request.form.get("device_name_bi", None)
    revoke_user_id = request.form.get("revoke_user_id",
                                      None)  # ID of user to be revoked
    user = User.get_using_jwt_token(request.headers.get("Authorization", ""))
    user_to_revoke = User.get_by_id(revoke_user_id)

    arg_check = check_missing_request_argument(
        (device_name_bi, DEVICE_NAME_BI_MISSING_ERROR_MSG),
        (revoke_user_id, REVOKE_USER_ID_MISSING_ERROR_MSG),
        (None if user_to_revoke is None or user_to_revoke.id == user.id else
         user_to_revoke, REVOKE_USER_ID_INVALID_ERROR_MSG))
    if arg_check is not True:
        return arg_check

    device = Device.get_by_name_bi(device_name_bi)
    if device is None or not User.can_use_device(user, device.id):
        return http_json_response(False, 400,
                                  **{"error": UNAUTHORIZED_USER_ERROR_MSG})

    device = Device.get_by_id(device.id)

    if next((ud for ud in device.users if ud.user_id == user_to_revoke.id),
            None) is None:
        return http_json_response(
            False, 400, **{"error": REVOKE_USER_NOT_AUTHORIZED_ERROR_MSG})

    ud_to_remove = UserDevice.get_by_ids(int(device.id), user_to_revoke.id)

    device.users.remove(ud_to_remove)
    db.session.add(device)
    user_to_revoke.remove_acls_for_device(device.id)
    device.remove_acls_for_user(revoke_user_id)
    db.session.add(device)
    db.session.add(user_to_revoke)
    db.session.commit()

    return http_json_response()
Beispiel #8
0
def test_delete_account(client, app_and_ctx):
    server_data = {}
    aa_data = {}
    server_provider_token = "server_token"
    aa_provider_token = "aa_token"

    device_id = 99999
    token_hash = bcrypt.using(rounds=13).hash(server_provider_token)
    aa_token_hash = bcrypt.using(rounds=13).hash(aa_provider_token)

    user = User(access_token=token_hash,
                access_token_update=datetime.now(),
                owned_devices=[
                    Device(id=device_id, name=b"test", correctness_hash="")
                ])
    aa_user = AttrAuthUser(access_token=aa_token_hash,
                           access_token_update=datetime.now())

    db.session.add(aa_user)
    db.session.add(user)
    db.session.commit()

    app, ctx = app_and_ctx

    with app.app_context():
        server_data["access_token"] = generate_auth_token(
            user.id, server_provider_token)
        aa_data["access_token"] = generate_auth_token(user.id,
                                                      aa_provider_token)

    assert db.session.query(User).filter(
        User.access_token == token_hash).first() is not None
    assert db.session.query(Device).filter(
        Device.id == device_id).first() is not None
    assert db.session.query(AttrAuthUser).filter(
        AttrAuthUser.access_token == aa_token_hash).first() is not None

    assert_got_data_from_post(client, '/delete_account', server_data)
    assert_got_data_from_post(client, '/attr_auth/delete_account', aa_data)

    assert db.session.query(User).filter(
        User.access_token == token_hash).first() is None
    assert db.session.query(Device).filter(
        Device.id == device_id).first() is None
    assert db.session.query(AttrAuthUser).filter(
        AttrAuthUser.access_token == aa_token_hash).first() is None
Beispiel #9
0
def authorize_user():
    device_name_bi = request.form.get("device_name_bi", None)
    auth_user_id = request.form.get("auth_user_id",
                                    None)  # ID of user to be authorized
    user = User.get_using_jwt_token(request.headers.get("Authorization", ""))
    auth_user = User.get_by_id(auth_user_id)

    arg_check = check_missing_request_argument(
        (device_name_bi, DEVICE_NAME_BI_MISSING_ERROR_MSG),
        (auth_user_id, AUTH_USER_ID_MISSING_ERROR_MSG),
        (None if auth_user is None or auth_user.id == user.id else auth_user,
         AUTH_USER_ID_INVALID_ERROR_MSG))
    if arg_check is not True:
        return arg_check

    device = Device.get_by_name_bi(device_name_bi)
    if device is None or not User.can_use_device(user, device.id):
        return http_json_response(False, 400,
                                  **{"error": UNAUTHORIZED_USER_ERROR_MSG})

    if not auth_user.is_registered_with_broker:
        return http_json_response(
            False, 400, **{"error": NOT_REGISTERED_WITH_BROKER_ERROR_MSG})

    if next((ud for ud in device.users if ud.user_id == auth_user.id),
            None) is not None:
        return http_json_response(
            False, 400, **{"error": AUTH_USER_ALREADY_AUTHORIZED_ERROR_MSG})

    ud = UserDevice()
    ud.device = device
    ud.user = auth_user
    db.session.add(ud)
    auth_user.add_acls_for_device(device.id)
    device.add_acls_for_user(auth_user_id)

    db.session.add(auth_user)
    db.session.add(device)
    db.session.commit()

    return http_json_response()
Beispiel #10
0
def test_is_device():
    user = MQTTUser()
    assert not user.is_device

    user.device = Device()
    assert user.is_device
Beispiel #11
0
    keys["users"][user.id]["actions"] = {}
    keys["users"][user.id]["aa_secret_keys"] = {}

    for i in range(100, device_no + 100):  # 3 devices per user
        dv_bi_key = os.urandom(32)
        dv_name_key = os.urandom(32)
        cipher = Fernet(base64.urlsafe_b64encode(dv_name_key))
        dv_name = cipher.encrypt(int_to_bytes(device_no))

        dv_status_key = os.urandom(32)
        cipher = Fernet(base64.urlsafe_b64encode(dv_status_key))
        dv_status = cipher.encrypt(int_to_bytes(0))
        # noinspection PyArgumentList
        dv = Device(status=dv_status,
                    device_type_id=random.choice(device_types).id,
                    name=dv_name,
                    name_bi=blind_index(dv_bi_key, str(i)),
                    correctness_hash=correctness_hash(str(i)),
                    owner=user)

        ud = UserDevice()
        ud.device = dv
        ud.user = user
        user.devices.append(ud)

        db.session.add(dv)
        db.session.flush()

        keys["users"][user.id]["devices"][dv.id] = {}
        keys["users"][user.id]["devices"][dv.id]["dv_bi_key"] = key_to_hex(
            dv_bi_key)
        keys["users"][user.id]["devices"][dv.id]["dv_name_key"] = key_to_hex(
Beispiel #12
0
def get_data_by_num_range():
    lower_bound = request.args.get("lower", "")
    upper_bound = request.args.get("upper", "")
    device_name_bi = request.args.get("device_name_bi", None)
    user = User.get_using_jwt_token(request.headers.get("Authorization", ""))

    arg_check = check_missing_request_argument(
        (device_name_bi, DEVICE_NAME_BI_MISSING_ERROR_MSG))
    if arg_check is not True:
        return arg_check

    device = Device.get_by_name_bi(device_name_bi)

    if device is None:
        return http_json_response(
            False, 400, **{"error": DEVICE_NAME_BI_INVALID_ERROR_MSG})

    if not User.can_use_device(user, device.id):
        return http_json_response(False, 400,
                                  **{"error": UNAUTHORIZED_USER_ERROR_MSG})

    if not is_number(lower_bound) and not is_number(upper_bound):
        return http_json_response(False, 400,
                                  **{"error": DATA_RANGE_MISSING_ERROR_MSG})

    with suppress(ValueError):
        lower_bound = int(lower_bound)
    with suppress(ValueError):
        upper_bound = int(upper_bound)

    data = []
    if isinstance(lower_bound, int) and isinstance(upper_bound, int):
        if -214748364800 <= lower_bound < upper_bound <= 214748364700:
            data = db.session.query(DeviceData).join(Device).filter(
                and_(DeviceData.num_data > lower_bound,
                     DeviceData.num_data < upper_bound,
                     Device.name_bi == device_name_bi)).all()
        else:
            return http_json_response(
                False, 400, **{"error": DATA_OUT_OF_OUTPUT_RANGE_ERROR_MSG})
    elif not isinstance(upper_bound, int) and isinstance(lower_bound, int):
        if -214748364800 <= lower_bound <= 214748364700:
            data = db.session.query(DeviceData).join(Device).filter(
                and_(DeviceData.num_data > lower_bound,
                     Device.name_bi == device_name_bi)).all()
        else:
            return http_json_response(
                False, 400, **{"error": DATA_OUT_OF_OUTPUT_RANGE_ERROR_MSG})

    elif not isinstance(lower_bound, int) and isinstance(upper_bound, int):
        if -214748364800 <= upper_bound <= 214748364700:
            data = db.session.query(DeviceData).join(Device).filter(
                and_(DeviceData.num_data < upper_bound,
                     Device.name_bi == device_name_bi)).all()
        else:
            return http_json_response(
                False, 400, **{"error": DATA_OUT_OF_OUTPUT_RANGE_ERROR_MSG})

    result = []
    for row in data:
        r = row.as_dict()
        for k, v in r.items():
            if isinstance(v, bytes):
                r[k] = v.decode()
        result.append(r)
    return http_json_response(**{'device_data': result})