def get(self, request: HttpRequest): """Render workflow-list page.""" ctx = JsonizeContext(request.user, request.session, request.locale_id, {}) def list_workflows_as_json(**kwargs) -> List[Dict[str, Any]]: workflows = (Workflow.objects.filter(**kwargs).prefetch_related( "acl", "owner", "last_delta").order_by("-last_delta__datetime").filter( Q(lesson_slug__isnull=True) | Q(lesson_slug=""))) return [ jsonize_clientside_workflow( w.to_clientside(include_tab_slugs=False), ctx, is_init=True) for w in workflows ] init_state = { "loggedInUser": jsonize_user(request.user), "workflows": { "owned": list_workflows_as_json(owner=request.user), "shared": list_workflows_as_json(acl__email=request.user.email), "templates": list_workflows_as_json(in_all_users_workflow_lists=True), }, } return TemplateResponse(request, "workflows.html", {"initState": init_state})
def import_from_github(request): if not request.user.is_staff: return JsonResponse({"error": "Only an admin can call this method"}, status=403) try: url = str(json.loads(request.body)["url"]) except (ValueError, KeyError, TypeError): return JsonResponse( {"error": "You must pass a 'url' to a Git repository"}, status=400) try: clientside_module, module_zipfile = import_module_from_url(url) ctx = JsonizeContext( user=request.user, user_profile=None, session=request.session, locale_id=request.locale_id, module_zipfiles={module_zipfile.module_id: module_zipfile}, ) data = jsonize_clientside_module(clientside_module, ctx) return JsonResponse(data, status=201) except WorkbenchModuleImportError as err: # Respond with 200 OK so the client side can read the error message. # TODO make the client smarter return JsonResponse({"error": str(err)}, status=200)
def _render_workflows(request: HttpRequest, **kwargs) -> TemplateResponse: ctx = JsonizeContext(request.locale_id, {}) workflows = list( Workflow.objects.filter( **kwargs).filter(Q(lesson_slug__isnull=True) | Q(lesson_slug="")).prefetch_related( "acl", "owner").order_by("-updated_at")) clientside_workflows = [ w.to_clientside(include_tab_slugs=False, include_block_slugs=False) for w in workflows ] json_workflows = [ jsonize_clientside_workflow(w, ctx, is_init=True) for w in clientside_workflows ] if request.user.is_anonymous: json_user = None else: with transaction.atomic(): lock_user_by_id(request.user.id, for_write=False) json_user = jsonize_clientside_user( query_clientside_user(request.user.id)) init_state = { "loggedInUser": json_user, "workflows": json_workflows, } return TemplateResponse(request, "workflows.html", {"initState": init_state})
def _get_request_jsonize_context( request: HttpRequest, module_zipfiles: Dict[str, ModuleZipfile]) -> JsonizeContext: return JsonizeContext( locale_id=request.locale_id, module_zipfiles=module_zipfiles, )
def embed(request, wfmodule_id): try: wf_module = WfModule.objects.get(pk=wfmodule_id, is_deleted=False) except WfModule.DoesNotExist: wf_module = None if wf_module and ( not wf_module.workflow or not wf_module.workflow.request_authorized_read(request) or not wf_module.module_version or not wf_module.module_version.html_output ): wf_module = None if wf_module: ctx = JsonizeContext(request.user, request.session, request.locale_id) init_state = { "workflow": jsonize_clientside_workflow( wf_module.workflow.to_clientside(include_tab_slugs=False), ctx, is_init=True, ), "wf_module": jsonize_clientside_step(wf_module.to_clientside(), ctx), } else: init_state = {"workflow": None, "wf_module": None} return TemplateResponse(request, "embed.html", {"initState": init_state})
def make_init_state(request, workflow: Workflow, modules: Dict[str, ModuleZipfile]) -> Dict[str, Any]: """Build a dict to embed as JSON in `window.initState` in HTML. Raise Http404 if the workflow disappeared. Side-effect: update workflow.last_viewed_at. """ try: with workflow.cooperative_lock(): # raise DoesNotExist on race if request.user.is_anonymous: user = None else: lock_user_by_id(request.user.id, for_write=False) user = query_clientside_user(request.user.id) workflow.last_viewed_at = datetime.datetime.now() workflow.save(update_fields=["last_viewed_at"]) state = clientside.Init( user=user, workflow=workflow.to_clientside(), tabs={ tab.slug: tab.to_clientside() for tab in workflow.live_tabs }, steps={ step.id: step.to_clientside( force_module_zipfile=modules.get(step.module_id_name)) for step in Step.live_in_workflow( workflow).prefetch_related("tab") }, modules={ module_id: clientside.Module( spec=module.get_spec(), js_module=module.get_optional_js_module(), ) for module_id, module in modules.items() }, blocks={ block.slug: block.to_clientside() for block in workflow.blocks.all() }, settings={ "bigTableRowsPerTile": settings.BIG_TABLE_ROWS_PER_TILE, "bigTableColumnsPerTile": settings.BIG_TABLE_COLUMNS_PER_TILE, }, ) except Workflow.DoesNotExist: raise Http404("Workflow was recently deleted") ctx = JsonizeContext(request.locale_id, modules) return jsonize_clientside_init(state, ctx)
async def send_update(self, update: clientside.Update) -> None: logger.debug("Send update to Workflow %d", self.workflow_id) module_zipfiles = await _load_latest_modules() ctx = JsonizeContext( self.scope["user"], self.scope["session"], self.scope["locale_id"], module_zipfiles, ) json_dict = jsonize_clientside_update(update, ctx) await self.send_json({"type": "apply-delta", "data": json_dict})
def _get_request_jsonize_context( request: HttpRequest, module_zipfiles: Dict[str, ModuleZipfile] ) -> JsonizeContext: # Anonymous has no user_profile user_profile = UserProfile.objects.filter(user_id=request.user.id).first() return JsonizeContext( user=request.user, user_profile=user_profile, session=request.session, locale_id=request.locale_id, module_zipfiles=module_zipfiles, )
def post(self, request: HttpRequest, workflow_id_or_secret_id: Union[int, str]): workflow = lookup_workflow_and_auth(authorized_read, workflow_id_or_secret_id, request) workflow2 = workflow.duplicate(request.user) ctx = JsonizeContext(request.locale_id, MODULE_REGISTRY.all_latest()) json_dict = jsonize_clientside_workflow(workflow2.to_clientside(), ctx, is_init=True) async_to_sync(rabbitmq.queue_render)(workflow2.id, workflow2.last_delta_id) return JsonResponse(json_dict, status=status.CREATED)
def post(self, request: HttpRequest, workflow: Workflow): workflow2 = workflow.duplicate(request.user) ctx = JsonizeContext(request.user, request.session, request.locale_id) json_dict = jsonize_clientside_workflow(workflow2.to_clientside(), ctx, is_init=True) server.utils.log_user_event_from_request(request, "Duplicate Workflow", {"name": workflow.name}) async_to_sync(rabbitmq.queue_render)(workflow2.id, workflow2.last_delta_id) return JsonResponse(json_dict, status=status.HTTP_201_CREATED)
async def send_update(self, update: clientside.Update) -> None: logger.debug("Send update to Workflow %d", self.workflow_id) module_zipfiles = await _load_latest_modules() ctx = JsonizeContext( user=self.scope["user"], user_profile=None, # [2021-02-05] no updates read it session=self.scope["session"], locale_id=self.scope["locale_id"], module_zipfiles=module_zipfiles, ) json_dict = jsonize_clientside_update(update, ctx) await self.send_json_ignoring_connection_closed({ "type": "apply-delta", "data": json_dict })
def import_from_github(request): if not request.user.is_staff: return JsonResponse( {"error": "Only an admin can call this method"}, status=status.HTTP_403_FORBIDDEN, ) try: module = import_module_from_github(request.data["url"]) ctx = JsonizeContext(request.user, request.session, request.locale_id) data = jsonize_clientside_module(module.to_clientside(), ctx) return JsonResponse(data, status=status.HTTP_201_CREATED) except (RuntimeError, ValueError, ModuleError) as err: # Respond with 200 OK so the client side can read the error message. # TODO make the client smarter return JsonResponse({"error": str(err)}, status=status.HTTP_200_OK)
def embed(request, wfmodule_id): try: wf_module = WfModule.objects.get(pk=wfmodule_id, is_deleted=False) except WfModule.DoesNotExist: wf_module = None if wf_module: if not wf_module.workflow: wf_module = None elif not wf_module.workflow.request_authorized_read(request): wf_module = None else: try: module_zipfile = MODULE_REGISTRY.latest( wf_module.module_id_name) if not module_zipfile.get_spec().html_output: wf_module = None except KeyError: wf_module = None if wf_module: ctx = JsonizeContext( request.user, request.session, request.locale_id, {module_zipfile.module_id: module_zipfile}, ) init_state = { "workflow": jsonize_clientside_workflow( wf_module.workflow.to_clientside(include_tab_slugs=False), ctx, is_init=True, ), "wf_module": jsonize_clientside_step(wf_module.to_clientside(), ctx), } else: init_state = {"workflow": None, "wf_module": None} return TemplateResponse(request, "embed.html", {"initState": init_state})
def import_from_github(request): if not request.user.is_staff: return JsonResponse( {"error": "Only an admin can call this method"}, status=status.HTTP_403_FORBIDDEN, ) try: clientside_module, module_zipfile = import_module_from_url( request.data["url"]) ctx = JsonizeContext( request.user, request.session, request.locale_id, {module_zipfile.module_id: module_zipfile}, ) data = jsonize_clientside_module(clientside_module, ctx) return JsonResponse(data, status=status.HTTP_201_CREATED) except WorkbenchModuleImportError as err: # Respond with 200 OK so the client side can read the error message. # TODO make the client smarter return JsonResponse({"error": str(err)}, status=status.HTTP_200_OK)
def make_init_state(request, workflow: Workflow, modules: Dict[str, ModuleZipfile]) -> Dict[str, Any]: """ Build a dict to embed as JSON in `window.initState` in HTML. Raise Http404 if the workflow disappeared. Side-effect: update workflow.last_viewed_at. """ try: with workflow.cooperative_lock(): # raise DoesNotExist on race workflow.last_viewed_at = timezone.now() workflow.save(update_fields=["last_viewed_at"]) state = clientside.Init( workflow=workflow.to_clientside(), tabs={ tab.slug: tab.to_clientside() for tab in workflow.live_tabs }, steps={ step.id: step.to_clientside() for step in WfModule.live_in_workflow(workflow) }, modules={ module_id: clientside.Module( spec=module.get_spec(), js_module=module.get_optional_js_module(), ) for module_id, module in modules.items() }, ) except Workflow.DoesNotExist: raise Http404("Workflow was recently deleted") ctx = JsonizeContext(request.user, request.session, request.locale_id, modules) return jsonize_clientside_init(state, ctx)
def mock_jsonize_context(user=None, session=None, locale_id=None): return JsonizeContext(user=user, session=session, locale_id=locale_id)