Skip to content

Commit

Permalink
chore: start working on the email verification flow
Browse files Browse the repository at this point in the history
  • Loading branch information
miran248 committed Sep 11, 2023
1 parent 5a2abe0 commit 36ac5fb
Show file tree
Hide file tree
Showing 11 changed files with 138 additions and 65 deletions.
2 changes: 1 addition & 1 deletion src/website/app/ErrorBoundary.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ const ErrorMessage: FC<{
Go back home
</Link>
<Link
to="mailto:hi@bitshare.sh"
to="mailto:hi@248.sh"
className="rounded-md bg-gray-200 px-3.5 py-2.5 text-sm font-semibold text-gray-500 shadow-sm hover:bg-gray-100 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-gray-200"
>
Contact support <span aria-hidden="true">&rarr;</span>
Expand Down
7 changes: 5 additions & 2 deletions src/website/app/routes/_index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,10 @@ import { SectionItem } from "~/layout/SectionItem";
import { KratosIdentity, KratosSession } from "~/openapi/kratos";
import { disableMySession } from "~/services/kratos/disableMySession";
import { exchangeSessionToken } from "~/services/kratos/exchangeSessionToken";
import { listMySessions } from "~/services/kratos/listMySessions";
import {
ListMySessions,
listMySessions,
} from "~/services/kratos/listMySessions";
import { sessionStorage } from "~/session.server";
import {
ActionData,
Expand All @@ -44,7 +47,7 @@ export const loader = async ({
LoaderData & {
user: KratosIdentity;
currentSession: KratosSession;
otherSessions: KratosSession[];
otherSessions: ListMySessions;
// roles: any[];
}
>
Expand Down
33 changes: 25 additions & 8 deletions src/website/app/routes/index/OtherSessions.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { CalendarIcon } from "@heroicons/react/20/solid";
import { Link } from "@remix-run/react";
import { formatDistance, isAfter, parseISO } from "date-fns";
import { FC, useState } from "react";
import {
Expand All @@ -12,11 +11,30 @@ import { SectionHeader } from "~/layout/SectionHeader";
import { SectionItem } from "~/layout/SectionItem";
import { ServerMessage } from "~/layout/ServerMessage";
import { KratosSession } from "~/openapi/kratos";
import { ListMySessions } from "~/services/kratos/listMySessions";
import { ActionData, join, LoaderData } from "~/utils";
import { SessionDetails } from "./SessionDetails";

export const OtherSessions: FC<{ sessions: KratosSession[] }> = ({ sessions }) => {
const [selectedSession, setSelectedSession] = useState<KratosSession | null>(null);
export const OtherSessions: FC<{ sessions: ListMySessions }> = ({
sessions,
}) => {
const [selectedSession, setSelectedSession] = useState<KratosSession | null>(
null
);

if (sessions.type === "failure") {
return (
<Section>
<SectionHeader
title="Other Sessions"
description="This information will be displayed publicly so be careful what you share."
/>
<SectionItem withStripe>
<p>couldn't load sessions: {sessions.message}</p>
</SectionItem>
</Section>
);
}

return (
<>
Expand All @@ -25,17 +43,16 @@ export const OtherSessions: FC<{ sessions: KratosSession[] }> = ({ sessions }) =
title="Other Sessions"
description="This information will be displayed publicly so be careful what you share."
/>

{sessions.map((session, i) => (
{sessions.identities.map((session, i) => (
// <Link
// key={session.id}
// to="#"
// onClick={() => setSelectedSession(session)}
// className="block"
// >
<SectionItem key={session.id} withStripe={i % 2 === 0}>
<SessionItem session={session} />
</SectionItem>
<SectionItem key={session.id} withStripe={i % 2 === 0}>
<SessionItem session={session} />
</SectionItem>
// </Link>
))}
</Section>
Expand Down
8 changes: 8 additions & 0 deletions src/website/app/routes/register.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,14 @@ export const action = async ({
session.set("session_token", response.session_token);

return redirectToHome(guard);
// case "verify":
// return json({
// type: "verify",
// flow: response.flow,
// email: response.email,

// defaultValues: guard.defaultValues,
// });
case "redirect":
return redirect(response.redirect_browser_to, {
status: 303,
Expand Down
2 changes: 1 addition & 1 deletion src/website/app/services/kratos/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@ import { createClient } from "fets";
import { Kratos } from "~/openapi/kratos";

export const kratos = createClient<Kratos>({
endpoint: process.env.KRATOS_ADMIN_ENDPOINT,
endpoint: process.env.KRATOS_PUBLIC_ENDPOINT,
});
5 changes: 3 additions & 2 deletions src/website/app/services/kratos/listMySessions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,10 @@ type Success = {
};
type Failure = { type: "failure"; message: string };

export type ListMySessions = Success | Failure;
export const listMySessions = async (
request: Simplify<OASRequestParams<Kratos, "/sessions", "get">>
): Promise<Success | Failure> => {
): Promise<ListMySessions> => {
const response = await kratos["/sessions"].get(request);

if (response.ok === false) {
Expand All @@ -30,4 +31,4 @@ export const listMySessions = async (
console.log("listMySessions", response.status, JSON.stringify(body, null, 2));

return { type: "success", identities: body };
};
};
22 changes: 20 additions & 2 deletions src/website/app/services/kratos/updateRegistrationFlow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,15 @@ import { kratos } from "~/services/kratos/client";

type Success = { type: "success"; session_token: string };
type Failure = { type: "failure"; message: string };
type Verify = { type: "verify"; flow: string; email: string };
type Info = { type: "info"; message: string };
type Redirect = { type: "redirect"; redirect_browser_to: string };

export const updateRegistrationFlow = async (
request: Simplify<OASRequestParams<Kratos, "/self-service/registration", "post">>
): Promise<Success | Failure | Info | Redirect> => {
request: Simplify<
OASRequestParams<Kratos, "/self-service/registration", "post">
>
): Promise<Success | Failure | Verify | Info | Redirect> => {
const response = await kratos["/self-service/registration"].post(request);

switch (response.status) {
Expand All @@ -29,6 +32,21 @@ export const updateRegistrationFlow = async (
};
}

if (body.continue_with !== undefined && body.continue_with) {
for (const item of body.continue_with) {
if (item.action === "show_verification_ui") {
return {
type: "verify",
// TODO: figure out why openapi + fets produce the incorrect type
// @ts-ignore
flow: item.flow.id,
// @ts-ignore
email: item.flow.verifiable_address,
};
}
}
}

return {
type: "success",
session_token: body.session_token,
Expand Down
3 changes: 3 additions & 0 deletions src/website/hydra/kratos/identity.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@
"password": {
"identifier": true
}
},
"verification": {
"via": "email"
}
}
},
Expand Down
34 changes: 21 additions & 13 deletions src/website/hydra/kratos/kratos.yml
Original file line number Diff line number Diff line change
Expand Up @@ -57,35 +57,43 @@ selfservice:
hd: null # If you want the Google Workspace domain

flows:
settings:
ui_url: http://localhost:3000/settings
# settings:
# ui_url: http://localhost:3000/settings

verification:
enabled: true
ui_url: http://localhost:3000/verification
use: code
notify_unknown_recipients: false
# ui_url: http://localhost:3000/verification

recovery:
enabled: true
ui_url: http://localhost:3000/recovery
use: code
notify_unknown_recipients: false
# ui_url: http://localhost:3000/recovery

logout:
after:
default_browser_return_url: http://localhost:3000/login
# logout:
# after:
# default_browser_return_url: http://localhost:3000/login

login:
ui_url: http://localhost:3000/login
# login:
# # ui_url: http://localhost:3000/login
# after:
# hooks:
# - hook: require_verified_address

registration:
ui_url: http://localhost:3000/registration
enabled: true
# ui_url: http://localhost:3000/registration
after:
password:
hooks:
- hook: session
- hook: show_verification_ui
oidc:
hooks:
- hook: session
error:
ui_url: http://localhost:3000/error
# error:
# ui_url: http://localhost:3000/error

log:
level: debug
Expand Down
Loading

0 comments on commit 36ac5fb

Please sign in to comment.