Example #1
0
def octoprint_http_tunnel(request, pk):
    # We need to catch the moment when tunnel page loads,
    # and redirect to v2 url if plugin version is compatible.
    if request.path == tunnel_views.URL_PREFIX.format(pk=pk) + '/':
        get_printer_or_404(pk, request)
        version = (cache.printer_settings_get(pk)
                   or {}).get('tsd_plugin_version', '')
        if tunnelv2_views.is_plugin_version_supported(version):
            return tunnelv2_views.redirect_to_tunnel_url(request, pk)
    return tunnel_views.octoprint_http_tunnel(request, pk)
Example #2
0
def tunnel(request, pk, template_dir=None):
    get_printer_or_404(pk, request)
    version = (cache.printer_settings_get(pk)
               or {}).get('tsd_plugin_version', '')
    is_v1 = version and not is_plugin_version_supported(version)
    return render(
        request,
        get_template_path('tunnel', template_dir),
        {"v1": is_v1},
    )
Example #3
0
 def response_from_printer(self, request):
     printer = get_printer_or_404(request.GET.get('printer_id'), request)
     return Response(
         self.serializer_class(
             SharedResource.objects.select_related('printer').filter(
                 printer=printer),
             many=True).data)
Example #4
0
 def create(self, request):
     printer = get_printer_or_404(request.GET.get('printer_id'), request)
     # When the GET API is slow, the user may try to turn on the sharing toggle when it's on already
     SharedResource.objects.get_or_create(
         printer=printer,
         defaults={'share_token': hexlify(os.urandom(18)).decode()})
     return self.response_from_printer(request)
    def send_webhook_test(self, request, pk=None):
        printer = get_printer_or_404(pk, request)
        req = requests.post(url=settings.EXT_3D_GEEKS_ENDPOINT,
                            json=dict(token=printer.service_token,
                                      event="test"))
        req.raise_for_status()

        return Response(dict(status='okay'))
def integration(request, pk):
    printer = get_printer_or_404(pk, request)
    if request.method == "POST":
        if request.POST.get('enable') == 't' and not printer.service_token:
            printer.service_token = hexlify(os.urandom(24)).decode()
            printer.save()
        elif request.POST.get('enable') == 'f':
            printer.service_token = None
            printer.save()
            messages.success(
                request,
                "3D Geeks integration has been turned off successfully.")

    return render(request, 'printer_integration.html', {'printer': printer})
    def create(self, request):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        validated_data = serializer.validated_data

        printer = get_printer_or_404(validated_data['target_printer_id'], request)
        app_name = validated_data['app_name']

        if not app_name or app_name == OctoPrintTunnel.INTERNAL_APP:
            raise PermissionDenied

        tunnel = OctoPrintTunnel.create(printer, app_name)
        tunnel_endpoint = tunnel.get_basicauth_url(request, tunnel.plain_basicauth_password)
        return Response({'tunnel_endpoint': tunnel_endpoint}, status=status.HTTP_201_CREATED)
def share_printer(request, pk, template_dir=None):
    printer = get_printer_or_404(pk, request)

    if request.method == "POST":
        if request.POST.get('shared') == 'on':
            if not hasattr(printer, 'sharedresource'):
                SharedResource.objects.create(printer=printer,
                                              share_token=hexlify(
                                                  os.urandom(18)).decode())
        else:
            SharedResource.objects.filter(printer=printer).delete()
            messages.success(
                request,
                'You have disabled printer feed sharing. Previous shareable link has now been revoked.'
            )

    return render(request, get_template_path('share_printer', template_dir),
                  dict(printer=printer, user=request.user))
Example #9
0
    def mute_current_print(self, request, pk=None):
        printer = get_printer_or_404(pk, request)
        printer.mute_current_print(request.GET.get('mute_alert', 'false').lower() == 'true')

        return self.send_command_response(printer, True)
