Skip to content

Commit

Permalink
stuff build during ep 3
Browse files Browse the repository at this point in the history
  • Loading branch information
Nipsuli committed Apr 29, 2022
1 parent 767087c commit a2cba65
Show file tree
Hide file tree
Showing 10 changed files with 9,916 additions and 12,504 deletions.
15 changes: 13 additions & 2 deletions app/auth.server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
import type { Session } from "@supabase/supabase-js";
import { Authenticator, AuthorizationError } from "remix-auth";
import { SupabaseStrategy } from "remix-auth-supabase";
import { supabaseAdmin } from "./supabase.server";
import { supabase, supabaseAdmin } from "./supabase.server";

export const getAuth = (context: AppLoadContext) => {
const sessionCookie = createCookie("__session", {
Expand Down Expand Up @@ -57,7 +57,18 @@ export const getSession = async (
const redirect = redirectBack
? `?redirectTo=${new URL(request.url).pathname}`
: "";
return getAuth(context).authStrategy.checkSession(request, {
const session = await getAuth(context).authStrategy.checkSession(request, {
failureRedirect: `/signin${redirect}`,
});
if (!session.user) throw new Response("No user found", { status: 401 });
return session;
};

export const getSupabase = async (
context: AppLoadContext,
session: Session
) => {
const sp = supabase(context);
sp.auth.setAuth(session.access_token);
return sp;
};
2 changes: 1 addition & 1 deletion app/root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export const links: LinksFunction = () => [{ rel: "stylesheet", href: styles }];

export const meta: MetaFunction = () => ({
charset: "utf-8",
title: "New Remix App",
title: "reconfigured",
viewport: "width=device-width,initial-scale=1",
});

Expand Down
2 changes: 1 addition & 1 deletion app/routes/__auth/logout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ const Logout = () => {
return (
<>
<Form method="post">
<Button className="btn-poo">logout</Button>
<Button>logout</Button>
</Form>
</>
)
Expand Down
87 changes: 73 additions & 14 deletions app/routes/userprofile.tsx
Original file line number Diff line number Diff line change
@@ -1,27 +1,86 @@
import type { LoaderFunction } from "@remix-run/cloudflare";
import type { ActionFunction, LoaderFunction } from "@remix-run/cloudflare";
import { json } from "@remix-run/cloudflare";
import { getSession } from "~/auth.server";
import { getSession, getSupabase } from "~/auth.server";
import type { AuthUser } from "@supabase/supabase-js";
import { useLoaderData } from "@remix-run/react";
import { Typography } from "@supabase/ui";
import { Form, useLoaderData } from "@remix-run/react";
import { Button, Input, Loading, Typography } from "@supabase/ui";
import { useTransition } from "@remix-run/react";
import type { definitions } from "~/types/supabase";

type UserProfile = {
authUser: AuthUser;
user: definitions["users"] | null;
};

export const action: ActionFunction = async ({ request, context }) => {
const session = await getSession(context, request);
const supabase = await getSupabase(context, session);
const formData = await request.formData();
const { error } = await supabase.from("users").upsert({
id: session.user?.id,
email: session.user?.email,
full_name: formData.get("fullname"),
display_name: formData.get("displayname"),
});
if (error) throw error;
return {};
};

export const loader: LoaderFunction = async ({ request, context }) => {
const session = await getSession(context, request)
const session = await getSession(context, request);
const supabase = await getSupabase(context, session);
const { data, error } = await supabase
.from<definitions["users"]>("users")
.select("id,email,full_name,display_name")
.eq("id", session.user?.id || "")
.maybeSingle();

if (!session.user) throw new Response("No user found", { status: 401 })
if (error) throw error;

return json<AuthUser>(session.user)
}
return json<UserProfile>({
authUser: session.user ?? (() => {throw new Error('No bonus')})(),
user: data,
});
};

const Profile = () => {
const user = useLoaderData<AuthUser>()
const userProfile = useLoaderData<UserProfile>();
const { state } = useTransition();
const email = userProfile.authUser.email;
const fullName =
userProfile.user?.full_name ||
userProfile.authUser.user_metadata?.full_name ||
"";
const displayName =
userProfile.user?.display_name ||
(userProfile.authUser.user_metadata?.full_name || "").split(" ")[0];
return (
<>
<Typography.Title level={1}>User Profile</Typography.Title>
<Typography.Text>Hello {user.email}! Full user data:</Typography.Text>
<Typography.Text><pre>{JSON.stringify(user, undefined, 2)}</pre></Typography.Text>
<Loading active={state === "submitting"}>
<Form method="post" replace>
<div className="sbui-space-col sbui-space-y-3">
<Input name="email" label="Email" value={email} disabled />
<Input
name="fullname"
label="Full Name"
placeholder="Full Name"
defaultValue={fullName}
/>
<Input
name="displayname"
label="Display Name"
placeholder="Display Name"
defaultValue={displayName}
/>
<Button htmlType="submit" disabled={state === "submitting"}>
{state === "submitting" ? "Saving..." : "Save"}
</Button>
</div>
</Form>
</Loading>
</>
)
}
);
};

export default Profile
export default Profile;
20 changes: 20 additions & 0 deletions app/supabase.server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,24 @@ export const supabaseAdmin = (context: AppLoadContext) => {
)
}

export const supabase = (context: AppLoadContext) => {
if (!context.SUPABASE_URL)
throw new Error('ENV: SUPABASE_URL is required')

if (!context.PUBLIC_SUPABASE_ANON_KEY)
throw new Error('ENV: PUBLIC_SUPABASE_ANON_KEY is required')

const supabaseOptions = {
fetch: fetch.bind(globalThis), // see ⚠️ cloudflare
schema: "public",
autoRefreshToken: true,
};

return createClient(
context.SUPABASE_URL,
context.PUBLIC_SUPABASE_ANON_KEY,
supabaseOptions
)
}

export { Session, ApiError }
8 changes: 8 additions & 0 deletions app/tailwind.css
Original file line number Diff line number Diff line change
Expand Up @@ -477,6 +477,14 @@ body {
--tw-backdrop-sepia: ;
}

.w-10 {
width: 2.5rem;
}

.min-w-\[50\] {
min-width: 50;
}

.auth-container {
display: grid;
height: 100vh;
Expand Down
179 changes: 179 additions & 0 deletions app/types/supabase.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
/**
* This file was auto-generated by openapi-typescript.
* Do not make direct changes to the file.
*/

export interface paths {
"/": {
get: {
responses: {
/** OK */
200: unknown;
};
};
};
"/users": {
get: {
parameters: {
query: {
id?: parameters["rowFilter.users.id"];
created_at?: parameters["rowFilter.users.created_at"];
full_name?: parameters["rowFilter.users.full_name"];
display_name?: parameters["rowFilter.users.display_name"];
email?: parameters["rowFilter.users.email"];
/** Filtering Columns */
select?: parameters["select"];
/** Ordering */
order?: parameters["order"];
/** Limiting and Pagination */
offset?: parameters["offset"];
/** Limiting and Pagination */
limit?: parameters["limit"];
};
header: {
/** Limiting and Pagination */
Range?: parameters["range"];
/** Limiting and Pagination */
"Range-Unit"?: parameters["rangeUnit"];
/** Preference */
Prefer?: parameters["preferCount"];
};
};
responses: {
/** OK */
200: {
schema: definitions["users"][];
};
/** Partial Content */
206: unknown;
};
};
post: {
parameters: {
body: {
/** users */
users?: definitions["users"];
};
query: {
/** Filtering Columns */
select?: parameters["select"];
};
header: {
/** Preference */
Prefer?: parameters["preferReturn"];
};
};
responses: {
/** Created */
201: unknown;
};
};
delete: {
parameters: {
query: {
id?: parameters["rowFilter.users.id"];
created_at?: parameters["rowFilter.users.created_at"];
full_name?: parameters["rowFilter.users.full_name"];
display_name?: parameters["rowFilter.users.display_name"];
email?: parameters["rowFilter.users.email"];
};
header: {
/** Preference */
Prefer?: parameters["preferReturn"];
};
};
responses: {
/** No Content */
204: never;
};
};
patch: {
parameters: {
query: {
id?: parameters["rowFilter.users.id"];
created_at?: parameters["rowFilter.users.created_at"];
full_name?: parameters["rowFilter.users.full_name"];
display_name?: parameters["rowFilter.users.display_name"];
email?: parameters["rowFilter.users.email"];
};
body: {
/** users */
users?: definitions["users"];
};
header: {
/** Preference */
Prefer?: parameters["preferReturn"];
};
};
responses: {
/** No Content */
204: never;
};
};
};
}

export interface definitions {
/** @description stores users */
users: {
/**
* Format: uuid
* @description Note:
* This is a Primary Key.<pk/>
*/
id: string;
/**
* Format: timestamp with time zone
* @default now()
*/
created_at: string;
/** Format: text */
full_name: string;
/** Format: text */
display_name: string;
/** Format: text */
email: string;
};
}

export interface parameters {
/** @description Preference */
preferParams: "params=single-object";
/** @description Preference */
preferReturn: "return=representation" | "return=minimal" | "return=none";
/** @description Preference */
preferCount: "count=none";
/** @description Filtering Columns */
select: string;
/** @description On Conflict */
on_conflict: string;
/** @description Ordering */
order: string;
/** @description Limiting and Pagination */
range: string;
/**
* @description Limiting and Pagination
* @default items
*/
rangeUnit: string;
/** @description Limiting and Pagination */
offset: string;
/** @description Limiting and Pagination */
limit: string;
/** @description users */
"body.users": definitions["users"];
/** Format: uuid */
"rowFilter.users.id": string;
/** Format: timestamp with time zone */
"rowFilter.users.created_at": string;
/** Format: text */
"rowFilter.users.full_name": string;
/** Format: text */
"rowFilter.users.display_name": string;
/** Format: text */
"rowFilter.users.email": string;
}

export interface operations {}

export interface external {}
Loading

0 comments on commit a2cba65

Please sign in to comment.