def cleanup_preview_destination(event, resources): storage = event.request.registry.storage for impacted in event.impacted_records: old_collection = impacted["old"] resource, signer = pick_resource_and_signer(event.request, resources, bucket_id=event.payload["bucket_id"], collection_id=old_collection["id"]) if resource is None: continue for k in ("preview", "destination"): if k not in resource: # pragma: nocover continue bid = resource[k]["bucket"] cid = resource[k]["collection"] collection_uri = instance_uri(event.request, "collection", bucket_id=bid, id=cid) storage.delete_all("record", collection_uri, with_deleted=True) updater = LocalUpdater(signer=signer, storage=storage, permission=event.request.registry.permission, source=resource['source'], destination=resource[k]) updater.sign_and_update_destination(event.request, source_attributes=old_collection, next_source_status=None)
def test_updater_raises_if_resources_are_not_set_properly(self): with pytest.raises(ValueError) as excinfo: LocalUpdater(source={'bucket': 'source'}, destination={}, signer=self.signer_instance, storage=self.storage, permission=self.permission) assert str(excinfo.value) == ("Resources should contain both " "bucket and collection")
def set_work_in_progress_status(event, resources): """Put the status in work-in-progress if was signed. """ resource, signer = pick_resource_and_signer(event.request, resources, bucket_id=event.payload["bucket_id"], collection_id=event.payload["collection_id"]) # Skip if resource is not configured. if resource is None: return updater = LocalUpdater(signer=signer, storage=event.request.registry.storage, permission=event.request.registry.permission, source=resource['source'], destination=resource['destination']) updater.update_source_status(STATUS.WORK_IN_PROGRESS, event.request)
def setUp(self): self.storage = mock.MagicMock() self.permission = mock.MagicMock() self.signer_instance = mock.MagicMock() self.updater = LocalUpdater(source={ 'bucket': 'sourcebucket', 'collection': 'sourcecollection' }, destination={ 'bucket': 'destbucket', 'collection': 'destcollection' }, signer=self.signer_instance, storage=self.storage, permission=self.permission) # Resource events are bypassed completely in this test suite. patcher = mock.patch('kinto_signer.updater.build_request') self.addCleanup(patcher.stop) patcher.start()
def set_work_in_progress_status(event, resources): """Put the status in work-in-progress if was signed. """ payload = event.payload key = instance_uri(event.request, "collection", bucket_id=payload["bucket_id"], id=payload["collection_id"]) resource = resources.get(key) # Skip if resource is not configured. if resource is None: return registry = event.request.registry updater = LocalUpdater(signer=registry.signers[key], storage=registry.storage, permission=registry.permission, source=resource['source'], destination=resource['destination']) updater.update_source_status(STATUS.WORK_IN_PROGRESS, event.request)
def sign_collection_data(event, resources): """ Listen to resource change events, to check if a new signature is requested. When a source collection specified in settings is modified, and its new metadata ``status`` is set to ``"to-sign"``, then sign the data and update the destination. """ payload = event.payload current_user_id = event.request.prefixed_userid if current_user_id == _PLUGIN_USERID: # Ignore changes made by plugin. return # Prevent recursivity, since the following operations will alter the current collection. impacted_records = list(event.impacted_records) for impacted in impacted_records: new_collection = impacted['new'] old_collection = impacted.get('old', {}) uri = instance_uri(event.request, "collection", bucket_id=payload['bucket_id'], id=new_collection['id']) resource = resources.get(uri) # Only sign the configured resources. if resource is None: continue registry = event.request.registry updater = LocalUpdater(signer=registry.signers[uri], storage=registry.storage, permission=registry.permission, source=resource['source'], destination=resource['destination']) review_event_cls = None try: new_status = new_collection.get("status") old_status = old_collection.get("status") # Autorize kinto-attachment metadata write access. #190 event.request._attachment_auto_save = True if new_status == STATUS.TO_SIGN: # Run signature process (will set `last_reviewer` field). updater.sign_and_update_destination(event.request, source=new_collection) if old_status != STATUS.SIGNED: review_event_cls = signer_events.ReviewApproved elif new_status == STATUS.TO_REVIEW: if 'preview' in resource: # If preview collection: update and sign preview collection updater.destination = resource['preview'] updater.sign_and_update_destination( event.request, source=new_collection, next_source_status=STATUS.TO_REVIEW) else: # If no preview collection: just track `last_editor` with updater.send_events(event.request): updater.update_source_editor(event.request) review_event_cls = signer_events.ReviewRequested elif old_status == STATUS.TO_REVIEW and new_status == STATUS.WORK_IN_PROGRESS: review_event_cls = signer_events.ReviewRejected except Exception: logger.exception("Could not sign '{0}'".format(uri)) event.request.response.status = 503 # Notify request of review. if review_event_cls: payload = payload.copy() payload["uri"] = uri payload["collection_id"] = new_collection['id'] review_event = review_event_cls(request=event.request, payload=payload, impacted_records=[impacted], resource=resource, original_event=event) event.request.bound_data.setdefault('kinto_signer.events', []).append(review_event)
def sign_collection_data(event, resources, to_review_enabled, **kwargs): """ Listen to resource change events, to check if a new signature is requested. When a source collection specified in settings is modified, and its new metadata ``status`` is set to ``"to-sign"``, then sign the data and update the destination. """ payload = event.payload is_new_collection = payload['action'] == ACTIONS.CREATE.value current_user_id = event.request.prefixed_userid if current_user_id == PLUGIN_USERID: # Ignore changes made by plugin. return # Prevent recursivity, since the following operations will alter the current collection. impacted_records = list(event.impacted_records) for impacted in impacted_records: new_collection = impacted['new'] old_collection = impacted.get('old', {}) # Only sign the configured resources. resource, signer = pick_resource_and_signer(event.request, resources, bucket_id=payload['bucket_id'], collection_id=new_collection['id']) if resource is None: continue updater = LocalUpdater(signer=signer, storage=event.request.registry.storage, permission=event.request.registry.permission, source=resource['source'], destination=resource['destination']) uri = instance_uri(event.request, "collection", bucket_id=payload['bucket_id'], id=new_collection['id']) has_review_enabled = ('preview' in resource and resource.get('to_review_enabled', to_review_enabled)) review_event_cls = None new_status = new_collection.get("status") old_status = old_collection.get("status") # Autorize kinto-attachment metadata write access. #190 event.request._attachment_auto_save = True try: if is_new_collection: if has_review_enabled: updater.destination = resource['preview'] updater.sign_and_update_destination(event.request, source_attributes=new_collection, next_source_status=None) updater.destination = resource['destination'] updater.sign_and_update_destination(event.request, source_attributes=new_collection, next_source_status=None) if old_status == new_status: continue if new_status == STATUS.TO_SIGN: # Run signature process (will set `last_reviewer` field). updater.destination = resource['destination'] updater.sign_and_update_destination(event.request, source_attributes=new_collection, previous_source_status=old_status) if old_status == STATUS.SIGNED: # When we refresh the signature, it is mainly in order to make sure that # the latest signer certificate was used. When a preview collection # is configured, we also want to refresh its signature. if has_review_enabled: updater.destination = resource['preview'] updater.sign_and_update_destination(event.request, source_attributes=new_collection, previous_source_status=old_status) else: review_event_cls = signer_events.ReviewApproved elif new_status == STATUS.TO_REVIEW: if has_review_enabled: # If preview collection: update and sign preview collection updater.destination = resource['preview'] updater.sign_and_update_destination(event.request, source_attributes=new_collection, next_source_status=STATUS.TO_REVIEW) else: # If no preview collection: just track `last_editor` updater.update_source_review_request_by(event.request) review_event_cls = signer_events.ReviewRequested elif old_status == STATUS.TO_REVIEW and new_status == STATUS.WORK_IN_PROGRESS: review_event_cls = signer_events.ReviewRejected elif new_status == STATUS.TO_REFRESH: updater.refresh_signature(event.request, next_source_status=old_status) if has_review_enabled: updater.destination = resource['preview'] updater.refresh_signature(event.request, next_source_status=old_status) except Exception: logger.exception("Could not sign '{0}'".format(uri)) event.request.response.status = 503 # Notify request of review. if review_event_cls: payload = payload.copy() payload["uri"] = uri payload["collection_id"] = new_collection['id'] review_event = review_event_cls(request=event.request, payload=payload, impacted_records=[impacted], resource=resource, original_event=event) event.request.bound_data.setdefault('kinto_signer.events', []).append(review_event)