Radish alpha
r
rad:z4V1sjrXqjvFdnCUbxPFqd5p4DtH5
Radicle web interface
Radicle
Git
Improve authentication error modal
Merged rudolfs opened 2 years ago

We tell users to check their firewall and ad blocker settings in case they bump into authentication problems.

check check-visual check-unit-test check-httpd-api-unit-test check-e2e check-build

👉 Preview
👉 Workflow runs
👉 Branch on GitHub

12 files changed +72 -52 8f43a579 4a5e67dd
modified src/lib/router/definitions.ts
@@ -22,7 +22,7 @@ export interface NotFoundRoute {
  params: { title: string };
}

-
interface SessionRoute {
+
export interface SessionRoute {
  resource: "session";
  params: {
    id: string;
modified src/lib/utils.ts
@@ -94,8 +94,8 @@ export function formatEditedCaption(
  } edited ${absoluteTimestamp(timestamp)}`;
}

-
export function baseUrlToUrl(baseUrl: BaseUrl): URL {
-
  return new URL(`${baseUrl.scheme}://${baseUrl.hostname}:${baseUrl.port}`);
+
export function baseUrlToString(baseUrl: BaseUrl): string {
+
  return `${baseUrl.scheme}://${baseUrl.hostname}:${baseUrl.port}`;
}

// Generates a publicly shareable link.
modified src/modals/AuthenticationErrorModal.svelte
@@ -1,15 +1,36 @@
<script lang="ts">
+
  import { baseUrlToString } from "@app/lib/utils";
+
  import * as httpd from "@app/lib/httpd";
+

  import Modal from "@app/components/Modal.svelte";
  import Icon from "@app/components/Icon.svelte";

-
  export let title: string;
-
  export let subtitle: string[];
+
  // @ts-expect-error https://github.com/microsoft/TypeScript/issues/41532
+
  const isBrave = navigator.brave !== undefined;
+
  const url = baseUrlToString(httpd.api.baseUrl);
</script>

-
<Modal {title} showCloseButton>
+
<Modal title="Authentication failed" showCloseButton>
  <Icon name="alert" size="48" slot="icon" />

  <div slot="subtitle">
-
    {@html subtitle.join("<br />")}
+
    Make sure your browser is able to connect to <a href={url}>{url}</a>
+
    &#x200B.
+

+
    <br />
+

+
    {#if isBrave}
+
      It seems like you're using Brave browser, to make authentication work, <br />
+
      disable trackers and ad blockers in settings/shields.
+
    {:else}
+
      Firewalls and ad blockers can interfere with authentication, <br />
+
      try disabling them and try again.
+
    {/if}
+

+
    <br />
+
    <br />
+
    If the above doesn't help, check for errors in the browser console and
+
    <br />
+
    in the terminal where you ran the auth command.
  </div>
</Modal>
modified src/views/home/Index.svelte
@@ -10,7 +10,7 @@

  import { api, httpdStore } from "@app/lib/httpd";
  import { deduplicateStore } from "@app/lib/deduplicateStore";
-
  import { baseUrlToUrl } from "@app/lib/utils";
+
  import { baseUrlToString } from "@app/lib/utils";
  import { getProjectsListingData } from "@app/lib/projects";
  import { handleError } from "@app/views/home/error";
  import { isDelegate } from "@app/lib/roles";
@@ -160,10 +160,7 @@
              </div>
            {:else if localProjects instanceof Error}
              <ErrorMessage
-
                {...handleError(
-
                  localProjects,
-
                  baseUrlToUrl(api.baseUrl).toString(),
-
                )} />
+
                {...handleError(localProjects, baseUrlToString(api.baseUrl))} />
            {:else if !localProjects?.length}
              <div class="heading">No local projects</div>
              <div class="label">
@@ -219,7 +216,7 @@
            <ErrorMessage
              {...handleError(
                preferredSeedProjects,
-
                baseUrlToUrl(api.baseUrl).toString(),
+
                baseUrlToString(api.baseUrl),
              )} />
          {:else}
            <div class="heading">Nothing to see here</div>
modified src/views/nodes/router.ts
@@ -4,7 +4,7 @@ import type { ProjectWithListingData } from "@app/lib/projects";

import { HttpdClient } from "@httpd-client";
import { config } from "@app/lib/config";
-
import { baseUrlToUrl, isLocal } from "@app/lib/utils";
+
import { baseUrlToString, isLocal } from "@app/lib/utils";
import { getProjectsListingData } from "@app/lib/projects";
import { handleError } from "@app/views/nodes/error";

@@ -77,6 +77,6 @@ export async function loadNodeRoute(
      },
    };
  } catch (error: any) {
-
    return handleError(error, baseUrlToUrl(api.baseUrl).toString());
+
    return handleError(error, baseUrlToString(api.baseUrl));
  }
}
modified src/views/projects/Cob/Revision.svelte
@@ -509,9 +509,9 @@
          style:border-radius="var(--border-radius-small">
          <ErrorMessage
            title="Failed to load diff for this revision"
-
            description="Make sure you are able to connect to the seed <code>${utils
-
              .baseUrlToUrl(api.baseUrl)
-
              .toString()}</code>"
