Esempio n. 1
0
    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)
Esempio n. 3
0
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})
Esempio n. 4
0
def _get_request_jsonize_context(
        request: HttpRequest,
        module_zipfiles: Dict[str, ModuleZipfile]) -> JsonizeContext:
    return JsonizeContext(
        locale_id=request.locale_id,
        module_zipfiles=module_zipfiles,
    )
Esempio n. 5
0
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})
Esempio n. 6
0
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)
Esempio n. 7
0
 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})
Esempio n. 8
0
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,
    )
Esempio n. 9
0
    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)
Esempio n. 10
0
    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)
Esempio n. 11
0
 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
     })
Esempio n. 12
0
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)
Esempio n. 13
0
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})
Esempio n. 14
0
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)
Esempio n. 15
0
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)