Example #10
0
def octoprint_http_tunnel(request, pk):
    get_printer_or_404(pk, request)
    if request.user.tunnel_usage_over_cap():
        return HttpResponse(
            '<html><body><center><h1>Over Free Limit</h1><hr><h3 style="color: red;">Your month-to-date usage of OctoPrint Tunneling is over the free limit. Support this project and get unlimited tunneling by <a target="_blank" href="https://app.thespaghettidetective.com/ent_pub/pricing/">upgrading to The Spaghetti Detective Pro plan</a>, or wait for the reset of free limit at the start of the next month.</h3></center></body></html>',
            status=412)

    prefix = URL_PREFIX.format(pk=pk)
    method = request.method.lower()
    path = request.get_full_path()[len(prefix):]

    IGNORE_HEADERS = [
        'HTTP_HOST',
        'HTTP_ORIGIN',
        'HTTP_REFERER',
        'HTTP_COOKIE',
    ]

    # Recreate http headers, because django put headers in request.META as "HTTP_XXX_XXX". Is there a better way?
    req_headers = {
        k[5:].replace("_", " ").title().replace(" ", "-"): v
        for (k, v) in request.META.items() if k.startswith("HTTP")
        and not k.startswith('HTTP_X_') and k not in IGNORE_HEADERS
    }

    if 'CONTENT_TYPE' in request.META:
        req_headers['Content-Type'] = request.META['CONTENT_TYPE']

    ref = f'{pk}.{method}.{time.time()}.{path}'

    channels.send_msg_to_printer(
        pk, {
            "http.tunnel": {
                "ref": ref,
                "method": method,
                "headers": req_headers,
                "path": path,
                "data": request.body
            },
            'as_binary': True,
        })

    data = cache.octoprinttunnel_http_response_get(ref)
    if data is None:
        return HttpResponse(
            '<html><body><center><h1>Timed Out</h1><hr><h3 style="color: red;">Either your OctoPrint is offline, or The Spaghetti Detective plugin version is lower than 1.4.0.</h3></center></body></html>',
            status=504)

    content_type = data['response']['headers'].get('Content-Type') or None
    resp = HttpResponse(
        status=data["response"]["status"],
        content_type=content_type,
    )
    for k, v in data['response']['headers'].items():
        if k in ['Content-Length', 'Content-Encoding']:
            continue

        if k == 'Etag':
            v = fix_etag(v)

        resp[k] = v

    url_path = urllib.parse.urlparse(path).path
    if data['response'].get('compressed', False):
        content = zlib.decompress(data['response']['content'])
    else:
        content = data['response']['content']

    cache.octoprinttunnel_update_stats(request.user.id, len(content))

    if content_type and content_type.startswith('text/html'):
        content = rewrite_html(prefix, ensure_bytes(content))
    elif url_path.endswith('jquery.js') or url_path.endswith('jquery.min.js'):
        content = inject_ajax_prefilter(prefix, content)
    elif url_path.endswith('socket.js'):
        content = re.sub(_R_SOCKJS_TRANSPORTS, _rewrite_sockjs_transports,
                         ensure_bytes(content))
    elif url_path.endswith('packed_client.js'):
        content = re.sub(_R_SOCKJS_TRANSPORTS, _rewrite_sockjs_transports,
                         ensure_bytes(content))
    elif url_path.endswith('packed_libs.js'):
        content = re.sub(_R_WS_CONNECT_PATH, _rewrite_ws_connect_path,
                         ensure_bytes(content))
        content = inject_ajax_prefilter(prefix, content)
    elif url_path.endswith('sockjs.js'):
        content = re.sub(_R_WS_CONNECT_PATH, _rewrite_ws_connect_path,
                         ensure_bytes(content))
    elif url_path.endswith('sockjs.min.js'):
        content = re.sub(_R_WS_CONNECT_PATH, _rewrite_ws_connect_path,
                         ensure_bytes(content))

    resp.write(content)
    return resp
def redirect_to_tunnel_url(request, pk):
    printer = get_printer_or_404(pk, request)
    pt = OctoPrintTunnel.get_or_create_for_internal_use(printer)
    url = pt.get_internal_tunnel_url(request)
    return HttpResponseRedirect(url)
Example #12
0
    def partial_update(self, request, pk=None):
        self.get_queryset().filter(pk=pk).update(**request.data)
        printer = get_printer_or_404(pk, request)
        printer.send_should_watch_status()

        return self.send_command_response(printer, True)
    def cancel_print(self, request, pk=None):
        printer = get_printer_or_404(pk, request)
        succeeded = printer.cancel_print(initiator='api')

        return self.send_command_response(printer, succeeded)
 def create(self, request):
     printer = get_printer_or_404(request.GET.get('printer_id'), request)
     SharedResource.objects.create(printer=printer,
                                   share_token=hexlify(
                                       os.urandom(18)).decode())
     return self.response_from_printer(request)
Example #15
0
    def acknowledge_alert(self, request, pk=None):
        printer = get_printer_or_404(pk, request)
        printer.acknowledge_alert(request.GET.get('alert_overwrite'))

        return self.send_command_response(printer, True)
Example #16
0
    def send_command(self, request, pk=None):
        printer = get_printer_or_404(pk, request)
        printer.send_octoprint_command(request.data['cmd'], request.data['args'])

        return self.send_command_response(printer, True)
def delete_printer(request, pk=None):
    printer = get_printer_or_404(pk, request, with_archived=True)
    printer.delete()
    messages.success(request, f'{printer.name} has been deleted!')

    return redirect('/printers/')
Example #18
0
    def resume_print(self, request, pk=None):
        printer = get_printer_or_404(pk, request)
        succeeded = printer.resume_print()

        return self.send_command_response(printer, succeeded)
def tunnel(request, pk, template_dir=None):
    get_printer_or_404(pk, request)
    return render(
        request,
        get_template_path('tunnel', template_dir),
    )