Example #1
0
def create_migrate(migrates: list):
    """
    Manages the creation of a Migrate event, like doing so for the devices.
    Heavily inspired by the hook 'on_insert_snapshot', uses the same idea on a group of devices.
    """
    all_events = []  # We will delete all events if exception
    try:
        for migrate in migrates:
            if 'from' in migrate:
                setattr(g, MIGRATE_RETURNED_SAME_AS, dict())
                devices_id = []
                migrate['components'] = []
                for device in migrate['devices']:
                    if device['@type'] in Component.types:
                        raise SchemaError('devices', 'You cannot directly migrate components.')
                    creator = MigrateCreator(device, device.pop('components'))
                    events = creator.execute()
                    all_events += events
                    migrate['events'] = [new_events['_id'] for new_events in events]
                    devices_id.append(device['_id'])
                    migrate['components'] += [component['_id'] for component in creator.components]
                    migrate['unsecured'] = creator.unsecured
                    getattr(g, MIGRATE_RETURNED_SAME_AS).update(creator.returned_same_as)
                from ereuse_devicehub.resources.hooks import set_date
                set_date(None, migrates)
                migrate['devices'] = devices_id
    except Exception as e:
        for event in all_events:
            # Could result in 404 (ex: delete an 'Add' after deleting 'Register' of the same device)
            execute_delete(Naming.resource(event['@type']), event['_id'])
        raise e
Example #2
0
def create_migrate(migrates: list):
    """
    Manages the creation of a Migrate event, like doing so for the devices.
    Heavily inspired by the hook 'on_insert_snapshot', uses the same idea on a group of devices.
    """
    all_events = []  # We will delete all events if exception
    try:
        for migrate in migrates:
            if 'from' in migrate:
                setattr(g, MIGRATE_RETURNED_SAME_AS, dict())
                devices_id = []
                migrate['components'] = []
                for device in migrate['devices']:
                    if device['@type'] in Component.types:
                        raise SchemaError('devices', 'You cannot directly migrate components.')
                    creator = MigrateCreator(device, device.pop('components'))
                    events = creator.execute()
                    all_events += events
                    migrate['events'] = [new_events['_id'] for new_events in events]
                    devices_id.append(device['_id'])
                    migrate['components'] += [component['_id'] for component in creator.components]
                    migrate['unsecured'] = creator.unsecured
                    getattr(g, MIGRATE_RETURNED_SAME_AS).update(creator.returned_same_as)
                from ereuse_devicehub.resources.hooks import set_date
                set_date(None, migrates)
                migrate['devices'] = devices_id
    except Exception as e:
        for event in all_events:
            # Could result in 404 (ex: delete an 'Add' after deleting 'Register' of the same device)
            execute_delete(Naming.resource(event['@type']), event['_id'])
        raise e
Example #3
0
def redirect_to_first_snapshot(resource, request, lookup):
    """
    DELETE /device should be an internal method, but it is open to redirect to the door that is going to effictevely
    delete the device; this is the first Snapshot that made the Register that made the device.
    """
    if resource in Device.resource_types:
        snapshot_id = str(DeviceEventDomain.get_first_snapshot(lookup['_id'])['_id'])
        execute_delete(Naming.resource('devices:Snapshot'), snapshot_id)
        raise RequestAnother('', 204)
Example #4
0
def redirect_to_first_snapshot(resource, request, lookup):
    """
    DELETE /device should be an internal method, but it is open to redirect to the door that is going to effictevely
    delete the device; this is the first Snapshot that made the Register that made the device.
    """
    if resource in Device.resource_types:
        snapshot_id = str(
            DeviceEventDomain.get_first_snapshot(lookup['_id'])['_id'])
        execute_delete(Naming.resource('devices:Snapshot'), snapshot_id)
        raise RequestAnother('', 204)
Example #5
0
def delete_events(_, snapshot: dict):
    """
    Deletes the events that were created with the snapshot.
    """
    if snapshot.get('@type') == 'devices:Snapshot':
        for event_id in snapshot['events']:
            try:
                # If the first event is Register, erasing the device will erase the rest of events
                event = DeviceEventDomain.get_one(event_id)
            except EventNotFound:
                pass
            else:
                try:
                    execute_delete(Naming.resource(event['@type']), event['_id'])
                except InnerRequestError as e:
                    if e.status_code != 404:
                        raise e
Example #6
0
def delete_events(_, snapshot: dict):
    """
    Deletes the events that were created with the snapshot.
    """
    if snapshot.get('@type') == 'devices:Snapshot':
        for event_id in snapshot['events']:
            try:
                # If the first event is Register, erasing the device will erase the rest of events
                event = DeviceEventDomain.get_one(event_id)
            except EventNotFound:
                pass
            else:
                try:
                    execute_delete(Naming.resource(event['@type']),
                                   event['_id'])
                except InnerRequestError as e:
                    if e.status_code != 404:
                        raise e
