def test_activate_channel(self): previous_tree = self.channel.previous_tree tree(parent=previous_tree) garbage_node = get_deleted_chefs_root() # Previous tree shouldn't be in garbage tree until activate_channel is called self.assertFalse(garbage_node.get_descendants().filter( pk=previous_tree.pk).exists()) activate_channel(self.channel, self.user) garbage_node.refresh_from_db() previous_tree.refresh_from_db() self.channel.refresh_from_db() # We can't use MPTT methods on the deleted chefs tree because we are not running the sort code # for performance reasons, so just do a parent test instead. self.assertTrue(previous_tree.parent == garbage_node) # New previous tree should not be in garbage tree self.assertFalse(self.channel.previous_tree.parent) self.assertNotEqual(garbage_node.tree_id, self.channel.previous_tree.tree_id) child_pk = previous_tree.children.first().pk clean_up_deleted_chefs() self.assertFalse( cc.ContentNode.objects.filter(parent=garbage_node).exists()) self.assertFalse(cc.ContentNode.objects.filter(pk=child_pk).exists())
def test_activate_channel(self): previous_tree = self.channel.previous_tree tree(parent=previous_tree) garbage_node = get_deleted_chefs_root() # Previous tree shouldn't be in garbage tree until activate_channel is called self.assertFalse(garbage_node.get_descendants().filter(pk=previous_tree.pk).exists()) activate_channel(self.channel, self.user) garbage_node.refresh_from_db() previous_tree.refresh_from_db() self.channel.refresh_from_db() # We can't use MPTT methods on the deleted chefs tree because we are not running the sort code # for performance reasons, so just do a parent test instead. self.assertTrue(previous_tree.parent == garbage_node) # New previous tree should not be in garbage tree self.assertFalse(self.channel.previous_tree.parent) self.assertNotEqual(garbage_node.tree_id, self.channel.previous_tree.tree_id) child_pk = previous_tree.children.first().pk clean_up_deleted_chefs() self.assertFalse(cc.ContentNode.objects.filter(parent=garbage_node).exists()) self.assertFalse(cc.ContentNode.objects.filter(pk=child_pk).exists())
def api_channel_structure_upload(request): """ Creates a channel based on the structure sent in the request. :param request: POST request containing the tree structure of a channel. :return: The channel_id of the newly created channel. """ data = json.loads(request.body) try: channel_id = data['channel_id'] channel_structure = data['channel_structure'] new_channel = create_channel_from_structure(channel_id, channel_structure, request.user) if not data.get( 'stage' ): # If user says to stage rather than submit, skip changing trees at this step activate_channel(new_channel, request.user) return HttpResponse( json.dumps({ 'success': True, 'channel_id': new_channel.pk, })) except KeyError: raise ObjectDoesNotExist( 'Missing attribute from data: {}'.format(data)) except Exception as e: return HttpResponseServerError(content=str(e), reason=str(e))
def activate_channel_endpoint(request): if request.method == 'POST': data = json.loads(request.body) channel = Channel.objects.get(pk=data['channel_id']) activate_channel(channel) return HttpResponse(json.dumps({"success": True}))
def api_commit_channel(request): """ Commit the channel staging tree to the main tree """ data = json.loads(request.body) try: channel_id = data['channel_id'] obj = Channel.objects.get(pk=channel_id) # rebuild MPTT tree for this channel (since we set "disable_mptt_updates", and bulk_create doesn't trigger rebuild signals anyway) ContentNode.objects.partial_rebuild(obj.chef_tree.tree_id) obj.chef_tree.get_descendants(include_self=True).update( original_channel_id=channel_id, source_channel_id=channel_id) old_staging = obj.staging_tree obj.staging_tree = obj.chef_tree obj.chef_tree = None obj.save() # Delete staging tree if it already exists if old_staging and old_staging != obj.main_tree: old_staging.delete() if not data.get( 'stage' ): # If user says to stage rather than submit, skip changing trees at this step activate_channel(obj) return HttpResponse( json.dumps({ "success": True, "new_channel": obj.pk, })) except KeyError: raise ObjectDoesNotExist( "Missing attribute from data: {}".format(data))
def activate_channel_internal(request): try: data = json.loads(request.body) channel = Channel.objects.get(pk=data['channel_id']) activate_channel(channel, request.user) return HttpResponse(json.dumps({"success": True})) except Exception as e: return HttpResponseServerError(content=str(e), reason=str(e))
def activate_channel_internal(request): try: data = json.loads(request.body) channel = Channel.objects.get(pk=data['channel_id']) activate_channel(channel, request.user) return HttpResponse(json.dumps({"success": True})) except Exception as e: handle_server_error(request) return HttpResponseServerError(content=str(e), reason=str(e))
def api_commit_channel(request): """ Commit the channel chef_tree to staging tree to the main tree. This view backs the endpoint `/api/internal/finish_channel` called by ricecooker. """ data = json.loads(request.body) try: channel_id = data['channel_id'] request.user.can_edit(channel_id) obj = Channel.objects.get(pk=channel_id) # Need to rebuild MPTT tree pointers since we used `disable_mptt_updates` ContentNode.objects.partial_rebuild(obj.chef_tree.tree_id) # set original_channel_id and source_channel_id to self since chef tree obj.chef_tree.get_descendants(include_self=True).update( original_channel_id=channel_id, source_channel_id=channel_id) # replace staging_tree with chef_tree old_staging = obj.staging_tree obj.staging_tree = obj.chef_tree obj.chef_tree = None obj.save() # Mark old staging tree for garbage collection if old_staging and old_staging != obj.main_tree: # IMPORTANT: Do not remove this block, MPTT updating the deleted chefs block could hang the server with ContentNode.objects.disable_mptt_updates(): garbage_node = get_deleted_chefs_root() old_staging.parent = garbage_node old_staging.title = "Old staging tree for channel {}".format( obj.pk) old_staging.save() # If ricecooker --stage flag used, we're done (skip ACTIVATE step), else # we ACTIVATE the channel, i.e., set the main tree from the staged tree if not data.get('stage'): try: activate_channel(obj, request.user) except PermissionDenied as e: return Response(str(e), status=e.status_code) return Response({ "success": True, "new_channel": obj.pk, }) except (Channel.DoesNotExist, PermissionDenied): return HttpResponseNotFound( "No channel matching: {}".format(channel_id)) except KeyError as e: return HttpResponseBadRequest("Required attribute missing: {}".format( e.message)) except Exception as e: handle_server_error(request) return HttpResponseServerError(content=str(e), reason=str(e))
def activate_channel_endpoint(request): if request.method == 'POST': data = json.loads(request.body) channel = Channel.objects.get(pk=data['channel_id']) try: activate_channel(channel, request.user) except PermissionDenied as e: return HttpResponseForbidden(str(e)) return HttpResponse(json.dumps({"success": True}))
def activate_channel_internal(request): try: data = json.loads(request.body) channel_id = data['channel_id'] request.user.can_edit(channel_id) channel = Channel.objects.get(pk=channel_id) activate_channel(channel, request.user) return Response({"success": True}) except (Channel.DoesNotExist, PermissionDenied): return HttpResponseNotFound("No channel matching: {}".format(channel_id)) except Exception as e: handle_server_error(request) return HttpResponseServerError(content=str(e), reason=str(e))
def api_commit_channel(request): """ Commit the channel staging tree to the main tree """ data = json.loads(request.body) try: channel_id = data['channel_id'] obj = Channel.objects.get(pk=channel_id) # rebuild MPTT tree for this channel (since we set "disable_mptt_updates", and bulk_create doesn't trigger rebuild signals anyway) ContentNode.objects.partial_rebuild(obj.chef_tree.tree_id) obj.chef_tree.get_descendants(include_self=True).update( original_channel_id=channel_id, source_channel_id=channel_id) old_staging = obj.staging_tree obj.staging_tree = obj.chef_tree obj.chef_tree = None obj.save() # Delete staging tree if it already exists if old_staging and old_staging != obj.main_tree: # IMPORTANT: Do not remove this block, MPTT updating the deleted chefs block could hang the server with ContentNode.objects.disable_mptt_updates(): garbage_node = get_deleted_chefs_root() old_staging.parent = garbage_node old_staging.title = "Old staging tree for channel {}".format( obj.pk) old_staging.save() if not data.get( 'stage' ): # If user says to stage rather than submit, skip changing trees at this step try: activate_channel(obj, request.user) except PermissionDenied as e: return HttpResponseForbidden(str(e)) return HttpResponse( json.dumps({ "success": True, "new_channel": obj.pk, })) except KeyError as e: return HttpResponseBadRequest("Required attribute missing: {}".format( e.message)) except Exception as e: handle_server_error(request) return HttpResponseServerError(content=str(e), reason=str(e))
def api_commit_channel(request): """ Commit the channel staging tree to the main tree """ data = json.loads(request.body) try: channel_id = data['channel_id'] obj = Channel.objects.get(pk=channel_id) # rebuild MPTT tree for this channel (since we set "disable_mptt_updates", and bulk_create doesn't trigger rebuild signals anyway) ContentNode.objects.partial_rebuild(obj.chef_tree.tree_id) obj.chef_tree.get_descendants(include_self=True).update(original_channel_id=channel_id, source_channel_id=channel_id) old_staging = obj.staging_tree obj.staging_tree = obj.chef_tree obj.chef_tree = None obj.save() # Delete staging tree if it already exists if old_staging and old_staging != obj.main_tree: # IMPORTANT: Do not remove this block, MPTT updating the deleted chefs block could hang the server with ContentNode.objects.disable_mptt_updates(): garbage_node = get_deleted_chefs_root() old_staging.parent = garbage_node old_staging.title = "Old staging tree for channel {}".format(obj.pk) old_staging.save() if not data.get('stage'): # If user says to stage rather than submit, skip changing trees at this step try: activate_channel(obj, request.user) except PermissionDenied as e: return HttpResponseForbidden(str(e)) return HttpResponse(json.dumps({ "success": True, "new_channel": obj.pk, })) except KeyError as e: return HttpResponseBadRequest("Required attribute missing: {}".format(e.message)) except Exception as e: handle_server_error(request) return HttpResponseServerError(content=str(e), reason=str(e))
def activate_channel_endpoint(request): data = request.data try: channel = Channel.filter_edit_queryset( Channel.objects.all(), request.user).get(pk=data["channel_id"]) except Channel.DoesNotExist: return HttpResponseNotFound("Channel not found") changes = [] try: change = activate_channel(channel, request.user) changes.append(change) except PermissionDenied as e: return HttpResponseForbidden(str(e)) return HttpResponse(json.dumps({"success": True, "changes": changes}))
def api_channel_structure_upload(request): """ Creates a channel based on the structure sent in the request. :param request: POST request containing the tree structure of a channel. :return: The channel_id of the newly created channel. """ data = json.loads(request.body) try: channel_id = data['channel_id'] channel_structure = data['channel_structure'] new_channel = create_channel_from_structure(channel_id, channel_structure, request.user) if not data.get('stage'): # If user says to stage rather than submit, skip changing trees at this step activate_channel(new_channel, request.user) return HttpResponse(json.dumps({ 'success': True, 'channel_id': new_channel.pk, })) except KeyError: raise ObjectDoesNotExist('Missing attribute from data: {}'.format(data)) except Exception as e: return HttpResponseServerError(content=str(e), reason=str(e))
def activate_channel_endpoint(request): if request.method != "POST": return HttpResponseBadRequest( "Only POST requests are allowed on this endpoint." ) data = json.loads(request.body) channel = Channel.objects.get(pk=data["channel_id"]) changes = [] try: change = activate_channel(channel, request.user) changes.append(change) except PermissionDenied as e: return HttpResponseForbidden(str(e)) return HttpResponse(json.dumps({"success": True, "changes": changes}))
def activate_channel_internal(request): data = json.loads(request.body) channel = Channel.objects.get(pk=data['channel_id']) activate_channel(channel) return HttpResponse(json.dumps({"success": True}))