+
            description="Make sure you are able to connect to the seed <code>${utils.baseUrlToString(
+
              api.baseUrl,
+
            )}</code>"
            {error} />
        </div>
      {/if}
modified src/views/projects/History.svelte
@@ -10,7 +10,7 @@

  import { COMMITS_PER_PAGE } from "./router";
  import { HttpdClient } from "@httpd-client";
-
  import { baseUrlToUrl } from "@app/lib/utils";
+
  import { baseUrlToString } from "@app/lib/utils";
  import { groupCommits } from "@app/lib/commit";

  import Button from "@app/components/Button.svelte";
@@ -160,9 +160,9 @@
    <div class="message">
      <ErrorMessage
        title="Couldn't load commits"
-
        description="Make sure you are able to connect to the seed <code>${baseUrlToUrl(
+
        description="Make sure you are able to connect to the seed <code>${baseUrlToString(
          api.baseUrl,
-
        ).toString()}</code>"
+
        )}</code>"
        {error} />
    </div>
  {/if}
modified src/views/projects/Issue/New.svelte
@@ -8,7 +8,7 @@
  import { httpdStore } from "@app/lib/httpd";

  import AssigneeInput from "@app/views/projects/Cob/AssigneeInput.svelte";
-
  import AuthenticationErrorModal from "@app/modals/AuthenticationErrorModal.svelte";
+
  import ErrorModal from "@app/modals/ErrorModal.svelte";
  import CobHeader from "@app/views/projects/Cob/CobHeader.svelte";
  import ErrorMessage from "@app/components/ErrorMessage.svelte";
  import ExtendedTextarea from "@app/components/ExtendedTextarea.svelte";
@@ -45,16 +45,26 @@
        node: baseUrl,
        issue: result.id,
      });
-
    } catch {
-
      modal.show({
-
        component: AuthenticationErrorModal,
-
        props: {
-
          title: "Authentication failed",
-
          subtitle: [
-
            "Could not create the issue. Make sure you're still logged in.",
-
          ],
-
        },
-
      });
+
    } catch (error) {
+
      if (error instanceof Error) {
+
        modal.show({
+
          component: ErrorModal,
+
          props: {
+
            title: "Coult not create issue",
+
            subtitle: [
+
              "There was an error while updating the issue.",
+
              "Make sure you're authenticated.",
+
              "Check your radicle-httpd logs for details.",
+
            ],
+
            error: {
+
              message: error.message,
+
              stack: error.stack,
+
            },
+
          },
+
        });
+
      } else {
+
        console.error(error);
+
      }
    }
  }

