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()
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})
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)
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})
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()
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'
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()
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
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()
def test_is_device(): user = MQTTUser() assert not user.is_device user.device = Device() assert user.is_device
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(
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})