Example #7
0
def submit_migrate(migrates: dict):
    """
    Sends a Migrate event to the other DeviceHub.
    Note as the other DeviceHub requires the url of this event,
    this method needs to be executed after reaching the Database.
    """
    for migrate in migrates:
        if 'to' in migrate:
            auth = AgentAuth(migrate['to']['baseUrl'])
            submitter = MigrateSubmitter(current_app, MigrateTranslator(current_app.config), auth=auth)
            try:
                response, *_ = submitter.submit(migrate, AccountDomain.get_requested_database())
                migrate['to']['url'] = migrate['to']['baseUrl'] + response['_links']['self']['href']
                _update_same_as(response['returnedSameAs'])
            except InnerRequestError as e:
                execute_delete(Migrate.resource_name, migrate['_id'])
                raise e
            else:
                _remove_devices_from_places(migrate)
                update = {'$set': {'to.url': migrate['to']['url'], 'devices': [_id for _id in migrate['devices']]}}
                DeviceEventDomain.update_one_raw(migrate['_id'], update)
Example #8
0
def submit_migrate(migrates: dict):
    """
    Sends a Migrate event to the other DeviceHub.
    Note as the other DeviceHub requires the url of this event,
    this method needs to be executed after reaching the Database.
    """
    for migrate in migrates:
        if 'to' in migrate:
            auth = AgentAuth(migrate['to']['baseUrl'])
            submitter = MigrateSubmitter(current_app, MigrateTranslator(current_app.config), auth=auth)
            try:
                response, *_ = submitter.submit(migrate, AccountDomain.get_requested_database())
                migrate['to']['url'] = migrate['to']['baseUrl'] + response['_links']['self']['href']
                _update_same_as(response['returnedSameAs'])
            except InnerRequestError as e:
                execute_delete(Migrate.resource_name, migrate['_id'])
                raise e
            else:
                _remove_devices_from_places(migrate)
                update = {'$set': {'to.url': migrate['to']['url'], 'devices': [_id for _id in migrate['devices']]}}
                DeviceEventDomain.update_one_raw(migrate['_id'], update)
Example #9
0
def delete_events_in_device(resource_name: str, device: dict):
    """
    Deletes the references of the given device in all the events, and deletes the full event if it references only to
    the device.
    """
    if resource_name in Device.resource_types:
        _id = device["_id"]
        qin = {"$in": [_id]}
        query = {"$or": [{"device": _id}, {"devices": qin}, {"components": qin}], "@type": {"$ne": "devices:Register"}}
        sort = {"_created": pymongo.ASCENDING}  # Order is important to find the first Snapshot (see below)
        first_snapshot_found = False
        for event in DeviceEventDomain.get({"$query": query, "$orderby": sort}):
            if not first_snapshot_found and event["@type"] == "devices:Snapshot":
                # We cannot delete the Snapshot that created the device, because there is a change to create
                # an infinite loop: Snapshot that created device -> Register -> DEL /device -> Snapshot that created...
                first_snapshot_found = True
            else:
                event_resource = Naming.resource(event["@type"])
                if event.get("device", None) == _id:  # Am I the 'device' of the event?
                    execute_delete(event_resource, event["_id"])
                elif [_id] == event.get("devices", []):  # Is there no more 'devices' in the event, apart from me?
                    execute_delete(event_resource, event["_id"])
                # All events that do not use 'components' for materialization (aka Add/Remove) should be erased
                # if there are no more components
                elif event["@type"] in ("devices:Add", "devices:Remove") and event["components"] == [_id]:
                    execute_delete(event_resource, event["_id"])
                else:  # Keep the event; just delete my reference
                    DeviceEventDomain.update_raw(event["_id"], {"$pull": {"devices": qin, "components": qin}})
Example #10
0
def delete_events_in_device(resource_name: str, device: dict):
    """
    Deletes the references of the given device in all the events, and deletes the full event if it references only to
    the device.
    """
    if resource_name in Device.resource_types:
        _id = device['_id']
        qin = {'$in': [_id]}
        query = {'$or': [{'device': _id}, {'devices': qin}, {'components': qin}], '@type': {'$ne': 'devices:Register'}}
        sort = {'_created': pymongo.ASCENDING}  # Order is important to find the first Snapshot (see below)
        first_snapshot_found = False
        for event in DeviceEventDomain.get({'$query': query, '$orderby': sort}):
            if not first_snapshot_found and event['@type'] == 'devices:Snapshot':
                # We cannot delete the Snapshot that created the device, because there is a change to create
                # an infinite loop: Snapshot that created device -> Register -> DEL /device -> Snapshot that created...
                first_snapshot_found = True
            else:
                event_resource = Naming.resource(event['@type'])
                if event.get('device', None) == _id:  # Am I the 'device' of the event?
                    execute_delete(event_resource, event['_id'])
                elif [_id] == event.get('devices', []):  # Is there no more 'devices' in the event, apart from me?
                    execute_delete(event_resource, event['_id'])
                # All events that do not use 'components' for materialization (aka Add/Remove) should be erased
                # if there are no more components
                elif event['@type'] in ('devices:Add', 'devices:Remove') and event['components'] == [_id]:
                    execute_delete(event_resource, event['_id'])
                else:  # Keep the event; just delete my reference
                    DeviceEventDomain.update_raw(event['_id'], {'$pull': {'devices': qin, 'components': qin}})
Example #11
0
def delete_device(_, register):
    if register.get('@type') == Register.type_name:
        for device_id in [register['device']] + register.get('components', []):
            execute_delete(Naming.resource(DeviceDomain.get_one(device_id)['@type']), device_id)
Example #12
0
def delete_device(_, register):
    if register.get('@type') == Register.type_name:
        for device_id in [register['device']] + register.get('components', []):
            execute_delete(
                Naming.resource(DeviceDomain.get_one(device_id)['@type']),
                device_id)