modified src/views/projects/Issues.svelte
@@ -5,7 +5,7 @@
  import { ISSUES_PER_PAGE } from "./router";
  import { closeFocused } from "@app/components/Popover.svelte";
  import { httpdStore } from "@app/lib/httpd";
-
  import { baseUrlToUrl, isLocal } from "@app/lib/utils";
+
  import { baseUrlToString, isLocal } from "@app/lib/utils";
  import capitalize from "lodash/capitalize";

  import Button from "@app/components/Button.svelte";
@@ -176,9 +176,9 @@
  {#if error}
    <ErrorMessage
      title="Couldn't load issues"
-
      description="Please make sure you are able to connect to the seed <code>${baseUrlToUrl(
+
      description="Please make sure you are able to connect to the seed <code>${baseUrlToString(
        api.baseUrl,
-
      ).toString()}</code>"
+
      )}</code>"
      {error} />
  {/if}

modified src/views/projects/Patches.svelte
@@ -6,7 +6,7 @@

  import { PATCHES_PER_PAGE } from "./router";
  import { httpdStore } from "@app/lib/httpd";
-
  import { baseUrlToUrl, isLocal } from "@app/lib/utils";
+
  import { baseUrlToString, isLocal } from "@app/lib/utils";

  import Button from "@app/components/Button.svelte";
  import DropdownList from "@app/components/DropdownList.svelte";
@@ -195,9 +195,9 @@
  {#if error}
    <ErrorMessage
      title="Couldn't load patches"
-
      description="Please make sure you are able to connect to the seed <code>${baseUrlToUrl(
+
      description="Please make sure you are able to connect to the seed <code>${baseUrlToString(
        api.baseUrl,
-
      ).toString()}</code>"
+
      )}</code>"
      {error} />
  {/if}

modified src/views/projects/error.ts
@@ -1,7 +1,7 @@
import type { ErrorRoute, NotFoundRoute } from "@app/lib/router/definitions";
import type { ProjectRoute } from "@app/views/projects/router";

-
import { baseUrlToUrl, isLocal } from "@app/lib/utils";
+
import { baseUrlToString, isLocal } from "@app/lib/utils";
import { ResponseParseError, ResponseError } from "@httpd-client/lib/fetcher";
import { httpdStore } from "@app/lib/httpd";
import { get } from "svelte/store";
@@ -10,7 +10,7 @@ export function handleError(
  error: Error | ResponseParseError | ResponseError,
  route: ProjectRoute,
): NotFoundRoute | ErrorRoute {
-
  const url = baseUrlToUrl(route.node);
+
  const url = baseUrlToString(route.node);
  if (error instanceof ResponseError && error.status === 404) {
    let subject;

modified src/views/session/Index.svelte
@@ -1,5 +1,5 @@
<script lang="ts">
-
  import type { Route } from "@app/lib/router/definitions";
+
  import type { SessionRoute } from "@app/lib/router/definitions";

  import { onMount } from "svelte";

@@ -12,7 +12,7 @@

  import AuthenticationErrorModal from "@app/modals/AuthenticationErrorModal.svelte";

-
  export let activeRoute: Extract<Route, { resource: "session" }>;
+
  export let activeRoute: SessionRoute;

  onMount(async () => {
    const port = Number.parseInt(activeRoute.params.apiAddr.split(":")[1]);
@@ -21,18 +21,10 @@
    }
    const isAuthenticated = await httpd.authenticate(activeRoute.params);

-
    if (isAuthenticated) {
-
      // TODO: Show toast.
-
    } else {
+
    if (!isAuthenticated) {
      modal.show({
        component: AuthenticationErrorModal,
-
        props: {
-
          title: "Authentication failed",
-
          subtitle: [
-
            "There was an error while authenticating.",
-
            "Check your radicle-httpd logs for details.",
-
          ],
-
        },
+
        props: {},
      });
    }
    void router.navigateToUrl(